Skip to content

Commit c6f6a01

Browse files
authored
Merge pull request #465 from mobotsar/main
Add `take_while` and `rtake_while` to `CCString`, addressing #463
2 parents 510db54 + 1e06423 commit c6f6a01

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

src/core/CCString.ml

+18
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,24 @@ let take n s =
585585
else
586586
s
587587

588+
let take_while f s =
589+
let i = ref 0 in
590+
while !i < String.length s && f (String.unsafe_get s !i) do
591+
incr i
592+
done;
593+
String.sub s 0 !i
594+
595+
let rtake_while f s =
596+
let s_len_pred = String.length s - 1 in
597+
let i = ref s_len_pred in
598+
while !i >= 0 && f (String.unsafe_get s !i) do
599+
decr i
600+
done;
601+
if !i < s_len_pred then
602+
String.sub s (!i + 1) (s_len_pred - !i)
603+
else
604+
""
605+
588606
let drop n s =
589607
if n < String.length s then
590608
String.sub s n (String.length s - n)

src/core/CCString.mli

+10
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,16 @@ val take : int -> string -> string
182182
(** [take n s] keeps only the [n] first chars of [s].
183183
@since 0.17 *)
184184

185+
val take_while : (char -> bool) -> string -> string
186+
(** [take_while f s] keeps only the longest prefix [t] of [s] such that every
187+
character [c] in [t] satisfies [f c].
188+
@since 3.16 *)
189+
190+
val rtake_while : (char -> bool) -> string -> string
191+
(** [rtake_while f s] keeps only the longest suffix [t] of [s] such that every
192+
character [c] in [t] satisfies [f c].
193+
@since 3.16 *)
194+
185195
val drop : int -> string -> string
186196
(** [drop n s] removes the [n] first chars of [s].
187197
@since 0.17 *)

src/core/CCStringLabels.mli

+10
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,16 @@ val take : int -> string -> string
193193
(** [take n s] keeps only the [n] first chars of [s].
194194
@since 0.17 *)
195195

196+
val take_while : f:(char -> bool) -> string -> string
197+
(** [take_while ~f s] keeps only the longest prefix [t] of [s] such that every
198+
character [c] in [t] satisfies [f c].
199+
@since 3.16 *)
200+
201+
val rtake_while : f:(char -> bool) -> string -> string
202+
(** [rtake_while ~f s] keeps only the longest suffix [t] of [s] such that every
203+
character [c] in [t] satisfies [f c].
204+
@since 3.16 *)
205+
196206
val drop : int -> string -> string
197207
(** [drop n s] removes the [n] first chars of [s].
198208
@since 0.17 *)

tests/core/t_string.ml

+17
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,23 @@ eq ~printer:CCFun.id "" (unlines []);;
280280
eq ~printer:CCFun.id "ab\nc\n" (unlines [ "ab"; "c" ]);;
281281
q Q.printable_string (fun s -> trim (unlines (lines s)) = trim s);;
282282
q Q.printable_string (fun s -> trim (unlines_gen (lines_gen s)) = trim s);;
283+
eq ~printer:CCFun.id "" (take_while (Char.equal 'c') "heloo_cc");;
284+
eq ~printer:CCFun.id "" (take_while (Char.equal 'c') "");;
285+
eq ~printer:CCFun.id "c" (take_while (Char.equal 'c') "c");;
286+
eq ~printer:CCFun.id "ccc" (take_while (Char.equal 'c') "cccujsuy");;
287+
288+
eq ~printer:CCFun.id "THIS"
289+
(take_while (fun c -> Char.code c < 91) "THISisNotWHAtIwANTED")
290+
;;
291+
292+
eq ~printer:CCFun.id "cc" (rtake_while (Char.equal 'c') "heloo_cc");;
293+
eq ~printer:CCFun.id "" (rtake_while (Char.equal 'c') "");;
294+
eq ~printer:CCFun.id "c" (rtake_while (Char.equal 'c') "c");;
295+
eq ~printer:CCFun.id "" (rtake_while (Char.equal 'c') "cccujsuy");;
296+
297+
eq ~printer:CCFun.id "ANTED"
298+
(rtake_while (fun c -> Char.code c < 91) "THISisNotWHAtIwANTED")
299+
;;
283300

284301
q
285302
Q.(small_list small_string)

0 commit comments

Comments
 (0)