3
-export([compile_pattern/1,match/2,match/3,matches/2,matches/3,
4
split/2,split/3,replace/3,replace/4,first/1,last/1,at/2,
5
part/2,part/3,copy/1,copy/2,encode_unsigned/1,encode_unsigned/2,
6
decode_unsigned/1,decode_unsigned/2,referenced_byte_size/1,
7
longest_common_prefix/1,longest_common_suffix/1,bin_to_list/1,
8
bin_to_list/2,bin_to_list/3,list_to_bin/1]).
11
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12
%% compile_pattern, a dummy
13
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14
compile_pattern(Pattern) when is_binary(Pattern) ->
16
compile_pattern(Pattern) ->
18
[ true = is_binary(P) || P <- Pattern ],
26
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
28
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31
match(Haystack,Needle,Options) when is_binary(Needle) ->
32
match(Haystack,[Needle],Options);
33
match(Haystack,{Needles},Options) ->
34
match(Haystack,Needles,Options);
35
match(Haystack,Needles,Options) ->
37
true = is_binary(Haystack) and is_list(Needles), % badarg, not function_clause
38
case get_opts_match(Options,nomatch) of
40
mloop(Haystack,Needles);
42
<<_:A/binary,SubStack:B/binary,_/binary>> = Haystack,
43
mloop(SubStack,Needles,A,B+A);
47
<<_:Start/binary,SubStack:Len/binary,_/binary>> = Haystack,
48
mloop(SubStack,Needles,Start,Len+Start);
58
matches(Haystack,Needle,Options) when is_binary(Needle) ->
59
matches(Haystack,[Needle],Options);
60
matches(Haystack,{Needles},Options) ->
61
matches(Haystack,Needles,Options);
62
matches(Haystack,Needles,Options) ->
64
true = is_binary(Haystack) and is_list(Needles), % badarg, not function_clause
65
case get_opts_match(Options,nomatch) of
67
msloop(Haystack,Needles);
69
<<_:A/binary,SubStack:B/binary,_/binary>> = Haystack,
70
msloop(SubStack,Needles,A,B+A);
74
<<_:Start/binary,SubStack:Len/binary,_/binary>> = Haystack,
75
msloop(SubStack,Needles,Start,Len+Start);
84
mloop(Haystack,Needles) ->
85
mloop(Haystack,Needles,0,byte_size(Haystack)).
87
mloop(_Haystack,_Needles,N,M) when N >= M ->
89
mloop(Haystack,Needles,N,M) ->
90
case mloop2(Haystack,Needles,N,nomatch) of
93
<<_:8,NewStack/binary>> = Haystack,
94
mloop(NewStack,Needles,N+1,M);
99
msloop(Haystack,Needles) ->
100
msloop(Haystack,Needles,0,byte_size(Haystack)).
102
msloop(_Haystack,_Needles,N,M) when N >= M ->
104
msloop(Haystack,Needles,N,M) ->
105
case mloop2(Haystack,Needles,N,nomatch) of
108
<<_:8,NewStack/binary>> = Haystack,
109
msloop(NewStack,Needles,N+1,M);
116
<<_:Len/binary,NewStack/binary>> = Haystack,
117
[{N,Len} | msloop(NewStack,Needles,NewN,M)]
121
mloop2(_Haystack,[],_N,Res) ->
123
mloop2(Haystack,[Needle|Tail],N,Candidate) ->
124
NS = byte_size(Needle),
126
<<Needle:NS/binary,_/binary>> ->
127
NewCandidate = case Candidate of
130
{N,ONS} when ONS < NS ->
135
mloop2(Haystack,Tail,N,NewCandidate);
137
mloop2(Haystack,Tail,N,Candidate)
141
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146
split(Haystack,{Needles},Options) ->
147
split(Haystack, Needles, Options);
148
split(Haystack,Needles0,Options) ->
153
is_binary(Needles0) ->
158
{Part,Global,Trim} = get_opts_split(Options,{nomatch,false,false}),
159
{Start,End,NewStack} =
162
{0,byte_size(Haystack),Haystack};
164
<<_:A/binary,SubStack:B/binary,_/binary>> = Haystack,
169
<<_:S/binary,SubStack:L/binary,_/binary>> = Haystack,
174
msloop(NewStack,Needles,Start,End);
176
case mloop(NewStack,Needles,Start,End) of
183
do_split(Haystack,MList,0,Trim)
189
do_split(H,[],N,true) when N >= byte_size(H) ->
191
do_split(H,[],N,_) ->
192
[part(H,{N,byte_size(H)-N})];
193
do_split(H,[{A,B}|T],N,Trim) ->
194
case part(H,{N,A-N}) of
196
Rest = do_split(H,T,A+B,Trim),
204
[Oth | do_split(H,T,A+B,Trim)]
208
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213
replace(Haystack,{Needles},Replacement,Options) ->
214
replace(Haystack,Needles,Replacement,Options);
216
replace(Haystack,Needles0,Replacement,Options) ->
221
is_binary(Needles0) ->
226
true = is_binary(Replacement), % Make badarg instead of function clause
227
{Part,Global,Insert} = get_opts_replace(Options,{nomatch,false,[]}),
228
{Start,End,NewStack} =
231
{0,byte_size(Haystack),Haystack};
233
<<_:A/binary,SubStack:B/binary,_/binary>> = Haystack,
238
<<_:S/binary,SubStack:L/binary,_/binary>> = Haystack,
243
msloop(NewStack,Needles,Start,End);
245
case mloop(NewStack,Needles,Start,End) of
252
ReplList = case Insert of
255
Y when is_integer(Y) ->
256
splitat(Replacement,0,[Y]);
257
Li when is_list(Li) ->
258
splitat(Replacement,0,lists:sort(Li))
260
erlang:iolist_to_binary(do_replace(Haystack,MList,ReplList,0))
267
do_replace(H,[],_,N) ->
268
[part(H,{N,byte_size(H)-N})];
269
do_replace(H,[{A,B}|T],Replacement,N) ->
272
is_list(Replacement) ->
273
do_insert(Replacement, part(H,{A,B}));
277
| do_replace(H,T,Replacement,A+B)].
281
do_insert([H|T],R) ->
282
[H,R|do_insert(T,R)].
285
[part(H,{N,byte_size(H)-N})];
286
splitat(H,N,[I|T]) ->
287
[part(H,{N,I-N})|splitat(H,I,T)].
291
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
292
%% first, last and at
293
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296
<<A:8,_/binary>> = Subject,
305
N = byte_size(Subject) - 1,
306
<<_:N/binary,A:8>> = Subject,
315
<<_:X/binary,A:8,_/binary>> = Subject,
322
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
324
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
325
bin_to_list(Subject) ->
327
binary_to_list(Subject)
333
bin_to_list(Subject,T) ->
342
binary_to_list(Subject,A+1,A+B)
348
bin_to_list(Subject,A,B) ->
350
bin_to_list(Subject,{A,B})
355
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
357
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360
erlang:list_to_binary(List)
366
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367
%% longest_common_prefix
368
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369
longest_common_prefix(LB) ->
371
true = is_list(LB) and (length(LB) > 0), % Make badarg instead of function clause
372
do_longest_common_prefix(LB,0)
378
do_longest_common_prefix(LB,X) ->
379
case do_lcp(LB,X,no) of
381
do_longest_common_prefix(LB,X+1);
387
do_lcp([Bin|_],X,_) when byte_size(Bin) =< X ->
389
do_lcp([Bin|T],X,no) ->
392
do_lcp([Bin|T],X,Ch) ->
401
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
402
%% longest_common_suffix
403
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
404
longest_common_suffix(LB) ->
406
true = is_list(LB) and (length(LB) > 0), % Make badarg instead of function clause
407
do_longest_common_suffix(LB,0)
413
do_longest_common_suffix(LB,X) ->
414
case do_lcs(LB,X,no) of
416
do_longest_common_suffix(LB,X+1);
422
do_lcs([Bin|_],X,_) when byte_size(Bin) =< X ->
424
do_lcs([Bin|T],X,no) ->
425
Ch = at(Bin,byte_size(Bin) - 1 - X),
427
do_lcs([Bin|T],X,Ch) ->
428
Ch2 = at(Bin,byte_size(Bin) - 1 - X),
437
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
440
part(Subject,Part) ->
442
do_part(Subject,Part)
448
part(Subject,Pos,Len) ->
449
part(Subject,{Pos,Len}).
451
do_part(Bin,{A,B}) when B >= 0 ->
452
<<_:A/binary,Sub:B/binary,_/binary>> = Bin,
454
do_part(Bin,{A,B}) when B < 0 ->
457
<<_:S/binary,Sub:L/binary,_/binary>> = Bin,
461
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
463
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
468
true = is_integer(N) and (N >= 0) and is_binary(Subject), % Badarg, not function clause
469
erlang:list_to_binary(lists:duplicate(N,Subject))
475
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
478
encode_unsigned(Unsigned) ->
479
encode_unsigned(Unsigned,big).
480
encode_unsigned(Unsigned,Endian) ->
482
true = is_integer(Unsigned) and (Unsigned >= 0),
489
list_to_binary(do_encode(Unsigned,[]));
491
list_to_binary(do_encode_r(Unsigned))
504
do_encode(NewN,[Byte|L]).
511
[Byte|do_encode_r(NewN)].
512
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
514
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
515
decode_unsigned(Subject) ->
516
decode_unsigned(Subject,big).
518
decode_unsigned(Subject,Endian) ->
520
true = is_binary(Subject),
523
do_decode(Subject,0);
525
do_decode_r(Subject,0)
534
do_decode(<<X:8,Bin/binary>>,N) ->
535
do_decode(Bin,(N bsl 8) bor X).
537
do_decode_r(<<>>,N) ->
539
do_decode_r(Bin,N) ->
540
Sz = byte_size(Bin) - 1,
541
<<NewBin:Sz/binary,X>> = Bin,
542
do_decode_r(NewBin, (N bsl 8) bor X).
544
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
545
%% referenced_byte_size cannot
546
%% be implemented in pure
548
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
549
referenced_byte_size(Bin) when is_binary(Bin) ->
550
erlang:error(not_implemented);
551
referenced_byte_size(_) ->
552
erlang:error(badarg).
556
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
557
%% Simple helper functions
558
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
561
get_opts_match([],Part) ->
563
get_opts_match([{scope,{A,B}} | T],_Part) ->
564
get_opts_match(T,{A,B});
565
get_opts_match(_,_) ->
568
get_opts_split([],{Part,Global,Trim}) ->
570
get_opts_split([{scope,{A,B}} | T],{_Part,Global,Trim}) ->
571
get_opts_split(T,{{A,B},Global,Trim});
572
get_opts_split([global | T],{Part,_Global,Trim}) ->
573
get_opts_split(T,{Part,true,Trim});
574
get_opts_split([trim | T],{Part,Global,_Trim}) ->
575
get_opts_split(T,{Part,Global,true});
576
get_opts_split(_,_) ->
579
get_opts_replace([],{Part,Global,Insert}) ->
580
{Part,Global,Insert};
581
get_opts_replace([{scope,{A,B}} | T],{_Part,Global,Insert}) ->
582
get_opts_replace(T,{{A,B},Global,Insert});
583
get_opts_replace([global | T],{Part,_Global,Insert}) ->
584
get_opts_replace(T,{Part,true,Insert});
585
get_opts_replace([{insert_replaced,N} | T],{Part,Global,_Insert}) ->
586
get_opts_replace(T,{Part,Global,N});
587
get_opts_replace(_,_) ->