Skip to content

Commit

Permalink
Tagging NIF parsing results with {ok, _}
Browse files Browse the repository at this point in the history
  • Loading branch information
paulgray committed Jul 18, 2011
1 parent 8179ffe commit eaa90a5
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 12 deletions.
4 changes: 3 additions & 1 deletion c_src/exml.c
Expand Up @@ -141,7 +141,9 @@ ERL_NIF_TERM parse(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
enif_make_string(env, errstring, ERL_NIF_LATIN1));
}

return parser_data->result;
return enif_make_tuple(env, 2,
enif_make_atom(env, "ok"),
parser_data->result);
};

static int load(ErlNifEnv* env, void **priv, ERL_NIF_TERM info)
Expand Down
9 changes: 7 additions & 2 deletions src/exml.erl
Expand Up @@ -23,9 +23,14 @@ new_parser() ->
free_parser(_Parser) ->
throw({?MODULE, nif_not_loaded}).

-spec parse(term(), binary(), boolean()) -> list().
-spec parse(term(), binary(), boolean()) -> {ok, list()} | {error, string()}.
parse(Parser, Data, Final) ->
lists:reverse(parse_nif(Parser, Data, bool(Final))).
case parse_nif(Parser, Data, bool(Final)) of
{ok, Res} ->
{ok, lists:reverse(Res)};
Error ->
Error
end.

-spec parse_nif(term(), binary(), integer()) -> list().
parse_nif(_Parser, _Data, _Final) ->
Expand Down
63 changes: 63 additions & 0 deletions test/benchmarks.erl
@@ -0,0 +1,63 @@
%%%-------------------------------------------------------------------
%%% @author Michal Ptaszek <michal.ptaszek@erlang-solutions.com>
%%% @copyright (C) 2011, Erlang Solutions Ltd.
%%% @doc A set of benchmarks comparing expat_sax_parser, erlsom and exml.
%%%
%%% @end
%%% Created : 15 Jul 2011 by Michal Ptaszek <michal.ptaszek@erlang-solutions.com>
%%%-------------------------------------------------------------------
-module(benchmarks).

-export([run/2,
run_exml/3,
run_erlsom/3,
run_xmerl/3]).

run(Path, N) ->
application:start(exml),
[apply(?MODULE, F, [Path, N, []]) || F <- [run_exml, run_erlsom, run_xmerl]],
application:stop(exml).

run_exml(_, 0, Acc) ->
Avg = avg(Acc),
io:format("Total: ~w~n"
"Avg: ~w~n"
"Std dev.: ~w~n",
[total(Acc), Avg, std_dev(Acc, Avg)]);
run_exml(Path, N, Acc) ->
{ok, Fd} = file:open(Path, [read, binary, read_ahead]),
T = now(),

{ok, Parser} = exml:new_parser(),
run_exml(Fd, Parser),
exml:free_parser(Parser),

Diff = timer:now_diff(now(), T),
run_exml(Path, N-1, [Diff | Acc]).

run_exml(Fd, Parser) ->
case file:read_line(Fd) of
eof ->
ok;
{ok, Data} ->
exml:parse(Parser, Data, true),
run_exml(Fd, Parser)
end.

total(Times) ->
lists:sum(Times).

avg(Times) ->
total(Times)/length(Times).

std_dev(Times, Avg) ->
Sums = lists:foldl(
fun(V, Acc) -> D = V - Avg, Acc + (D * D) end,
0, Times),
math:sqrt(Sums / (length(Times) - 1)).

run_xmerl(_, _, _) ->
ok.

run_erlsom(_, _, _) ->
ok.
18 changes: 9 additions & 9 deletions test/exml_tests.erl
Expand Up @@ -23,33 +23,33 @@ application_test() ->
basic_parse_test() ->
{ok, Parser} = exml:new_parser(),

?assertEqual([{xml_element_start, <<"test">>, []},
{xml_element_end, <<"test">>}],
?assertEqual({ok, [{xml_element_start, <<"test">>, []},
{xml_element_end, <<"test">>}]},
exml:parse(Parser, <<"<test/>">>, true)),
?assertEqual(ok, exml:free_parser(Parser)).

attrs_parsing_test() ->
{ok, Parser} = exml:new_parser(),

?assertEqual([{xml_element_start, <<"test">>, [{<<"attr">>, <<"val">>},
{<<"second_attr">>, <<"val2">>}]},
{xml_element_end, <<"test">>}],
?assertEqual({ok, [{xml_element_start, <<"test">>, [{<<"attr">>, <<"val">>},
{<<"second_attr">>, <<"val2">>}]},
{xml_element_end, <<"test">>}]},
exml:parse(Parser, <<"<test attr='val' second_attr='val2'/>">>, true)),
?assertEqual(ok, exml:free_parser(Parser)).

open_tag_test() ->
{ok, Parser} = exml:new_parser(),

?assertEqual([{xml_element_start, <<"test">>, []}],
?assertEqual({ok, [{xml_element_start, <<"test">>, []}]},
exml:parse(Parser, <<"<test>">>, false)),
?assertEqual(ok, exml:free_parser(Parser)).

cdata_test() ->
{ok, Parser} = exml:new_parser(),

?assertEqual([{xml_element_start, <<"test">>, []},
{xml_cdata, <<"some_cdata stuff">>},
{xml_element_end, <<"test">>}],
?assertEqual({ok, [{xml_element_start, <<"test">>, []},
{xml_cdata, <<"some_cdata stuff">>},
{xml_element_end, <<"test">>}]},
exml:parse(Parser, <<"<test>some_cdata stuff</test>">>, true)),
?assertEqual(ok, exml:free_parser(Parser)).

Expand Down

0 comments on commit eaa90a5

Please sign in to comment.