mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-10 13:14:09 -05:00
55 lines
1.3 KiB
OCaml
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'
|
|
|