The unpac monorepo manager self-hosting as a monorepo using unpac
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add String.{drop,take,cut}_{first,last}_while (#14362)

* Add String.{drop,take,cut}_{first,last}_while

* Address Nicolás' review

* Address David Allsop's review

* Be consistent in using [p] instead of [sat]

authored by

Daniel Bünzli and committed by
GitHub
e6d70197 c5451c06

+158 -2
+5 -1
Changes
··· 88 88 89 89 ### Standard library: 90 90 91 + - #14362: Add String.{drop,take,cut}_{first,last}_while 92 + (Daniel Bünzli, review by Nicolás Ojeda Bär and David Allsopp) 93 + 91 94 - #14363: Preserve the backtrace at exceptional domain termination. Domain.join 92 95 on an exceptionally terminated domain re-raises the exception with the 93 96 backtrace. ··· 99 102 (Leonardo Santos, review by Florian Angeletti and Gabriel Scherer) 100 103 101 104 - #14352: Add String.{drop,take,cut}_{first,last}. 102 - (Daniel Bünzli, review by David Allsopp, Vincent Laviron) 105 + (Daniel Bünzli, review by David Allsopp, Nicolás Ojeda Bär and 106 + Vincent Laviron) 103 107 104 108 - #14185: List.split_map 105 109 (Jeremy Yallop, review by Daniel Bünzli, Nicolás Ojeda Bär and Damien Doligez)
+42
stdlib/string.ml
··· 243 243 let drop_last n s = subrange ~last:(length s - n - 1) s 244 244 let cut_last n s = (drop_last n s, take_last n s) 245 245 246 + (* Splitting with predicates *) 247 + 248 + let take_first_while sat s = 249 + let len = length s and i = ref 0 in 250 + while !i < len && sat (unsafe_get s !i) do incr i done; 251 + if !i = len then s else sub s 0 !i 252 + 253 + let drop_first_while sat s = 254 + let len = length s and i = ref 0 in 255 + while !i < len && sat (unsafe_get s !i) do incr i done; 256 + if !i = 0 then s else sub s !i (len - !i) 257 + 258 + let cut_first_while sat s = 259 + let len = length s and i = ref 0 in 260 + while !i < len && sat (unsafe_get s !i) do incr i done; 261 + if !i = len then s, "" else 262 + if !i = 0 then "", s else 263 + sub s 0 !i, sub s !i (len - !i) 264 + 265 + let take_last_while sat s = 266 + let len = length s in 267 + let i = ref (len - 1) in 268 + while !i >= 0 && sat (unsafe_get s !i) do decr i done; 269 + if !i < 0 then s else 270 + let j = !i + 1 in 271 + sub s j (len - j) 272 + 273 + let drop_last_while sat s = 274 + let len = length s in 275 + let i = ref (len - 1) in 276 + while !i >= 0 && sat (unsafe_get s !i) do decr i done; 277 + if !i < 0 then "" else sub s 0 (!i + 1) 278 + 279 + let cut_last_while sat s = 280 + let len = length s in 281 + let i = ref (len - 1) in 282 + while !i >= 0 && sat (unsafe_get s !i) do decr i done; 283 + if !i < 0 then "", s else 284 + if !i = len - 1 then s, "" else 285 + let j = !i + 1 in 286 + sub s 0 j, sub s j (len - j) 287 + 246 288 (* Splitting with separators *) 247 289 248 290 (* duplicated in bytes.ml *)
+38
stdlib/string.mli
··· 230 230 231 231 @since 5.5 *) 232 232 233 + (** {2:splitting_preds Splitting with predicates} *) 234 + 235 + val take_first_while : (char -> bool) -> string -> string 236 + (** [take_first_while p s] is the first consecutive bytes of [s] 237 + satisfying the predicate [p]. 238 + 239 + @since 5.5 *) 240 + 241 + val take_last_while : (char -> bool) -> string -> string 242 + (** [take_last_while p s] is the last consecutive bytes of [s] 243 + satisfying the predicate [p]. 244 + 245 + @since 5.5 *) 246 + 247 + val drop_first_while : (char -> bool) -> string -> string 248 + (** [drop_first_while p s] is [s] without the first consecutive bytes of [s] 249 + satisfying the predicate [p]. 250 + 251 + @since 5.5 *) 252 + 253 + val drop_last_while : (char -> bool) -> string -> string 254 + (** [drop_last_while p s] is [s] without the last consecutive bytes of [s] 255 + satisfying the predicate [p]. 256 + 257 + @since 5.5 *) 258 + 259 + val cut_first_while : (char -> bool) -> string -> string * string 260 + (** [cut_first_while p s] is 261 + [(take_first_while p s, drop_first_while p s)]. 262 + 263 + @since 5.5 *) 264 + 265 + val cut_last_while : (char -> bool) -> string -> string * string 266 + (** [cut_last_while p s] is 267 + [(drop_last_while p s, take_last_while p s)]. 268 + 269 + @since 5.5 *) 270 + 233 271 (** {2:splitting_sep Splitting with separators} *) 234 272 235 273 val split_on_char : char -> string -> string list
+38
stdlib/stringLabels.mli
··· 230 230 231 231 @since 5.5 *) 232 232 233 + (** {2:splitting_preds Splitting with predicates} *) 234 + 235 + val take_first_while : (char -> bool) -> string -> string 236 + (** [take_first_while p s] is the first consecutive bytes of [s] 237 + satisfying the predicate [p]. 238 + 239 + @since 5.5 *) 240 + 241 + val take_last_while : (char -> bool) -> string -> string 242 + (** [take_last_while p s] is the last consecutive bytes of [s] 243 + satisfying the predicate [p]. 244 + 245 + @since 5.5 *) 246 + 247 + val drop_first_while : (char -> bool) -> string -> string 248 + (** [drop_first_while p s] is [s] without the first consecutive bytes of [s] 249 + satisfying the predicate [p]. 250 + 251 + @since 5.5 *) 252 + 253 + val drop_last_while : (char -> bool) -> string -> string 254 + (** [drop_last_while p s] is [s] without the last consecutive bytes of [s] 255 + satisfying the predicate [p]. 256 + 257 + @since 5.5 *) 258 + 259 + val cut_first_while : (char -> bool) -> string -> string * string 260 + (** [cut_first_while p s] is 261 + [(take_first_while p s, drop_first_while p s)]. 262 + 263 + @since 5.5 *) 264 + 265 + val cut_last_while : (char -> bool) -> string -> string * string 266 + (** [cut_last_while p s] is 267 + [(drop_last_while p s, take_last_while p s)]. 268 + 269 + @since 5.5 *) 270 + 233 271 (** {2:splitting_sep Splitting with separators} *) 234 272 235 273 val split_on_char : sep:char -> string -> string list
+35 -1
testsuite/tests/lib-string/test_string.ml
··· 138 138 assert (Sys.max_string_length - 1 < max_int) 139 139 140 140 let () = 141 - (* Test breaking with magnitudes *) 141 + (* Test splitting with magnitudes *) 142 142 (* String.take_first *) 143 143 assert (String.take_first (-1) "" = ""); 144 144 assert (String.take_first (-1) "a" = ""); ··· 218 218 assert (String.cut_last 2 "a" = ("", "a")); 219 219 assert (String.cut_last 2 "ab" = ("", "ab")); 220 220 () 221 + 222 + let () = 223 + (* Test splitting with predicates *) 224 + (* String.take_first_while *) 225 + assert (String.take_first_while Char.Ascii.is_white "" = ""); 226 + assert (String.take_first_while Char.Ascii.is_white " " = " "); 227 + assert (String.take_first_while Char.Ascii.is_white "abc" = ""); 228 + assert (String.take_first_while Char.Ascii.is_white " abc" = " "); 229 + (* String.drop_first_while *) 230 + assert (String.drop_first_while Char.Ascii.is_white "" = ""); 231 + assert (String.drop_first_while Char.Ascii.is_white " " = ""); 232 + assert (String.drop_first_while Char.Ascii.is_white "abc" = "abc"); 233 + assert (String.drop_first_while Char.Ascii.is_white " abc" = "abc"); 234 + (* String.cut_first_while *) 235 + assert (String.cut_first_while Char.Ascii.is_white "" = ("", "")); 236 + assert (String.cut_first_while Char.Ascii.is_white " " = (" ", "")); 237 + assert (String.cut_first_while Char.Ascii.is_white "abc" = ("", "abc")); 238 + assert (String.cut_first_while Char.Ascii.is_white " abc" = (" ", "abc")); 239 + (* String.take_last_while *) 240 + assert (String.take_last_while Char.Ascii.is_white "" = ""); 241 + assert (String.take_last_while Char.Ascii.is_white " " = " "); 242 + assert (String.take_last_while Char.Ascii.is_white "abc" = ""); 243 + assert (String.take_last_while Char.Ascii.is_white "abc " = " "); 244 + (* String.drop_last_while *) 245 + assert (String.drop_last_while Char.Ascii.is_white "" = ""); 246 + assert (String.drop_last_while Char.Ascii.is_white " " = ""); 247 + assert (String.drop_last_while Char.Ascii.is_white "abc" = "abc"); 248 + assert (String.drop_last_while Char.Ascii.is_white "abc " = "abc"); 249 + (* String.cut_last_while *) 250 + assert (String.cut_last_while Char.Ascii.is_white "" = ("", "")); 251 + assert (String.cut_last_while Char.Ascii.is_white " " = ("", " ")); 252 + assert (String.cut_last_while Char.Ascii.is_white "abc" = ("abc", "")); 253 + assert (String.cut_last_while Char.Ascii.is_white "abc " = ("abc", " ")); 254 + ()