type t = { buffer : Buffer.t; handler : (string -> int -> int -> unit) option ref } let create () = { buffer = Buffer.create 1024; handler = ref None } let discard buf = Buffer.clear buf.buffer; buf.handler := None let find_nl str ofs len = let rec aux at = if at >= len then None else if str.[ofs + at] = '\n' then Some at else aux (at + 1) in aux 0 let rec set_handler buf handler = assert (!(buf.handler) = None); buf.handler := Some handler; (* if we already had some data, feed it to the handler; but reset the buffer before calling it! *) if Buffer.length buf.buffer > 0 then let s = Buffer.contents buf.buffer in Buffer.clear buf.buffer; handler s 0 (String.length s) let rec get_line buf cont = set_handler buf (fun str ofs len -> match find_nl str ofs len with | None -> Buffer.add_substring buf.buffer str ofs len | Some len' -> let str' = Buffer.contents buf.buffer ^ String.sub str ofs len' in discard buf; cont str'; feed_substring buf str (ofs + len' + 1) (len - len' - 1) ) and get_n buf n cont = set_handler buf (fun str ofs len -> if Buffer.length buf.buffer + len >= n then let take = n - Buffer.length buf.buffer in let str' = Buffer.contents buf.buffer ^ String.sub str ofs take in discard buf; cont str'; feed_substring buf str (ofs + take) (len - take) else Buffer.add_substring buf.buffer str ofs len ) and feed_substring buf str ofs len = (* Printf.printf "feed substring: %s %d %d\n%!" str ofs len;*) match !(buf.handler) with | None -> Buffer.add_substring buf.buffer str ofs len | Some h -> h str ofs len let feed buf str = feed_substring buf str 0 (String.length str) (* let usecase_main lb fd = let lb = Lb.create () in let rec setup () = Lb.get_line lb ( fun line -> Lb.get_n lb (int_of_string line) ( fun block -> Printf.printf "Received: %s\n" line; setup () ) ) in setup (); io.callback fd (fun input -> Lb.add lb input 0 (String.length input)) *)