massive simplification of api, operation and internals. removes all demo modules temporarily

This commit is contained in:
alisdair sullivan 2011-08-31 18:52:01 -07:00
parent 7fbb29369b
commit 7e88a14525
19 changed files with 1358 additions and 3086 deletions

View file

@ -1,234 +0,0 @@
%% 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.
-module(jsx_verify).
-export([is_json/2]).
-include("../include/jsx_common.hrl").
-record(verify_opts, {
repeated_keys = true,
naked_values = true
}).
-spec is_json(JSON::binary(), Opts::verify_opts()) -> true | false
; (Terms::list(jsx_encodeable()), Opts::verify_opts()) -> true | false.
is_json(JSON, OptsList) when is_binary(JSON) ->
F = jsx:decoder(extract_parser_opts(OptsList)),
verify(F(JSON), parse_opts(OptsList));
is_json(JSON, OptsList) when is_list(JSON) ->
F = jsx:encoder(extract_parser_opts(OptsList)),
verify(F(JSON), parse_opts(OptsList)).
extract_parser_opts(Opts) ->
extract_parser_opts(Opts, []).
extract_parser_opts([], Acc) -> Acc;
extract_parser_opts([{K,V}|Rest], Acc) ->
case lists:member(K, [encoding]) of
true -> [{K,V}] ++ Acc
; false -> extract_parser_opts(Rest, Acc)
end;
extract_parser_opts([K|Rest], Acc) ->
case lists:member(K, [encoding]) of
true -> [K] ++ Acc
; false -> extract_parser_opts(Rest, Acc)
end.
parse_opts(Opts) -> parse_opts(Opts, #verify_opts{}).
parse_opts([{repeated_keys, Val}|Rest], Opts)
when Val =:= true; Val =:= false ->
parse_opts(Rest, Opts#verify_opts{repeated_keys = Val});
parse_opts([repeated_keys|Rest], Opts) ->
parse_opts(Rest, Opts#verify_opts{repeated_keys = true});
parse_opts([{naked_values, Val}|Rest], Opts)
when Val =:= true; Val =:= false ->
parse_opts(Rest, Opts#verify_opts{naked_values = Val});
parse_opts([naked_values|Rest], Opts) ->
parse_opts(Rest, Opts#verify_opts{naked_values = true});
parse_opts([{encoding, _}|Rest], Opts) ->
parse_opts(Rest, Opts);
parse_opts([encoding|Rest], Opts) ->
parse_opts(Rest, Opts);
parse_opts([], Opts) ->
Opts.
verify({error, {badjson, _}}, _Opts) -> false;
verify({jsx, incomplete, More}, Opts) -> verify(More(end_stream), Opts);
verify({jsx, [First|Rest], _}, Opts=#verify_opts{naked_values=false}) ->
case First of
start_object -> verify(Rest, Opts, [])
; start_array -> verify(Rest, Opts, [])
; _ -> false
end;
verify({jsx, Terms, _}, Opts) -> verify(Terms, Opts, []).
verify([end_json], _Opts, _Keys) -> true;
%% allocate new key accumulator at start_object, discard it at end_object
verify([start_object|Rest], Opts=#verify_opts{repeated_keys=false}, Keys) ->
verify(Rest, Opts, [[]] ++ Keys);
verify([end_object|Rest], Opts=#verify_opts{repeated_keys=false}, [_|Keys]) ->
verify(Rest, Opts, Keys);
%% check to see if key has already been encountered, if not add it to the key
%% accumulator and continue, else return false
verify([{key, Key}|Rest], Opts=#verify_opts{repeated_keys=false}, [Current|Keys]) ->
case lists:member(Key, Current) of
true -> false
; false -> verify(Rest, Opts, [[Key] ++ Current] ++ Keys)
end;
verify([_|Rest], Opts, Keys) -> verify(Rest, Opts, Keys);
verify(_, _, _) -> false.
%% eunit tests
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
true_test_() ->
[
{"empty object", ?_assert(is_json(<<"{}">>, []) =:= true)},
{"empty array", ?_assert(is_json(<<"[]">>, []) =:= true)},
{"whitespace",
?_assert(is_json(<<" \n \t \r [true] \t \n\r ">>,
[]
) =:= true
)
},
{"nested terms",
?_assert(is_json(
<<"[{ \"x\": [ {}, {}, {} ], \"y\": [{}] }, {}, [[[]]]]">>,
[]
) =:= true
)
},
{"numbers",
?_assert(is_json(
<<"[ -1.0, -1, -0, 0, 1e-1, 1, 1.0, 1e1 ]">>,
[]
) =:= true
)
},
{"strings",
?_assert(is_json(
<<"[ \"a\", \"string\", \"in\", \"multiple\", \"acts\" ]">>,
[]
) =:= true
)
},
{"literals",
?_assert(is_json(<<"[ true, false, null ]">>, []) =:= true)
},
{"nested objects",
?_assert(is_json(<<"{\"key\": { \"key\": true}}">>, []) =:= true)
},
{"naked true", ?_assert(is_json(<<"true">>, []) =:= true)},
{"naked number", ?_assert(is_json(<<"1">>, []) =:= true)},
{"naked string",
?_assert(is_json(<<"\"i am not really json\"">>, []) =:= true)
}
].
false_test_() ->
[
{"unbalanced list", ?_assert(is_json(<<"[[[]]">>, []) =:= false)},
{"trailing comma",
?_assert(is_json(<<"[ true, false, null, ]">>, []) =:= false)
}
].
repeated_keys_test_() ->
[
{"repeated key forbidden",
?_assert(is_json(
<<"{\"key\": true, \"key\": true}">>,
[{repeated_keys, false}]
) =:= false
)
},
{"repeated key allowed",
?_assert(is_json(
<<"{\"key\": true, \"key\": true}">>,
[{repeated_keys, true}]
) =:= true
)
},
{"repeated key nested",
?_assert(is_json(
<<"{\"a\": {\"a\": {\"a\": true, \"a\":false}}}">>,
[{repeated_keys, false}]
) =:= false
)
}
].
naked_value_test_() ->
[
{"naked true",
?_assert(is_json(<<"true">>, []) =:= true)
},
{"naked number",
?_assert(is_json(<<"1">>, []) =:= true)
},
{"naked string",
?_assert(is_json(<<"\"i am not json\"">>, []) =:= true)
},
{"naked true",
?_assert(is_json(<<"true">>, [{naked_values, false}]) =:= false)
},
{"naked number",
?_assert(is_json(<<"1">>, [{naked_values, false}]) =:= false)
},
{"naked string",
?_assert(is_json(
<<"\"i am not json\"">>,
[{naked_values, false}]
) =:= false
)
}
].
terms_test_() ->
[
{"terms",
?_assert(is_json([start_object,
{key, <<"key">>},
{string, <<"value">>},
end_object
], []) =:= true
)}
].
-endif.