|
21 | 21 | word/2, |
22 | 22 | trim/1]). |
23 | 23 |
|
| 24 | +%% BEGIN: Remove when OTP 17 not officially supported |
| 25 | +-export([split/3]). |
| 26 | + |
| 27 | +-export_type([cp/0]). |
| 28 | + |
| 29 | +-opaque cp() :: {'am' | 'bm', binary()}. |
| 30 | +-type part() :: {Start :: non_neg_integer(), Length :: integer()}. |
| 31 | +%% END: Remove when OTP 17 not officially supported |
| 32 | + |
24 | 33 | -export([quoted_string/2]). |
25 | 34 |
|
26 | 35 | to_binary(V) when is_list(V) -> |
@@ -361,3 +370,80 @@ quoted_string(<< $\\, C, Rest/binary >>, Fun, Acc) -> |
361 | 370 | quoted_string(Rest, Fun, << Acc/binary, C >>); |
362 | 371 | quoted_string(<< C, Rest/binary >>, Fun, Acc) -> |
363 | 372 | quoted_string(Rest, Fun, << Acc/binary, C >>). |
| 373 | + |
| 374 | +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 375 | +%% binary:split/3 from OTP 18 |
| 376 | +%% remove when support for < 18 |
| 377 | +%% formally dropped |
| 378 | +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 379 | + |
| 380 | +-spec split(Subject, Pattern, Options) -> Parts when |
| 381 | + Subject :: binary(), |
| 382 | + Pattern :: binary() | [binary()] | cp(), |
| 383 | + Options :: [Option], |
| 384 | + Option :: {scope, part()} | trim | global | trim_all, |
| 385 | + Parts :: [binary()]. |
| 386 | + |
| 387 | +split(Haystack,Needles,Options) -> |
| 388 | + try |
| 389 | + {Part,Global,Trim,TrimAll} = |
| 390 | + get_opts_split(Options,{no,false,false,false}), |
| 391 | + Moptlist = case Part of |
| 392 | + no -> |
| 393 | + []; |
| 394 | + {A,B} -> |
| 395 | + [{scope,{A,B}}] |
| 396 | + end, |
| 397 | + MList = if |
| 398 | + Global -> |
| 399 | + binary:matches(Haystack,Needles,Moptlist); |
| 400 | + true -> |
| 401 | + case binary:match(Haystack,Needles,Moptlist) of |
| 402 | + nomatch -> []; |
| 403 | + Match -> [Match] |
| 404 | + end |
| 405 | + end, |
| 406 | + do_split(Haystack,MList,0,Trim,TrimAll) |
| 407 | + catch |
| 408 | + _:_ -> |
| 409 | + erlang:error(badarg) |
| 410 | + end. |
| 411 | + |
| 412 | +do_split(H,[],N,true,_) when N >= byte_size(H) -> |
| 413 | + []; |
| 414 | +do_split(H,[],N,_,true) when N >= byte_size(H) -> |
| 415 | + []; |
| 416 | +do_split(H,[],N,_,_) -> |
| 417 | + [binary:part(H,{N,byte_size(H)-N})]; |
| 418 | +do_split(H,[{A,B}|T],N,Trim,TrimAll) -> |
| 419 | + case binary:part(H,{N,A-N}) of |
| 420 | + <<>> when TrimAll == true -> |
| 421 | + do_split(H,T,A+B,Trim,TrimAll); |
| 422 | + <<>> -> |
| 423 | + Rest = do_split(H,T,A+B,Trim,TrimAll), |
| 424 | + case {Trim, Rest} of |
| 425 | + {true,[]} -> |
| 426 | + []; |
| 427 | + _ -> |
| 428 | + [<<>> | Rest] |
| 429 | + end; |
| 430 | + Oth -> |
| 431 | + [Oth | do_split(H,T,A+B,Trim,TrimAll)] |
| 432 | + end. |
| 433 | + |
| 434 | +get_opts_split([],{Part,Global,Trim,TrimAll}) -> |
| 435 | + {Part,Global,Trim,TrimAll}; |
| 436 | +get_opts_split([{scope,{A,B}} | T],{_Part,Global,Trim,TrimAll}) -> |
| 437 | + get_opts_split(T,{{A,B},Global,Trim,TrimAll}); |
| 438 | +get_opts_split([global | T],{Part,_Global,Trim,TrimAll}) -> |
| 439 | + get_opts_split(T,{Part,true,Trim,TrimAll}); |
| 440 | +get_opts_split([trim | T],{Part,Global,_Trim,TrimAll}) -> |
| 441 | + get_opts_split(T,{Part,Global,true,TrimAll}); |
| 442 | +get_opts_split([trim_all | T],{Part,Global,Trim,_TrimAll}) -> |
| 443 | + get_opts_split(T,{Part,Global,Trim,true}); |
| 444 | +get_opts_split(_,_) -> |
| 445 | + throw(badopt). |
| 446 | + |
| 447 | +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 448 | +%% END binary:split from OTP 18 |
| 449 | +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
0 commit comments