123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135(* This file is free software, part of containers. See file "license" for more details. *)(** {1 Bit Field} *)exceptionTooManyFieldsexceptionFrozenletmax_width=Sys.word_size-2(*$R
let module B = CCBitField.Make(struct end) in
let x = B.mk_field () in
let y = B.mk_field () in
let z = B.mk_field () in
let f = B.empty |> B.set x true |> B.set y true in
assert_bool "z_false" (not (B.get z f)) ;
assert_bool "z_true" (f |> B.set z true |> B.get z);
*)(*$R
let module B = CCBitField.Make(struct end) in
let _ = B.mk_field () in
B.freeze();
assert_bool "must raise"
(try ignore (B.mk_field()); false with Frozen -> true);
*)(*$R
let module B = CCBitField.Make(struct end) in
let x = B.mk_field () in
let y = B.mk_field () in
let z = B.mk_field () in
let u = B.mk_field () in
B.freeze();
let f = B.empty
|> B.set y true
|> B.set z true
in
assert_equal ~printer:CCInt.to_string 6 (f :> int) ;
assert_equal false (B.get x f) ;
assert_equal true (B.get y f) ;
assert_equal true (B.get z f);
let f' = B.set u true f in
assert_equal false (B.get x f') ;
assert_equal true (B.get y f') ;
assert_equal true (B.get z f');
assert_equal true (B.get u f');
()
*)moduletypeS=sigtypet=privateint(** Generative type of bitfields. Each instantiation of the functor
should create a new, incompatible type *)valempty:t(** Empty bitfields (all bits 0) *)typefieldvalget:field->t->bool(** Get the value of this field *)valset:field->bool->t->t(** Set the value of this field *)valmk_field:unit->field(** Make a new field *)valfreeze:unit->unit(** Prevent new fields from being added. From now on, creating
a field will raise Frozen *)valtotal_width:unit->int(** Current width of the bitfield *)end(* all bits from 0 to w-1 set to true *)letrecall_bits_accw=ifw=0thenaccelseletacc=acclor(1lslw-1)inall_bits_acc(w-1)(*$T
all_bits_ 0 1 = 1
all_bits_ 0 2 = 3
all_bits_ 0 3 = 7
all_bits_ 0 4 = 15
*)(* increment and return previous value *)letget_then_incrn=letx=!ninincrn;xmoduleMake(X:sigend):S=structtypet=intletempty=0letwidth_=ref0letfrozen_=reffalsetypefield=int(* a mask *)let[@inline]getfieldx=(xlandfield)<>0let[@inline]setfieldbx=ifbthenxlorfieldelsexland(lnotfield)letmk_field()=if!frozen_thenraiseFrozen;letn=get_then_incrwidth_inifn>max_widththenraiseTooManyFields;letmask=1lslninmaskletfreeze()=frozen_:=truelettotal_width()=!width_end