aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib/src/binary.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib/src/binary.erl')
-rw-r--r--lib/stdlib/src/binary.erl203
1 files changed, 150 insertions, 53 deletions
diff --git a/lib/stdlib/src/binary.erl b/lib/stdlib/src/binary.erl
index d649f974bb..3eaf011db4 100644
--- a/lib/stdlib/src/binary.erl
+++ b/lib/stdlib/src/binary.erl
@@ -20,61 +20,158 @@
%%
%% The following functions implemented as BIF's
%% binary:compile_pattern/1
-%% binary:find/3
-%% XXX:PaN more to come...
-
--export([first/1,first/2,last/1,last/2,nth/2,extract/3]).
+%% binary:match/{2,3}
+%% binary:matches/{2,3}
+%% - Not yet:
+%% binary:longest_common_prefix/1
+%% binary:longest_common_suffix/1
+%% binary:first/1
+%% binary:last/1
+%% binary:at/2
+%% binary:part/{2,3}
+%% binary:bin_to_list/{1,2,3}
+%% binary:list_to_bin/1
+%% binary:copy/{1,2}
+%% binary:referenced_byte_size/1
+%% binary:decode_unsigned/{1,2}
+%%
+%% Implemented in this module:
+-export([split/2,split/3,replace/3,replace/4]).
-first(<<F:1/binary,_/binary>>) ->
- F;
-first(_) ->
- erlang:error(badarg).
-first(N,Bin) when is_integer(N), N >= 0 ->
- case Bin of
- <<F:N/binary,_/binary>> ->
- F;
- _ ->
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% split
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+split(H,N) ->
+ split(H,N,[]).
+split(Haystack,Needles,Options) ->
+ try
+ {Part,Global,Trim} = get_opts_split(Options,{no,false,false}),
+ Moptlist = case Part of
+ no ->
+ [];
+ {A,B} ->
+ [{scope,{A,B}}]
+ end,
+ MList = if
+ Global ->
+ binary:matches(Haystack,Needles,Moptlist);
+ true ->
+ case binary:match(Haystack,Needles,Moptlist) of
+ nomatch -> [];
+ Match -> [Match]
+ end
+ end,
+ do_split(Haystack,MList,0,Trim)
+ catch
+ _:_ ->
erlang:error(badarg)
- end;
-first(_,_) ->
- erlang:error(badarg).
-last(<<>>) ->
- erlang:error(badarg);
-last(Bin) when is_binary(Bin) ->
- Sz = byte_size(Bin) - 1,
- <<_:Sz/binary,L:1/binary>> = Bin,
- L;
-last(_) ->
- erlang:error(badarg).
-last(N,Bin) when is_integer(N), N >= 0, is_binary(Bin) ->
- Sz = byte_size(Bin) - N,
- case Bin of
- <<_:Sz/binary,L:N/binary>> ->
- L;
- _ ->
- erlang:error(badarg)
- end;
-last(_,_) ->
- erlang:error(badarg).
+ end.
-nth(N, Bin) when is_integer(N), N > 0 ->
- M = N - 1,
- case Bin of
- <<_:M/binary,V:1/binary,_/binary>> ->
- V;
- _ ->
- erlang:error(badarg)
- end;
-nth(_,_) ->
- erlang:error(badarg).
+do_split(H,[],N,true) when N >= byte_size(H) ->
+ [];
+do_split(H,[],N,_) ->
+ [binary:part(H,{N,byte_size(H)-N})];
+do_split(H,[{A,B}|T],N,Trim) ->
+ case binary:part(H,{N,A-N}) of
+ <<>> ->
+ Rest = do_split(H,T,A+B,Trim),
+ case {Trim, Rest} of
+ {true,[]} ->
+ [];
+ _ ->
+ [<<>> | Rest]
+ end;
+ Oth ->
+ [Oth | do_split(H,T,A+B,Trim)]
+ end.
-extract(N,Size,Bin) when is_integer(N), is_integer(Size), is_binary(Bin) ->
- M = N - 1,
- case Bin of
- <<_:M/binary,V:Size/binary,_/binary>> ->
- V;
- _ ->
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% replace
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+replace(H,N,R) ->
+ replace(H,N,R,[]).
+replace(Haystack,Needles,Replacement,Options) ->
+ try
+ true = is_binary(Replacement), % Make badarg instead of function clause
+ {Part,Global,Insert} = get_opts_replace(Options,{no,false,[]}),
+ Moptlist = case Part of
+ no ->
+ [];
+ {A,B} ->
+ [{scope,{A,B}}]
+ end,
+ MList = if
+ Global ->
+ binary:matches(Haystack,Needles,Moptlist);
+ true ->
+ case binary:match(Haystack,Needles,Moptlist) of
+ nomatch -> [];
+ Match -> [Match]
+ end
+ end,
+ ReplList = case Insert of
+ [] ->
+ Replacement;
+ Y when is_integer(Y) ->
+ splitat(Replacement,0,[Y]);
+ Li when is_list(Li) ->
+ splitat(Replacement,0,lists:sort(Li))
+ end,
+ erlang:iolist_to_binary(do_replace(Haystack,MList,ReplList,0))
+ catch
+ _:_ ->
erlang:error(badarg)
- end;
-extract(_,_,_) ->
- erlang:error(badarg).
+ end.
+
+
+do_replace(H,[],_,N) ->
+ [binary:part(H,{N,byte_size(H)-N})];
+do_replace(H,[{A,B}|T],Replacement,N) ->
+ [binary:part(H,{N,A-N}),
+ if
+ is_list(Replacement) ->
+ do_insert(Replacement, binary:part(H,{A,B}));
+ true ->
+ Replacement
+ end
+ | do_replace(H,T,Replacement,A+B)].
+
+do_insert([X],_) ->
+ [X];
+do_insert([H|T],R) ->
+ [H,R|do_insert(T,R)].
+
+splitat(H,N,[]) ->
+ [binary:part(H,{N,byte_size(H)-N})];
+splitat(H,N,[I|T]) ->
+ [binary:part(H,{N,I-N})|splitat(H,I,T)].
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Simple helper functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+get_opts_split([],{Part,Global,Trim}) ->
+ {Part,Global,Trim};
+get_opts_split([{scope,{A,B}} | T],{_Part,Global,Trim}) ->
+ get_opts_split(T,{{A,B},Global,Trim});
+get_opts_split([global | T],{Part,_Global,Trim}) ->
+ get_opts_split(T,{Part,true,Trim});
+get_opts_split([trim | T],{Part,Global,_Trim}) ->
+ get_opts_split(T,{Part,Global,true});
+get_opts_split(_,_) ->
+ throw(badopt).
+
+get_opts_replace([],{Part,Global,Insert}) ->
+ {Part,Global,Insert};
+get_opts_replace([{scope,{A,B}} | T],{_Part,Global,Insert}) ->
+ get_opts_replace(T,{{A,B},Global,Insert});
+get_opts_replace([global | T],{Part,_Global,Insert}) ->
+ get_opts_replace(T,{Part,true,Insert});
+get_opts_replace([{insert_replaced,N} | T],{Part,Global,_Insert}) ->
+ get_opts_replace(T,{Part,Global,N});
+get_opts_replace(_,_) ->
+ throw(badopt).
+