(* span.ml - Span type for referencing byte ranges in a buffer *) open Base (* Span with int fields - sufficient for 32KB max buffer. *) type t = { off : int ; len : int } let make ~off ~len = { off; len } (* Accessors - return int *) let off sp = sp.off let len sp = sp.len let equal buf sp s = let slen = String.length s in let sp_len = sp.len in if sp_len <> slen then false else Base_bigstring.memcmp_string buf ~pos1:sp.off s ~pos2:0 ~len:slen = 0 ;; (* Case-insensitive comparison working with int bytes directly. Assumes s is lowercase (all call sites use lowercase constants). *) let equal_caseless buf sp s = let slen = String.length s in let sp_len = sp.len in if sp_len <> slen then false else ( let i = ref 0 in let eq = ref true in let sp_off = sp.off in while !eq && !i < slen do let b1 = Char.to_int (Base_bigstring.unsafe_get buf (sp_off + !i)) in let b2 = Char.to_int (String.unsafe_get s !i) in (* Fast case-insensitive: lowercase b1 if uppercase letter, compare to b2 *) let lower_b1 = if b1 >= 65 && b1 <= 90 then b1 + 32 else b1 in if lower_b1 <> b2 then eq := false else Int.incr i done; !eq) ;; (* Parse int64 from span - returns -1L for empty/invalid values. Note: This does NOT check for overflow. Use parse_int64_limited for security. *) let parse_int64 buf sp = let sp_len = sp.len in if sp_len = 0 then -1L else ( let acc = ref 0L in let i = ref 0 in let valid = ref true in let sp_off = sp.off in while !valid && !i < sp_len do let c = Base_bigstring.unsafe_get buf (sp_off + !i) in match c with | '0' .. '9' -> let digit = Int64.of_int (Char.to_int c - 48) in acc := Int64.(!acc * 10L + digit); Int.incr i | _ -> valid := false done; if !i = 0 then -1L else !acc) ;; (* Parse int64 with overflow protection and maximum value limit. Returns (value, overflow_flag) - value: parsed value or -1L if empty/invalid - overflow_flag: true if value exceeds max_value or has too many digits *) let parse_int64_limited buf sp ~max_value:max_val = let sp_len = sp.len in if sp_len = 0 then (-1L, false) else if sp_len > 19 then (-1L, true) (* int64 max is 19 digits *) else ( let acc = ref 0L in let i = ref 0 in let valid = ref true in let overflow = ref false in let sp_off = sp.off in while !valid && !i < sp_len do let c = Base_bigstring.unsafe_get buf (sp_off + !i) in match c with | '0' .. '9' -> let digit = Int64.of_int (Char.to_int c - 48) in (* Check for multiplication overflow before multiplying *) let new_acc = Int64.(!acc * 10L + digit) in if Int64.(new_acc < !acc) then ( (* Overflow occurred during multiplication *) overflow := true; valid := false ) else if Int64.(new_acc > max_val) then ( overflow := true; valid := false ) else ( acc := new_acc; Int.incr i ) | _ -> valid := false done; if !i = 0 then (-1L, false) else if !overflow then (-1L, true) else (!acc, false) ) ;; let to_string buf sp = Base_bigstring.To_string.sub buf ~pos:sp.off ~len:sp.len let to_bytes buf sp = Base_bigstring.To_bytes.sub buf ~pos:sp.off ~len:sp.len let pp_with_buf buf fmt sp = Stdlib.Format.fprintf fmt "%s" (to_string buf sp) ;; let pp fmt sp = Stdlib.Format.fprintf fmt "{ off = %d; len = %d }" sp.off sp.len ;;