package bytream
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
A streaming bytes and crunching them library
Install
dune-project
Dependency
Authors
Maintainers
Sources
0.2.tar.gz
md5=86080ca17c645960050642fe02d03e41
sha512=f6bc5dfb5c5a9cc2c719bbff4eb66e587e0cbafd1b45a6b7c207df4f810f46466a93508339fd54e5f1c8ee0691e270060bf7535996b1d84d6724b5494de9de1f
doc/src/bytream/in.ml.html
Source file in.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307type t = { mutable reader : unit -> chunk; (* Current chunk *) mutable buffer : buffer; mutable offset : int; (** Buffer's offset *) mutable length : int; (** Buffer's length *) (* *) mutable total_offset : int; (** Total read bytes from some source *) (* *) overlap_buffer : buffer; (** A small buffer to resolve the data gap situation between chunks *) } and buffer = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t and chunk = buffer:buffer * offset:int * length:int (* =================================================================== CONSTRUCTORS =================================================================== *) let make' ?(overlap_size = 0xFF) reader = { reader; buffer = Bstr.empty; offset = 0; length = 0; total_offset = 0; overlap_buffer = Bstr.create overlap_size; } let make ?overlap_size reader = let reader () = let buffer = reader () in (~buffer, ~offset:0, ~length:Bstr.(length buffer)) in make' ?overlap_size reader let of_buffer buffer = { reader = (fun () -> raise End_of_file); buffer; offset = 0; length = Bstr.length buffer; total_offset = 0; overlap_buffer = Bstr.empty; } let of_string s = Bstr.of_string s |> of_buffer let of_channel ?(io_buffer_size = 4096) ic = let buffer = Bstr.create io_buffer_size in let reader () = match In_channel.input_bigarray ic buffer 0 io_buffer_size with | 0 -> raise End_of_file | length -> (~buffer, ~offset:0, ~length) in make' reader (* =================================================================== BUFFER MANIPULATION UTILITY FUNCTIONS =================================================================== *) let[@inline] available_to_read in_stream = in_stream.length let advance_offset in_stream n = (* assert (in_stream.length - n >= 0); *) in_stream.offset <- in_stream.offset + n; in_stream.length <- in_stream.length - n; in_stream.total_offset <- in_stream.total_offset + n let[@inline] acquire_chunk in_stream = in_stream.reader () let set_chunk in_stream ((~buffer, ~offset, ~length) : chunk) = in_stream.buffer <- buffer; in_stream.offset <- offset; in_stream.length <- length let get_chunk in_stream = (~buffer:in_stream.buffer, ~offset:in_stream.offset, ~length:in_stream.length) let[@inline] position in_stream = in_stream.total_offset let rec consume_bytes in_stream len = if len <> 0 then begin let available_bytes = available_to_read in_stream in let available_to_consume = min available_bytes len in advance_offset in_stream available_to_consume; if available_to_consume < len then begin set_chunk in_stream (acquire_chunk in_stream); consume_bytes in_stream (len - available_to_consume) end end (* =================================================================== INPUTS =================================================================== *) let gen_input ~(blit : Bstr.t -> src_off:int -> 'buf -> dst_off:int -> len:int -> unit) in_stream buffer off len = assert (len > 0); let available_bytes = available_to_read in_stream in if available_bytes = 0 then begin set_chunk in_stream (acquire_chunk in_stream) end; let batched_bytes = min len available_bytes in blit in_stream.buffer ~src_off:in_stream.offset buffer ~dst_off:off ~len:batched_bytes; advance_offset in_stream batched_bytes; batched_bytes let rec gen_really_input ~blit in_stream buffer off len = if len > 0 then let batched_bytes = gen_input ~blit in_stream buffer off len in gen_really_input ~blit in_stream buffer (off + batched_bytes) (len - batched_bytes) let[@inline] input in_stream buffer off len = gen_input ~blit:Bstr.blit in_stream buffer off len and[@inline] really_input in_stream buffer off len = gen_really_input ~blit:Bstr.blit in_stream buffer off len let[@inline] input_bytes in_stream bytes off len = gen_input ~blit:Bstr.blit_to_bytes in_stream bytes off len and[@inline] really_input_bytes in_stream bytes off len = gen_really_input ~blit:Bstr.blit_to_bytes in_stream bytes off len (* =================================================================== ENSURE MECHANISM WITH OVERLAPPING =================================================================== *) let push_back in_stream chunk = let acquire_chunk' = in_stream.reader in in_stream.reader <- (fun () -> in_stream.reader <- acquire_chunk'; chunk) let[@inline] ensure_bytes in_stream length = (* assert (length <= Bstr.length in_stream.overlap_buffer); *) let aux in_stream available_bytes length = if available_bytes <> 0 then ( really_input in_stream in_stream.overlap_buffer 0 length; push_back in_stream @@ get_chunk in_stream; set_chunk in_stream (~buffer:in_stream.overlap_buffer, ~offset:0, ~length)) else set_chunk in_stream (acquire_chunk in_stream) in let available_bytes = (available_to_read [@inlined]) in_stream in if available_bytes < length then aux in_stream available_bytes length let[@inline] ensure_bytes_at in_stream len = (ensure_bytes [@inlined]) in_stream len; let offset = in_stream.offset in (advance_offset [@inlined]) in_stream len; offset let ensure_chunk in_stream length = let offset = ensure_bytes_at in_stream length in (~buffer:in_stream.buffer, ~offset, ~length) let ensure_buffer in_stream len = let off = ensure_bytes_at in_stream len in Bstr.sub in_stream.buffer ~off ~len (* =================================================================== COMBINATORS =================================================================== *) let take n input_value in_stream = List.init n @@ fun _ -> input_value in_stream let with_size f in_stream = let off = position in_stream in let result = f in_stream in let off' = position in_stream in (result, off' - off) let[@tail_mod_cons] rec many input_value in_stream = match input_value in_stream with | exception End_of_file -> [] | value -> value :: many input_value in_stream (* =================================================================== INPUT INTEGER VALUES =================================================================== *) let[@inline] gen_get in_stream f n = let off = (ensure_bytes_at [@inlined]) in_stream n in f in_stream.buffer off let[@inline] input_char in_stream = gen_get in_stream Bstr.get 1 let[@inline] input_int8 in_stream = gen_get in_stream Bstr.get_int8 1 let[@inline] input_uint8 in_stream = gen_get in_stream Bstr.get_uint8 1 let[@inline] input_byte in_stream = gen_get in_stream Bstr.get_uint8 1 (* int16 *) let[@inline] input_int16_be in_stream = gen_get in_stream Bstr.get_int16_be 2 let[@inline] input_int16_ne in_stream = gen_get in_stream Bstr.get_int16_ne 2 let[@inline] input_int16_le in_stream = gen_get in_stream Bstr.get_int16_le 2 let[@inline] input_uint16_be in_stream = gen_get in_stream Bstr.get_uint16_be 2 let[@inline] input_uint16_ne in_stream = gen_get in_stream Bstr.get_uint16_ne 2 let[@inline] input_uint16_le in_stream = gen_get in_stream Bstr.get_uint16_le 2 (* int32 *) let[@inline] input_int32_be in_stream = gen_get in_stream Bstr.get_int32_be 4 let[@inline] input_int32_ne in_stream = gen_get in_stream Bstr.get_int32_ne 4 let[@inline] input_int32_le in_stream = gen_get in_stream Bstr.get_int32_le 4 (* int64 *) let[@inline] input_int64_be in_stream = gen_get in_stream Bstr.get_int64_be 4 let[@inline] input_int64_ne in_stream = gen_get in_stream Bstr.get_int64_ne 4 let[@inline] input_int64_le in_stream = gen_get in_stream Bstr.get_int64_le 4 (* =================================================================== OTHER =================================================================== *) let input_string in_stream len = let bytes = Bytes.create len in (really_input_bytes [@inlined]) in_stream bytes 0 len; Bytes.unsafe_to_string bytes let input_while_into_buffer ~max_len p in_stream buffer = let rec aux count = try if count <= max_len then begin (ensure_bytes [@inlined]) in_stream 1; let ch = Bstr.get in_stream.buffer in_stream.offset in if p ch then begin (advance_offset [@inlined]) in_stream 1; Buffer.add_char buffer ch; aux (succ count) end end with _ -> () in aux 0 let check_on_end_of_file in_steam = try let new_chunk = acquire_chunk in_steam in push_back in_steam new_chunk; false with End_of_file -> true let input_while ?(max_len = Int.max_int) p in_stream = let[@inline] input_while_buffered max_len p in_stream = let[@local] buffer = Buffer.create (if max_len <> Int.max_int then max_len else 60) in input_while_into_buffer ~max_len p in_stream buffer; Buffer.contents buffer in let rec try_count_in_buffer max_len p in_stream length = let remaining_bytes_in_buffer = available_to_read in_stream - length in if remaining_bytes_in_buffer > 0 then begin let ch = Bstr.get in_stream.buffer (in_stream.offset + length) in if length <= max_len && p ch then try_count_in_buffer max_len p in_stream (succ length) else input_string in_stream length end else if check_on_end_of_file in_stream then input_string in_stream length else (input_while_buffered [@inlined]) max_len p in_stream in try_count_in_buffer max_len p in_stream 0 let input_while' ~max_len p in_stream = let string = input_while ~max_len p in_stream in consume_bytes in_stream (max_len - String.length string); string let input_line in_stream = let string = input_while (( <> ) '\n') in_stream in match input_char in_stream with | exception End_of_file when "" = string -> raise End_of_file | (exception End_of_file) | '\n' -> string | _ -> failwith "impossible state of input_line" (* =================================================================== TRANSFORMING =================================================================== *) (* ... *)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>