general cleanup of modules, moved most types, specs, defines and records to header files and did some minor reformatting to adhere to style guidelines

This commit is contained in:
alisdair sullivan 2010-08-19 18:22:34 -07:00
parent 86b4fbbec9
commit c098b06e88
16 changed files with 247 additions and 147 deletions

51
include/jsx.hrl Normal file
View file

@ -0,0 +1,51 @@
%% The MIT License
%% Copyright (c) 2010 Alisdair Sullivan <alisdairsullivan@yahoo.ca>
%% Permission is hereby granted, free of charge, to any person obtaining a copy
%% of this software and associated documentation files (the "Software"), to deal
%% in the Software without restriction, including without limitation the rights
%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
%% copies of the Software, and to permit persons to whom the Software is
%% furnished to do so, subject to the following conditions:
%% The above copyright notice and this permission notice shall be included in
%% all copies or substantial portions of the Software.
%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
%% THE SOFTWARE.
-include("jsx_common.hrl").
%% opts record
-record(opts, {
comments = false,
escaped_unicode = codepoint,
multi_term = false,
encoding = auto
}).
-spec parser() -> jsx_parser().
-spec parser(Opts::jsx_opts()) -> jsx_parser().
-spec term_to_json(JSON::eep0018()) -> binary().
-spec term_to_json(JSON::eep0018(), Opts::encoder_opts()) -> binary().
-spec json_to_term(JSON::binary()) -> eep0018().
-spec json_to_term(JSON::binary(), Opts::decoder_opts()) -> eep0018().
-spec is_json(JSON::binary()) -> true | false.
-spec is_json(JSON::binary(), Opts::verify_opts()) -> true | false.
-spec format(JSON::binary()) -> binary() | iolist().
-spec format(JSON::binary(), Opts::format_opts()) -> binary() | iolist().
-spec eventify(List::list()) -> jsx_parser_result().

View file

@ -21,8 +21,10 @@
%% THE SOFTWARE. %% THE SOFTWARE.
%% unsure of how to specify a binary with a complex structure like utfx encoded
%% binaries. this should be further limited somehow probably. -define(is_utf_encoding(X),
X == utf8; X == utf16; X == utf32; X == {utf16, little}; X == {utf32, little}
).
-type jsx_opts() :: [jsx_opt()]. -type jsx_opts() :: [jsx_opt()].
@ -33,7 +35,6 @@
%% events emitted by the parser and component types %% events emitted by the parser and component types
-type unicode_codepoint() :: 0..16#10ffff. -type unicode_codepoint() :: 0..16#10ffff.
-type unicode_string() :: [unicode_codepoint()]. -type unicode_string() :: [unicode_codepoint()].
@ -52,7 +53,6 @@
%% this probably doesn't work properly %% this probably doesn't work properly
-type jsx_parser() :: fun((binary()) -> jsx_parser_result()). -type jsx_parser() :: fun((binary()) -> jsx_parser_result()).
-type jsx_parser_result() :: {event, jsx_event(), fun(() -> jsx_parser_result())} -type jsx_parser_result() :: {event, jsx_event(), fun(() -> jsx_parser_result())}
@ -60,7 +60,11 @@
| {error, badjson} | {error, badjson}
| ok. | ok.
-type supported_utf() :: utf8 | utf16 | {utf16, little} | utf32 | {utf32, little}.
%% eep0018 json specification
-type eep0018() :: eep0018_object() | eep0018_array(). -type eep0018() :: eep0018_object() | eep0018_array().
-type eep0018_array() :: [eep0018_term()]. -type eep0018_array() :: [eep0018_term()].
@ -75,9 +79,6 @@
-type eep0018_number() :: float() | integer(). -type eep0018_number() :: float() | integer().
-type supported_utf() :: utf8 | utf16 | {utf16, little} | utf32 | {utf32, little}.
-type encoder_opts() :: [encoder_opt()]. -type encoder_opts() :: [encoder_opt()].
-type encoder_opt() :: {strict, true | false} -type encoder_opt() :: {strict, true | false}
| {encoding, supported_utf()} | {encoding, supported_utf()}
@ -87,7 +88,6 @@
| indent. | indent.
-type decoder_opts() :: [decoder_opt()]. -type decoder_opts() :: [decoder_opt()].
-type decoder_opt() :: {strict, true | false} -type decoder_opt() :: {strict, true | false}
| {comments, true | false} | {comments, true | false}

View file

@ -20,6 +20,13 @@
%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
%% THE SOFTWARE. %% THE SOFTWARE.
-include("./include/jsx_common.hrl").
-spec parse(JSON::eep0018(), Opts::jsx_opts()) -> jsx_parser_result().
%% option flags %% option flags
-define(comments_enabled(X), {_, true, _, _, _} = X). -define(comments_enabled(X), {_, true, _, _, _} = X).

30
include/jsx_eep0018.hrl Normal file
View file

@ -0,0 +1,30 @@
%% The MIT License
%% Copyright (c) 2010 Alisdair Sullivan <alisdairsullivan@yahoo.ca>
%% Permission is hereby granted, free of charge, to any person obtaining a copy
%% of this software and associated documentation files (the "Software"), to deal
%% in the Software without restriction, including without limitation the rights
%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
%% copies of the Software, and to permit persons to whom the Software is
%% furnished to do so, subject to the following conditions:
%% The above copyright notice and this permission notice shall be included in
%% all copies or substantial portions of the Software.
%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
%% THE SOFTWARE.
-include("jsx_common.hrl").
-spec json_to_term(JSON::binary(), Opts::decoder_opts()) -> eep0018().
-spec term_to_json(JSON::eep0018(), Opts::encoder_opts()) -> binary().

46
include/jsx_format.hrl Normal file
View file

@ -0,0 +1,46 @@
%% The MIT License
%% Copyright (c) 2010 Alisdair Sullivan <alisdairsullivan@yahoo.ca>
%% Permission is hereby granted, free of charge, to any person obtaining a copy
%% of this software and associated documentation files (the "Software"), to deal
%% in the Software without restriction, including without limitation the rights
%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
%% copies of the Software, and to permit persons to whom the Software is
%% furnished to do so, subject to the following conditions:
%% The above copyright notice and this permission notice shall be included in
%% all copies or substantial portions of the Software.
%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
%% THE SOFTWARE.
-include("jsx_common.hrl").
-record(opts, {
space = 0,
indent = 0,
output_encoding = utf8,
strict = true
}).
-define(newline, $\n).
-define(space, 16#20). %% ascii code for space
-define(quote, $\").
-define(comma, $,).
-define(colon, $:).
-define(start_object, ${).
-define(end_object, $}).
-define(start_array, $[).
-define(end_array, $]).
-spec format(JSON::binary(), Opts::format_opts()) -> binary() | iolist().

27
include/jsx_verify.hrl Normal file
View file

@ -0,0 +1,27 @@
%% The MIT License
%% Copyright (c) 2010 Alisdair Sullivan <alisdairsullivan@yahoo.ca>
%% Permission is hereby granted, free of charge, to any person obtaining a copy
%% of this software and associated documentation files (the "Software"), to deal
%% in the Software without restriction, including without limitation the rights
%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
%% copies of the Software, and to permit persons to whom the Software is
%% furnished to do so, subject to the following conditions:
%% The above copyright notice and this permission notice shall be included in
%% all copies or substantial portions of the Software.
%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
%% THE SOFTWARE.
-include("jsx_common.hrl").
-spec is_json(JSON::binary(), Opts::verify_opts()) -> true | false.

View file

@ -29,15 +29,14 @@
-module(?name). -module(?name).
-author("alisdairsullivan@yahoo.ca"). -author("alisdairsullivan@yahoo.ca").
-export([parse/2]). -export([parse/2]).
-include("./include/jsx_decoder.hrl"). -include("./include/jsx_decoder.hrl").
-include("./include/jsx_types.hrl").
-spec parse(JSON::eep0018(), Opts::jsx_opts()) -> jsx_parser_result().
parse(JSON, Opts) -> parse(JSON, Opts) ->
start(JSON, [], Opts). start(JSON, [], Opts).
@ -70,6 +69,7 @@ start(Bin, Stack, Opts) ->
; false -> {error, badjson} ; false -> {error, badjson}
end. end.
maybe_done(<<S/?encoding, Rest/binary>>, Stack, Opts) when ?is_whitespace(S) -> maybe_done(<<S/?encoding, Rest/binary>>, Stack, Opts) when ?is_whitespace(S) ->
maybe_done(Rest, Stack, Opts); maybe_done(Rest, Stack, Opts);
maybe_done(<<?end_object/?encoding, Rest/binary>>, [object|Stack], Opts) -> maybe_done(<<?end_object/?encoding, Rest/binary>>, [object|Stack], Opts) ->
@ -91,7 +91,8 @@ maybe_done(Bin, Stack, Opts) ->
true -> {incomplete, fun(end_stream) -> {error, badjson}; (Stream) -> maybe_done(<<Bin/binary, Stream/binary>>, Stack, Opts) end} true -> {incomplete, fun(end_stream) -> {error, badjson}; (Stream) -> maybe_done(<<Bin/binary, Stream/binary>>, Stack, Opts) end}
; false -> {error, badjson} ; false -> {error, badjson}
end. end.
done(<<S/?encoding, Rest/binary>>, Opts) when ?is_whitespace(S) -> done(<<S/?encoding, Rest/binary>>, Opts) when ?is_whitespace(S) ->
done(Rest, Opts); done(Rest, Opts);
done(<<?solidus/?encoding, Rest/binary>>, ?comments_enabled(Opts)) -> done(<<?solidus/?encoding, Rest/binary>>, ?comments_enabled(Opts)) ->
@ -243,7 +244,7 @@ partial_utf(<<X, Rest/binary>>) when X >= 16#f0, X =< 16#f4 ->
end; end;
partial_utf(_) -> false. partial_utf(_) -> false.
-endif. -endif.
-ifdef(utf16). -ifdef(utf16).
partial_utf(<<>>) -> true; partial_utf(<<>>) -> true;
%% this case is not strictly true, there are single bytes that should be rejected, but %% this case is not strictly true, there are single bytes that should be rejected, but
@ -348,6 +349,7 @@ escaped_unicode(Bin, Stack, Opts, String, Acc) ->
; false -> {error, badjson} ; false -> {error, badjson}
end. end.
%% upon encountering a low pair json/hex encoded value, check to see if there's a high %% upon encountering a low pair json/hex encoded value, check to see if there's a high
%% value already in the accumulator %% value already in the accumulator
check_acc_for_surrogate([D, C, B, A, $u, ?rsolidus|Rest]) check_acc_for_surrogate([D, C, B, A, $u, ?rsolidus|Rest])
@ -361,6 +363,7 @@ check_acc_for_surrogate([D, C, B, A, $u, ?rsolidus|Rest])
check_acc_for_surrogate(_) -> check_acc_for_surrogate(_) ->
false. false.
%% stole this from the unicode spec %% stole this from the unicode spec
surrogate_to_codepoint(High, Low) -> surrogate_to_codepoint(High, Low) ->
(High - 16#d800) * 16#400 + (Low - 16#dc00) + 16#10000. (High - 16#d800) * 16#400 + (Low - 16#dc00) + 16#10000.

View file

@ -24,6 +24,7 @@
-module(jsx). -module(jsx).
-author("alisdairsullivan@yahoo.ca"). -author("alisdairsullivan@yahoo.ca").
%% the core parser api %% the core parser api
-export([parser/0, parser/1]). -export([parser/0, parser/1]).
-export([term_to_json/1, term_to_json/2]). -export([term_to_json/1, term_to_json/2]).
@ -34,21 +35,9 @@
%% types for function specifications %% types for function specifications
-include("./include/jsx_types.hrl"). -include("./include/jsx.hrl").
%% opts record
-record(opts, {
comments = false,
escaped_unicode = codepoint,
multi_term = false,
encoding = auto
}).
-spec parser() -> jsx_parser().
-spec parser(Opts::jsx_opts()) -> jsx_parser().
parser() -> parser() ->
parser([]). parser([]).
@ -67,9 +56,6 @@ parser(OptsList) ->
; Opts -> fun(Stream) -> F(Stream, Opts) end ; Opts -> fun(Stream) -> F(Stream, Opts) end
end. end.
-spec term_to_json(JSON::eep0018()) -> binary().
-spec term_to_json(JSON::eep0018(), Opts::encoder_opts()) -> binary().
term_to_json(JSON) -> term_to_json(JSON) ->
term_to_json(JSON, []). term_to_json(JSON, []).
@ -78,9 +64,6 @@ term_to_json(JSON, Opts) ->
jsx_eep0018:term_to_json(JSON, Opts). jsx_eep0018:term_to_json(JSON, Opts).
-spec json_to_term(JSON::binary()) -> eep0018().
-spec json_to_term(JSON::binary(), Opts::decoder_opts()) -> eep0018().
json_to_term(JSON) -> json_to_term(JSON) ->
json_to_term(JSON, []). json_to_term(JSON, []).
@ -88,9 +71,6 @@ json_to_term(JSON, Opts) ->
jsx_eep0018:json_to_term(JSON, Opts). jsx_eep0018:json_to_term(JSON, Opts).
-spec is_json(JSON::binary()) -> true | false.
-spec is_json(JSON::binary(), Opts::verify_opts()) -> true | false.
is_json(JSON) -> is_json(JSON) ->
is_json(JSON, []). is_json(JSON, []).
@ -98,9 +78,6 @@ is_json(JSON, Opts) ->
jsx_verify:is_json(JSON, Opts). jsx_verify:is_json(JSON, Opts).
-spec format(JSON::binary()) -> binary() | iolist().
-spec format(JSON::binary(), Opts::format_opts()) -> binary() | iolist().
format(JSON) -> format(JSON) ->
format(JSON, []). format(JSON, []).
@ -108,11 +85,8 @@ format(JSON, Opts) ->
jsx_format:format(JSON, Opts). jsx_format:format(JSON, Opts).
-spec eventify(List::list()) -> jsx_parser_result().
%% fake the jsx api for any list, useful if you want to serialize a structure to %% fake the jsx api for any list, useful if you want to serialize a structure to
%% json using the pretty printer, or verify a sequence could be valid json %% json using the pretty printer, or verify a sequence could be valid json
eventify([]) -> eventify([]) ->
fun() -> {incomplete, fun(List) when is_list(List) -> eventify(List); (_) -> erlang:error(badarg) end} end; fun() -> {incomplete, fun(List) when is_list(List) -> eventify(List); (_) -> erlang:error(badarg) end} end;
eventify([Next|Rest]) -> eventify([Next|Rest]) ->

View file

@ -24,9 +24,12 @@
-module(jsx_eep0018). -module(jsx_eep0018).
-author("alisdairsullivan@yahoo.ca"). -author("alisdairsullivan@yahoo.ca").
-export([json_to_term/2, term_to_json/2]). -export([json_to_term/2, term_to_json/2]).
-include("./include/jsx_types.hrl").
-include("./include/jsx_eep0018.hrl").
-ifdef(test). -ifdef(test).
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
@ -34,8 +37,6 @@
-spec json_to_term(JSON::binary(), Opts::decoder_opts()) -> eep0018().
json_to_term(JSON, Opts) -> json_to_term(JSON, Opts) ->
P = jsx:parser(opts_to_jsx_opts(Opts)), P = jsx:parser(opts_to_jsx_opts(Opts)),
case proplists:get_value(strict, Opts, true) of case proplists:get_value(strict, Opts, true) of
@ -48,9 +49,6 @@ json_to_term(JSON, Opts) ->
%% terms to json strings, but it expects a jsx event iterator. luckily, the mapping from %% terms to json strings, but it expects a jsx event iterator. luckily, the mapping from
%% erlang terms to jsx events is straightforward and the iterator can be faked with an %% erlang terms to jsx events is straightforward and the iterator can be faked with an
%% anonymous function %% anonymous function
-spec term_to_json(JSON::eep0018(), Opts::encoder_opts()) -> binary().
term_to_json(List, Opts) -> term_to_json(List, Opts) ->
case proplists:get_value(strict, Opts, true) of case proplists:get_value(strict, Opts, true) of
true when is_list(List) -> continue true when is_list(List) -> continue
@ -62,7 +60,6 @@ term_to_json(List, Opts) ->
%% parse opts for the decoder %% parse opts for the decoder
opts_to_jsx_opts(Opts) -> opts_to_jsx_opts(Opts) ->
opts_to_jsx_opts(Opts, []). opts_to_jsx_opts(Opts, []).
@ -85,18 +82,15 @@ opts_to_jsx_opts([], Acc) ->
%% ensure the first jsx event we get is start_object or start_array when running %% ensure the first jsx event we get is start_object or start_array when running
%% in strict mode %% in strict mode
collect_strict({event, Start, Next}, Acc, Opts) when Start =:= start_object; Start =:= start_array -> collect_strict({event, Start, Next}, Acc, Opts) when Start =:= start_object; Start =:= start_array ->
collect(Next(), [[]|Acc], Opts); collect(Next(), [[]|Acc], Opts);
collect_strict(_, _, _) -> collect_strict(_, _, _) ->
erlang:error(badarg). erlang:error(badarg).
%% collect decoder events and convert to eep0018 format %% collect decoder events and convert to eep0018 format
collect({event, Start, Next}, Acc, Opts) when Start =:= start_object; Start =:= start_array -> collect({event, Start, Next}, Acc, Opts) when Start =:= start_object; Start =:= start_array ->
collect(Next(), [[]|Acc], Opts); collect(Next(), [[]|Acc], Opts);
%% special case for empty object %% special case for empty object
collect({event, end_object, Next}, [[], Parent|Rest], Opts) when is_list(Parent) -> collect({event, end_object, Next}, [[], Parent|Rest], Opts) when is_list(Parent) ->
collect(Next(), [[[{}]] ++ Parent] ++ Rest, Opts); collect(Next(), [[[{}]] ++ Parent] ++ Rest, Opts);
@ -110,11 +104,9 @@ collect({event, end_object, Next}, [[], Key, Parent|Rest], Opts) ->
collect(Next(), [[{Key, [{}]}] ++ Parent] ++ Rest, Opts); collect(Next(), [[{Key, [{}]}] ++ Parent] ++ Rest, Opts);
collect({event, End, Next}, [Current, Key, Parent|Rest], Opts) collect({event, End, Next}, [Current, Key, Parent|Rest], Opts)
when End =:= end_object; End =:= end_array -> when End =:= end_object; End =:= end_array ->
collect(Next(), [[{Key, lists:reverse(Current)}] ++ Parent] ++ Rest, Opts); collect(Next(), [[{Key, lists:reverse(Current)}] ++ Parent] ++ Rest, Opts);
collect({event, end_json, _Next}, [[Acc]], _Opts) -> collect({event, end_json, _Next}, [[Acc]], _Opts) ->
Acc; Acc;
%% key can only be emitted inside of a json object, so just insert it directly into %% key can only be emitted inside of a json object, so just insert it directly into
%% the head of the accumulator and deal with it when we receive it's paired value %% the head of the accumulator and deal with it when we receive it's paired value
collect({event, {key, _} = PreKey, Next}, [Current|_] = Acc, Opts) -> collect({event, {key, _} = PreKey, Next}, [Current|_] = Acc, Opts) ->
@ -123,7 +115,6 @@ collect({event, {key, _} = PreKey, Next}, [Current|_] = Acc, Opts) ->
true -> erlang:error(badarg) true -> erlang:error(badarg)
; false -> collect(Next(), [Key] ++ Acc, Opts) ; false -> collect(Next(), [Key] ++ Acc, Opts)
end; end;
%% check acc to see if we're inside an object or an array. because inside an object %% check acc to see if we're inside an object or an array. because inside an object
%% context the events that fall this far are always preceded by a key (which are %% context the events that fall this far are always preceded by a key (which are
%% binaries or atoms), if Current is a list, we're inside an array, else, an %% binaries or atoms), if Current is a list, we're inside an array, else, an
@ -132,7 +123,6 @@ collect({event, Event, Next}, [Current|Rest], Opts) when is_list(Current) ->
collect(Next(), [[event(Event, Opts)] ++ Current] ++ Rest, Opts); collect(Next(), [[event(Event, Opts)] ++ Current] ++ Rest, Opts);
collect({event, Event, Next}, [Key, Current|Rest], Opts) -> collect({event, Event, Next}, [Key, Current|Rest], Opts) ->
collect(Next(), [[{Key, event(Event, Opts)}] ++ Current] ++ Rest, Opts); collect(Next(), [[{Key, event(Event, Opts)}] ++ Current] ++ Rest, Opts);
%% if our first returned event is {incomplete, ...} try to force end and return the %% if our first returned event is {incomplete, ...} try to force end and return the
%% Event if one is returned %% Event if one is returned
collect({incomplete, More}, [[]], Opts) -> collect({incomplete, More}, [[]], Opts) ->
@ -140,13 +130,11 @@ collect({incomplete, More}, [[]], Opts) ->
{event, Event, _Next} -> event(Event, Opts) {event, Event, _Next} -> event(Event, Opts)
; _ -> erlang:error(badarg) ; _ -> erlang:error(badarg)
end; end;
%% any other event is an error %% any other event is an error
collect(_, _, _) -> erlang:error(badarg). collect(_, _, _) -> erlang:error(badarg).
%% helper functions for converting jsx events to eep0018 formats %% helper functions for converting jsx events to eep0018 formats
event({string, String}, _Opts) -> event({string, String}, _Opts) ->
unicode:characters_to_binary(String); unicode:characters_to_binary(String);
event({key, Key}, Opts) -> event({key, Key}, Opts) ->
@ -180,7 +168,6 @@ decode_key_repeats(_Key, []) -> false.
%% convert eep0018 representation to jsx events. note special casing for the empty object %% convert eep0018 representation to jsx events. note special casing for the empty object
term_to_events([{}]) -> term_to_events([{}]) ->
[end_object, start_object]; [end_object, start_object];
term_to_events([First|_] = List) when is_tuple(First) -> term_to_events([First|_] = List) when is_tuple(First) ->
@ -347,7 +334,6 @@ format(Dpoint, Digits) when Dpoint > 0 ->
format(Dpoint, Digits) when Dpoint < 0 -> format(Dpoint, Digits) when Dpoint < 0 ->
format(Digits, 1, []) ++ "e" ++ integer_to_list(Dpoint - 1). format(Digits, 1, []) ++ "e" ++ integer_to_list(Dpoint - 1).
format([], 0, Acc) -> format([], 0, Acc) ->
lists:reverse("0." ++ Acc); lists:reverse("0." ++ Acc);
format([], ignore, Acc) -> format([], ignore, Acc) ->
@ -364,7 +350,6 @@ to_ascii(X) -> [X + 48]. %% ascii "1" is [49], "2" is [50], etc...
%% json string escaping, for utf8 binaries. escape the json control sequences to their %% json string escaping, for utf8 binaries. escape the json control sequences to their
%% json equivalent, escape other control characters to \uXXXX sequences, everything %% json equivalent, escape other control characters to \uXXXX sequences, everything
%% else should be a legal json string component %% else should be a legal json string component
json_escape(String) -> json_escape(String) ->
json_escape(String, <<>>). json_escape(String, <<>>).
@ -400,6 +385,7 @@ json_escape_sequence(C) when C < 16#20 ->
<<_:8, A:4, B:4>> = <<C:16>>, % first two hex digits are always zero <<_:8, A:4, B:4>> = <<C:16>>, % first two hex digits are always zero
<<$\\, $u, $0, $0, (to_hex(A)), (to_hex(B))>>. <<$\\, $u, $0, $0, (to_hex(A)), (to_hex(B))>>.
to_hex(15) -> $f; to_hex(15) -> $f;
to_hex(14) -> $e; to_hex(14) -> $e;
to_hex(13) -> $d; to_hex(13) -> $d;

View file

@ -24,10 +24,11 @@
-module(jsx_format). -module(jsx_format).
-author("alisdairsullivan@yahoo.ca"). -author("alisdairsullivan@yahoo.ca").
-export([format/2]). -export([format/2]).
-include("./include/jsx_types.hrl"). -include("./include/jsx_format.hrl").
-ifdef(test). -ifdef(test).
@ -35,33 +36,10 @@
-endif. -endif.
-record(opts, {
space = 0,
indent = 0,
output_encoding = utf8,
strict = true
}).
-define(newline, $\n).
-define(space, 16#20). %% ascii code for space
-define(quote, $\").
-define(comma, $,).
-define(colon, $:).
-define(start_object, ${).
-define(end_object, $}).
-define(start_array, $[).
-define(end_array, $]).
-spec format(JSON::binary(), Opts::format_opts()) -> binary() | iolist().
format(JSON, Opts) when is_binary(JSON) -> format(JSON, Opts) when is_binary(JSON) ->
P = jsx:parser(extract_parser_opts(Opts)), P = jsx:parser(extract_parser_opts(Opts)),
format(fun() -> P(JSON) end, Opts); format(fun() -> P(JSON) end, Opts);
format(F, OptsList) when is_function(F) -> format(F, OptsList) when is_function(F) ->
Opts = parse_opts(OptsList, #opts{}), Opts = parse_opts(OptsList, #opts{}),
{Continue, String} = format_something(F(), Opts, 0), {Continue, String} = format_something(F(), Opts, 0),
@ -125,7 +103,8 @@ format_object({event, {key, Key}, Next}, Acc, Opts, Level) ->
Level Level
) )
end. end.
format_array({event, end_array, Next}, Acc, _Opts, _Level) -> format_array({event, end_array, Next}, Acc, _Opts, _Level) ->
{Next, Acc}; {Next, Acc};
format_array(Event, Acc, Opts, Level) -> format_array(Event, Acc, Opts, Level) ->
@ -138,10 +117,6 @@ format_array(Event, Acc, Opts, Level) ->
end. end.
-define(is_utf_encoding(X),
X == utf8; X == utf16; X == utf32; X == {utf16, little}; X == {utf32, little}
).
encode(Acc, Opts) when is_list(Acc) -> encode(Acc, Opts) when is_list(Acc) ->
case Opts#opts.output_encoding of case Opts#opts.output_encoding of
iolist -> Acc iolist -> Acc

View file

@ -8,9 +8,7 @@
-file("./include/jsx_decoder.hrl", 1). -file("./include/jsx_decoder.hrl", 1).
-file("priv/jsx_decoder_template.erl", 35). -file("./include/jsx_common.hrl", 1).
-file("./include/jsx_types.hrl", 1).
-type jsx_opts() :: [jsx_opt()]. -type jsx_opts() :: [jsx_opt()].
@ -51,6 +49,12 @@
| {error, badjson} | {error, badjson}
| ok. | ok.
-type supported_utf() :: utf8
| utf16
| {utf16, little}
| utf32
| {utf32, little}.
-type eep0018() :: eep0018_object() | eep0018_array(). -type eep0018() :: eep0018_object() | eep0018_array().
-type eep0018_array() :: [eep0018_term()]. -type eep0018_array() :: [eep0018_term()].
@ -71,12 +75,6 @@
-type eep0018_number() :: float() | integer(). -type eep0018_number() :: float() | integer().
-type supported_utf() :: utf8
| utf16
| {utf16, little}
| utf32
| {utf32, little}.
-type encoder_opts() :: [encoder_opt()]. -type encoder_opts() :: [encoder_opt()].
-type encoder_opt() :: {strict, true | false} -type encoder_opt() :: {strict, true | false}
@ -111,11 +109,13 @@
| indent | indent
| {output_encoding, supported_utf()}. | {output_encoding, supported_utf()}.
-file("priv/jsx_decoder_template.erl", 36). -file("./include/jsx_decoder.hrl", 24).
-spec parse(JSON :: eep0018(), Opts :: jsx_opts()) -> -spec parse(JSON :: eep0018(), Opts :: jsx_opts()) ->
jsx_parser_result(). jsx_parser_result().
-file("priv/jsx_decoder_template.erl", 35).
parse(JSON, Opts) -> parse(JSON, Opts) ->
start(JSON, [], Opts). start(JSON, [], Opts).

View file

@ -8,9 +8,7 @@
-file("./include/jsx_decoder.hrl", 1). -file("./include/jsx_decoder.hrl", 1).
-file("priv/jsx_decoder_template.erl", 35). -file("./include/jsx_common.hrl", 1).
-file("./include/jsx_types.hrl", 1).
-type jsx_opts() :: [jsx_opt()]. -type jsx_opts() :: [jsx_opt()].
@ -51,6 +49,12 @@
| {error, badjson} | {error, badjson}
| ok. | ok.
-type supported_utf() :: utf8
| utf16
| {utf16, little}
| utf32
| {utf32, little}.
-type eep0018() :: eep0018_object() | eep0018_array(). -type eep0018() :: eep0018_object() | eep0018_array().
-type eep0018_array() :: [eep0018_term()]. -type eep0018_array() :: [eep0018_term()].
@ -71,12 +75,6 @@
-type eep0018_number() :: float() | integer(). -type eep0018_number() :: float() | integer().
-type supported_utf() :: utf8
| utf16
| {utf16, little}
| utf32
| {utf32, little}.
-type encoder_opts() :: [encoder_opt()]. -type encoder_opts() :: [encoder_opt()].
-type encoder_opt() :: {strict, true | false} -type encoder_opt() :: {strict, true | false}
@ -111,11 +109,13 @@
| indent | indent
| {output_encoding, supported_utf()}. | {output_encoding, supported_utf()}.
-file("priv/jsx_decoder_template.erl", 36). -file("./include/jsx_decoder.hrl", 24).
-spec parse(JSON :: eep0018(), Opts :: jsx_opts()) -> -spec parse(JSON :: eep0018(), Opts :: jsx_opts()) ->
jsx_parser_result(). jsx_parser_result().
-file("priv/jsx_decoder_template.erl", 35).
parse(JSON, Opts) -> parse(JSON, Opts) ->
start(JSON, [], Opts). start(JSON, [], Opts).

View file

@ -8,9 +8,7 @@
-file("./include/jsx_decoder.hrl", 1). -file("./include/jsx_decoder.hrl", 1).
-file("priv/jsx_decoder_template.erl", 35). -file("./include/jsx_common.hrl", 1).
-file("./include/jsx_types.hrl", 1).
-type jsx_opts() :: [jsx_opt()]. -type jsx_opts() :: [jsx_opt()].
@ -51,6 +49,12 @@
| {error, badjson} | {error, badjson}
| ok. | ok.
-type supported_utf() :: utf8
| utf16
| {utf16, little}
| utf32
| {utf32, little}.
-type eep0018() :: eep0018_object() | eep0018_array(). -type eep0018() :: eep0018_object() | eep0018_array().
-type eep0018_array() :: [eep0018_term()]. -type eep0018_array() :: [eep0018_term()].
@ -71,12 +75,6 @@
-type eep0018_number() :: float() | integer(). -type eep0018_number() :: float() | integer().
-type supported_utf() :: utf8
| utf16
| {utf16, little}
| utf32
| {utf32, little}.
-type encoder_opts() :: [encoder_opt()]. -type encoder_opts() :: [encoder_opt()].
-type encoder_opt() :: {strict, true | false} -type encoder_opt() :: {strict, true | false}
@ -111,11 +109,13 @@
| indent | indent
| {output_encoding, supported_utf()}. | {output_encoding, supported_utf()}.
-file("priv/jsx_decoder_template.erl", 36). -file("./include/jsx_decoder.hrl", 24).
-spec parse(JSON :: eep0018(), Opts :: jsx_opts()) -> -spec parse(JSON :: eep0018(), Opts :: jsx_opts()) ->
jsx_parser_result(). jsx_parser_result().
-file("priv/jsx_decoder_template.erl", 35).
parse(JSON, Opts) -> parse(JSON, Opts) ->
start(JSON, [], Opts). start(JSON, [], Opts).

View file

@ -8,9 +8,7 @@
-file("./include/jsx_decoder.hrl", 1). -file("./include/jsx_decoder.hrl", 1).
-file("priv/jsx_decoder_template.erl", 35). -file("./include/jsx_common.hrl", 1).
-file("./include/jsx_types.hrl", 1).
-type jsx_opts() :: [jsx_opt()]. -type jsx_opts() :: [jsx_opt()].
@ -51,6 +49,12 @@
| {error, badjson} | {error, badjson}
| ok. | ok.
-type supported_utf() :: utf8
| utf16
| {utf16, little}
| utf32
| {utf32, little}.
-type eep0018() :: eep0018_object() | eep0018_array(). -type eep0018() :: eep0018_object() | eep0018_array().
-type eep0018_array() :: [eep0018_term()]. -type eep0018_array() :: [eep0018_term()].
@ -71,12 +75,6 @@
-type eep0018_number() :: float() | integer(). -type eep0018_number() :: float() | integer().
-type supported_utf() :: utf8
| utf16
| {utf16, little}
| utf32
| {utf32, little}.
-type encoder_opts() :: [encoder_opt()]. -type encoder_opts() :: [encoder_opt()].
-type encoder_opt() :: {strict, true | false} -type encoder_opt() :: {strict, true | false}
@ -111,11 +109,13 @@
| indent | indent
| {output_encoding, supported_utf()}. | {output_encoding, supported_utf()}.
-file("priv/jsx_decoder_template.erl", 36). -file("./include/jsx_decoder.hrl", 24).
-spec parse(JSON :: eep0018(), Opts :: jsx_opts()) -> -spec parse(JSON :: eep0018(), Opts :: jsx_opts()) ->
jsx_parser_result(). jsx_parser_result().
-file("priv/jsx_decoder_template.erl", 35).
parse(JSON, Opts) -> parse(JSON, Opts) ->
start(JSON, [], Opts). start(JSON, [], Opts).

View file

@ -8,9 +8,7 @@
-file("./include/jsx_decoder.hrl", 1). -file("./include/jsx_decoder.hrl", 1).
-file("priv/jsx_decoder_template.erl", 35). -file("./include/jsx_common.hrl", 1).
-file("./include/jsx_types.hrl", 1).
-type jsx_opts() :: [jsx_opt()]. -type jsx_opts() :: [jsx_opt()].
@ -51,6 +49,12 @@
| {error, badjson} | {error, badjson}
| ok. | ok.
-type supported_utf() :: utf8
| utf16
| {utf16, little}
| utf32
| {utf32, little}.
-type eep0018() :: eep0018_object() | eep0018_array(). -type eep0018() :: eep0018_object() | eep0018_array().
-type eep0018_array() :: [eep0018_term()]. -type eep0018_array() :: [eep0018_term()].
@ -71,12 +75,6 @@
-type eep0018_number() :: float() | integer(). -type eep0018_number() :: float() | integer().
-type supported_utf() :: utf8
| utf16
| {utf16, little}
| utf32
| {utf32, little}.
-type encoder_opts() :: [encoder_opt()]. -type encoder_opts() :: [encoder_opt()].
-type encoder_opt() :: {strict, true | false} -type encoder_opt() :: {strict, true | false}
@ -111,11 +109,13 @@
| indent | indent
| {output_encoding, supported_utf()}. | {output_encoding, supported_utf()}.
-file("priv/jsx_decoder_template.erl", 36). -file("./include/jsx_decoder.hrl", 24).
-spec parse(JSON :: eep0018(), Opts :: jsx_opts()) -> -spec parse(JSON :: eep0018(), Opts :: jsx_opts()) ->
jsx_parser_result(). jsx_parser_result().
-file("priv/jsx_decoder_template.erl", 35).
parse(JSON, Opts) -> parse(JSON, Opts) ->
start(JSON, [], Opts). start(JSON, [], Opts).

View file

@ -24,9 +24,12 @@
-module(jsx_verify). -module(jsx_verify).
-author("alisdairsullivan@yahoo.ca"). -author("alisdairsullivan@yahoo.ca").
-export([is_json/2]). -export([is_json/2]).
-include("./include/jsx_types.hrl").
-include("./include/jsx_verify.hrl").
-ifdef(test). -ifdef(test).
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
@ -34,8 +37,6 @@
-spec is_json(JSON::binary(), Opts::verify_opts()) -> true | false.
is_json(JSON, Opts) -> is_json(JSON, Opts) ->
Encoding = proplists:get_value(encoding, Opts, utf8), Encoding = proplists:get_value(encoding, Opts, utf8),
Comments = proplists:get_value(comments, Opts, false), Comments = proplists:get_value(comments, Opts, false),