add CCBitField, a safe abstraction for bitfields of < 62 bits

This commit is contained in:
Simon Cruanes 2015-08-11 20:26:47 +02:00
parent 13b20cac73
commit 99fb2f84db
3 changed files with 144 additions and 1 deletions

2
_oasis
View file

@ -84,7 +84,7 @@ Library "containers_data"
Modules: CCMultiMap, CCMultiSet, CCTrie, CCFlatHashtbl, CCCache,
CCPersistentHashtbl, CCDeque, CCFQueue, CCBV, CCMixtbl,
CCMixmap, CCRingBuffer, CCIntMap, CCPersistentArray,
CCMixset, CCHashconsedSet, CCGraph, CCHashSet
CCMixset, CCHashconsedSet, CCGraph, CCHashSet, CCBitField
BuildDepends: bytes
FindlibParent: containers
FindlibName: data

80
src/data/CCBitField.ml Normal file
View 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
View 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