type t = { mutable buf: string; mutable bpos: int; mutable epos: int; } let create size = {buf = String.create size; bpos = 0; epos = 0} let make text = {buf = text; bpos = 0; epos = String.length text;} let replace buf text = buf.buf <- text; buf.bpos <- 0; buf.epos <- String.length text let length buf = buf.epos - buf.bpos let empty buf = length buf = 0 let index buf char = let result = String.index_from buf.buf buf.bpos char in if result < buf.epos then result - buf.bpos else raise Not_found let contents buf = String.sub buf.buf buf.bpos (buf.epos - buf.bpos) (* Return the first N characters of a buffer *) let head buf n = if buf.bpos + n <= buf.epos then String.sub buf.buf buf.bpos n else raise (Invalid_argument "Charqueue.head") (* Return the last N characters of a buffer *) let tail buf n = if buf.bpos + n <= buf.epos then String.sub buf.buf (buf.epos - n) n else raise (Invalid_argument "Charqueue.tail") let clear buf = buf.epos <- buf.bpos let discard buf n = (* Discard the beginning of the buffer text *) if n <= length buf then buf.bpos <- buf.bpos + n else raise (Invalid_argument "Charqueue.discard") let pop buf n = (* Discard the end of the buffer text *) if n <= length buf then buf.epos <- buf.epos - n else raise (Invalid_argument "Charqueue.pop") (* Make a buffer capable of holding at least LENGTH characters. *) let extend buf length = if String.length buf.buf - buf.bpos >= length then () (* We have sufficent space. *) else if length > Sys.max_string_length then raise (Invalid_argument "Charqueue.extend") else if String.length buf.buf < length then begin (* Allocate a new and longer buffer *) let newdim = (let rec loop n = if n >= length then min n Sys.max_string_length else loop (n * 2) in loop (min 1 (String.length buf.buf))) in let newbuf = String.create newdim in String.blit buf.buf buf.bpos newbuf 0 (buf.epos - buf.bpos); buf.epos <- buf.epos - buf.bpos; buf.bpos <- 0; buf.buf <- newbuf end else begin (* Reclaim enough space by moving the buffer contents to the left *) String.blit buf.buf buf.bpos buf.buf 0 (buf.epos - buf.bpos); buf.epos <- buf.epos - buf.bpos; buf.bpos <- 0 end let add_string buf text = let len = String.length text in extend buf (length buf + len); String.blit text 0 buf.buf buf.epos len; buf.epos <- buf.epos + len