2010-08-10 11:05:40 -07:00
|
|
|
-file("priv/jsx_decoder_template.erl", 1).
|
2010-08-04 22:24:50 -07:00
|
|
|
|
2010-08-19 23:30:22 -07:00
|
|
|
|
|
|
|
%% @hidden hide this module from edoc, exported functions are internal to jsx
|
|
|
|
%% and may be altered or removed without notice
|
|
|
|
|
|
|
|
|
2010-08-04 22:24:50 -07:00
|
|
|
-module(jsx_utf16le).
|
|
|
|
|
|
|
|
-author("alisdairsullivan@yahoo.ca").
|
|
|
|
|
|
|
|
-export([parse/2]).
|
|
|
|
|
|
|
|
-file("./include/jsx_decoder.hrl", 1).
|
|
|
|
|
2010-08-19 18:22:34 -07:00
|
|
|
-file("./include/jsx_common.hrl", 1).
|
2010-08-04 22:24:50 -07:00
|
|
|
|
|
|
|
-type jsx_opts() :: [jsx_opt()].
|
|
|
|
|
|
|
|
-type jsx_opt() :: {comments, true | false}
|
|
|
|
| {escaped_unicode, ascii | codepoint | none}
|
|
|
|
| {multi_term, true | false}
|
|
|
|
| {encoding,
|
|
|
|
auto |
|
|
|
|
utf8 |
|
|
|
|
utf16 |
|
|
|
|
{utf16, little} |
|
|
|
|
utf32 |
|
|
|
|
{utf32, little}}.
|
|
|
|
|
|
|
|
-type unicode_codepoint() :: 0..1114111.
|
|
|
|
|
|
|
|
-type unicode_string() :: [unicode_codepoint()].
|
|
|
|
|
|
|
|
-type jsx_event() :: start_object
|
|
|
|
| end_object
|
|
|
|
| start_array
|
|
|
|
| end_array
|
|
|
|
| end_json
|
|
|
|
| {key, unicode_string()}
|
|
|
|
| {string, unicode_string()}
|
|
|
|
| {integer, unicode_string()}
|
|
|
|
| {float, unicode_string()}
|
|
|
|
| {literal, true}
|
|
|
|
| {literal, false}
|
|
|
|
| {literal, null}.
|
|
|
|
|
|
|
|
-type jsx_parser() :: fun((binary()) -> jsx_parser_result()).
|
|
|
|
|
|
|
|
-type jsx_parser_result() :: {event,
|
|
|
|
jsx_event(),
|
|
|
|
fun(() -> jsx_parser_result())}
|
|
|
|
| {incomplete, jsx_parser()}
|
|
|
|
| {error, badjson}
|
|
|
|
| ok.
|
|
|
|
|
2010-08-19 18:22:34 -07:00
|
|
|
-type supported_utf() :: utf8
|
|
|
|
| utf16
|
|
|
|
| {utf16, little}
|
|
|
|
| utf32
|
|
|
|
| {utf32, little}.
|
|
|
|
|
2010-08-12 21:32:03 -07:00
|
|
|
-type eep0018() :: eep0018_object() | eep0018_array().
|
2010-08-04 22:24:50 -07:00
|
|
|
|
2010-08-12 21:32:03 -07:00
|
|
|
-type eep0018_array() :: [eep0018_term()].
|
2010-08-04 22:24:50 -07:00
|
|
|
|
2010-08-12 21:32:03 -07:00
|
|
|
-type eep0018_object() :: [{eep0018_key(), eep0018_term()}].
|
2010-08-04 22:24:50 -07:00
|
|
|
|
2010-08-12 21:32:03 -07:00
|
|
|
-type eep0018_key() :: binary() | atom().
|
2010-08-04 22:24:50 -07:00
|
|
|
|
2010-08-12 21:32:03 -07:00
|
|
|
-type eep0018_term() :: eep0018_array()
|
|
|
|
| eep0018_object()
|
|
|
|
| eep0018_string()
|
|
|
|
| eep0018_number()
|
|
|
|
| true
|
|
|
|
| false
|
|
|
|
| null.
|
2010-08-04 22:24:50 -07:00
|
|
|
|
2010-08-12 21:32:03 -07:00
|
|
|
-type eep0018_string() :: binary().
|
2010-08-04 22:24:50 -07:00
|
|
|
|
2010-08-12 21:32:03 -07:00
|
|
|
-type eep0018_number() :: float() | integer().
|
2010-08-04 22:24:50 -07:00
|
|
|
|
|
|
|
-type encoder_opts() :: [encoder_opt()].
|
|
|
|
|
|
|
|
-type encoder_opt() :: {strict, true | false}
|
2010-08-12 21:32:03 -07:00
|
|
|
| {encoding, supported_utf()}
|
2010-08-04 22:24:50 -07:00
|
|
|
| {space, integer()}
|
|
|
|
| space
|
|
|
|
| {indent, integer()}
|
|
|
|
| indent.
|
|
|
|
|
|
|
|
-type decoder_opts() :: [decoder_opt()].
|
|
|
|
|
|
|
|
-type decoder_opt() :: {strict, true | false}
|
|
|
|
| {comments, true | false}
|
|
|
|
| {encoding, supported_utf()}
|
|
|
|
| {label, atom | binary | existing_atom}
|
|
|
|
| {float, true | false}.
|
|
|
|
|
|
|
|
-type verify_opts() :: [verify_opt()].
|
|
|
|
|
|
|
|
-type verify_opt() :: {strict, true | false}
|
|
|
|
| {encoding, auto | supported_utf()}
|
|
|
|
| {comments, true | false}.
|
|
|
|
|
|
|
|
-type format_opts() :: [format_opt()].
|
|
|
|
|
|
|
|
-type format_opt() :: {strict, true | false}
|
|
|
|
| {encoding, auto | supported_utf()}
|
|
|
|
| {comments, true | false}
|
|
|
|
| {space, integer()}
|
|
|
|
| space
|
|
|
|
| {indent, integer()}
|
|
|
|
| indent
|
|
|
|
| {output_encoding, supported_utf()}.
|
|
|
|
|
2010-08-19 18:22:34 -07:00
|
|
|
-file("./include/jsx_decoder.hrl", 24).
|
2010-08-04 22:24:50 -07:00
|
|
|
|
2010-08-12 21:32:03 -07:00
|
|
|
-spec parse(JSON :: eep0018(), Opts :: jsx_opts()) ->
|
|
|
|
jsx_parser_result().
|
2010-08-04 22:24:50 -07:00
|
|
|
|
2010-08-19 18:22:34 -07:00
|
|
|
-file("priv/jsx_decoder_template.erl", 35).
|
|
|
|
|
2010-08-04 22:24:50 -07:00
|
|
|
parse(JSON, Opts) ->
|
|
|
|
start(JSON, [], Opts).
|
|
|
|
|
|
|
|
start(<<S/utf16-little,Rest/binary>>, Stack, Opts)
|
|
|
|
when S =:= 32; S =:= 9; S =:= 13; S =:= 10 ->
|
|
|
|
start(Rest, Stack, Opts);
|
|
|
|
start(<<123/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
{event,
|
|
|
|
start_object,
|
|
|
|
fun() ->
|
|
|
|
object(Rest, [key|Stack], Opts)
|
|
|
|
end};
|
|
|
|
start(<<91/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
{event,
|
|
|
|
start_array,
|
|
|
|
fun() ->
|
|
|
|
array(Rest, [array|Stack], Opts)
|
|
|
|
end};
|
|
|
|
start(<<34/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
string(Rest, Stack, Opts, []);
|
|
|
|
start(<<$t/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
tr(Rest, Stack, Opts);
|
|
|
|
start(<<$f/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
fa(Rest, Stack, Opts);
|
|
|
|
start(<<$n/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
nu(Rest, Stack, Opts);
|
|
|
|
start(<<45/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
negative(Rest, Stack, Opts, "-");
|
|
|
|
start(<<48/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
zero(Rest, Stack, Opts, "0");
|
|
|
|
start(<<S/utf16-little,Rest/binary>>, Stack, Opts)
|
|
|
|
when
|
|
|
|
S >= $1
|
|
|
|
andalso
|
|
|
|
S =< $9 ->
|
|
|
|
integer(Rest, Stack, Opts, [S]);
|
|
|
|
start(<<47/utf16-little,Rest/binary>>, Stack, {_,true,_,_,_} = Opts) ->
|
|
|
|
maybe_comment(Rest,
|
|
|
|
fun(Resume) ->
|
|
|
|
start(Resume, Stack, Opts)
|
|
|
|
end);
|
|
|
|
start(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
start(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
maybe_done(<<S/utf16-little,Rest/binary>>, Stack, Opts)
|
|
|
|
when S =:= 32; S =:= 9; S =:= 13; S =:= 10 ->
|
|
|
|
maybe_done(Rest, Stack, Opts);
|
|
|
|
maybe_done(<<125/utf16-little,Rest/binary>>, [object|Stack], Opts) ->
|
|
|
|
{event,
|
|
|
|
end_object,
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
maybe_done(<<93/utf16-little,Rest/binary>>, [array|Stack], Opts) ->
|
|
|
|
{event,
|
|
|
|
end_array,
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
maybe_done(<<44/utf16-little,Rest/binary>>, [object|Stack], Opts) ->
|
|
|
|
key(Rest, [key|Stack], Opts);
|
|
|
|
maybe_done(<<44/utf16-little,Rest/binary>>, [array|_] = Stack, Opts) ->
|
|
|
|
value(Rest, Stack, Opts);
|
|
|
|
maybe_done(<<47/utf16-little,Rest/binary>>,
|
|
|
|
Stack,
|
|
|
|
{_,true,_,_,_} = Opts) ->
|
|
|
|
maybe_comment(Rest,
|
|
|
|
fun(Resume) ->
|
|
|
|
maybe_done(Resume, Stack, Opts)
|
|
|
|
end);
|
|
|
|
maybe_done(Rest, [], {_,_,_,true,_} = Opts) ->
|
|
|
|
{event,
|
|
|
|
end_json,
|
|
|
|
fun() ->
|
|
|
|
start(Rest, [], Opts)
|
|
|
|
end};
|
|
|
|
maybe_done(Rest, [], Opts) ->
|
|
|
|
done(Rest, Opts);
|
|
|
|
maybe_done(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
maybe_done(<<Bin/binary,Stream/binary>>,
|
|
|
|
Stack,
|
|
|
|
Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
done(<<S/utf16-little,Rest/binary>>, Opts)
|
|
|
|
when S =:= 32; S =:= 9; S =:= 13; S =:= 10 ->
|
|
|
|
done(Rest, Opts);
|
|
|
|
done(<<47/utf16-little,Rest/binary>>, {_,true,_,_,_} = Opts) ->
|
|
|
|
maybe_comment(Rest,
|
|
|
|
fun(Resume) ->
|
|
|
|
done(Resume, Opts)
|
|
|
|
end);
|
|
|
|
done(<<>>, Opts) ->
|
|
|
|
{event,
|
|
|
|
end_json,
|
|
|
|
fun() ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
2010-08-12 21:32:03 -07:00
|
|
|
{error,badjson};
|
2010-08-04 22:24:50 -07:00
|
|
|
(Stream) ->
|
|
|
|
done(Stream, Opts)
|
|
|
|
end}
|
|
|
|
end};
|
|
|
|
done(Bin, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
done(<<Bin/binary,Stream/binary>>, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
object(<<S/utf16-little,Rest/binary>>, Stack, Opts)
|
|
|
|
when S =:= 32; S =:= 9; S =:= 13; S =:= 10 ->
|
|
|
|
object(Rest, Stack, Opts);
|
|
|
|
object(<<34/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
string(Rest, Stack, Opts, []);
|
|
|
|
object(<<125/utf16-little,Rest/binary>>, [key|Stack], Opts) ->
|
|
|
|
{event,
|
|
|
|
end_object,
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
object(<<47/utf16-little,Rest/binary>>, Stack, {_,true,_,_,_} = Opts) ->
|
|
|
|
maybe_comment(Rest,
|
|
|
|
fun(Resume) ->
|
|
|
|
object(Resume, Stack, Opts)
|
|
|
|
end);
|
|
|
|
object(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
object(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
array(<<S/utf16-little,Rest/binary>>, Stack, Opts)
|
|
|
|
when S =:= 32; S =:= 9; S =:= 13; S =:= 10 ->
|
|
|
|
array(Rest, Stack, Opts);
|
|
|
|
array(<<34/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
string(Rest, Stack, Opts, []);
|
|
|
|
array(<<$t/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
tr(Rest, Stack, Opts);
|
|
|
|
array(<<$f/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
fa(Rest, Stack, Opts);
|
|
|
|
array(<<$n/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
nu(Rest, Stack, Opts);
|
|
|
|
array(<<45/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
negative(Rest, Stack, Opts, "-");
|
|
|
|
array(<<48/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
zero(Rest, Stack, Opts, "0");
|
|
|
|
array(<<S/utf16-little,Rest/binary>>, Stack, Opts)
|
|
|
|
when
|
|
|
|
S >= $1
|
|
|
|
andalso
|
|
|
|
S =< $9 ->
|
|
|
|
integer(Rest, Stack, Opts, [S]);
|
|
|
|
array(<<123/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
{event,
|
|
|
|
start_object,
|
|
|
|
fun() ->
|
|
|
|
object(Rest, [key|Stack], Opts)
|
|
|
|
end};
|
|
|
|
array(<<91/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
{event,
|
|
|
|
start_array,
|
|
|
|
fun() ->
|
|
|
|
array(Rest, [array|Stack], Opts)
|
|
|
|
end};
|
|
|
|
array(<<93/utf16-little,Rest/binary>>, [array|Stack], Opts) ->
|
|
|
|
{event,
|
|
|
|
end_array,
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
array(<<47/utf16-little,Rest/binary>>, Stack, {_,true,_,_,_} = Opts) ->
|
|
|
|
maybe_comment(Rest,
|
|
|
|
fun(Resume) ->
|
|
|
|
array(Resume, Stack, Opts)
|
|
|
|
end);
|
|
|
|
array(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
array(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
value(<<S/utf16-little,Rest/binary>>, Stack, Opts)
|
|
|
|
when S =:= 32; S =:= 9; S =:= 13; S =:= 10 ->
|
|
|
|
value(Rest, Stack, Opts);
|
|
|
|
value(<<34/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
string(Rest, Stack, Opts, []);
|
|
|
|
value(<<$t/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
tr(Rest, Stack, Opts);
|
|
|
|
value(<<$f/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
fa(Rest, Stack, Opts);
|
|
|
|
value(<<$n/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
nu(Rest, Stack, Opts);
|
|
|
|
value(<<45/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
negative(Rest, Stack, Opts, "-");
|
|
|
|
value(<<48/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
zero(Rest, Stack, Opts, "0");
|
|
|
|
value(<<S/utf16-little,Rest/binary>>, Stack, Opts)
|
|
|
|
when
|
|
|
|
S >= $1
|
|
|
|
andalso
|
|
|
|
S =< $9 ->
|
|
|
|
integer(Rest, Stack, Opts, [S]);
|
|
|
|
value(<<123/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
{event,
|
|
|
|
start_object,
|
|
|
|
fun() ->
|
|
|
|
object(Rest, [key|Stack], Opts)
|
|
|
|
end};
|
|
|
|
value(<<91/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
{event,
|
|
|
|
start_array,
|
|
|
|
fun() ->
|
|
|
|
array(Rest, [array|Stack], Opts)
|
|
|
|
end};
|
|
|
|
value(<<47/utf16-little,Rest/binary>>, Stack, {_,true,_,_,_} = Opts) ->
|
|
|
|
maybe_comment(Rest,
|
|
|
|
fun(Resume) ->
|
|
|
|
value(Resume, Stack, Opts)
|
|
|
|
end);
|
|
|
|
value(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
value(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
colon(<<S/utf16-little,Rest/binary>>, Stack, Opts)
|
|
|
|
when S =:= 32; S =:= 9; S =:= 13; S =:= 10 ->
|
|
|
|
colon(Rest, Stack, Opts);
|
|
|
|
colon(<<58/utf16-little,Rest/binary>>, [key|Stack], Opts) ->
|
|
|
|
value(Rest, [object|Stack], Opts);
|
|
|
|
colon(<<47/utf16-little,Rest/binary>>, Stack, {_,true,_,_,_} = Opts) ->
|
|
|
|
maybe_comment(Rest,
|
|
|
|
fun(Resume) ->
|
|
|
|
colon(Resume, Stack, Opts)
|
|
|
|
end);
|
|
|
|
colon(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
colon(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
key(<<S/utf16-little,Rest/binary>>, Stack, Opts)
|
|
|
|
when S =:= 32; S =:= 9; S =:= 13; S =:= 10 ->
|
|
|
|
key(Rest, Stack, Opts);
|
|
|
|
key(<<34/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
string(Rest, Stack, Opts, []);
|
|
|
|
key(<<47/utf16-little,Rest/binary>>, Stack, {_,true,_,_,_} = Opts) ->
|
|
|
|
maybe_comment(Rest,
|
|
|
|
fun(Resume) ->
|
|
|
|
key(Resume, Stack, Opts)
|
|
|
|
end);
|
|
|
|
key(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
key(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
string(<<34/utf16-little,Rest/binary>>, [key|_] = Stack, Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{key,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
colon(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
string(<<34/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{string,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
string(<<92/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
escape(Rest, Stack, Opts, Acc);
|
|
|
|
string(<<S/utf16-little,Rest/binary>>, Stack, Opts, Acc) when S >= 32 ->
|
|
|
|
string(Rest, Stack, Opts, [S] ++ Acc);
|
|
|
|
string(Bin, Stack, Opts, Acc) ->
|
|
|
|
case partial_utf(Bin) of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
string(<<Bin/binary,Stream/binary>>,
|
|
|
|
Stack,
|
|
|
|
Opts,
|
|
|
|
Acc)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
partial_utf(<<>>) ->
|
|
|
|
true;
|
|
|
|
partial_utf(<<_X>>) ->
|
|
|
|
true;
|
|
|
|
partial_utf(<<_Y,X>>) when X >= 216, X =< 223 ->
|
|
|
|
true;
|
|
|
|
partial_utf(<<_Y,X,_Z>>) when X >= 216, X =< 223 ->
|
|
|
|
true;
|
|
|
|
partial_utf(_) ->
|
|
|
|
false.
|
|
|
|
|
|
|
|
escape(<<$b/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
string(Rest, Stack, Opts, "\b" ++ Acc);
|
|
|
|
escape(<<$f/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
string(Rest, Stack, Opts, "\f" ++ Acc);
|
|
|
|
escape(<<$n/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
string(Rest, Stack, Opts, "\n" ++ Acc);
|
|
|
|
escape(<<$r/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
string(Rest, Stack, Opts, "\r" ++ Acc);
|
|
|
|
escape(<<$t/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
string(Rest, Stack, Opts, "\t" ++ Acc);
|
|
|
|
escape(<<$u/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
escaped_unicode(Rest, Stack, Opts, Acc, []);
|
|
|
|
escape(<<S/utf16-little,Rest/binary>>, Stack, Opts, Acc)
|
|
|
|
when S =:= 34; S =:= 47; S =:= 92 ->
|
|
|
|
string(Rest, Stack, Opts, [S] ++ Acc);
|
|
|
|
escape(Bin, Stack, Opts, Acc) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
escape(<<Bin/binary,Stream/binary>>,
|
|
|
|
Stack,
|
|
|
|
Opts,
|
|
|
|
Acc)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
escaped_unicode(<<D/utf16-little,Rest/binary>>,
|
|
|
|
Stack,
|
|
|
|
{_,_,ascii,_,_} = Opts,
|
|
|
|
String,
|
|
|
|
[C,B,A])
|
|
|
|
when
|
|
|
|
D >= $a
|
|
|
|
andalso
|
|
|
|
D =< $z;
|
|
|
|
D >= $A
|
|
|
|
andalso
|
|
|
|
D =< $Z;
|
|
|
|
D >= $0
|
|
|
|
andalso
|
|
|
|
D =< $9 ->
|
|
|
|
case erlang:list_to_integer([A,B,C,D], 16) of
|
|
|
|
X when X < 128 ->
|
|
|
|
string(Rest, Stack, Opts, [X] ++ String);
|
|
|
|
_ ->
|
|
|
|
string(Rest, Stack, Opts, [D,C,B,A,$u,92] ++ String)
|
|
|
|
end;
|
|
|
|
escaped_unicode(<<D/utf16-little,Rest/binary>>,
|
|
|
|
Stack,
|
|
|
|
{_,_,codepoint,_,_} = Opts,
|
|
|
|
String,
|
|
|
|
[C,B,A])
|
|
|
|
when
|
|
|
|
D >= $a
|
|
|
|
andalso
|
|
|
|
D =< $z;
|
|
|
|
D >= $A
|
|
|
|
andalso
|
|
|
|
D =< $Z;
|
|
|
|
D >= $0
|
|
|
|
andalso
|
|
|
|
D =< $9 ->
|
|
|
|
case erlang:list_to_integer([A,B,C,D], 16) of
|
|
|
|
X when X >= 56320, X =< 57343 ->
|
|
|
|
case check_acc_for_surrogate(String) of
|
|
|
|
false ->
|
|
|
|
string(Rest, Stack, Opts, [D,C,B,A,$u,92] ++ String);
|
|
|
|
{Y,NewString} ->
|
|
|
|
string(Rest,
|
|
|
|
Stack,
|
|
|
|
Opts,
|
|
|
|
[surrogate_to_codepoint(Y, X)] ++ NewString)
|
|
|
|
end;
|
|
|
|
X when X < 55296; X > 57343, X < 65534 ->
|
|
|
|
string(Rest, Stack, Opts, [X] ++ String);
|
|
|
|
_ ->
|
|
|
|
string(Rest, Stack, Opts, [D,C,B,A,$u,92] ++ String)
|
|
|
|
end;
|
|
|
|
escaped_unicode(<<D/utf16-little,Rest/binary>>,
|
|
|
|
Stack,
|
|
|
|
Opts,
|
|
|
|
String,
|
|
|
|
[C,B,A])
|
|
|
|
when
|
|
|
|
D >= $a
|
|
|
|
andalso
|
|
|
|
D =< $z;
|
|
|
|
D >= $A
|
|
|
|
andalso
|
|
|
|
D =< $Z;
|
|
|
|
D >= $0
|
|
|
|
andalso
|
|
|
|
D =< $9 ->
|
|
|
|
string(Rest, Stack, Opts, [D,C,B,A,$u,92] ++ String);
|
|
|
|
escaped_unicode(<<S/utf16-little,Rest/binary>>,
|
|
|
|
Stack,
|
|
|
|
Opts,
|
|
|
|
String,
|
|
|
|
Acc)
|
|
|
|
when
|
|
|
|
S >= $a
|
|
|
|
andalso
|
|
|
|
S =< $z;
|
|
|
|
S >= $A
|
|
|
|
andalso
|
|
|
|
S =< $Z;
|
|
|
|
S >= $0
|
|
|
|
andalso
|
|
|
|
S =< $9 ->
|
|
|
|
escaped_unicode(Rest, Stack, Opts, String, [S] ++ Acc);
|
|
|
|
escaped_unicode(Bin, Stack, Opts, String, Acc) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
escaped_unicode(<<Bin/binary,Stream/binary>>,
|
|
|
|
Stack,
|
|
|
|
Opts,
|
|
|
|
String,
|
|
|
|
Acc)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
check_acc_for_surrogate([D,C,B,A,$u,92|Rest])
|
|
|
|
when
|
|
|
|
D >= $a
|
|
|
|
andalso
|
|
|
|
D =< $z;
|
|
|
|
D >= $A
|
|
|
|
andalso
|
|
|
|
D =< $Z;
|
|
|
|
D >= $0
|
|
|
|
andalso
|
|
|
|
D =< $9,
|
|
|
|
C >= $a
|
|
|
|
andalso
|
|
|
|
C =< $z;
|
|
|
|
C >= $A
|
|
|
|
andalso
|
|
|
|
C =< $Z;
|
|
|
|
C >= $0
|
|
|
|
andalso
|
|
|
|
C =< $9,
|
|
|
|
B >= $a
|
|
|
|
andalso
|
|
|
|
B =< $z;
|
|
|
|
B >= $A
|
|
|
|
andalso
|
|
|
|
B =< $Z;
|
|
|
|
B >= $0
|
|
|
|
andalso
|
|
|
|
B =< $9,
|
|
|
|
A >= $a
|
|
|
|
andalso
|
|
|
|
A =< $z;
|
|
|
|
A >= $A
|
|
|
|
andalso
|
|
|
|
A =< $Z;
|
|
|
|
A >= $0
|
|
|
|
andalso
|
|
|
|
A =< $9 ->
|
|
|
|
case erlang:list_to_integer([A,B,C,D], 16) of
|
|
|
|
X when X >= 55296, X =< 56319 ->
|
|
|
|
{X,Rest};
|
|
|
|
_ ->
|
|
|
|
false
|
|
|
|
end;
|
|
|
|
check_acc_for_surrogate(_) ->
|
|
|
|
false.
|
|
|
|
|
|
|
|
surrogate_to_codepoint(High, Low) ->
|
|
|
|
(High - 55296) * 1024 + (Low - 56320) + 65536.
|
|
|
|
|
|
|
|
negative(<<$0/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
zero(Rest, Stack, Opts, "0" ++ Acc);
|
|
|
|
negative(<<S/utf16-little,Rest/binary>>, Stack, Opts, Acc)
|
|
|
|
when
|
|
|
|
S >= $1
|
|
|
|
andalso
|
|
|
|
S =< $9 ->
|
|
|
|
integer(Rest, Stack, Opts, [S] ++ Acc);
|
|
|
|
negative(Bin, Stack, Opts, Acc) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
negative(<<Bin/binary,Stream/binary>>,
|
|
|
|
Stack,
|
|
|
|
Opts,
|
|
|
|
Acc)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
zero(<<125/utf16-little,Rest/binary>>, [object|Stack], Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{integer,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
{event,
|
|
|
|
end_object,
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end}
|
|
|
|
end};
|
|
|
|
zero(<<93/utf16-little,Rest/binary>>, [array|Stack], Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{integer,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
{event,
|
|
|
|
end_array,
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end}
|
|
|
|
end};
|
|
|
|
zero(<<44/utf16-little,Rest/binary>>, [object|Stack], Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{integer,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
key(Rest, [key|Stack], Opts)
|
|
|
|
end};
|
|
|
|
zero(<<44/utf16-little,Rest/binary>>, [array|_] = Stack, Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{integer,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
value(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
zero(<<46/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
initial_decimal(Rest, Stack, Opts, [46] ++ Acc);
|
|
|
|
zero(<<S/utf16-little,Rest/binary>>, Stack, Opts, Acc)
|
|
|
|
when S =:= 32; S =:= 9; S =:= 13; S =:= 10 ->
|
|
|
|
{event,
|
|
|
|
{integer,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
zero(<<47/utf16-little,Rest/binary>>, Stack, {_,true,_,_,_} = Opts, Acc) ->
|
|
|
|
maybe_comment(Rest,
|
|
|
|
fun(Resume) ->
|
|
|
|
zero(Resume, Stack, Opts, Acc)
|
|
|
|
end);
|
|
|
|
zero(<<>>, [], Opts, Acc) ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{event,
|
|
|
|
{integer,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
{event,
|
|
|
|
end_json,
|
|
|
|
fun() ->
|
|
|
|
zero(<<>>, [], Opts, Acc)
|
|
|
|
end}
|
|
|
|
end};
|
|
|
|
(Stream) ->
|
|
|
|
zero(Stream, [], Opts, Acc)
|
|
|
|
end};
|
|
|
|
zero(Bin, Stack, Opts, Acc) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
zero(<<Bin/binary,Stream/binary>>, Stack, Opts, Acc)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
integer(<<S/utf16-little,Rest/binary>>, Stack, Opts, Acc)
|
|
|
|
when
|
|
|
|
S >= $1
|
|
|
|
andalso
|
|
|
|
S =< $9 ->
|
|
|
|
integer(Rest, Stack, Opts, [S] ++ Acc);
|
|
|
|
integer(<<125/utf16-little,Rest/binary>>, [object|Stack], Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{integer,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
{event,
|
|
|
|
end_object,
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end}
|
|
|
|
end};
|
|
|
|
integer(<<93/utf16-little,Rest/binary>>, [array|Stack], Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{integer,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
{event,
|
|
|
|
end_array,
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end}
|
|
|
|
end};
|
|
|
|
integer(<<44/utf16-little,Rest/binary>>, [object|Stack], Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{integer,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
key(Rest, [key|Stack], Opts)
|
|
|
|
end};
|
|
|
|
integer(<<44/utf16-little,Rest/binary>>, [array|_] = Stack, Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{integer,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
value(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
integer(<<46/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
initial_decimal(Rest, Stack, Opts, [46] ++ Acc);
|
|
|
|
integer(<<48/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
integer(Rest, Stack, Opts, [48] ++ Acc);
|
|
|
|
integer(<<$e/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
e(Rest, Stack, Opts, "e0." ++ Acc);
|
|
|
|
integer(<<$E/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
e(Rest, Stack, Opts, "e0." ++ Acc);
|
|
|
|
integer(<<S/utf16-little,Rest/binary>>, Stack, Opts, Acc)
|
|
|
|
when S =:= 32; S =:= 9; S =:= 13; S =:= 10 ->
|
|
|
|
{event,
|
|
|
|
{integer,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
integer(<<47/utf16-little,Rest/binary>>,
|
|
|
|
Stack,
|
|
|
|
{_,true,_,_,_} = Opts,
|
|
|
|
Acc) ->
|
|
|
|
maybe_comment(Rest,
|
|
|
|
fun(Resume) ->
|
|
|
|
integer(Resume, Stack, Opts, Acc)
|
|
|
|
end);
|
|
|
|
integer(<<>>, [], Opts, Acc) ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{event,
|
|
|
|
{integer,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
{event,
|
|
|
|
end_json,
|
|
|
|
fun() ->
|
|
|
|
integer(<<>>, [], Opts, Acc)
|
|
|
|
end}
|
|
|
|
end};
|
|
|
|
(Stream) ->
|
|
|
|
integer(Stream, [], Opts, Acc)
|
|
|
|
end};
|
|
|
|
integer(Bin, Stack, Opts, Acc) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
integer(<<Bin/binary,Stream/binary>>,
|
|
|
|
Stack,
|
|
|
|
Opts,
|
|
|
|
Acc)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
initial_decimal(<<S/utf16-little,Rest/binary>>, Stack, Opts, Acc)
|
|
|
|
when
|
|
|
|
S >= $1
|
|
|
|
andalso
|
|
|
|
S =< $9 ->
|
|
|
|
decimal(Rest, Stack, Opts, [S] ++ Acc);
|
|
|
|
initial_decimal(<<48/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
decimal(Rest, Stack, Opts, [48] ++ Acc);
|
|
|
|
initial_decimal(Bin, Stack, Opts, Acc) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
initial_decimal(<<Bin/binary,Stream/binary>>,
|
|
|
|
Stack,
|
|
|
|
Opts,
|
|
|
|
Acc)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
decimal(<<S/utf16-little,Rest/binary>>, Stack, Opts, Acc)
|
|
|
|
when
|
|
|
|
S >= $1
|
|
|
|
andalso
|
|
|
|
S =< $9 ->
|
|
|
|
decimal(Rest, Stack, Opts, [S] ++ Acc);
|
|
|
|
decimal(<<125/utf16-little,Rest/binary>>, [object|Stack], Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{float,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
{event,
|
|
|
|
end_object,
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end}
|
|
|
|
end};
|
|
|
|
decimal(<<93/utf16-little,Rest/binary>>, [array|Stack], Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{float,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
{event,
|
|
|
|
end_array,
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end}
|
|
|
|
end};
|
|
|
|
decimal(<<44/utf16-little,Rest/binary>>, [object|Stack], Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{float,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
key(Rest, [key|Stack], Opts)
|
|
|
|
end};
|
|
|
|
decimal(<<44/utf16-little,Rest/binary>>, [array|_] = Stack, Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{float,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
value(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
decimal(<<48/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
decimal(Rest, Stack, Opts, [48] ++ Acc);
|
|
|
|
decimal(<<$e/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
e(Rest, Stack, Opts, "e" ++ Acc);
|
|
|
|
decimal(<<$E/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
e(Rest, Stack, Opts, "e" ++ Acc);
|
|
|
|
decimal(<<S/utf16-little,Rest/binary>>, Stack, Opts, Acc)
|
|
|
|
when S =:= 32; S =:= 9; S =:= 13; S =:= 10 ->
|
|
|
|
{event,
|
|
|
|
{float,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
decimal(<<47/utf16-little,Rest/binary>>,
|
|
|
|
Stack,
|
|
|
|
{_,true,_,_,_} = Opts,
|
|
|
|
Acc) ->
|
|
|
|
maybe_comment(Rest,
|
|
|
|
fun(Resume) ->
|
|
|
|
decimal(Resume, Stack, Opts, Acc)
|
|
|
|
end);
|
|
|
|
decimal(<<>>, [], Opts, Acc) ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{event,
|
|
|
|
{float,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
{event,
|
|
|
|
end_json,
|
|
|
|
fun() ->
|
|
|
|
decimal(<<>>, [], Opts, Acc)
|
|
|
|
end}
|
|
|
|
end};
|
|
|
|
(Stream) ->
|
|
|
|
decimal(Stream, [], Opts, Acc)
|
|
|
|
end};
|
|
|
|
decimal(Bin, Stack, Opts, Acc) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
decimal(<<Bin/binary,Stream/binary>>,
|
|
|
|
Stack,
|
|
|
|
Opts,
|
|
|
|
Acc)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
e(<<S/utf16-little,Rest/binary>>, Stack, Opts, Acc)
|
|
|
|
when
|
|
|
|
S =:= 48;
|
|
|
|
S >= $1
|
|
|
|
andalso
|
|
|
|
S =< $9 ->
|
|
|
|
exp(Rest, Stack, Opts, [S] ++ Acc);
|
|
|
|
e(<<S/utf16-little,Rest/binary>>, Stack, Opts, Acc)
|
|
|
|
when S =:= 43; S =:= 45 ->
|
|
|
|
ex(Rest, Stack, Opts, [S] ++ Acc);
|
|
|
|
e(Bin, Stack, Opts, Acc) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
e(<<Bin/binary,Stream/binary>>, Stack, Opts, Acc)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
ex(<<S/utf16-little,Rest/binary>>, Stack, Opts, Acc)
|
|
|
|
when
|
|
|
|
S =:= 48;
|
|
|
|
S >= $1
|
|
|
|
andalso
|
|
|
|
S =< $9 ->
|
|
|
|
exp(Rest, Stack, Opts, [S] ++ Acc);
|
|
|
|
ex(Bin, Stack, Opts, Acc) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
ex(<<Bin/binary,Stream/binary>>, Stack, Opts, Acc)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
exp(<<S/utf16-little,Rest/binary>>, Stack, Opts, Acc)
|
|
|
|
when
|
|
|
|
S >= $1
|
|
|
|
andalso
|
|
|
|
S =< $9 ->
|
|
|
|
exp(Rest, Stack, Opts, [S] ++ Acc);
|
|
|
|
exp(<<125/utf16-little,Rest/binary>>, [object|Stack], Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{float,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
{event,
|
|
|
|
end_object,
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end}
|
|
|
|
end};
|
|
|
|
exp(<<93/utf16-little,Rest/binary>>, [array|Stack], Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{float,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
{event,
|
|
|
|
end_array,
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end}
|
|
|
|
end};
|
|
|
|
exp(<<44/utf16-little,Rest/binary>>, [object|Stack], Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{float,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
key(Rest, [key|Stack], Opts)
|
|
|
|
end};
|
|
|
|
exp(<<44/utf16-little,Rest/binary>>, [array|_] = Stack, Opts, Acc) ->
|
|
|
|
{event,
|
|
|
|
{float,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
value(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
exp(<<48/utf16-little,Rest/binary>>, Stack, Opts, Acc) ->
|
|
|
|
exp(Rest, Stack, Opts, [48] ++ Acc);
|
|
|
|
exp(<<S/utf16-little,Rest/binary>>, Stack, Opts, Acc)
|
|
|
|
when S =:= 32; S =:= 9; S =:= 13; S =:= 10 ->
|
|
|
|
{event,
|
|
|
|
{float,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
exp(<<47/utf16-little,Rest/binary>>, Stack, {_,true,_,_,_} = Opts, Acc) ->
|
|
|
|
maybe_comment(Rest,
|
|
|
|
fun(Resume) ->
|
|
|
|
exp(Resume, Stack, Opts, Acc)
|
|
|
|
end);
|
|
|
|
exp(<<>>, [], Opts, Acc) ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{event,
|
|
|
|
{float,lists:reverse(Acc)},
|
|
|
|
fun() ->
|
|
|
|
{event,
|
|
|
|
end_json,
|
|
|
|
fun() ->
|
|
|
|
exp(<<>>, [], Opts, Acc)
|
|
|
|
end}
|
|
|
|
end};
|
|
|
|
(Stream) ->
|
|
|
|
exp(Stream, [], Opts, Acc)
|
|
|
|
end};
|
|
|
|
exp(Bin, Stack, Opts, Acc) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
exp(<<Bin/binary,Stream/binary>>, Stack, Opts, Acc)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
tr(<<$r/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
tru(Rest, Stack, Opts);
|
|
|
|
tr(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
tr(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
tru(<<$u/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
true(Rest, Stack, Opts);
|
|
|
|
tru(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
tru(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
true(<<$e/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
{event,
|
|
|
|
{literal,true},
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
true(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
true(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
fa(<<$a/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
fal(Rest, Stack, Opts);
|
|
|
|
fa(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
fa(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
fal(<<$l/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
fals(Rest, Stack, Opts);
|
|
|
|
fal(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
fal(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
fals(<<$s/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
false(Rest, Stack, Opts);
|
|
|
|
fals(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
fals(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
false(<<$e/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
{event,
|
|
|
|
{literal,false},
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
false(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
nu(<<$u/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
nul(Rest, Stack, Opts);
|
|
|
|
nu(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
nu(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
nul(<<$l/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
null(Rest, Stack, Opts);
|
|
|
|
nul(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
nul(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
null(<<$l/utf16-little,Rest/binary>>, Stack, Opts) ->
|
|
|
|
{event,
|
|
|
|
{literal,null},
|
|
|
|
fun() ->
|
|
|
|
maybe_done(Rest, Stack, Opts)
|
|
|
|
end};
|
|
|
|
null(Bin, Stack, Opts) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
null(<<Bin/binary,Stream/binary>>, Stack, Opts)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
maybe_comment(<<42/utf16-little,Rest/binary>>, Resume) ->
|
|
|
|
comment(Rest, Resume);
|
|
|
|
maybe_comment(Bin, Resume) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
maybe_comment(<<Bin/binary,Stream/binary>>, Resume)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
comment(<<42/utf16-little,Rest/binary>>, Resume) ->
|
|
|
|
maybe_comment_done(Rest, Resume);
|
|
|
|
comment(<<_/utf16-little,Rest/binary>>, Resume) ->
|
|
|
|
comment(Rest, Resume);
|
|
|
|
comment(Bin, Resume) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
comment(<<Bin/binary,Stream/binary>>, Resume)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
maybe_comment_done(<<47/utf16-little,Rest/binary>>, Resume) ->
|
|
|
|
Resume(Rest);
|
|
|
|
maybe_comment_done(<<_/utf16-little,Rest/binary>>, Resume) ->
|
|
|
|
comment(Rest, Resume);
|
|
|
|
maybe_comment_done(Bin, Resume) ->
|
|
|
|
case byte_size(Bin) < 2 of
|
|
|
|
true ->
|
|
|
|
{incomplete,
|
|
|
|
fun(end_stream) ->
|
|
|
|
{error,badjson};
|
|
|
|
(Stream) ->
|
|
|
|
maybe_comment_done(<<Bin/binary,Stream/binary>>,
|
|
|
|
Resume)
|
|
|
|
end};
|
|
|
|
false ->
|
|
|
|
{error,badjson}
|
|
|
|
end.
|
|
|
|
|
|
|
|
|
|
|
|
|