mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 03:05:28 -05:00
feat(CCParse): add take_until_success
this reads a slice using the given parser to parse the end delimiter
(e.g "end gpg signature" 😉)
This commit is contained in:
parent
ea0e4473a8
commit
84173382db
3 changed files with 50 additions and 0 deletions
|
|
@ -600,6 +600,36 @@ let take len : slice t =
|
|||
));
|
||||
}
|
||||
|
||||
let take_until_success p : (slice * _) t =
|
||||
{
|
||||
run =
|
||||
(fun st ~ok ~err ->
|
||||
let i = ref st.i in
|
||||
let st_after_p = ref st in
|
||||
let continue = ref true in
|
||||
let res = ref None in
|
||||
|
||||
while !continue && !i < st.j do
|
||||
let st' = { st with i = !i } in
|
||||
p.run st'
|
||||
~ok:(fun new_st x ->
|
||||
(* success *)
|
||||
res := Some x;
|
||||
continue := false;
|
||||
(* parsing will continue where [p] left off *)
|
||||
st_after_p := new_st)
|
||||
~err:(fun _ -> incr i)
|
||||
done;
|
||||
|
||||
match !res with
|
||||
| None ->
|
||||
err
|
||||
(mk_error_ st (const_str_ "take_until_success: no position worked"))
|
||||
| Some x ->
|
||||
let slice = { st with j = !i } in
|
||||
ok !st_after_p (slice, x));
|
||||
}
|
||||
|
||||
let any_char_n len : _ t = take len >|= Slice.to_string
|
||||
|
||||
let exact s =
|
||||
|
|
|
|||
|
|
@ -304,6 +304,15 @@ val chars_fold_transduce :
|
|||
|
||||
@since 3.6 *)
|
||||
|
||||
val take_until_success : 'a t -> (slice * 'a) t
|
||||
(** [take_until_success p] accumulates characters of the input into a slice,
|
||||
until [p] successfully parses a value [x]; then it returns [slice, x].
|
||||
|
||||
{b NOTE} performance wise, if [p] does a lot of work at each position,
|
||||
this can be costly (thing naive substring search if [p] is [string "very long needle"]).
|
||||
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val take : int -> slice t
|
||||
(** [take len] parses exactly [len] characters from the input.
|
||||
Fails if the input doesn't contain at least [len] chars.
|
||||
|
|
|
|||
|
|
@ -287,3 +287,14 @@ eq
|
|||
~printer:Q.Print.(errpp (pair int int))
|
||||
(Ok (1, 2))
|
||||
U.(parse_string (pair int int) "(1 , 2 )")
|
||||
;;
|
||||
|
||||
eq
|
||||
~printer:Q.Print.(errpp (pair (pair string string) string))
|
||||
(Ok (("!this is the text between!", "LOL"), " and a lot of other stuff"))
|
||||
(parse_string
|
||||
(string "COUCOU"
|
||||
*> let* slice, x = take_until_success (string "LOL") in
|
||||
let+ rest = take_if (fun _ -> true) <* eoi in
|
||||
(Slice.to_string slice, x), Slice.to_string rest)
|
||||
"COUCOU!this is the text between!LOL and a lot of other stuff")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue