An OCaml webserver, but the allocating version (vs httpz which doesnt)
1(* span.ml - Span type for referencing byte ranges in a buffer *)
2
3open Base
4
5(* Span with int fields - sufficient for 32KB max buffer. *)
6type t =
7 { off : int
8 ; len : int
9 }
10
11let make ~off ~len = { off; len }
12
13(* Accessors - return int *)
14let off sp = sp.off
15let len sp = sp.len
16
17let equal buf sp s =
18 let slen = String.length s in
19 let sp_len = sp.len in
20 if sp_len <> slen
21 then false
22 else Base_bigstring.memcmp_string buf ~pos1:sp.off s ~pos2:0 ~len:slen = 0
23;;
24
25(* Case-insensitive comparison working with int bytes directly.
26 Assumes s is lowercase (all call sites use lowercase constants). *)
27let equal_caseless buf sp s =
28 let slen = String.length s in
29 let sp_len = sp.len in
30 if sp_len <> slen
31 then false
32 else (
33 let i = ref 0 in
34 let eq = ref true in
35 let sp_off = sp.off in
36 while !eq && !i < slen do
37 let b1 = Char.to_int (Base_bigstring.unsafe_get buf (sp_off + !i)) in
38 let b2 = Char.to_int (String.unsafe_get s !i) in
39 (* Fast case-insensitive: lowercase b1 if uppercase letter, compare to b2 *)
40 let lower_b1 = if b1 >= 65 && b1 <= 90 then b1 + 32 else b1 in
41 if lower_b1 <> b2
42 then eq := false
43 else Int.incr i
44 done;
45 !eq)
46;;
47
48(* Parse int64 from span - returns -1L for empty/invalid values.
49 Note: This does NOT check for overflow. Use parse_int64_limited for security. *)
50let parse_int64 buf sp =
51 let sp_len = sp.len in
52 if sp_len = 0
53 then -1L
54 else (
55 let acc = ref 0L in
56 let i = ref 0 in
57 let valid = ref true in
58 let sp_off = sp.off in
59 while !valid && !i < sp_len do
60 let c = Base_bigstring.unsafe_get buf (sp_off + !i) in
61 match c with
62 | '0' .. '9' ->
63 let digit = Int64.of_int (Char.to_int c - 48) in
64 acc := Int64.(!acc * 10L + digit);
65 Int.incr i
66 | _ -> valid := false
67 done;
68 if !i = 0 then -1L else !acc)
69;;
70
71(* Parse int64 with overflow protection and maximum value limit.
72 Returns (value, overflow_flag)
73 - value: parsed value or -1L if empty/invalid
74 - overflow_flag: true if value exceeds max_value or has too many digits *)
75let parse_int64_limited buf sp ~max_value:max_val =
76 let sp_len = sp.len in
77 if sp_len = 0 then (-1L, false)
78 else if sp_len > 19 then (-1L, true) (* int64 max is 19 digits *)
79 else (
80 let acc = ref 0L in
81 let i = ref 0 in
82 let valid = ref true in
83 let overflow = ref false in
84 let sp_off = sp.off in
85 while !valid && !i < sp_len do
86 let c = Base_bigstring.unsafe_get buf (sp_off + !i) in
87 match c with
88 | '0' .. '9' ->
89 let digit = Int64.of_int (Char.to_int c - 48) in
90 (* Check for multiplication overflow before multiplying *)
91 let new_acc = Int64.(!acc * 10L + digit) in
92 if Int64.(new_acc < !acc) then (
93 (* Overflow occurred during multiplication *)
94 overflow := true;
95 valid := false
96 ) else if Int64.(new_acc > max_val) then (
97 overflow := true;
98 valid := false
99 ) else (
100 acc := new_acc;
101 Int.incr i
102 )
103 | _ -> valid := false
104 done;
105 if !i = 0 then (-1L, false)
106 else if !overflow then (-1L, true)
107 else (!acc, false)
108 )
109;;
110
111let to_string buf sp = Base_bigstring.To_string.sub buf ~pos:sp.off ~len:sp.len
112let to_bytes buf sp = Base_bigstring.To_bytes.sub buf ~pos:sp.off ~len:sp.len
113
114let pp_with_buf buf fmt sp =
115 Stdlib.Format.fprintf fmt "%s" (to_string buf sp)
116;;
117
118let pp fmt sp =
119 Stdlib.Format.fprintf fmt "{ off = %d; len = %d }" sp.off sp.len
120;;