This commit is contained in:
parent
aa2ff7b2f0
commit
2f3113f55d
11742 changed files with 1223940 additions and 0 deletions
114
unikernel/duniverse/ocaml-re/lib/search.ml
Normal file
114
unikernel/duniverse/ocaml-re/lib/search.ml
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
let all ?(pos = 0) ?len re s : _ Seq.t =
|
||||
if pos < 0 then invalid_arg "Re.all";
|
||||
(* index of the first position we do not consider.
|
||||
!pos < limit is an invariant *)
|
||||
let limit =
|
||||
match len with
|
||||
| None -> String.length s
|
||||
| Some l ->
|
||||
if l < 0 || pos + l > String.length s then invalid_arg "Re.all";
|
||||
pos + l
|
||||
in
|
||||
(* iterate on matches. When a match is found, search for the next
|
||||
one just after its end *)
|
||||
let rec aux pos on_match () =
|
||||
if pos > limit
|
||||
then Seq.Nil (* no more matches *)
|
||||
else (
|
||||
match
|
||||
Compile.match_str ~groups:true ~partial:false re s ~pos ~len:(limit - pos)
|
||||
with
|
||||
| Match substr ->
|
||||
let p1 = Group.start_offset substr 0 |> Group.Offset.get_no_check in
|
||||
let p2 = Group.stop_offset substr 0 |> Group.Offset.get_no_check in
|
||||
if on_match && p1 = pos && p1 = p2
|
||||
then (* skip empty match right after a match *)
|
||||
aux (pos + 1) false ()
|
||||
else (
|
||||
let pos = if p1 = p2 then p2 + 1 else p2 in
|
||||
Seq.Cons (substr, aux pos (p1 <> p2)))
|
||||
| Running _ | Failed -> Seq.Nil)
|
||||
in
|
||||
aux pos false
|
||||
;;
|
||||
|
||||
let matches ?pos ?len re s : _ Seq.t =
|
||||
all ?pos ?len re s |> Seq.map (fun sub -> Group.get sub 0)
|
||||
;;
|
||||
|
||||
let split_full ?(pos = 0) ?len re s : _ Seq.t =
|
||||
if pos < 0 then invalid_arg "Re.split";
|
||||
let limit =
|
||||
match len with
|
||||
| None -> String.length s
|
||||
| Some l ->
|
||||
if l < 0 || pos + l > String.length s then invalid_arg "Re.split";
|
||||
pos + l
|
||||
in
|
||||
(* i: start of delimited string
|
||||
pos: first position after last match of [re]
|
||||
limit: first index we ignore (!pos < limit is an invariant) *)
|
||||
let pos0 = pos in
|
||||
let rec aux state i pos () =
|
||||
match state with
|
||||
| `Idle when pos > limit ->
|
||||
(* We had an empty match at the end of the string *)
|
||||
assert (i = limit);
|
||||
Seq.Nil
|
||||
| `Idle ->
|
||||
(match
|
||||
Compile.match_str ~groups:true ~partial:false re s ~pos ~len:(limit - pos)
|
||||
with
|
||||
| Match substr ->
|
||||
let p1 = Group.start_offset substr 0 |> Group.Offset.get_no_check in
|
||||
let p2 = Group.stop_offset substr 0 |> Group.Offset.get_no_check in
|
||||
let pos = if p1 = p2 then p2 + 1 else p2 in
|
||||
let old_i = i in
|
||||
let i = p2 in
|
||||
if old_i = p1 && p1 = p2 && p1 > pos0
|
||||
then (* Skip empty match right after a delimiter *)
|
||||
aux state i pos ()
|
||||
else if p1 > pos0
|
||||
then (
|
||||
(* string does not start by a delimiter *)
|
||||
let text = String.sub s old_i (p1 - old_i) in
|
||||
let state = `Yield (`Delim substr) in
|
||||
Seq.Cons (`Text text, aux state i pos))
|
||||
else Seq.Cons (`Delim substr, aux state i pos)
|
||||
| Running _ -> Seq.Nil
|
||||
| Failed ->
|
||||
if i < limit
|
||||
then (
|
||||
let text = String.sub s i (limit - i) in
|
||||
(* yield last string *)
|
||||
Seq.Cons (`Text text, aux state limit pos))
|
||||
else Seq.Nil)
|
||||
| `Yield x -> Seq.Cons (x, aux `Idle i pos)
|
||||
in
|
||||
aux `Idle pos pos
|
||||
;;
|
||||
|
||||
let split ?pos ?len re s : _ Seq.t =
|
||||
let seq = split_full ?pos ?len re s in
|
||||
let rec filter seq () =
|
||||
match seq () with
|
||||
| Seq.Nil -> Seq.Nil
|
||||
| Seq.Cons (`Delim _, tl) -> filter tl ()
|
||||
| Seq.Cons (`Text s, tl) -> Seq.Cons (s, filter tl)
|
||||
in
|
||||
filter seq
|
||||
;;
|
||||
|
||||
let split_delim ?pos ?len re s : _ Seq.t =
|
||||
let seq = split_full ?pos ?len re s in
|
||||
let rec filter ~delim seq () =
|
||||
match seq () with
|
||||
| Seq.Nil -> if delim then Seq.Cons ("", fun () -> Seq.Nil) else Seq.Nil
|
||||
| Seq.Cons (`Delim _, tl) ->
|
||||
if delim
|
||||
then Seq.Cons ("", fun () -> filter ~delim:true tl ())
|
||||
else filter ~delim:true tl ()
|
||||
| Seq.Cons (`Text s, tl) -> Seq.Cons (s, filter ~delim:false tl)
|
||||
in
|
||||
filter ~delim:true seq
|
||||
;;
|
||||
Loading…
Add table
Add a link
Reference in a new issue