101 lines
2.3 KiB
OCaml
101 lines
2.3 KiB
OCaml
(* Copyright 2012 Tony Garnock-Jones <tonygarnockjones@gmail.com>. *)
|
|
|
|
(* This file is part of Hop. *)
|
|
|
|
(* Hop is free software: you can redistribute it and/or modify it *)
|
|
(* under the terms of the GNU General Public License as published by the *)
|
|
(* Free Software Foundation, either version 3 of the License, or (at your *)
|
|
(* option) any later version. *)
|
|
|
|
(* Hop is distributed in the hope that it will be useful, but *)
|
|
(* WITHOUT ANY WARRANTY; without even the implied warranty of *)
|
|
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *)
|
|
(* General Public License for more details. *)
|
|
|
|
(* You should have received a copy of the GNU General Public License *)
|
|
(* along with Hop. If not, see <http://www.gnu.org/licenses/>. *)
|
|
|
|
type t = {
|
|
mutable pos: int;
|
|
limit: int;
|
|
buf: bytes;
|
|
}
|
|
|
|
let create s ofs len = {
|
|
pos = ofs;
|
|
limit = ofs + len;
|
|
buf = s
|
|
}
|
|
|
|
let of_bytes s = create s 0 (Bytes.length s)
|
|
|
|
let sub b ofs len =
|
|
if b.pos + ofs + len > b.limit
|
|
then
|
|
raise End_of_file
|
|
else
|
|
{ pos = b.pos + ofs;
|
|
limit = b.pos + ofs + len;
|
|
buf = b.buf }
|
|
|
|
let remaining b = b.limit - b.pos
|
|
|
|
let skip_byte b =
|
|
if b.pos < b.limit
|
|
then b.pos <- b.pos + 1
|
|
else raise End_of_file
|
|
|
|
let skip_ws b =
|
|
while b.pos < b.limit && Bytes.get b.buf b.pos <= ' ' do
|
|
b.pos <- b.pos + 1
|
|
done
|
|
|
|
let peek_char b =
|
|
if b.pos < b.limit
|
|
then Bytes.get b.buf b.pos
|
|
else raise End_of_file
|
|
|
|
let peek_byte b = int_of_char (peek_char b)
|
|
|
|
let next_char b =
|
|
if b.pos < b.limit
|
|
then
|
|
let v = Bytes.get b.buf b.pos in
|
|
b.pos <- b.pos + 1;
|
|
v
|
|
else
|
|
raise End_of_file
|
|
|
|
let next_byte b = int_of_char (next_char b)
|
|
|
|
let next_chars b n =
|
|
if remaining b < n
|
|
then
|
|
raise End_of_file
|
|
else
|
|
let dst = Bytes.create n in
|
|
Bytes.blit b.buf b.pos dst 0 n;
|
|
b.pos <- b.pos + n;
|
|
dst
|
|
|
|
let next_sub b n =
|
|
let v = sub b 0 n in
|
|
b.pos <- b.pos + n;
|
|
v
|
|
|
|
let until_pred pred b =
|
|
let rec loop acc len =
|
|
if remaining b = 0
|
|
then
|
|
if pred None
|
|
then Hopstr.bytes_of_revlist acc len
|
|
else raise End_of_file
|
|
else
|
|
let ch = peek_char b in
|
|
if pred (Some ch)
|
|
then Hopstr.bytes_of_revlist acc len
|
|
else loop (next_char b :: acc) (len + 1)
|
|
in loop [] 0
|
|
|
|
let until_char c b = until_pred (function Some x -> x = c | None -> false) b
|