sidekick/src/util/Bitvec.ml
2021-07-19 09:57:02 -04:00

55 lines
1.3 KiB
OCaml

type t = {
mutable chunks: bytes; (* TODO: use a in32vec with bigarray *)
}
let create () : t = {
chunks = Bytes.make 32 '\x00';
}
let i2c = Char.chr
let c2i = Char.code
(* from index to offset in bytes *)
let[@inline] idx_bytes_ (i:int) : int = i lsr 3
(* from index to offset in a single char *)
let mask_ = 0b111
(* number of bytes *)
let[@inline] len_ (self:t) : int = Bytes.length self.chunks
let[@inline never] resize_ self idx : unit =
let new_size =
min Sys.max_string_length
(max (idx+2) (let l = len_ self in l + 10 + l / 2))
in
let new_chunks = Bytes.make new_size (i2c 0) in
Bytes.blit self.chunks 0 new_chunks 0 (len_ self);
self.chunks <- new_chunks;
assert (len_ self > idx)
let[@inline] ensure_size self i =
let idx = idx_bytes_ i in
if idx >= len_ self then (
resize_ self idx
)
let[@inline] get self i : bool =
let idx = idx_bytes_ i in
let c = c2i (Bytes.get self.chunks idx) in
(c land (1 lsl (i land mask_))) <> 0
let set self i b : unit =
let idx = idx_bytes_ i in
let c = c2i (Bytes.get self.chunks idx) in
let c =
if b
then c lor (1 lsl (i land mask_))
else c land (lnot (1 lsl (i land mask_)))
in
Bytes.set self.chunks idx (i2c c)
let clear_all self =
Bytes.fill self.chunks 0 (len_ self) '\x00'