|
@@ -30,10 +30,10 @@
|
|
|
%%--------------------------------------------------------------------------------
|
|
|
%% Exported API
|
|
|
%%--------------------------------------------------------------------------------
|
|
|
--export([decode/1]).
|
|
|
+-export([decode/1, decode/2]).
|
|
|
|
|
|
%%--------------------------------------------------------------------------------
|
|
|
-%% Macros & Types
|
|
|
+%% Macros & Records & Types
|
|
|
%%--------------------------------------------------------------------------------
|
|
|
-define(ERROR(Function, Args), {error, {badarg, [{?MODULE, Function, Args, [{line, ?LINE}]}]}}).
|
|
|
|
|
@@ -51,110 +51,120 @@
|
|
|
|
|
|
-type decode_result() :: {ok, jsone:json_value(), Rest::binary()} | {error, {Reason::term(), [erlang:stack_item()]}}.
|
|
|
|
|
|
+-record(decode_opt_v1, { format=eep18 :: eep18 | proplist}).
|
|
|
+-define(OPT, #decode_opt_v1).
|
|
|
+-type opt() :: #decode_opt_v1{}.
|
|
|
+
|
|
|
%%--------------------------------------------------------------------------------
|
|
|
%% Exported Functions
|
|
|
%%--------------------------------------------------------------------------------
|
|
|
-%% @doc Decodes an erlang term from json text (a utf8 encoded binary)
|
|
|
-spec decode(binary()) -> decode_result().
|
|
|
-decode(<<Json/binary>>) ->
|
|
|
- whitespace(Json, value, [], <<"">>).
|
|
|
+decode(Json) ->
|
|
|
+ decode(Json, []).
|
|
|
+
|
|
|
+-spec decode(binary(), [jsone:decode_option()]) -> decode_result().
|
|
|
+decode(<<Json/binary>>, Options) ->
|
|
|
+ Opt = parse_options(Options),
|
|
|
+ whitespace(Json, value, [], <<"">>, Opt).
|
|
|
|
|
|
%%--------------------------------------------------------------------------------
|
|
|
%% Internal Functions
|
|
|
%%--------------------------------------------------------------------------------
|
|
|
--spec next(binary(), jsone:json_value(), [next()], binary()) -> decode_result().
|
|
|
-next(<<Bin/binary>>, Value, [], _Buf) ->
|
|
|
+-spec next(binary(), jsone:json_value(), [next()], binary(), opt()) -> decode_result().
|
|
|
+next(<<Bin/binary>>, Value, [], _Buf, _Opt) ->
|
|
|
{ok, Value, Bin};
|
|
|
-next(<<Bin/binary>>, Value, [Next | Nexts], Buf) ->
|
|
|
+next(<<Bin/binary>>, Value, [Next | Nexts], Buf, Opt) ->
|
|
|
case Next of
|
|
|
- {array_next, Values} -> whitespace(Bin, {array_next, [Value | Values]}, Nexts, Buf);
|
|
|
- {object_value, Members} -> whitespace(Bin, {object_value, Value, Members}, Nexts, Buf);
|
|
|
- {object_next, Key, Members} -> whitespace(Bin, {object_next, [{Key, Value} | Members]}, Nexts, Buf)
|
|
|
+ {array_next, Values} -> whitespace(Bin, {array_next, [Value | Values]}, Nexts, Buf, Opt);
|
|
|
+ {object_value, Members} -> whitespace(Bin, {object_value, Value, Members}, Nexts, Buf, Opt);
|
|
|
+ {object_next, Key, Members} -> whitespace(Bin, {object_next, [{Key, Value} | Members]}, Nexts, Buf, Opt)
|
|
|
end.
|
|
|
|
|
|
--spec whitespace(binary(), whitespace_next(), [next()], binary()) -> decode_result().
|
|
|
-whitespace(<<$ , Bin/binary>>, Next, Nexts, Buf) -> whitespace(Bin, Next, Nexts, Buf);
|
|
|
-whitespace(<<$\t, Bin/binary>>, Next, Nexts, Buf) -> whitespace(Bin, Next, Nexts, Buf);
|
|
|
-whitespace(<<$\r, Bin/binary>>, Next, Nexts, Buf) -> whitespace(Bin, Next, Nexts, Buf);
|
|
|
-whitespace(<<$\n, Bin/binary>>, Next, Nexts, Buf) -> whitespace(Bin, Next, Nexts, Buf);
|
|
|
-whitespace(<<Bin/binary>>, Next, Nexts, Buf) ->
|
|
|
+-spec whitespace(binary(), whitespace_next(), [next()], binary(), opt()) -> decode_result().
|
|
|
+whitespace(<<$ , Bin/binary>>, Next, Nexts, Buf, Opt) -> whitespace(Bin, Next, Nexts, Buf, Opt);
|
|
|
+whitespace(<<$\t, Bin/binary>>, Next, Nexts, Buf, Opt) -> whitespace(Bin, Next, Nexts, Buf, Opt);
|
|
|
+whitespace(<<$\r, Bin/binary>>, Next, Nexts, Buf, Opt) -> whitespace(Bin, Next, Nexts, Buf, Opt);
|
|
|
+whitespace(<<$\n, Bin/binary>>, Next, Nexts, Buf, Opt) -> whitespace(Bin, Next, Nexts, Buf, Opt);
|
|
|
+whitespace(<<Bin/binary>>, Next, Nexts, Buf, Opt) ->
|
|
|
case Next of
|
|
|
- value -> value(Bin, Nexts, Buf);
|
|
|
- array -> array(Bin, Nexts, Buf);
|
|
|
- object -> object(Bin, Nexts, Buf);
|
|
|
- {object_key, Members} -> object_key(Bin, Members, Nexts, Buf);
|
|
|
- {array_next, Values} -> array_next(Bin, Values, Nexts, Buf);
|
|
|
- {object_value, Key, Members} -> object_value(Bin, Key, Members, Nexts, Buf);
|
|
|
- {object_next, Members} -> object_next(Bin, Members, Nexts, Buf)
|
|
|
+ value -> value(Bin, Nexts, Buf, Opt);
|
|
|
+ array -> array(Bin, Nexts, Buf, Opt);
|
|
|
+ object -> object(Bin, Nexts, Buf, Opt);
|
|
|
+ {object_key, Members} -> object_key(Bin, Members, Nexts, Buf, Opt);
|
|
|
+ {array_next, Values} -> array_next(Bin, Values, Nexts, Buf, Opt);
|
|
|
+ {object_value, Key, Members} -> object_value(Bin, Key, Members, Nexts, Buf, Opt);
|
|
|
+ {object_next, Members} -> object_next(Bin, Members, Nexts, Buf, Opt)
|
|
|
end.
|
|
|
|
|
|
--spec value(binary(), [next()], binary()) -> decode_result().
|
|
|
-value(<<"false", Bin/binary>>, Nexts, Buf) -> next(Bin, false, Nexts, Buf);
|
|
|
-value(<<"true", Bin/binary>>, Nexts, Buf) -> next(Bin, true, Nexts, Buf);
|
|
|
-value(<<"null", Bin/binary>>, Nexts, Buf) -> next(Bin, null, Nexts, Buf);
|
|
|
-value(<<$[, Bin/binary>>, Nexts, Buf) -> whitespace(Bin, array, Nexts, Buf);
|
|
|
-value(<<${, Bin/binary>>, Nexts, Buf) -> whitespace(Bin, object, Nexts, Buf);
|
|
|
-value(<<$", Bin/binary>>, Nexts, Buf) -> string(Bin, byte_size(Buf), Nexts, Buf);
|
|
|
-value(<<Bin/binary>>, Nexts, Buf) -> number(Bin, Nexts, Buf).
|
|
|
+-spec value(binary(), [next()], binary(), opt()) -> decode_result().
|
|
|
+value(<<"false", Bin/binary>>, Nexts, Buf, Opt) -> next(Bin, false, Nexts, Buf, Opt);
|
|
|
+value(<<"true", Bin/binary>>, Nexts, Buf, Opt) -> next(Bin, true, Nexts, Buf, Opt);
|
|
|
+value(<<"null", Bin/binary>>, Nexts, Buf, Opt) -> next(Bin, null, Nexts, Buf, Opt);
|
|
|
+value(<<$[, Bin/binary>>, Nexts, Buf, Opt) -> whitespace(Bin, array, Nexts, Buf, Opt);
|
|
|
+value(<<${, Bin/binary>>, Nexts, Buf, Opt) -> whitespace(Bin, object, Nexts, Buf, Opt);
|
|
|
+value(<<$", Bin/binary>>, Nexts, Buf, Opt) -> string(Bin, byte_size(Buf), Nexts, Buf, Opt);
|
|
|
+value(<<Bin/binary>>, Nexts, Buf, Opt) -> number(Bin, Nexts, Buf, Opt).
|
|
|
|
|
|
--spec array(binary(), [next()], binary()) -> decode_result().
|
|
|
-array(<<$], Bin/binary>>, Nexts, Buf) -> next(Bin, [], Nexts, Buf);
|
|
|
-array(<<Bin/binary>>, Nexts, Buf) -> value(Bin, [{array_next, []} | Nexts], Buf).
|
|
|
+-spec array(binary(), [next()], binary(), opt()) -> decode_result().
|
|
|
+array(<<$], Bin/binary>>, Nexts, Buf, Opt) -> next(Bin, [], Nexts, Buf, Opt);
|
|
|
+array(<<Bin/binary>>, Nexts, Buf, Opt) -> value(Bin, [{array_next, []} | Nexts], Buf, Opt).
|
|
|
|
|
|
--spec array_next(binary(), [jsone:json_value()], [next()], binary()) -> decode_result().
|
|
|
-array_next(<<$], Bin/binary>>, Values, Nexts, Buf) -> next(Bin, lists:reverse(Values), Nexts, Buf);
|
|
|
-array_next(<<$,, Bin/binary>>, Values, Nexts, Buf) -> whitespace(Bin, value, [{array_next, Values} | Nexts], Buf);
|
|
|
-array_next(Bin, Values, Nexts, Buf) -> ?ERROR(array_next, [Bin, Values, Nexts, Buf]).
|
|
|
+-spec array_next(binary(), [jsone:json_value()], [next()], binary(), opt()) -> decode_result().
|
|
|
+array_next(<<$], Bin/binary>>, Values, Nexts, Buf, Opt) -> next(Bin, lists:reverse(Values), Nexts, Buf, Opt);
|
|
|
+array_next(<<$,, Bin/binary>>, Values, Nexts, Buf, Opt) -> whitespace(Bin, value, [{array_next, Values} | Nexts], Buf, Opt);
|
|
|
+array_next(Bin, Values, Nexts, Buf, Opt) -> ?ERROR(array_next, [Bin, Values, Nexts, Buf, Opt]).
|
|
|
|
|
|
--spec object(binary(), [next()], binary()) -> decode_result().
|
|
|
-object(<<$}, Bin/binary>>, Nexts, Buf) -> next(Bin, {[]}, Nexts, Buf);
|
|
|
-object(<<Bin/binary>>, Nexts, Buf) -> object_key(Bin, [], Nexts, Buf).
|
|
|
+-spec object(binary(), [next()], binary(), opt()) -> decode_result().
|
|
|
+object(<<$}, Bin/binary>>, Nexts, Buf, Opt = ?OPT{format = proplist}) -> next(Bin, [{}], Nexts, Buf, Opt);
|
|
|
+object(<<$}, Bin/binary>>, Nexts, Buf, Opt) -> next(Bin, {[]}, Nexts, Buf, Opt);
|
|
|
+object(<<Bin/binary>>, Nexts, Buf, Opt) -> object_key(Bin, [], Nexts, Buf, Opt).
|
|
|
|
|
|
--spec object_key(binary(), jsone:json_object_members(), [next()], binary()) -> decode_result().
|
|
|
-object_key(<<$", Bin/binary>>, Members, Nexts, Buf) -> string(Bin, byte_size(Buf), [{object_value, Members} | Nexts], Buf);
|
|
|
-object_key(<<Bin/binary>>, Members, Nexts, Buf) -> ?ERROR(object_key, [Bin, Members, Nexts, Buf]).
|
|
|
+-spec object_key(binary(), jsone:json_object_members(), [next()], binary(), opt()) -> decode_result().
|
|
|
+object_key(<<$", Bin/binary>>, Members, Nexts, Buf, Opt) -> string(Bin, byte_size(Buf), [{object_value, Members} | Nexts], Buf, Opt);
|
|
|
+object_key(<<Bin/binary>>, Members, Nexts, Buf, Opt) -> ?ERROR(object_key, [Bin, Members, Nexts, Buf, Opt]).
|
|
|
|
|
|
--spec object_value(binary(), jsone:json_string(), jsone:json_object_members(), [next()], binary()) -> decode_result().
|
|
|
-object_value(<<$:, Bin/binary>>, Key, Members, Nexts, Buf) -> whitespace(Bin, value, [{object_next, Key, Members} | Nexts], Buf);
|
|
|
-object_value(Bin, Key, Members, Nexts, Buf) -> ?ERROR(object_value, [Bin, Key, Members, Nexts, Buf]).
|
|
|
+-spec object_value(binary(), jsone:json_string(), jsone:json_object_members(), [next()], binary(), opt()) -> decode_result().
|
|
|
+object_value(<<$:, Bin/binary>>, Key, Members, Nexts, Buf, Opt) -> whitespace(Bin, value, [{object_next, Key, Members} | Nexts], Buf, Opt);
|
|
|
+object_value(Bin, Key, Members, Nexts, Buf, Opt) -> ?ERROR(object_value, [Bin, Key, Members, Nexts, Buf, Opt]).
|
|
|
|
|
|
--spec object_next(binary(), jsone:json_object_members(), [next()], binary()) -> decode_result().
|
|
|
-object_next(<<$}, Bin/binary>>, Members, Nexts, Buf) -> next(Bin, {Members}, Nexts, Buf);
|
|
|
-object_next(<<$,, Bin/binary>>, Members, Nexts, Buf) -> whitespace(Bin, {object_key, Members}, Nexts, Buf);
|
|
|
-object_next(Bin, Members, Nexts, Buf) -> ?ERROR(object_next, [Bin, Members, Nexts, Buf]).
|
|
|
+-spec object_next(binary(), jsone:json_object_members(), [next()], binary(), opt()) -> decode_result().
|
|
|
+object_next(<<$}, Bin/binary>>, Members, Nexts, Buf, Opt = ?OPT{format = proplist}) -> next(Bin, Members, Nexts, Buf, Opt);
|
|
|
+object_next(<<$}, Bin/binary>>, Members, Nexts, Buf, Opt) -> next(Bin, {Members}, Nexts, Buf, Opt);
|
|
|
+object_next(<<$,, Bin/binary>>, Members, Nexts, Buf, Opt) -> whitespace(Bin, {object_key, Members}, Nexts, Buf, Opt);
|
|
|
+object_next(Bin, Members, Nexts, Buf, Opt) -> ?ERROR(object_next, [Bin, Members, Nexts, Buf, Opt]).
|
|
|
|
|
|
--spec string(binary(), non_neg_integer(), [next()], binary()) -> decode_result().
|
|
|
-string(<<Bin/binary>>, Start, Nexts, Buf) ->
|
|
|
- string(Bin, Bin, Start, Nexts, Buf).
|
|
|
+-spec string(binary(), non_neg_integer(), [next()], binary(), opt()) -> decode_result().
|
|
|
+string(<<Bin/binary>>, Start, Nexts, Buf, Opt) ->
|
|
|
+ string(Bin, Bin, Start, Nexts, Buf, Opt).
|
|
|
|
|
|
--spec string(binary(), binary(), non_neg_integer(), [next()], binary()) -> decode_result().
|
|
|
-string(<<$", Bin/binary>>, Base, Start, Nexts, Buf) ->
|
|
|
+-spec string(binary(), binary(), non_neg_integer(), [next()], binary(), opt()) -> decode_result().
|
|
|
+string(<<$", Bin/binary>>, Base, Start, Nexts, Buf, Opt) ->
|
|
|
Prefix = binary:part(Base, 0, byte_size(Base) - byte_size(Bin) - 1),
|
|
|
case Start =:= byte_size(Buf) of
|
|
|
- true -> next(Bin, Prefix, Nexts, Buf);
|
|
|
+ true -> next(Bin, Prefix, Nexts, Buf, Opt);
|
|
|
false ->
|
|
|
Buf2 = <<Buf/binary, Prefix/binary>>,
|
|
|
- next(Bin, binary:part(Buf2, Start, byte_size(Buf2) - Start), Nexts, Buf2)
|
|
|
+ next(Bin, binary:part(Buf2, Start, byte_size(Buf2) - Start), Nexts, Buf2, Opt)
|
|
|
end;
|
|
|
-string(<<$\\, B/binary>>, Base, Start, Nexts, Buf) ->
|
|
|
+string(<<$\\, B/binary>>, Base, Start, Nexts, Buf, Opt) ->
|
|
|
Prefix = binary:part(Base, 0, byte_size(Base) - byte_size(B) - 1),
|
|
|
case B of
|
|
|
- <<$", Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $">>);
|
|
|
- <<$/, Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $/>>);
|
|
|
- <<$\\,Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $\\>>);
|
|
|
- <<$b, Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $\b>>);
|
|
|
- <<$f, Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $\f>>);
|
|
|
- <<$n, Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $\n>>);
|
|
|
- <<$r, Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $\r>>);
|
|
|
- <<$t, Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $\t>>);
|
|
|
- <<$u, Bin/binary>> -> unicode_string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary>>);
|
|
|
- _ -> ?ERROR(string, [<<$\\, B/binary>>, Base, Start, Nexts, Buf])
|
|
|
+ <<$", Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $">>, Opt);
|
|
|
+ <<$/, Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $/>>, Opt);
|
|
|
+ <<$\\,Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $\\>>, Opt);
|
|
|
+ <<$b, Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $\b>>, Opt);
|
|
|
+ <<$f, Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $\f>>, Opt);
|
|
|
+ <<$n, Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $\n>>, Opt);
|
|
|
+ <<$r, Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $\r>>, Opt);
|
|
|
+ <<$t, Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary, $\t>>, Opt);
|
|
|
+ <<$u, Bin/binary>> -> unicode_string(Bin, Start, Nexts, <<Buf/binary, Prefix/binary>>, Opt);
|
|
|
+ _ -> ?ERROR(string, [<<$\\, B/binary>>, Base, Start, Nexts, Buf, Opt])
|
|
|
end;
|
|
|
-string(<<C, Bin/binary>>, Base, Start, Nexts, Buf) when 16#20 =< C ->
|
|
|
- string(Bin, Base, Start, Nexts, Buf).
|
|
|
+string(<<C, Bin/binary>>, Base, Start, Nexts, Buf, Opt) when 16#20 =< C ->
|
|
|
+ string(Bin, Base, Start, Nexts, Buf, Opt).
|
|
|
|
|
|
--spec unicode_string(binary(), non_neg_integer(), [next()], binary()) -> decode_result().
|
|
|
-unicode_string(<<N:4/binary, Bin/binary>>, Start, Nexts, Buf) ->
|
|
|
+-spec unicode_string(binary(), non_neg_integer(), [next()], binary(), opt()) -> decode_result().
|
|
|
+unicode_string(<<N:4/binary, Bin/binary>>, Start, Nexts, Buf, Opt) ->
|
|
|
case binary_to_integer(N, 16) of
|
|
|
High when 16#D800 =< High, High =< 16#DBFF ->
|
|
|
%% surrogate pair
|
|
@@ -163,18 +173,18 @@ unicode_string(<<N:4/binary, Bin/binary>>, Start, Nexts, Buf) ->
|
|
|
case binary_to_integer(N2, 16) of
|
|
|
Low when 16#DC00 =< Low, Low =< 16#DFFF ->
|
|
|
Unicode = 16#10000 + (High - 16#D800) * 16#400 + (Low - 16#DC00),
|
|
|
- string(Bin2, Start, Nexts, unicode_to_utf8(Unicode, Buf));
|
|
|
- _ -> ?ERROR(unicode_string, [<<N/binary, Bin/binary>>, Start, Nexts, Buf])
|
|
|
+ string(Bin2, Start, Nexts, unicode_to_utf8(Unicode, Buf), Opt);
|
|
|
+ _ -> ?ERROR(unicode_string, [<<N/binary, Bin/binary>>, Start, Nexts, Buf, Opt])
|
|
|
end;
|
|
|
- _ -> ?ERROR(unicode_string, [<<N/binary, Bin/binary>>, Start, Nexts, Buf])
|
|
|
+ _ -> ?ERROR(unicode_string, [<<N/binary, Bin/binary>>, Start, Nexts, Buf, Opt])
|
|
|
end;
|
|
|
Unicode when 16#DC00 =< Unicode, Unicode =< 16#DFFF -> % second part of surrogate pair (without first part)
|
|
|
- ?ERROR(unicode_string, [<<N/binary, Bin/binary>>, Start, Nexts, Buf]);
|
|
|
- Unicode ->
|
|
|
- string(Bin, Start, Nexts, unicode_to_utf8(Unicode, Buf))
|
|
|
+ ?ERROR(unicode_string, [<<N/binary, Bin/binary>>, Start, Nexts, Buf, Opt]);
|
|
|
+ Unicode ->
|
|
|
+ string(Bin, Start, Nexts, unicode_to_utf8(Unicode, Buf), Opt)
|
|
|
end;
|
|
|
-unicode_string(Bin, Start, Nexts, Buf) ->
|
|
|
- ?ERROR(unicode_string, [Bin, Start, Nexts, Buf]).
|
|
|
+unicode_string(Bin, Start, Nexts, Buf, Opt) ->
|
|
|
+ ?ERROR(unicode_string, [Bin, Start, Nexts, Buf, Opt]).
|
|
|
|
|
|
-spec unicode_to_utf8(0..1114111, binary()) -> binary().
|
|
|
unicode_to_utf8(Code, Buf) when Code < 16#80 ->
|
|
@@ -195,62 +205,71 @@ unicode_to_utf8(Code, Buf) ->
|
|
|
D = 2#10000000 bor (Code band 2#111111),
|
|
|
<<Buf/binary, A, B, C, D>>.
|
|
|
|
|
|
--spec number(binary(), [next()], binary()) -> decode_result().
|
|
|
-number(<<$-, Bin/binary>>, Nexts, Buf) -> number_integer_part(Bin, -1, Nexts, Buf);
|
|
|
-number(<<Bin/binary>>, Nexts, Buf) -> number_integer_part(Bin, 1, Nexts, Buf).
|
|
|
+-spec number(binary(), [next()], binary(), opt()) -> decode_result().
|
|
|
+number(<<$-, Bin/binary>>, Nexts, Buf, Opt) -> number_integer_part(Bin, -1, Nexts, Buf, Opt);
|
|
|
+number(<<Bin/binary>>, Nexts, Buf, Opt) -> number_integer_part(Bin, 1, Nexts, Buf, Opt).
|
|
|
|
|
|
--spec number_integer_part(binary(), 1|-1, [next()], binary()) -> decode_result().
|
|
|
-number_integer_part(<<$0, Bin/binary>>, Sign, Nexts, Buf) ->
|
|
|
- number_fraction_part(Bin, Sign, 0, Nexts, Buf);
|
|
|
-number_integer_part(<<C, Bin/binary>>, Sign, Nexts, Buf) when $1 =< C, C =< $9 ->
|
|
|
- number_integer_part_rest(Bin, C - $0, Sign, Nexts, Buf);
|
|
|
-number_integer_part(Bin, Sign, Nexts, Buf) ->
|
|
|
- ?ERROR(number_integer_part, [Bin, Sign, Nexts, Buf]).
|
|
|
+-spec number_integer_part(binary(), 1|-1, [next()], binary(), opt()) -> decode_result().
|
|
|
+number_integer_part(<<$0, Bin/binary>>, Sign, Nexts, Buf, Opt) ->
|
|
|
+ number_fraction_part(Bin, Sign, 0, Nexts, Buf, Opt);
|
|
|
+number_integer_part(<<C, Bin/binary>>, Sign, Nexts, Buf, Opt) when $1 =< C, C =< $9 ->
|
|
|
+ number_integer_part_rest(Bin, C - $0, Sign, Nexts, Buf, Opt);
|
|
|
+number_integer_part(Bin, Sign, Nexts, Buf, Opt) ->
|
|
|
+ ?ERROR(number_integer_part, [Bin, Sign, Nexts, Buf, Opt]).
|
|
|
|
|
|
--spec number_integer_part_rest(binary(), non_neg_integer(), 1|-1, [next()], binary()) -> decode_result().
|
|
|
-number_integer_part_rest(<<C, Bin/binary>>, N, Sign, Nexts, Buf) when $0 =< C, C =< $9 ->
|
|
|
- number_integer_part_rest(Bin, N * 10 + C - $0, Sign, Nexts, Buf);
|
|
|
-number_integer_part_rest(<<Bin/binary>>, N, Sign, Nexts, Buf) ->
|
|
|
- number_fraction_part(Bin, Sign, N, Nexts, Buf).
|
|
|
+-spec number_integer_part_rest(binary(), non_neg_integer(), 1|-1, [next()], binary(), opt()) -> decode_result().
|
|
|
+number_integer_part_rest(<<C, Bin/binary>>, N, Sign, Nexts, Buf, Opt) when $0 =< C, C =< $9 ->
|
|
|
+ number_integer_part_rest(Bin, N * 10 + C - $0, Sign, Nexts, Buf, Opt);
|
|
|
+number_integer_part_rest(<<Bin/binary>>, N, Sign, Nexts, Buf, Opt) ->
|
|
|
+ number_fraction_part(Bin, Sign, N, Nexts, Buf, Opt).
|
|
|
|
|
|
--spec number_fraction_part(binary(), 1|-1, non_neg_integer(), [next()], binary()) -> decode_result().
|
|
|
-number_fraction_part(<<$., Bin/binary>>, Sign, Int, Nexts, Buf) ->
|
|
|
- number_fraction_part_rest(Bin, Sign, Int, 0, Nexts, Buf);
|
|
|
-number_fraction_part(<<Bin/binary>>, Sign, Int, Nexts, Buf) ->
|
|
|
- number_exponation_part(Bin, Sign * Int, 0, Nexts, Buf).
|
|
|
+-spec number_fraction_part(binary(), 1|-1, non_neg_integer(), [next()], binary(), opt()) -> decode_result().
|
|
|
+number_fraction_part(<<$., Bin/binary>>, Sign, Int, Nexts, Buf, Opt) ->
|
|
|
+ number_fraction_part_rest(Bin, Sign, Int, 0, Nexts, Buf, Opt);
|
|
|
+number_fraction_part(<<Bin/binary>>, Sign, Int, Nexts, Buf, Opt) ->
|
|
|
+ number_exponation_part(Bin, Sign * Int, 0, Nexts, Buf, Opt).
|
|
|
|
|
|
--spec number_fraction_part_rest(binary(), 1|-1, non_neg_integer(), non_neg_integer(), [next()], binary()) -> decode_result().
|
|
|
-number_fraction_part_rest(<<C, Bin/binary>>, Sign, N, DecimalOffset, Nexts, Buf) when $0 =< C, C =< $9 ->
|
|
|
- number_fraction_part_rest(Bin, Sign, N * 10 + C - $0, DecimalOffset + 1, Nexts, Buf);
|
|
|
-number_fraction_part_rest(<<Bin/binary>>, Sign, N, DecimalOffset, Nexts, Buf) when DecimalOffset > 0 ->
|
|
|
- number_exponation_part(Bin, Sign * N, DecimalOffset, Nexts, Buf);
|
|
|
-number_fraction_part_rest(Bin, Sign, N, DecimalOffset, Nexts, Buf) ->
|
|
|
- ?ERROR(number_fraction_part_rest, [Bin, Sign, N, DecimalOffset, Nexts, Buf]).
|
|
|
+-spec number_fraction_part_rest(binary(), 1|-1, non_neg_integer(), non_neg_integer(), [next()], binary(), opt()) -> decode_result().
|
|
|
+number_fraction_part_rest(<<C, Bin/binary>>, Sign, N, DecimalOffset, Nexts, Buf, Opt) when $0 =< C, C =< $9 ->
|
|
|
+ number_fraction_part_rest(Bin, Sign, N * 10 + C - $0, DecimalOffset + 1, Nexts, Buf, Opt);
|
|
|
+number_fraction_part_rest(<<Bin/binary>>, Sign, N, DecimalOffset, Nexts, Buf, Opt) when DecimalOffset > 0 ->
|
|
|
+ number_exponation_part(Bin, Sign * N, DecimalOffset, Nexts, Buf, Opt);
|
|
|
+number_fraction_part_rest(Bin, Sign, N, DecimalOffset, Nexts, Buf, Opt) ->
|
|
|
+ ?ERROR(number_fraction_part_rest, [Bin, Sign, N, DecimalOffset, Nexts, Buf, Opt]).
|
|
|
|
|
|
--spec number_exponation_part(binary(), integer(), non_neg_integer(), [next()], binary()) -> decode_result().
|
|
|
-number_exponation_part(<<$e, $+, Bin/binary>>, N, DecimalOffset, Nexts, Buf) ->
|
|
|
- number_exponation_part(Bin, N, DecimalOffset, 1, 0, true, Nexts, Buf);
|
|
|
-number_exponation_part(<<$E, $+, Bin/binary>>, N, DecimalOffset, Nexts, Buf) ->
|
|
|
- number_exponation_part(Bin, N, DecimalOffset, 1, 0, true, Nexts, Buf);
|
|
|
-number_exponation_part(<<$e, $-, Bin/binary>>, N, DecimalOffset, Nexts, Buf) ->
|
|
|
- number_exponation_part(Bin, N, DecimalOffset, -1, 0, true, Nexts, Buf);
|
|
|
-number_exponation_part(<<$E, $-, Bin/binary>>, N, DecimalOffset, Nexts, Buf) ->
|
|
|
- number_exponation_part(Bin, N, DecimalOffset, -1, 0, true, Nexts, Buf);
|
|
|
-number_exponation_part(<<$e, Bin/binary>>, N, DecimalOffset, Nexts, Buf) ->
|
|
|
- number_exponation_part(Bin, N, DecimalOffset, 1, 0, true, Nexts, Buf);
|
|
|
-number_exponation_part(<<$E, Bin/binary>>, N, DecimalOffset, Nexts, Buf) ->
|
|
|
- number_exponation_part(Bin, N, DecimalOffset, 1, 0, true, Nexts, Buf);
|
|
|
-number_exponation_part(<<Bin/binary>>, N, DecimalOffset, Nexts, Buf) ->
|
|
|
+-spec number_exponation_part(binary(), integer(), non_neg_integer(), [next()], binary(), opt()) -> decode_result().
|
|
|
+number_exponation_part(<<$e, $+, Bin/binary>>, N, DecimalOffset, Nexts, Buf, Opt) ->
|
|
|
+ number_exponation_part(Bin, N, DecimalOffset, 1, 0, true, Nexts, Buf, Opt);
|
|
|
+number_exponation_part(<<$E, $+, Bin/binary>>, N, DecimalOffset, Nexts, Buf, Opt) ->
|
|
|
+ number_exponation_part(Bin, N, DecimalOffset, 1, 0, true, Nexts, Buf, Opt);
|
|
|
+number_exponation_part(<<$e, $-, Bin/binary>>, N, DecimalOffset, Nexts, Buf, Opt) ->
|
|
|
+ number_exponation_part(Bin, N, DecimalOffset, -1, 0, true, Nexts, Buf, Opt);
|
|
|
+number_exponation_part(<<$E, $-, Bin/binary>>, N, DecimalOffset, Nexts, Buf, Opt) ->
|
|
|
+ number_exponation_part(Bin, N, DecimalOffset, -1, 0, true, Nexts, Buf, Opt);
|
|
|
+number_exponation_part(<<$e, Bin/binary>>, N, DecimalOffset, Nexts, Buf, Opt) ->
|
|
|
+ number_exponation_part(Bin, N, DecimalOffset, 1, 0, true, Nexts, Buf, Opt);
|
|
|
+number_exponation_part(<<$E, Bin/binary>>, N, DecimalOffset, Nexts, Buf, Opt) ->
|
|
|
+ number_exponation_part(Bin, N, DecimalOffset, 1, 0, true, Nexts, Buf, Opt);
|
|
|
+number_exponation_part(<<Bin/binary>>, N, DecimalOffset, Nexts, Buf, Opt) ->
|
|
|
case DecimalOffset of
|
|
|
- 0 -> next(Bin, N, Nexts, Buf);
|
|
|
- _ -> next(Bin, N / math:pow(10, DecimalOffset), Nexts, Buf)
|
|
|
+ 0 -> next(Bin, N, Nexts, Buf, Opt);
|
|
|
+ _ -> next(Bin, N / math:pow(10, DecimalOffset), Nexts, Buf, Opt)
|
|
|
end.
|
|
|
|
|
|
--spec number_exponation_part(binary(), integer(), non_neg_integer(), 1|-1, non_neg_integer(), boolean(), [next()], binary()) -> decode_result().
|
|
|
-number_exponation_part(<<C, Bin/binary>>, N, DecimalOffset, ExpSign, Exp, _, Nexts, Buf) when $0 =< C, C =< $9 ->
|
|
|
- number_exponation_part(Bin, N, DecimalOffset, ExpSign, Exp * 10 + C - $0, false, Nexts, Buf);
|
|
|
-number_exponation_part(<<Bin/binary>>, N, DecimalOffset, ExpSign, Exp, false, Nexts, Buf) ->
|
|
|
+-spec number_exponation_part(binary(), integer(), non_neg_integer(), 1|-1, non_neg_integer(), boolean(), [next()], binary(), opt()) -> decode_result().
|
|
|
+number_exponation_part(<<C, Bin/binary>>, N, DecimalOffset, ExpSign, Exp, _, Nexts, Buf, Opt) when $0 =< C, C =< $9 ->
|
|
|
+ number_exponation_part(Bin, N, DecimalOffset, ExpSign, Exp * 10 + C - $0, false, Nexts, Buf, Opt);
|
|
|
+number_exponation_part(<<Bin/binary>>, N, DecimalOffset, ExpSign, Exp, false, Nexts, Buf, Opt) ->
|
|
|
Pos = ExpSign * Exp - DecimalOffset,
|
|
|
- next(Bin, N * math:pow(10, Pos), Nexts, Buf);
|
|
|
-number_exponation_part(Bin, N, DecimalOffset, ExpSign, Exp, IsFirst, Nexts, Buf) ->
|
|
|
- ?ERROR(number_exponation_part, [Bin, N, DecimalOffset, ExpSign, Exp, IsFirst, Nexts, Buf]).
|
|
|
+ next(Bin, N * math:pow(10, Pos), Nexts, Buf, Opt);
|
|
|
+number_exponation_part(Bin, N, DecimalOffset, ExpSign, Exp, IsFirst, Nexts, Buf, Opt) ->
|
|
|
+ ?ERROR(number_exponation_part, [Bin, N, DecimalOffset, ExpSign, Exp, IsFirst, Nexts, Buf, Opt]).
|
|
|
+
|
|
|
+-spec parse_options([jsone:decode_option()]) -> opt().
|
|
|
+parse_options(Options) ->
|
|
|
+ parse_option(Options, ?OPT{}).
|
|
|
+
|
|
|
+-spec parse_option([jsone:decode_option()], opt()) -> opt().
|
|
|
+parse_option([], Opt) -> Opt;
|
|
|
+parse_option([{format,F}|T], Opt) ->
|
|
|
+ parse_option(T, Opt?OPT{format=F}).
|