An OCaml webserver, but the allocating version (vs httpz which doesnt)
at main 120 lines 3.5 kB view raw
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;;