Current section

Files

Jump to
ephp src ephp_lib_misc.erl
Raw

src/ephp_lib_misc.erl

-module(ephp_lib_misc).
-author('manuel@altenwald.com').
-behaviour(ephp_lib).
-export([init_func/0, init_config/0, init_const/0, handle_error/3, eval/3, constant/3,
uniqid/4, define/4, defined/3, sleep/3, usleep/3, exit/3, pack/3, unpack/4]).
-include("ephp.hrl").
-spec init_func() -> ephp_lib:php_function_results().
init_func() ->
[{eval, [string]},
{constant, [string]},
{uniqid, [{args, {0, 2, undefined, [{string, <<>>}, {boolean, false}]}}]},
{define, [string, mixed]},
{defined, [string]},
{sleep, [integer]},
{usleep, [integer]},
{exit, [{args, {0, 1, undefined, [{mixed, undefined}]}}, {alias, <<"die">>}]},
{exit, [{args, {0, 1, undefined, [{mixed, undefined}]}}]},
{pack, [pack_args]},
{unpack, [{args, {2, 2, undefined, [string, string]}}]}].
-spec init_config() -> ephp_lib:php_config_results().
init_config() ->
[].
-spec init_const() -> ephp_lib:php_const_results().
init_const() ->
[].
-spec handle_error(ephp_error:error_type(), ephp_error:error_level(), Args :: term()) ->
string() | ignore.
handle_error(eargunused, _Level, {Function, NumArgs}) ->
io_lib:format("~s(): ~p arguments unused", [Function, NumArgs]);
handle_error(efewargs, _Level, {Function, Cmd}) ->
io_lib:format("~s(): Type ~s: too few arguments", [Function, Cmd]);
handle_error(eoutstr, _Level, {Function, Cmd}) ->
io_lib:format("~s(): Type ~s: outside of string", [Function, Cmd]);
handle_error(eunknownfmt, _Level, {Function, Cmd}) ->
io_lib:format("~s(): Type ~s: unknown format code", [Function, Cmd]);
handle_error(ecmdignored, _Level, {Function, Cmd, Op}) ->
io_lib:format("~s(): Type ~s: '~s' ignored", [Function, Cmd, Op]);
handle_error(enoenoughin, _Level, {Function, Cmd, Size1, Size2}) ->
io_lib:format("~s(): Type ~s: not enough input, need ~p, have ~p",
[Function, Cmd, Size1, Size2]);
handle_error(enofindconst, _Level, {Const}) ->
io_lib:format("constant(): Couldn't find constant ~s", [Const]);
handle_error(_Type, _Level, _Data) ->
ignore.
-spec eval(ephp:context_id(), line(), Code :: var_value()) -> mixed().
eval(Context, _Line, {_, Code}) ->
{ok, SubCtx} = ephp_context:generate_subcontext(Context),
ActiveFile = ephp_context:get_active_file(Context),
%% FIXME: maybe the number should be changed according to whatever it means :-P
File = <<ActiveFile/binary, "(2) : eval()'d code">>,
case ephp:eval(File, SubCtx, <<"<?php ", Code/binary>>) of
{ok, false} ->
undefined;
{ok, {return, Value}} ->
Value;
{error, eparse, _ErrorLine, _File, _ErrorLevel, _Data} ->
undefined
end.
-spec constant(ephp:context_id(), line(), Name :: var_value()) -> mixed().
constant(Context, Line, {_, ConstantName}) ->
{NS, ClassName, ConstName} = ephp_const:get_ns(ConstantName),
case ephp_context:is_const_defined(Context, NS, ClassName, ConstName) of
true ->
ephp_context:get_const(Context, NS, ClassName, ConstName, Line);
false ->
File = ephp_context:get_active_file(Context),
Error = {error, enofindconst, Line, File, ?E_WARNING, {ConstantName}},
ephp_error:handle_error(Context, Error),
undefined
end.
-spec uniqid(ephp:context_id(), line(), var_value(), var_value()) -> binary().
uniqid(_Context, _Line, {_, Prefix}, {_, Extended}) ->
{M, S, U} = ephp_datetime:timestamp(),
Res = integer_to_binary((M * 1000000 + S) * 1000000 + U, 16),
Str = ephp_string:to_lower(Res),
Rand =
case ephp_data:to_bool(Extended) of
true ->
float_to_binary(ephp_data:urand(), [compact, {decimals, 8}]);
false ->
<<>>
end,
<<Prefix/binary, Str/binary, Rand/binary>>.
-spec define(ephp:context_id(),
line(),
Constant :: var_value(),
Content :: var_value()) ->
true.
define(Context, _Line, {#text{}, Constant}, {_, Content}) ->
ephp_context:register_const(Context, Constant, Content),
true;
define(Context, _Line, {#constant{name = Constant}, _}, {_UnParsedContent, Content}) ->
ephp_context:register_const(Context, Constant, Content),
true.
-spec defined(ephp:context_id(), line(), var_value()) -> boolean().
defined(Context, _Line, {_, ConstantName}) ->
case ephp_context:get_const(Context, ConstantName, false) of
false ->
false;
_ ->
true
end.
-spec sleep(ephp:context_id(), line(), Seconds :: var_value()) -> false | integer().
sleep(_Context, _Line, {_, Seconds}) when is_number(Seconds) ->
timer:sleep(trunc(Seconds) * 1000),
0;
sleep(Context, Line, {_, Val}) ->
File = ephp_context:get_active_file(Context),
Data = {<<"sleep">>, 1, <<"long">>, ephp_data:gettype(Val)},
ephp_error:handle_error(Context, {error, ewrongarg, Line, File, ?E_WARNING, Data}),
false.
-spec usleep(ephp:context_id(), line(), MicroSeconds :: var_value()) -> false | integer().
usleep(_Context, _Line, {_, MicroSeconds}) when is_number(MicroSeconds) ->
timer:sleep(trunc(MicroSeconds) div 1000),
0;
usleep(Context, Line, {_, Val}) ->
File = ephp_context:get_active_file(Context),
Data = {<<"usleep">>, 1, <<"long">>, ephp_data:gettype(Val)},
ephp_error:handle_error(Context, {error, ewrongarg, Line, File, ?E_WARNING, Data}),
false.
-spec exit(ephp:context_id(), line(), Message :: var_value()) -> undefined.
exit(_Context, _Line, {_, Value}) when is_integer(Value) orelse Value =:= undefined ->
throw(die);
exit(Context, _Line, {_, Value}) ->
ephp_context:set_output(Context, Value),
throw(die).
-spec pack(ephp:context_id(), line(), [var_value()]) -> binary().
pack(Context, Line, [{_, Format} | Args]) ->
do_pack(Context, Line, ephp_data:to_bin(Format), [A || {_, A} <- Args], <<>>).
-spec unpack(ephp:context_id(), line(), var_value(), var_value()) ->
ephp_array:ephp_array().
unpack(Context, Line, {_, Format}, {_, Binary}) ->
do_unpack(Context,
Line,
binary:split(
ephp_data:to_bin(Format), <<"/">>, [global]),
Binary,
ephp_array:new(),
<<>>).
%% ----------------------------------------------------------------------------
%% Internal functions
%% ----------------------------------------------------------------------------
do_unpack(_Context, _Line, [], _Binary, Array, _PrevBin) ->
Array;
do_unpack(Context, Line, [<<"a*", Rest/binary>> | Format], Binary, Array, PrevBin) ->
String = ephp_data:to_bin(Binary),
NewArray =
case Rest of
<<>> ->
ephp_array:store(1, String, Array);
_ ->
ephp_array:store(Rest, String, Array)
end,
do_unpack(Context, Line, Format, <<>>, NewArray, PrevBin);
do_unpack(Context, Line, [<<"a", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, Rest0} = get_numbers(Rest, 1),
String = ephp_data:to_bin(Binary),
Index =
case Rest0 of
<<>> ->
1;
_ ->
Rest0
end,
case Size - byte_size(String) of
N when N > 0 ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<"a">>, Size, byte_size(String)},
ephp_error:handle_error(Context, {error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
N when N =:= 0 ->
Array0 = ephp_array:store(Index, String, Array),
PrevStr = <<PrevBin/binary, String/binary>>,
do_unpack(Context, Line, Format, <<>>, Array0, PrevStr);
N when N < 0 ->
<<String1:Size/binary, RestStr/binary>> = String,
Array0 = ephp_array:store(Index, String1, Array),
PreStr = <<PrevBin/binary, String1/binary>>,
do_unpack(Context, Line, Format, RestStr, Array0, PreStr)
end;
do_unpack(Context, Line, [<<"A*", Rest/binary>> | Format], Binary, Array, PrevBin) ->
String =
ephp_string:rtrim(
ephp_data:to_bin(Binary), [32]),
NewArray =
case Rest of
<<>> ->
ephp_array:store(1, String, Array);
_ ->
ephp_array:store(Rest, String, Array)
end,
do_unpack(Context, Line, Format, <<>>, NewArray, PrevBin);
do_unpack(Context, Line, [<<"A", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, Rest0} = get_numbers(Rest, 1),
String = ephp_data:to_bin(Binary),
Index =
case Rest0 of
<<>> ->
1;
_ ->
Rest0
end,
case Size - byte_size(String) of
N when N > 0 ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<"A">>, Size, byte_size(String)},
ephp_error:handle_error(Context, {error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
N when N =:= 0 ->
SStr = ephp_string:rtrim(String, [32]),
Array0 = ephp_array:store(Index, SStr, Array),
PrevStr = <<PrevBin/binary, String/binary>>,
do_unpack(Context, Line, Format, <<>>, Array0, PrevStr);
N when N < 0 ->
<<String1:Size/binary, RestStr/binary>> = String,
SStr = ephp_string:rtrim(String1, [32]),
Array0 = ephp_array:store(Index, SStr, Array),
PreStr = <<PrevBin/binary, String1/binary>>,
do_unpack(Context, Line, Format, RestStr, Array0, PreStr)
end;
do_unpack(Context, Line, [<<"Z*", Rest/binary>> | Format], Binary, Array, PrevBin) ->
String =
ephp_string:rtrim(
ephp_data:to_bin(Binary), [0]),
NewArray =
case Rest of
<<>> ->
ephp_array:store(1, String, Array);
_ ->
ephp_array:store(Rest, String, Array)
end,
do_unpack(Context, Line, Format, <<>>, NewArray, PrevBin);
do_unpack(Context, Line, [<<"Z", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, Rest0} = get_numbers(Rest, 1),
String = ephp_data:to_bin(Binary),
Index =
case Rest0 of
<<>> ->
1;
_ ->
Rest0
end,
case Size - byte_size(String) of
N when N > 0 ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<"Z">>, Size, byte_size(String)},
ephp_error:handle_error(Context, {error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
N when N =:= 0 ->
ZStr = ephp_string:rtrim(String, [0]),
Array0 = ephp_array:store(Index, ZStr, Array),
PrevStr = <<PrevBin/binary, String/binary>>,
do_unpack(Context, Line, Format, <<>>, Array0, PrevStr);
N when N < 0 ->
<<String1:Size/binary, RestStr/binary>> = String,
ZStr = ephp_string:rtrim(String1, [0]),
Array0 = ephp_array:store(Index, ZStr, Array),
PreStr = <<PrevBin/binary, String1/binary>>,
do_unpack(Context, Line, Format, RestStr, Array0, PreStr)
end;
do_unpack(Context, Line, [<<"h*", Rest/binary>> | Format], Binary, Array, PrevBin) ->
String =
ephp_string:ibin2hex(
ephp_data:to_bin(Binary)),
NewArray =
case Rest of
<<>> ->
ephp_array:store(1, String, Array);
_ ->
ephp_array:store(Rest, String, Array)
end,
PreStr = <<PrevBin/binary, Binary/binary>>,
do_unpack(Context, Line, Format, <<>>, NewArray, PreStr);
do_unpack(Context, Line, [<<"h", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, Rest0} = get_numbers(Rest, 1),
Str = ephp_data:to_bin(Binary),
String = ephp_string:ibin2hex(Str),
Index =
case Rest0 of
<<>> ->
1;
_ ->
Rest0
end,
case Size - byte_size(String) of
N when N > 0 ->
File = ephp_context:get_active_file(Context),
TotalSize = ephp_data:ceiling(Size / 2),
Data = {<<"unpack">>, <<"h">>, TotalSize, byte_size(Str)},
ephp_error:handle_error(Context, {error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
N when N =:= 0 ->
Array0 = ephp_array:store(Index, String, Array),
PrevStr = <<PrevBin/binary, Binary/binary>>,
do_unpack(Context, Line, Format, <<>>, Array0, PrevStr);
N when N < 0 ->
TotalSize = ephp_data:ceiling(Size / 2),
<<String1:Size/binary, _/binary>> = String,
<<PrevStr:TotalSize/binary, RestStr/binary>> = Str,
Array0 = ephp_array:store(Index, String1, Array),
PStr = <<PrevBin/binary, PrevStr/binary>>,
do_unpack(Context, Line, Format, RestStr, Array0, PStr)
end;
do_unpack(Context, Line, [<<"H*", Rest/binary>> | Format], Binary, Array, PrevBin) ->
String =
ephp_string:bin2hex(
ephp_data:to_bin(Binary)),
NewArray =
case Rest of
<<>> ->
ephp_array:store(1, String, Array);
_ ->
ephp_array:store(Rest, String, Array)
end,
PrevStr = <<PrevBin/binary, Binary/binary>>,
do_unpack(Context, Line, Format, <<>>, NewArray, PrevStr);
do_unpack(Context, Line, [<<"H", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, Rest0} = get_numbers(Rest, 1),
Str = ephp_data:to_bin(Binary),
String = ephp_string:bin2hex(Str),
Index =
case Rest0 of
<<>> ->
1;
_ ->
Rest0
end,
case Size - byte_size(String) of
N when N > 0 ->
File = ephp_context:get_active_file(Context),
TotalSize = ephp_data:ceiling(Size / 2),
Data = {<<"unpack">>, <<"H">>, TotalSize, byte_size(Str)},
ephp_error:handle_error(Context, {error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
N when N =:= 0 ->
Array0 = ephp_array:store(Index, String, Array),
PrevStr = <<PrevBin/binary, Binary/binary>>,
do_unpack(Context, Line, Format, <<>>, Array0, PrevStr);
N when N < 0 ->
TotalSize = ephp_data:ceiling(Size / 2),
<<String1:Size/binary, _/binary>> = String,
<<PrevStr:TotalSize/binary, RestStr/binary>> = Str,
Array0 = ephp_array:store(Index, String1, Array),
PStr = <<PrevBin/binary, PrevStr/binary>>,
do_unpack(Context, Line, Format, RestStr, Array0, PStr)
end;
do_unpack(Context, Line, [<<"c*", Idx/binary>> | Format], Binary, Array, PrevBin) ->
%% FIXME when R16 is not supported anymore it could be rewrote:
Process =
fun (_P, _I, Array0, <<>>, Prev) ->
{Array0, Prev};
(P, I, Array0, <<Char:8/integer-signed, String/binary>>, Prev) when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Char, Array0),
PrevStr = <<Prev/binary, Char:8/integer-signed>>,
P(P, I + 1, Array1, String, PrevStr);
(P, I, Array0, <<Char:8/integer-signed, String/binary>>, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Char, Array0),
PrevStr = <<Prev/binary, Char:8/integer-signed>>,
P(P, I + 1, Array1, String, PrevStr)
end,
{Array0, PrevBin0} = Process(Process, 1, Array, Binary, PrevBin),
do_unpack(Context, Line, Format, <<>>, Array0, PrevBin0);
do_unpack(Context, Line, [<<"c", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, Idx} = get_numbers(Rest, 1),
Process =
fun (_P, _I, Array0, <<>>, 0, Prev) ->
do_unpack(Context, Line, Format, <<>>, Array0, Prev);
(_P, _I, _Array0, <<>>, _N, _Prev) ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<"c">>, 1, 0},
ephp_error:handle_error(Context,
{error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
(_P, 1, Array0, <<Char:8/integer-signed, String/binary>>, 1, Prev) when Idx =/= <<>> ->
Array1 = ephp_array:store(Idx, Char, Array0),
PrevStr = <<Prev/binary, Char:8/integer-signed>>,
do_unpack(Context, Line, Format, String, Array1, PrevStr);
(_P, _I, Array0, String, 0, Prev) ->
do_unpack(Context, Line, Format, String, Array0, Prev);
(P, I, Array0, <<Char:8/integer-signed, String/binary>>, N, Prev) when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Char, Array0),
PrevStr = <<Prev/binary, Char:8/integer-signed>>,
P(P, I + 1, Array1, String, N - 1, PrevStr);
(P, I, Array0, <<Char:8/integer-signed, String/binary>>, N, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Char, Array0),
PrevStr = <<Prev/binary, Char:8/integer-signed>>,
P(P, I + 1, Array1, String, N - 1, PrevStr)
end,
Process(Process, 1, Array, Binary, Size, PrevBin);
do_unpack(Context, Line, [<<"C*", Idx/binary>> | Format], Binary, Array, PrevBin) ->
%% FIXME when R16 is not supported anymore it could be rewrote:
Process =
fun (_P, _I, Array0, <<>>, Prev) ->
do_unpack(Context, Line, Format, <<>>, Array0, Prev);
(P, I, Array0, <<Char:8/integer-unsigned, String/binary>>, Prev) when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Char, Array0),
PrevStr = <<Prev/binary, Char:8/integer-unsigned>>,
P(P, I + 1, Array1, String, PrevStr);
(P, I, Array0, <<Char:8/integer-unsigned, String/binary>>, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Char, Array0),
PrevStr = <<Prev/binary, Char:8/integer-unsigned>>,
P(P, I + 1, Array1, String, PrevStr)
end,
Process(Process, 1, Array, Binary, PrevBin);
do_unpack(Context, Line, [<<"C", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, Idx} = get_numbers(Rest, 1),
Process =
fun (_P, _I, Array0, <<>>, 0, Prev) ->
do_unpack(Context, Line, Format, <<>>, Array0, Prev);
(_P, _I, _Array0, <<>>, _N, _Prev) ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<"C">>, 1, 0},
ephp_error:handle_error(Context,
{error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
(_P, 1, Array0, <<Char:8/integer-unsigned, String/binary>>, 1, Prev)
when Idx =/= <<>> ->
Array1 = ephp_array:store(Idx, Char, Array0),
PrevStr = <<Prev/binary, Char:8/integer-unsigned>>,
do_unpack(Context, Line, Format, String, Array1, PrevStr);
(_P, _I, Array0, String, 0, Prev) ->
do_unpack(Context, Line, Format, String, Array0, Prev);
(P, I, Array0, <<Char:8/integer-unsigned, String/binary>>, N, Prev) when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Char, Array0),
PrevStr = <<Prev/binary, Char:8/integer-unsigned>>,
P(P, I + 1, Array1, String, N - 1, PrevStr);
(P, I, Array0, <<Char:8/integer-unsigned, String/binary>>, N, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Char, Array0),
PrevStr = <<Prev/binary, Char:8/integer-unsigned>>,
P(P, I + 1, Array1, String, N - 1, PrevStr)
end,
Process(Process, 1, Array, Binary, Size, PrevBin);
do_unpack(Context, Line, [<<"s*", Idx/binary>> | Format], Binary, Array, PrevBin) ->
%% FIXME when R16 is not supported anymore it could be rewrote:
Process =
fun (_P, _I, Array0, String, Prev) when bit_size(String) < 16 ->
{Array0, Prev};
(P, I, Array0, <<Bin:16/integer-signed-little, String/binary>>, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-signed-little>>,
P(P, I + 1, Array1, String, PrevStr);
(P, I, Array0, <<Bin:16/integer-signed-little, String/binary>>, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-signed-little>>,
P(P, I + 1, Array1, String, PrevStr)
end,
{Array0, PrevBin0} = Process(Process, 1, Array, Binary, PrevBin),
do_unpack(Context, Line, Format, <<>>, Array0, PrevBin0);
do_unpack(Context, Line, [<<"s", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, Idx} = get_numbers(Rest, 1),
Process =
fun (_P, _I, Array0, String, 0, Prev) when bit_size(String) < 16 ->
do_unpack(Context, Line, Format, <<>>, Array0, Prev);
(_P, _I, _Array0, String, _N, _Prev) when bit_size(String) < 16 ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<"s">>, 2, byte_size(String)},
ephp_error:handle_error(Context,
{error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
(_P, 1, Array0, <<Bin:16/integer-signed-little, String/binary>>, 1, Prev)
when Idx =/= <<>> ->
Array1 = ephp_array:store(Idx, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-signed-little>>,
do_unpack(Context, Line, Format, String, Array1, PrevStr);
(_P, _I, Array0, String, 0, Prev) ->
do_unpack(Context, Line, Format, String, Array0, Prev);
(P, I, Array0, <<Bin:16/integer-signed-little, String/binary>>, N, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-signed-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr);
(P, I, Array0, <<Bin:16/integer-signed-little, String/binary>>, N, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-signed-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr)
end,
Process(Process, 1, Array, Binary, Size, PrevBin);
do_unpack(Context, Line, [<<"n*", Idx/binary>> | Format], Binary, Array, PrevBin) ->
%% FIXME when R16 is not supported anymore it could be rewrote:
Process =
fun (_P, _I, Array0, String, Prev) when bit_size(String) < 16 ->
{Array0, Prev};
(P, I, Array0, <<Bin:16/integer-unsigned-big, String/binary>>, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-unsigned-big>>,
P(P, I + 1, Array1, String, PrevStr);
(P, I, Array0, <<Bin:16/integer-unsigned-big, String/binary>>, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-unsigned-big>>,
P(P, I + 1, Array1, String, PrevStr)
end,
{Array0, PrevBin0} = Process(Process, 1, Array, Binary, PrevBin),
do_unpack(Context, Line, Format, <<>>, Array0, PrevBin0);
do_unpack(Context, Line, [<<"n", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, Idx} = get_numbers(Rest, 1),
Process =
fun (_P, _I, Array0, String, 0, Prev) when bit_size(String) < 16 ->
do_unpack(Context, Line, Format, <<>>, Array0, Prev);
(_P, _I, _Array0, String, _N, _Prev) when bit_size(String) < 16 ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<"n">>, 2, byte_size(String)},
ephp_error:handle_error(Context,
{error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
(_P, 1, Array0, <<Bin:16/integer-unsigned-big, String/binary>>, 1, Prev)
when Idx =/= <<>> ->
Array1 = ephp_array:store(Idx, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-unsigned-big>>,
do_unpack(Context, Line, Format, String, Array1, PrevStr);
(_P, _I, Array0, String, 0, Prev) ->
do_unpack(Context, Line, Format, String, Array0, Prev);
(P, I, Array0, <<Bin:16/integer-unsigned-big, String/binary>>, N, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-unsigned-big>>,
P(P, I + 1, Array1, String, N - 1, PrevStr);
(P, I, Array0, <<Bin:16/integer-unsigned-big, String/binary>>, N, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-unsigned-big>>,
P(P, I + 1, Array1, String, N - 1, PrevStr)
end,
Process(Process, 1, Array, Binary, Size, PrevBin);
do_unpack(Context, Line, [<<A:8, "*", Idx/binary>> | Format], Binary, Array, PrevBin)
when A =:= $v orelse A =:= $S ->
%% FIXME when R16 is not supported anymore it could be rewrote:
Process =
fun (_P, _I, Array0, String, Prev) when bit_size(String) < 16 ->
{Array0, Prev};
(P, I, Array0, <<Bin:16/integer-unsigned-little, String/binary>>, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-unsigned-little>>,
P(P, I + 1, Array1, String, PrevStr);
(P, I, Array0, <<Bin:16/integer-unsigned-little, String/binary>>, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-unsigned-little>>,
P(P, I + 1, Array1, String, PrevStr)
end,
{Array0, PrevBin0} = Process(Process, 1, Array, Binary, PrevBin),
do_unpack(Context, Line, Format, <<>>, Array0, PrevBin0);
do_unpack(Context, Line, [<<A:8, Rest/binary>> | Format], Binary, Array, PrevBin)
when A =:= $v orelse A =:= $S ->
{Size, Idx} = get_numbers(Rest, 1),
Process =
fun (_P, _I, Array0, String, 0, Prev) when bit_size(String) < 16 ->
do_unpack(Context, Line, Format, <<>>, Array0, Prev);
(_P, _I, _Array0, String, _N, _Prev) when bit_size(String) < 16 ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<A:8>>, 2, byte_size(String)},
ephp_error:handle_error(Context,
{error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
(_P, 1, Array0, <<Bin:16/integer-unsigned-little, String/binary>>, 1, Prev)
when Idx =/= <<>> ->
Array1 = ephp_array:store(Idx, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-unsigned-little>>,
do_unpack(Context, Line, Format, String, Array1, PrevStr);
(_P, _I, Array0, String, 0, Prev) ->
do_unpack(Context, Line, Format, String, Array0, Prev);
(P, I, Array0, <<Bin:16/integer-unsigned-little, String/binary>>, N, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-unsigned-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr);
(P, I, Array0, <<Bin:16/integer-unsigned-little, String/binary>>, N, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:16/integer-unsigned-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr)
end,
Process(Process, 1, Array, Binary, Size, PrevBin);
do_unpack(Context, Line, [<<A:8, "*", Idx/binary>> | Format], Binary, Array, PrevBin)
when A =:= $I orelse A =:= $L orelse A =:= $V ->
%% FIXME when R16 is not supported anymore it could be rewrote:
Process =
fun (_P, _I, Array0, String, Prev) when bit_size(String) < 32 ->
{Array0, Prev};
(P, I, Array0, <<Bin:32/integer-unsigned-little, String/binary>>, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-unsigned-little>>,
P(P, I + 1, Array1, String, PrevStr);
(P, I, Array0, <<Bin:32/integer-unsigned-little, String/binary>>, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-unsigned-little>>,
P(P, I + 1, Array1, String, PrevStr)
end,
{Array0, PrevBin0} = Process(Process, 1, Array, Binary, PrevBin),
do_unpack(Context, Line, Format, <<>>, Array0, PrevBin0);
do_unpack(Context, Line, [<<A:8, Rest/binary>> | Format], Binary, Array, PrevBin)
when A =:= $I orelse A =:= $L orelse A =:= $V ->
{Size, Idx} = get_numbers(Rest, 1),
Process =
fun (_P, _I, Array0, String, 0, Prev) when bit_size(String) < 32 ->
do_unpack(Context, Line, Format, <<>>, Array0, Prev);
(_P, _I, _Array0, String, _N, _Prev) when bit_size(String) < 32 ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<A:8>>, 4, byte_size(String)},
ephp_error:handle_error(Context,
{error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
(_P, 1, Array0, <<Bin:32/integer-unsigned-little, String/binary>>, 1, Prev)
when Idx =/= <<>> ->
Array1 = ephp_array:store(Idx, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-unsigned-little>>,
do_unpack(Context, Line, Format, String, Array1, PrevStr);
(_P, _I, Array0, String, 0, Prev) ->
do_unpack(Context, Line, Format, String, Array0, Prev);
(P, I, Array0, <<Bin:32/integer-unsigned-little, String/binary>>, N, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-unsigned-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr);
(P, I, Array0, <<Bin:32/integer-unsigned-little, String/binary>>, N, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-unsigned-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr)
end,
Process(Process, 1, Array, Binary, Size, PrevBin);
do_unpack(Context, Line, [<<A:8, "*", Idx/binary>> | Format], Binary, Array, PrevBin)
when A =:= $i orelse A =:= $l ->
%% FIXME when R16 is not supported anymore it could be rewrote:
Process =
fun (_P, _I, Array0, String, Prev) when bit_size(String) < 32 ->
{Array0, Prev};
(P, I, Array0, <<Bin:32/integer-signed-little, String/binary>>, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-signed-little>>,
P(P, I + 1, Array1, String, PrevStr);
(P, I, Array0, <<Bin:32/integer-signed-little, String/binary>>, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-signed-little>>,
P(P, I + 1, Array1, String, PrevStr)
end,
{Array0, PrevBin0} = Process(Process, 1, Array, Binary, PrevBin),
do_unpack(Context, Line, Format, <<>>, Array0, PrevBin0);
do_unpack(Context, Line, [<<A:8, Rest/binary>> | Format], Binary, Array, PrevBin)
when A =:= $i orelse A =:= $l ->
{Size, Idx} = get_numbers(Rest, 1),
Process =
fun (_P, _I, Array0, String, 0, Prev) when bit_size(String) < 32 ->
do_unpack(Context, Line, Format, <<>>, Array0, Prev);
(_P, _I, _Array0, String, _N, _Prev) when bit_size(String) < 32 ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<A:8>>, 4, byte_size(String)},
ephp_error:handle_error(Context,
{error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
(_P, 1, Array0, <<Bin:32/integer-signed-little, String/binary>>, 1, Prev)
when Idx =/= <<>> ->
Array1 = ephp_array:store(Idx, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-signed-little>>,
do_unpack(Context, Line, Format, String, Array1, PrevStr);
(_P, _I, Array0, String, 0, Prev) ->
do_unpack(Context, Line, Format, String, Array0, Prev);
(P, I, Array0, <<Bin:32/integer-signed-little, String/binary>>, N, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-signed-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr);
(P, I, Array0, <<Bin:32/integer-signed-little, String/binary>>, N, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-signed-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr)
end,
Process(Process, 1, Array, Binary, Size, PrevBin);
do_unpack(Context, Line, [<<"N*", Idx/binary>> | Format], Binary, Array, PrevBin) ->
%% FIXME when R16 is not supported anymore it could be rewrote:
Process =
fun (_P, _I, Array0, String, Prev) when bit_size(String) < 32 ->
{Array0, Prev};
(P, I, Array0, <<Bin:32/integer-unsigned-big, String/binary>>, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-unsigned-big>>,
P(P, I + 1, Array1, String, PrevStr);
(P, I, Array0, <<Bin:32/integer-unsigned-big, String/binary>>, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-unsigned-big>>,
P(P, I + 1, Array1, String, PrevStr)
end,
{Array0, PrevBin0} = Process(Process, 1, Array, Binary, PrevBin),
do_unpack(Context, Line, Format, <<>>, Array0, PrevBin0);
do_unpack(Context, Line, [<<"N", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, Idx} = get_numbers(Rest, 1),
Process =
fun (_P, _I, Array0, String, 0, Prev) when bit_size(String) < 32 ->
do_unpack(Context, Line, Format, <<>>, Array0, Prev);
(_P, _I, _Array0, String, _N, _Prev) when bit_size(String) < 32 ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<"N">>, 4, byte_size(String)},
ephp_error:handle_error(Context,
{error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
(_P, 1, Array0, <<Bin:32/integer-unsigned-big, String/binary>>, 1, Prev)
when Idx =/= <<>> ->
Array1 = ephp_array:store(Idx, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-unsigned-big>>,
do_unpack(Context, Line, Format, String, Array1, PrevStr);
(_P, _I, Array0, String, 0, Prev) ->
do_unpack(Context, Line, Format, String, Array0, Prev);
(P, I, Array0, <<Bin:32/integer-unsigned-big, String/binary>>, N, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-unsigned-big>>,
P(P, I + 1, Array1, String, N - 1, PrevStr);
(P, I, Array0, <<Bin:32/integer-unsigned-big, String/binary>>, N, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/integer-unsigned-big>>,
P(P, I + 1, Array1, String, N - 1, PrevStr)
end,
Process(Process, 1, Array, Binary, Size, PrevBin);
do_unpack(Context, Line, [<<A:8, "*", Idx/binary>> | Format], Binary, Array, PrevBin)
when A =:= $Q orelse A =:= $P ->
%% FIXME when R16 is not supported anymore it could be rewrote:
Process =
fun (_P, _I, Array0, String, Prev) when bit_size(String) < 64 ->
{Array0, Prev};
(P, I, Array0, <<Bin:64/integer-unsigned-little, String/binary>>, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-unsigned-little>>,
P(P, I + 1, Array1, String, PrevStr);
(P, I, Array0, <<Bin:64/integer-unsigned-little, String/binary>>, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-unsigned-little>>,
P(P, I + 1, Array1, String, PrevStr)
end,
{Array0, PrevBin0} = Process(Process, 1, Array, Binary, PrevBin),
do_unpack(Context, Line, Format, <<>>, Array0, PrevBin0);
do_unpack(Context, Line, [<<A:8, Rest/binary>> | Format], Binary, Array, PrevBin)
when A =:= $Q orelse A =:= $P ->
{Size, Idx} = get_numbers(Rest, 1),
Process =
fun (_P, _I, Array0, String, 0, Prev) when bit_size(String) < 64 ->
do_unpack(Context, Line, Format, <<>>, Array0, Prev);
(_P, _I, _Array0, String, _N, _Prev) when bit_size(String) < 64 ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<A:8>>, 8, byte_size(String)},
ephp_error:handle_error(Context,
{error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
(_P, 1, Array0, <<Bin:64/integer-unsigned-little, String/binary>>, 1, Prev)
when Idx =/= <<>> ->
Array1 = ephp_array:store(Idx, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-unsigned-little>>,
do_unpack(Context, Line, Format, String, Array1, PrevStr);
(_P, _I, Array0, String, 0, Prev) ->
do_unpack(Context, Line, Format, String, Array0, Prev);
(P, I, Array0, <<Bin:64/integer-unsigned-little, String/binary>>, N, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-unsigned-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr);
(P, I, Array0, <<Bin:64/integer-unsigned-little, String/binary>>, N, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-unsigned-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr)
end,
Process(Process, 1, Array, Binary, Size, PrevBin);
do_unpack(Context, Line, [<<"q*", Idx/binary>> | Format], Binary, Array, PrevBin) ->
%% FIXME when R16 is not supported anymore it could be rewrote:
Process =
fun (_P, _I, Array0, String, Prev) when bit_size(String) < 64 ->
{Array0, Prev};
(P, I, Array0, <<Bin:64/integer-signed-little, String/binary>>, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-signed-little>>,
P(P, I + 1, Array1, String, PrevStr);
(P, I, Array0, <<Bin:64/integer-signed-little, String/binary>>, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-signed-little>>,
P(P, I + 1, Array1, String, PrevStr)
end,
{Array0, PrevBin0} = Process(Process, 1, Array, Binary, PrevBin),
do_unpack(Context, Line, Format, <<>>, Array0, PrevBin0);
do_unpack(Context, Line, [<<"q", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, Idx} = get_numbers(Rest, 1),
Process =
fun (_P, _I, Array0, String, 0, Prev) when bit_size(String) < 64 ->
do_unpack(Context, Line, Format, <<>>, Array0, Prev);
(_P, _I, _Array0, String, _N, _Prev) when bit_size(String) < 64 ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<"q">>, 8, byte_size(String)},
ephp_error:handle_error(Context,
{error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
(_P, 1, Array0, <<Bin:64/integer-signed-little, String/binary>>, 1, Prev)
when Idx =/= <<>> ->
Array1 = ephp_array:store(Idx, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-signed-little>>,
do_unpack(Context, Line, Format, String, Array1, PrevStr);
(_P, _I, Array0, String, 0, Prev) ->
do_unpack(Context, Line, Format, String, Array0, Prev);
(P, I, Array0, <<Bin:64/integer-signed-little, String/binary>>, N, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-signed-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr);
(P, I, Array0, <<Bin:64/integer-signed-little, String/binary>>, N, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-signed-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr)
end,
Process(Process, 1, Array, Binary, Size, PrevBin);
do_unpack(Context, Line, [<<"J*", Idx/binary>> | Format], Binary, Array, PrevBin) ->
%% FIXME when R16 is not supported anymore it could be rewrote:
Process =
fun (_P, _I, Array0, String, Prev) when bit_size(String) < 32 ->
{Array0, Prev};
(P, I, Array0, <<Bin:64/integer-unsigned-big, String/binary>>, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-unsigned-big>>,
P(P, I + 1, Array1, String, PrevStr);
(P, I, Array0, <<Bin:64/integer-unsigned-big, String/binary>>, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-unsigned-big>>,
P(P, I + 1, Array1, String, PrevStr)
end,
{Array0, PrevBin0} = Process(Process, 1, Array, Binary, PrevBin),
do_unpack(Context, Line, Format, <<>>, Array0, PrevBin0);
do_unpack(Context, Line, [<<"J", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, Idx} = get_numbers(Rest, 1),
Process =
fun (_P, _I, Array0, String, 0, Prev) when bit_size(String) < 64 ->
do_unpack(Context, Line, Format, <<>>, Array0, Prev);
(_P, _I, _Array0, String, _N, _Prev) when bit_size(String) < 64 ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<"J">>, 8, byte_size(String)},
ephp_error:handle_error(Context,
{error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
(_P, 1, Array0, <<Bin:64/integer-unsigned-big, String/binary>>, 1, Prev)
when Idx =/= <<>> ->
Array1 = ephp_array:store(Idx, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-unsigned-big>>,
do_unpack(Context, Line, Format, String, Array1, PrevStr);
(_P, _I, Array0, String, 0, Prev) ->
do_unpack(Context, Line, Format, String, Array0, Prev);
(P, I, Array0, <<Bin:64/integer-unsigned-big, String/binary>>, N, Prev)
when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-unsigned-big>>,
P(P, I + 1, Array1, String, N - 1, PrevStr);
(P, I, Array0, <<Bin:64/integer-unsigned-big, String/binary>>, N, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/integer-unsigned-big>>,
P(P, I + 1, Array1, String, N - 1, PrevStr)
end,
Process(Process, 1, Array, Binary, Size, PrevBin);
do_unpack(Context, Line, [<<"f*", Idx/binary>> | Format], Binary, Array, PrevBin) ->
%% FIXME when R16 is not supported anymore it could be rewrot, PrevBine:
Process =
fun (_P, _I, Array0, String, Prev) when bit_size(String) < 32 ->
{Array0, Prev};
(P, I, Array0, <<Bin:32/float-little, String/binary>>, Prev) when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/float-little>>,
P(P, I + 1, Array1, String, PrevStr);
(P, I, Array0, <<Bin:32/float-little, String/binary>>, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/float-little>>,
P(P, I + 1, Array1, String, PrevStr)
end,
{Array0, PrevBin0} = Process(Process, 1, Array, Binary, PrevBin),
do_unpack(Context, Line, Format, <<>>, Array0, PrevBin0);
do_unpack(Context, Line, [<<"f", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, Idx} = get_numbers(Rest, 1),
Process =
fun (_P, _I, Array0, String, 0, Prev) when bit_size(String) < 32 ->
do_unpack(Context, Line, Format, <<>>, Array0, Prev);
(_P, _I, _Array0, String, _N, _Prev) when bit_size(String) < 32 ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<"f">>, 4, byte_size(String)},
ephp_error:handle_error(Context,
{error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
(_P, 1, Array0, <<Bin:32/float-little, String/binary>>, 1, Prev) when Idx =/= <<>> ->
Array1 = ephp_array:store(Idx, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/float-little>>,
do_unpack(Context, Line, Format, String, Array1, PrevStr);
(_P, _I, Array0, String, 0, Prev) ->
do_unpack(Context, Line, Format, String, Array0, Prev);
(P, I, Array0, <<Bin:32/float-little, String/binary>>, N, Prev) when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/float-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr);
(P, I, Array0, <<Bin:32/float-little, String/binary>>, N, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:32/float-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr)
end,
Process(Process, 1, Array, Binary, Size, PrevBin);
do_unpack(Context, Line, [<<"d*", Idx/binary>> | Format], Binary, Array, PrevBin) ->
%% FIXME when R16 is not supported anymore it could be rewrote:
Process =
fun (_P, _I, Array0, String, Prev) when bit_size(String) < 64 ->
{Array0, Prev};
(P, I, Array0, <<Bin:64/float-little, String/binary>>, Prev) when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/float-little>>,
P(P, I + 1, Array1, String, PrevStr);
(P, I, Array0, <<Bin:64/float-little, String/binary>>, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/float-little>>,
P(P, I + 1, Array1, String, PrevStr)
end,
{Array0, PrevBin0} = Process(Process, 1, Array, Binary, PrevBin),
do_unpack(Context, Line, Format, <<>>, Array0, PrevBin0);
do_unpack(Context, Line, [<<"d", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, Idx} = get_numbers(Rest, 1),
Process =
fun (_P, _I, Array0, String, 0, Prev) when bit_size(String) < 64 ->
do_unpack(Context, Line, Format, <<>>, Array0, Prev);
(_P, _I, _Array0, String, _N, _Prev) when bit_size(String) < 64 ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<"d">>, 8, byte_size(String)},
ephp_error:handle_error(Context,
{error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
(_P, 1, Array0, <<Bin:64/float-little, String/binary>>, 1, Prev) when Idx =/= <<>> ->
Array1 = ephp_array:store(Idx, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/float-little>>,
do_unpack(Context, Line, Format, String, Array1, PrevStr);
(_P, _I, Array0, String, 0, Prev) ->
do_unpack(Context, Line, Format, String, Array0, Prev);
(P, I, Array0, <<Bin:64/float-little, String/binary>>, N, Prev) when Idx =:= <<>> ->
Array1 = ephp_array:store(I, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/float-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr);
(P, I, Array0, <<Bin:64/float-little, String/binary>>, N, Prev) ->
Index = <<Idx/binary, (integer_to_binary(I))/binary>>,
Array1 = ephp_array:store(Index, Bin, Array0),
PrevStr = <<Prev/binary, Bin:64/float-little>>,
P(P, I + 1, Array1, String, N - 1, PrevStr)
end,
Process(Process, 1, Array, Binary, Size, PrevBin);
do_unpack(Context, Line, [<<A:8, "*", _/binary>> | Format], _Binary, Array, PrevBin)
when A =:= $x orelse A =:= $@ ->
do_unpack(Context, Line, Format, <<>>, Array, PrevBin);
do_unpack(Context, Line, [<<A:8, Rest/binary>> | Format], Binary, Array, PrevBin)
when A =:= $x orelse A =:= $@ ->
{Size, _} = get_numbers(Rest, 1),
case byte_size(Binary) of
N when N =:= Size ->
do_unpack(Context, Line, Format, <<>>, Array, Binary);
N when N < Size andalso A =:= $x ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<"x">>, 1, 0},
ephp_error:handle_error(Context, {error, enoenoughin, Line, File, ?E_WARNING, Data}),
false;
N when N < Size andalso A =:= $@ ->
File = ephp_context:get_active_file(Context),
Data = {<<"unpack">>, <<"@">>},
ephp_error:handle_error(Context, {error, eoutstr, Line, File, ?E_WARNING, Data}),
do_unpack(Context, Line, Format, Binary, Array, PrevBin);
N when N > Size ->
<<PreStr:Size/binary, RestBin/binary>> = Binary,
do_unpack(Context, Line, Format, RestBin, Array, PreStr)
end;
do_unpack(Context, Line, [<<"X", Rest/binary>> | Format], Binary, Array, PrevBin) ->
{Size, _} = get_numbers(Rest, 1),
Process =
fun (_P, 0, Bin, Prev) ->
{Bin, Prev};
(_P, _I, Bin, <<>>) ->
{Bin, <<>>};
(_P, _I, Bin, <<A:1/binary>>) ->
{<<A/binary, Bin/binary>>, <<>>};
(P, I, Bin, Prev) ->
PSize = byte_size(Prev) - 1,
<<PBin:PSize/binary, X:1/binary>> = Prev,
P(P, I - 1, <<X/binary, Bin/binary>>, PBin)
end,
{Binary0, PrevBin0} = Process(Process, Size, Binary, PrevBin),
do_unpack(Context, Line, Format, Binary0, Array, PrevBin0).
do_pack(_Context, _Line, <<>>, [], Binary) ->
Binary;
do_pack(Context, Line, <<>>, Args, Binary) ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, length(Args)},
ephp_error:handle_error(Context, {error, eargunused, Line, File, ?E_WARNING, Data}),
Binary;
do_pack(Context, Line, <<A:8, "*", Rest/binary>>, [Arg | Args], Binary)
when A =:= $A orelse A =:= $a ->
String = ephp_data:to_bin(Arg),
do_pack(Context, Line, Rest, Args, <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<"a", Rest/binary>>, [Arg | Args], Binary) ->
{Size, Rest0} = get_numbers(Rest, 0),
String = ephp_data:to_bin(Arg),
String0 =
case Size - byte_size(String) of
N when N =:= 0 ->
<<Binary/binary, String/binary>>;
N when N < 0 ->
<<Binary/binary, String:Size/binary>>;
N when N > 0 ->
Nulls = ephp_string:repeat(N, 0),
<<Binary/binary, String/binary, Nulls/binary>>
end,
do_pack(Context, Line, Rest0, Args, String0);
do_pack(Context, Line, <<"A", Rest/binary>>, [Arg | Args], Binary) ->
{Size0, Rest0} = get_numbers(Rest, 1),
String = ephp_data:to_bin(Arg),
String0 =
case Size0 - byte_size(String) of
N when N =:= 0 ->
<<Binary/binary, String/binary>>;
N when N < 0 ->
<<Binary/binary, String:Size0/binary>>;
N when N > 0 ->
Spaces = ephp_string:spaces(N),
<<Binary/binary, String/binary, Spaces/binary>>
end,
do_pack(Context, Line, Rest0, Args, String0);
do_pack(Context, Line, <<"H*", Rest/binary>>, [Arg | Args], Binary) ->
String = ephp_string:hex2bin(Arg),
do_pack(Context, Line, Rest, Args, <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<"H", Rest/binary>>, [Arg | Args], Binary) ->
{Size0, Rest0} = get_numbers(Rest, 1),
ArgStr = ephp_data:to_bin(Arg),
String =
case Size0 - byte_size(ArgStr) of
N when N =:= 0 ->
ephp_string:hex2bin(ArgStr);
N when N < 0 ->
<<ArgStr0:Size0/binary, _/binary>> = ArgStr,
ephp_string:hex2bin(ArgStr0);
N when N > 0 ->
%% TODO: warning
ephp_string:hex2bin(ArgStr)
end,
do_pack(Context, Line, Rest0, Args, <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<"h*", Rest/binary>>, [Arg | Args], Binary) ->
String = ephp_string:ihex2bin(Arg),
do_pack(Context, Line, Rest, Args, <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<"h", Rest/binary>>, [Arg | Args], Binary) ->
{Size0, Rest0} = get_numbers(Rest, 1),
ArgStr = ephp_data:to_bin(Arg),
String =
case Size0 - byte_size(ArgStr) of
N when N =:= 0 ->
ephp_string:ihex2bin(ArgStr);
N when N < 0 ->
<<ArgStr0:Size0/binary, _/binary>> = ArgStr,
ephp_string:ihex2bin(ArgStr0);
N when N > 0 ->
%% TODO: warning
ephp_string:ihex2bin(ArgStr)
end,
do_pack(Context, Line, Rest0, Args, <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<C:8, "*", Rest/binary>>, Args, Binary)
when C =:= $c orelse C =:= $C ->
String =
lists:foldl(fun (Arg, S) when is_number(Arg) ->
A = ephp_data:flooring(Arg),
<<S/binary, A:8>>;
(_, S) ->
<<S/binary, 0:8>>
end,
<<>>,
Args),
do_pack(Context, Line, Rest, [], <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<C:8, Rest/binary>>, Args, Binary)
when C =:= $c orelse C =:= $C ->
{Size0, Rest0} = get_numbers(Rest, 1),
{NSize, NArgs, String} =
lists:foldl(fun (Arg, {0, AA, Str}) ->
{0, AA ++ [Arg], Str};
(Arg, {Si, AA, Str}) when is_number(Arg) ->
A = ephp_data:flooring(Arg),
{Si - 1, AA, <<Str/binary, A:8>>};
(_, {Si, AA, Str}) ->
{Si - 1, AA, <<Str/binary, 0:8>>}
end,
{Size0, [], <<>>},
Args),
case NSize of
0 ->
do_pack(Context, Line, Rest0, NArgs, <<Binary/binary, String/binary>>);
_ ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, <<C:8>>},
ephp_error:handle_error(Context, {error, efewargs, Line, File, ?E_WARNING, Data}),
false
end;
do_pack(Context, Line, <<C:8, "*", Rest/binary>>, Args, Binary)
when C =:= $s orelse C =:= $S orelse C =:= $v ->
String =
lists:foldl(fun (Arg, S) when is_number(Arg) ->
A = ephp_data:flooring(Arg),
<<S/binary, A:16/integer-little>>;
(_, S) ->
<<S/binary, 0:16>>
end,
<<>>,
Args),
do_pack(Context, Line, Rest, [], <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<C:8, Rest/binary>>, Args, Binary)
when C =:= $s orelse C =:= $S orelse C =:= $v ->
{Size0, Rest0} = get_numbers(Rest, 1),
{NSize, NArgs, String} =
lists:foldl(fun (Arg, {0, AA, Str}) ->
{0, AA ++ [Arg], Str};
(Arg, {Si, AA, Str}) when is_number(Arg) ->
A = ephp_data:flooring(Arg),
{Si - 1, AA, <<Str/binary, A:16/integer-little>>};
(_, {Si, AA, Str}) ->
{Si - 1, AA, <<Str/binary, 0:16>>}
end,
{Size0, [], <<>>},
Args),
case NSize of
0 ->
do_pack(Context, Line, Rest0, NArgs, <<Binary/binary, String/binary>>);
_ ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, <<C:8>>},
ephp_error:handle_error(Context, {error, efewargs, Line, File, ?E_WARNING, Data}),
false
end;
do_pack(Context, Line, <<"n*", Rest/binary>>, Args, Binary) ->
String =
lists:foldl(fun (Arg, S) when is_number(Arg) ->
A = ephp_data:flooring(Arg),
<<S/binary, A:16/integer-big>>;
(_, S) ->
<<S/binary, 0:16>>
end,
<<>>,
Args),
do_pack(Context, Line, Rest, [], <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<"n", Rest/binary>>, Args, Binary) ->
{Size0, Rest0} = get_numbers(Rest, 1),
{NSize, NArgs, String} =
lists:foldl(fun (Arg, {0, AA, Str}) ->
{0, AA ++ [Arg], Str};
(Arg, {Si, AA, Str}) when is_number(Arg) ->
A = ephp_data:flooring(Arg),
{Si - 1, AA, <<Str/binary, A:16/integer-big>>};
(_, {Si, AA, Str}) ->
{Si - 1, AA, <<Str/binary, 0:16>>}
end,
{Size0, [], <<>>},
Args),
case NSize of
0 ->
do_pack(Context, Line, Rest0, NArgs, <<Binary/binary, String/binary>>);
_ ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, <<"n">>},
ephp_error:handle_error(Context, {error, efewargs, Line, File, ?E_WARNING, Data}),
false
end;
do_pack(Context, Line, <<C:8, "*", Rest/binary>>, Args, Binary)
when C =:= $i orelse C =:= $I orelse C =:= $l orelse C =:= $L orelse C =:= $V ->
String =
lists:foldl(fun (Arg, S) when is_number(Arg) ->
A = ephp_data:flooring(Arg),
<<S/binary, A:32/integer-little>>;
(_, S) ->
<<S/binary, 0:32>>
end,
<<>>,
Args),
do_pack(Context, Line, Rest, [], <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<C:8, Rest/binary>>, Args, Binary)
when C =:= $i orelse C =:= $I orelse C =:= $l orelse C =:= $L orelse C =:= $V ->
{Size0, Rest0} = get_numbers(Rest, 1),
{NSize, NArgs, String} =
lists:foldl(fun (Arg, {0, AA, Str}) ->
{0, AA ++ [Arg], Str};
(Arg, {Si, AA, Str}) when is_number(Arg) ->
A = ephp_data:flooring(Arg),
{Si - 1, AA, <<Str/binary, A:32/integer-little>>};
(_, {Si, AA, Str}) ->
{Si - 1, AA, <<Str/binary, 0:32>>}
end,
{Size0, [], <<>>},
Args),
case NSize of
0 ->
do_pack(Context, Line, Rest0, NArgs, <<Binary/binary, String/binary>>);
_ ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, <<C:8>>},
ephp_error:handle_error(Context, {error, efewargs, Line, File, ?E_WARNING, Data}),
false
end;
do_pack(Context, Line, <<"N*", Rest/binary>>, Args, Binary) ->
String =
lists:foldl(fun (Arg, S) when is_number(Arg) ->
A = ephp_data:flooring(Arg),
<<S/binary, A:32/integer-big>>;
(_, S) ->
<<S/binary, 0:32>>
end,
<<>>,
Args),
do_pack(Context, Line, Rest, [], <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<"N", Rest/binary>>, Args, Binary) ->
{Size0, Rest0} = get_numbers(Rest, 1),
{NSize, NArgs, String} =
lists:foldl(fun (Arg, {0, AA, Str}) ->
{0, AA ++ [Arg], Str};
(Arg, {Si, AA, Str}) when is_number(Arg) ->
A = ephp_data:flooring(Arg),
{Si - 1, AA, <<Str/binary, A:32/integer-big>>};
(_, {Si, AA, Str}) ->
{Si - 1, AA, <<Str/binary, 0:32>>}
end,
{Size0, [], <<>>},
Args),
case NSize of
0 ->
do_pack(Context, Line, Rest0, NArgs, <<Binary/binary, String/binary>>);
_ ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, <<"N">>},
ephp_error:handle_error(Context, {error, efewargs, Line, File, ?E_WARNING, Data}),
false
end;
do_pack(Context, Line, <<C:8, "*", Rest/binary>>, Args, Binary)
when C =:= $q orelse C =:= $Q orelse C =:= $P ->
String =
lists:foldl(fun (Arg, S) when is_number(Arg) ->
A = ephp_data:flooring(Arg),
<<S/binary, A:64/integer-little>>;
(_, S) ->
<<S/binary, 0:64>>
end,
<<>>,
Args),
do_pack(Context, Line, Rest, [], <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<C:8, Rest/binary>>, Args, Binary)
when C =:= $q orelse C =:= $Q orelse C =:= $P ->
{Size0, Rest0} = get_numbers(Rest, 1),
{NSize, NArgs, String} =
lists:foldl(fun (Arg, {0, AA, Str}) ->
{0, AA ++ [Arg], Str};
(Arg, {Si, AA, Str}) when is_number(Arg) ->
A = ephp_data:flooring(Arg),
{Si - 1, AA, <<Str/binary, A:64/integer-little>>};
(_, {Si, AA, Str}) ->
{Si - 1, AA, <<Str/binary, 0:64>>}
end,
{Size0, [], <<>>},
Args),
case NSize of
0 ->
do_pack(Context, Line, Rest0, NArgs, <<Binary/binary, String/binary>>);
_ ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, <<C:8>>},
ephp_error:handle_error(Context, {error, efewargs, Line, File, ?E_WARNING, Data}),
false
end;
do_pack(Context, Line, <<"J*", Rest/binary>>, Args, Binary) ->
String =
lists:foldl(fun (Arg, S) when is_number(Arg) ->
A = ephp_data:flooring(Arg),
<<S/binary, A:64/integer-big>>;
(_, S) ->
<<S/binary, 0:64>>
end,
<<>>,
Args),
do_pack(Context, Line, Rest, [], <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<"J", Rest/binary>>, Args, Binary) ->
{Size0, Rest0} = get_numbers(Rest, 1),
{NSize, NArgs, String} =
lists:foldl(fun (Arg, {0, AA, Str}) ->
{0, AA ++ [Arg], Str};
(Arg, {Si, AA, Str}) when is_number(Arg) ->
A = ephp_data:flooring(Arg),
{Si - 1, AA, <<Str/binary, A:64/integer-big>>};
(_, {Si, AA, Str}) ->
{Si - 1, AA, <<Str/binary, 0:64>>}
end,
{Size0, [], <<>>},
Args),
case NSize of
0 ->
do_pack(Context, Line, Rest0, NArgs, <<Binary/binary, String/binary>>);
_ ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, <<"J">>},
ephp_error:handle_error(Context, {error, efewargs, Line, File, ?E_WARNING, Data}),
false
end;
do_pack(Context, Line, <<"f*", Rest/binary>>, Args, Binary) ->
String =
lists:foldl(fun (Arg, S) when is_number(Arg) ->
<<S/binary, Arg:32/float-little>>;
(_, S) ->
<<S/binary, 0:32>>
end,
<<>>,
Args),
do_pack(Context, Line, Rest, [], <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<"f", Rest/binary>>, Args, Binary) ->
{Size0, Rest0} = get_numbers(Rest, 1),
{NSize, NArgs, String} =
lists:foldl(fun (Arg, {0, AA, Str}) ->
{0, AA ++ [Arg], Str};
(Arg, {Si, AA, Str}) when is_number(Arg) ->
Number = float(Arg),
{Si - 1, AA, <<Str/binary, Number:32/float-little>>};
(_, {Si, AA, Str}) ->
{Si - 1, AA, <<Str/binary, 0:32>>}
end,
{Size0, [], <<>>},
Args),
case NSize of
0 ->
do_pack(Context, Line, Rest0, NArgs, <<Binary/binary, String/binary>>);
_ ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, <<"f">>},
ephp_error:handle_error(Context, {error, efewargs, Line, File, ?E_WARNING, Data}),
false
end;
do_pack(Context, Line, <<"d*", Rest/binary>>, Args, Binary) ->
String =
lists:foldl(fun (Arg, S) when is_number(Arg) ->
<<S/binary, Arg:64/float-little>>;
(_, S) ->
<<S/binary, 0:64>>
end,
<<>>,
Args),
do_pack(Context, Line, Rest, [], <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<"d", Rest/binary>>, Args, Binary) ->
{Size0, Rest0} = get_numbers(Rest, 1),
{NSize, NArgs, String} =
lists:foldl(fun (Arg, {0, AA, Str}) ->
{0, AA ++ [Arg], Str};
(Arg, {Si, AA, Str}) when is_number(Arg) ->
Number = float(Arg),
{Si - 1, AA, <<Str/binary, Number:64/float-little>>};
(_, {Si, AA, Str}) ->
{Si - 1, AA, <<Str/binary, 0:64>>}
end,
{Size0, [], <<>>},
Args),
case NSize of
0 ->
do_pack(Context, Line, Rest0, NArgs, <<Binary/binary, String/binary>>);
_ ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, <<"d">>},
ephp_error:handle_error(Context, {error, efewargs, Line, File, ?E_WARNING, Data}),
false
end;
do_pack(Context, Line, <<"X*", Rest/binary>>, Args, <<>>) ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, <<"X">>},
ephp_error:handle_error(Context, {error, eoutstr, Line, File, ?E_WARNING, Data}),
do_pack(Context, Line, Rest, Args, <<>>);
do_pack(Context, Line, <<"X", Rest/binary>>, Args, <<>>) ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, <<"X">>},
ephp_error:handle_error(Context, {error, eoutstr, Line, File, ?E_WARNING, Data}),
do_pack(Context, Line, Rest, Args, <<>>);
do_pack(Context, Line, <<"X*", Rest/binary>>, Args, Binary) ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, <<"X">>, <<"*">>},
ephp_error:handle_error(Context, {error, ecmdignored, Line, File, ?E_WARNING, Data}),
do_pack(Context, Line, <<"X", Rest/binary>>, Args, Binary);
do_pack(Context, Line, <<"X", Rest/binary>>, Args, Binary) ->
{Size0, Rest0} = get_numbers(Rest, 1),
Result =
lists:foldl(fun (_, <<>>) ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, <<"X">>},
ephp_error:handle_error(Context,
{error, eoutstr, Line, File, ?E_WARNING, Data}),
undefined;
(_, undefined) ->
undefined;
(_, <<_:1/binary>>) ->
<<>>;
(_, B) ->
binary_part(B, {0, byte_size(Binary) - 1})
end,
Binary,
lists:seq(1, Size0)),
Binary0 =
if Result =:= undefined ->
<<>>;
true ->
Result
end,
do_pack(Context, Line, Rest0, Args, Binary0);
do_pack(Context, Line, <<"x*", Rest/binary>>, Args, Binary) ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, <<"x">>, <<"*">>},
ephp_error:handle_error(Context, {error, ecmdignored, Line, File, ?E_WARNING, Data}),
do_pack(Context, Line, Rest, Args, <<Binary/binary, 0:8>>);
do_pack(Context, Line, <<"x", Rest/binary>>, Args, Binary) ->
{Size0, Rest0} = get_numbers(Rest, 1),
String = ephp_string:repeat(Size0, 0),
do_pack(Context, Line, Rest0, Args, <<Binary/binary, String/binary>>);
do_pack(Context, Line, <<"Z*", Rest/binary>>, [Arg | Args], Binary) ->
String = ephp_data:to_bin(Arg),
do_pack(Context, Line, Rest, Args, <<Binary/binary, String/binary, 0:8>>);
do_pack(Context, Line, <<"Z", Rest/binary>>, [Arg | Args], Binary) ->
{Size0, Rest0} = get_numbers(Rest, 1),
String = ephp_data:to_bin(Arg),
Binary0 =
case Size0 - byte_size(String) of
_ when Size0 =:= 0 ->
Binary;
_ when Size0 =:= 1 ->
<<Binary/binary, 0:8>>;
N when N =< 0 ->
Size1 = Size0 - 1,
<<Binary/binary, String:Size1/binary, 0:8>>;
N when N > 0 ->
Nulls = ephp_string:repeat(N, 0),
<<Binary/binary, String/binary, Nulls/binary>>
end,
do_pack(Context, Line, Rest0, Args, Binary0);
do_pack(Context, Line, <<"@", Rest/binary>>, Args, Binary) ->
{Pos, Rest0} = get_numbers(Rest, 1),
Size = byte_size(Binary),
Binary0 =
if Size > Pos ->
binary_part(Binary, {0, Pos});
Size =:= Pos ->
Binary;
true ->
Pad = Pos - Size,
Nulls = ephp_string:repeat(Pad, 0),
<<Binary/binary, Nulls/binary>>
end,
do_pack(Context, Line, Rest0, Args, Binary0);
do_pack(Context, Line, <<C:1/binary, _/binary>>, _Args, _Binary) ->
File = ephp_context:get_active_file(Context),
Data = {<<"pack">>, C},
ephp_error:handle_error(Context, {error, eunknownfmt, Line, File, ?E_WARNING, Data}),
<<>>.
-spec get_numbers(binary(), integer()) -> {non_neg_integer(), binary()}.
%% @doc retrieve numbers from binary while it's possible.
get_numbers(Binary, Default) ->
get_numbers(Binary, <<>>, Default).
-spec get_numbers(binary(), binary(), integer()) -> {non_neg_integer(), binary()}.
%% @private
get_numbers(<<>>, <<>>, Default) ->
{Default, <<>>};
get_numbers(<<>>, Num, _Default) ->
{binary_to_integer(Num), <<>>};
get_numbers(<<A:8, Rest/binary>>, Num, Default) when A >= $0 andalso A =< $9 ->
get_numbers(Rest, <<Num/binary, A:8>>, Default);
get_numbers(Rest, <<>>, Default) ->
{Default, Rest};
get_numbers(Rest, Num, _Default) ->
{binary_to_integer(Num), Rest}.