70 lines
1.7 KiB
OCaml
70 lines
1.7 KiB
OCaml
open Import
|
|
|
|
type t =
|
|
{ s : string
|
|
; pos : int
|
|
; len : int
|
|
}
|
|
|
|
module L = struct
|
|
type nonrec t = t list
|
|
|
|
let get_substring slices ~start ~stop =
|
|
if stop = start
|
|
then ""
|
|
else (
|
|
let slices =
|
|
let rec drop slices remains =
|
|
if remains = 0
|
|
then slices
|
|
else (
|
|
match slices with
|
|
| [] -> assert false
|
|
| ({ s = _; pos; len } as slice) :: xs ->
|
|
let remains' = remains - len in
|
|
if remains' >= 0
|
|
then drop xs remains'
|
|
else (
|
|
let pos = pos + remains in
|
|
let len = len - remains in
|
|
{ slice with pos; len } :: xs))
|
|
in
|
|
drop slices start
|
|
in
|
|
let buf = Buffer.create (stop - start) in
|
|
let rec take slices remains =
|
|
if remains > 0
|
|
then (
|
|
match slices with
|
|
| [] -> assert false
|
|
| { s; pos; len } :: xs ->
|
|
let remains' = remains - len in
|
|
if remains' > 0
|
|
then (
|
|
Buffer.add_substring buf s pos len;
|
|
take xs remains')
|
|
else Buffer.add_substring buf s pos remains)
|
|
in
|
|
take slices (stop - start);
|
|
Buffer.contents buf)
|
|
;;
|
|
|
|
let rec drop t remains =
|
|
if remains = 0
|
|
then t
|
|
else (
|
|
match t with
|
|
| [] -> []
|
|
| ({ s = _; pos; len } as slice) :: t ->
|
|
if remains >= len
|
|
then drop t (remains - len)
|
|
else (
|
|
let delta = len - remains in
|
|
{ slice with pos = pos + delta; len = len - delta } :: t))
|
|
;;
|
|
|
|
let drop_rev t remains =
|
|
(* TODO Use a proper functional queue *)
|
|
if remains = 0 then t else List.rev (drop (List.rev t) remains)
|
|
;;
|
|
end
|