let window_size = 32768 type t = { data : bytes; mutable write_pos : int; mutable size : int; mutable total : int64 } let create () = { data = Bytes.make window_size '\000'; write_pos = 0; size = 0; total = 0L } let current_size t = t.size let total_processed t = t.total let add_byte t b = if b < 0 || b > 255 then invalid_arg "add_byte: byte out of range"; Bytes.set t.data t.write_pos (Char.chr b); t.write_pos <- (t.write_pos + 1) mod window_size; t.total <- Int64.succ t.total; if t.size < window_size then t.size <- t.size + 1 let add_bytes t buf ofs len = if ofs < 0 || ofs + len > Bytes.length buf then invalid_arg "add_bytes: out of bounds"; for i = 0 to len - 1 do Bytes.set t.data t.write_pos (Bytes.get buf (ofs + i)); t.write_pos <- (t.write_pos + 1) mod window_size; t.total <- Int64.succ t.total; if t.size < window_size then t.size <- t.size + 1 done let get_byte_at_distance t distance = if distance <= 0 || distance > t.size || distance > window_size then invalid_arg "get_byte_at_distance: invalid distance"; let pos = (t.write_pos - distance) mod window_size in let pos = if pos < 0 then pos + window_size else pos in Char.code (Bytes.get t.data pos) let extract_slice t start len = if start <= 0 || start > t.size then invalid_arg "extract_slice: invalid start"; if len < 0 then invalid_arg "extract_slice: negative len"; let out = Bytes.make len '\000' in for i = 0 to len - 1 do let dist = start + i in if dist > t.size then invalid_arg "extract_slice: out of range"; let pos = (t.write_pos - dist) mod window_size in let pos = if pos < 0 then pos + window_size else pos in Bytes.set out i (Bytes.get t.data pos) done; out let match_length_at_distance t distance lookahead ofs maxlen = if distance <= 0 || distance > t.size then invalid_arg "match_length_at_distance: invalid distance"; let remaining = Bytes.length lookahead - ofs in if remaining <= 0 || maxlen <= 0 then 0 else let available_in_window = t.size - distance + 1 in let max_cmp = min maxlen (min remaining available_in_window) in let start_pos = (t.write_pos - distance) mod window_size in let start_pos = if start_pos < 0 then start_pos + window_size else start_pos in let rec cmp i = if i >= max_cmp then i else let pos = (start_pos + i) mod window_size in if Bytes.get t.data pos = Bytes.get lookahead (ofs + i) then cmp (i + 1) else i in cmp 0