sidekick/src/util/Bitvec.ml
2022-07-14 22:09:13 -04:00

48 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'