diff --git a/src/core/CCString.cppo.ml b/src/core/CCString.cppo.ml index a4c66419..9fa460c8 100644 --- a/src/core/CCString.cppo.ml +++ b/src/core/CCString.cppo.ml @@ -652,6 +652,21 @@ let exists p s = try iter (fun c -> if p c then raise MyExit) s; false with MyExit -> true +(* notion of whitespace for trim *) +let is_space_ = function + | ' ' | '\012' | '\n' | '\r' | '\t' -> true + | _ -> false + +let ltrim s = + let i = ref 0 in + while !i < length s && is_space_ (unsafe_get s !i) do incr i done; + if !i > 0 then sub s !i (length s - !i) else s + +let rtrim s = + let i = ref (length s-1) in + while !i >= 0 && is_space_ (unsafe_get s !i) do decr i done; + if !i < length s-1 then sub s 0 (!i+1) else s + let map2 f s1 s2 = if length s1 <> length s2 then invalid_arg "CCString.map2"; init (String.length s1) (fun i -> f s1.[i] s2.[i]) diff --git a/src/core/CCString.mli b/src/core/CCString.mli index 9e7c1d23..98be782f 100644 --- a/src/core/CCString.mli +++ b/src/core/CCString.mli @@ -351,6 +351,32 @@ val exists : (char -> bool) -> string -> bool include S with type t := string +val ltrim : t -> t +(** trim space on the left (see {!String.trim} for more details) + @since NEXT_RELEASE *) + +val rtrim : t -> t +(** trim space on the right (see {!String.trim} for more details) + @since NEXT_RELEASE *) + +(*$= & ~printer:id + "abc " (ltrim " abc ") + " abc" (rtrim " abc ") +*) + +(*$Q + Q.(printable_string) (fun s -> \ + String.trim s = (s |> ltrim |> rtrim)) + Q.(printable_string) (fun s -> ltrim s = ltrim (ltrim s)) + Q.(printable_string) (fun s -> rtrim s = rtrim (rtrim s)) + Q.(printable_string) (fun s -> \ + let s' = ltrim s in \ + if s'="" then Q.assume_fail() else s'.[0] <> ' ') + Q.(printable_string) (fun s -> \ + let s' = rtrim s in \ + if s'="" then Q.assume_fail() else s'.[String.length s'-1] <> ' ') + *) + (** {2 Operations on 2 strings} *) val map2 : (char -> char -> char) -> string -> string -> string