diff --git a/src/core/CCString.ml b/src/core/CCString.ml index 260d9d69..ec87f351 100644 --- a/src/core/CCString.ml +++ b/src/core/CCString.ml @@ -585,6 +585,24 @@ let take n s = else s +let take_while f s = + let i = ref 0 in + while !i < String.length s && f (String.unsafe_get s !i) do + incr i + done; + String.sub s 0 !i + +let rtake_while f s = + let s_len_pred = String.length s - 1 in + let i = ref s_len_pred in + while !i >= 0 && f (String.unsafe_get s !i) do + decr i + done; + if !i < s_len_pred then + String.sub s (!i + 1) (s_len_pred - !i) + else + "" + let drop n s = if n < String.length s then String.sub s n (String.length s - n) diff --git a/src/core/CCString.mli b/src/core/CCString.mli index 0e5e7ba0..9d2a66ee 100644 --- a/src/core/CCString.mli +++ b/src/core/CCString.mli @@ -182,6 +182,16 @@ val take : int -> string -> string (** [take n s] keeps only the [n] first chars of [s]. @since 0.17 *) +val take_while : (char -> bool) -> string -> string +(** [take_while f s] keeps only the longest prefix [t] of [s] such that every + character [c] in [t] satisfies [f c]. + @since 3.16 *) + +val rtake_while : (char -> bool) -> string -> string +(** [rtake_while f s] keeps only the longest suffix [t] of [s] such that every + character [c] in [t] satisfies [f c]. + @since 3.16 *) + val drop : int -> string -> string (** [drop n s] removes the [n] first chars of [s]. @since 0.17 *) diff --git a/src/core/CCStringLabels.mli b/src/core/CCStringLabels.mli index 318e8237..0bd3f1d7 100644 --- a/src/core/CCStringLabels.mli +++ b/src/core/CCStringLabels.mli @@ -193,6 +193,16 @@ val take : int -> string -> string (** [take n s] keeps only the [n] first chars of [s]. @since 0.17 *) +val take_while : f:(char -> bool) -> string -> string +(** [take_while ~f s] keeps only the longest prefix [t] of [s] such that every + character [c] in [t] satisfies [f c]. + @since 3.16 *) + +val rtake_while : f:(char -> bool) -> string -> string +(** [rtake_while ~f s] keeps only the longest suffix [t] of [s] such that every + character [c] in [t] satisfies [f c]. + @since 3.16 *) + val drop : int -> string -> string (** [drop n s] removes the [n] first chars of [s]. @since 0.17 *) diff --git a/tests/core/t_string.ml b/tests/core/t_string.ml index 4db9bea5..47f1f00b 100644 --- a/tests/core/t_string.ml +++ b/tests/core/t_string.ml @@ -280,6 +280,23 @@ eq ~printer:CCFun.id "" (unlines []);; eq ~printer:CCFun.id "ab\nc\n" (unlines [ "ab"; "c" ]);; q Q.printable_string (fun s -> trim (unlines (lines s)) = trim s);; q Q.printable_string (fun s -> trim (unlines_gen (lines_gen s)) = trim s);; +eq ~printer:CCFun.id "" (take_while (Char.equal 'c') "heloo_cc");; +eq ~printer:CCFun.id "" (take_while (Char.equal 'c') "");; +eq ~printer:CCFun.id "c" (take_while (Char.equal 'c') "c");; +eq ~printer:CCFun.id "ccc" (take_while (Char.equal 'c') "cccujsuy");; + +eq ~printer:CCFun.id "THIS" + (take_while (fun c -> Char.code c < 91) "THISisNotWHAtIwANTED") +;; + +eq ~printer:CCFun.id "cc" (rtake_while (Char.equal 'c') "heloo_cc");; +eq ~printer:CCFun.id "" (rtake_while (Char.equal 'c') "");; +eq ~printer:CCFun.id "c" (rtake_while (Char.equal 'c') "c");; +eq ~printer:CCFun.id "" (rtake_while (Char.equal 'c') "cccujsuy");; + +eq ~printer:CCFun.id "ANTED" + (rtake_while (fun c -> Char.code c < 91) "THISisNotWHAtIwANTED") +;; q Q.(small_list small_string)