mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
add CCBitField, a safe abstraction for bitfields of < 62 bits
This commit is contained in:
parent
13b20cac73
commit
99fb2f84db
3 changed files with 144 additions and 1 deletions
2
_oasis
2
_oasis
|
|
@ -84,7 +84,7 @@ Library "containers_data"
|
||||||
Modules: CCMultiMap, CCMultiSet, CCTrie, CCFlatHashtbl, CCCache,
|
Modules: CCMultiMap, CCMultiSet, CCTrie, CCFlatHashtbl, CCCache,
|
||||||
CCPersistentHashtbl, CCDeque, CCFQueue, CCBV, CCMixtbl,
|
CCPersistentHashtbl, CCDeque, CCFQueue, CCBV, CCMixtbl,
|
||||||
CCMixmap, CCRingBuffer, CCIntMap, CCPersistentArray,
|
CCMixmap, CCRingBuffer, CCIntMap, CCPersistentArray,
|
||||||
CCMixset, CCHashconsedSet, CCGraph, CCHashSet
|
CCMixset, CCHashconsedSet, CCGraph, CCHashSet, CCBitField
|
||||||
BuildDepends: bytes
|
BuildDepends: bytes
|
||||||
FindlibParent: containers
|
FindlibParent: containers
|
||||||
FindlibName: data
|
FindlibName: data
|
||||||
|
|
|
||||||
80
src/data/CCBitField.ml
Normal file
80
src/data/CCBitField.ml
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
(* This file is free software, part of containers. See file "license" for more details. *)
|
||||||
|
|
||||||
|
(** {1 Bit Field} *)
|
||||||
|
|
||||||
|
exception TooManyFields
|
||||||
|
|
||||||
|
let max_width = Sys.word_size - 2
|
||||||
|
|
||||||
|
module type EMPTY = sig end
|
||||||
|
|
||||||
|
module type BITFIELD = sig
|
||||||
|
type t = private int
|
||||||
|
|
||||||
|
val empty : t
|
||||||
|
|
||||||
|
type 'a field
|
||||||
|
|
||||||
|
val get : 'a field -> t -> 'a
|
||||||
|
(** Get a field of type ['a] *)
|
||||||
|
|
||||||
|
val set : 'a field -> 'a -> t -> t
|
||||||
|
(** Set a field of type ['a] *)
|
||||||
|
|
||||||
|
val width : _ field -> int
|
||||||
|
(** Number of bits of the field *)
|
||||||
|
|
||||||
|
val bool : unit -> bool field
|
||||||
|
(** New field of type bool *)
|
||||||
|
|
||||||
|
val int2 : unit -> int field
|
||||||
|
(** New field of type 2-bits int *)
|
||||||
|
end
|
||||||
|
|
||||||
|
module Make(X : EMPTY) : BITFIELD = struct
|
||||||
|
type t = int
|
||||||
|
|
||||||
|
let empty = 0
|
||||||
|
|
||||||
|
let width_ = ref 0
|
||||||
|
|
||||||
|
type 'a field = {
|
||||||
|
start : int;
|
||||||
|
width : int;
|
||||||
|
get : t -> 'a;
|
||||||
|
set : 'a -> t -> t;
|
||||||
|
}
|
||||||
|
|
||||||
|
let get f x = f.get x
|
||||||
|
let set f v x = f.set v x
|
||||||
|
let width f = f.width
|
||||||
|
|
||||||
|
let bool () =
|
||||||
|
let n = !width_ in
|
||||||
|
incr width_;
|
||||||
|
if !width_ > max_width then raise TooManyFields;
|
||||||
|
let mask = 1 lsl n in
|
||||||
|
{
|
||||||
|
start=n;
|
||||||
|
width=1;
|
||||||
|
get=(fun x -> (x land mask) <> 0);
|
||||||
|
set=(fun b x ->
|
||||||
|
if b then x lor mask else x land (lnot mask)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let int2 () =
|
||||||
|
let n = !width_ in
|
||||||
|
width_ := n+2;
|
||||||
|
if !width_ > max_width then raise TooManyFields;
|
||||||
|
let mask = 3 lsl n in
|
||||||
|
{
|
||||||
|
start=n;
|
||||||
|
width=2;
|
||||||
|
get=(fun x -> (x land mask) lsr n);
|
||||||
|
set=(fun v x ->
|
||||||
|
let x = x land (lnot mask) in
|
||||||
|
x lor (v lsl n)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
end
|
||||||
63
src/data/CCBitField.mli
Normal file
63
src/data/CCBitField.mli
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
(* This file is free software, part of containers. See file "license" for more details. *)
|
||||||
|
|
||||||
|
(** {1 Bit Field}
|
||||||
|
|
||||||
|
This module defines efficient bitfields
|
||||||
|
up to 30 or 62 bits (depending on the architecture) in
|
||||||
|
a relatively type-safe way.
|
||||||
|
|
||||||
|
{b status: experimental}
|
||||||
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
|
module type EMPTY = sig end
|
||||||
|
|
||||||
|
(** {2 Bitfield Signature} *)
|
||||||
|
module type BITFIELD = sig
|
||||||
|
type t = private int
|
||||||
|
|
||||||
|
val empty : t
|
||||||
|
|
||||||
|
type 'a field
|
||||||
|
|
||||||
|
val get : 'a field -> t -> 'a
|
||||||
|
(** Get a field of type ['a] *)
|
||||||
|
|
||||||
|
val set : 'a field -> 'a -> t -> t
|
||||||
|
(** Set a field of type ['a] *)
|
||||||
|
|
||||||
|
val width : _ field -> int
|
||||||
|
(** Number of bits of the field *)
|
||||||
|
|
||||||
|
val bool : unit -> bool field
|
||||||
|
(** New field of type bool *)
|
||||||
|
|
||||||
|
val int2 : unit -> int field
|
||||||
|
(** New field of type 2-bits int *)
|
||||||
|
end
|
||||||
|
|
||||||
|
(** Create a new bitfield type
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
{[
|
||||||
|
module B = CCBitField.Make(struct end);;
|
||||||
|
|
||||||
|
let x = B.bool ();;
|
||||||
|
let y = B.int2 ();;
|
||||||
|
let z = B.bool ();;
|
||||||
|
|
||||||
|
B.width y ;; (* = 2 *)
|
||||||
|
|
||||||
|
let f = B.empty
|
||||||
|
|> B.set y 3
|
||||||
|
|> B.set z true ;;
|
||||||
|
(* = 14 *)
|
||||||
|
|
||||||
|
B.get x f ;; (* false *)
|
||||||
|
B.get y f ;; (* 3 *)
|
||||||
|
B.get z f ;; (* true *)
|
||||||
|
|
||||||
|
]}
|
||||||
|
|
||||||
|
*)
|
||||||
|
module Make(X : EMPTY) : BITFIELD
|
||||||
Loading…
Add table
Reference in a new issue