Skip to content

Commit 236c0ec

Browse files
authored
Merge pull request #50 from goodgamechat/use_maps
Add 'use_maps' option to fxml_stream.parse_element/2.
2 parents a26d40b + abbfda0 commit 236c0ec

File tree

4 files changed

+43
-14
lines changed

4 files changed

+43
-14
lines changed

c_src/fxml_stream.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -862,10 +862,25 @@ static ERL_NIF_TERM parse_element_nif(ErlNifEnv* env, int argc,
862862
{
863863
ERL_NIF_TERM el;
864864
ErlNifBinary bin;
865+
int use_maps = 0;
865866

866-
if (argc != 1)
867+
if (argc != 1 && argc != 2)
867868
return enif_make_badarg(env);
868869

870+
if (argc == 2) {
871+
if (!enif_is_list(env, argv[1]))
872+
return enif_make_badarg(env);
873+
874+
ERL_NIF_TERM head, tail = argv[1];
875+
while (enif_get_list_cell(env, tail, &head, &tail)) {
876+
char buf[16];
877+
if (enif_get_atom(env, head, buf, sizeof(buf), ERL_NIF_LATIN1)) {
878+
if (strcmp("use_maps", buf) == 0)
879+
use_maps = 1;
880+
}
881+
}
882+
}
883+
869884
if (!enif_inspect_binary(env, argv[0], &bin))
870885
return enif_make_badarg(env);
871886

@@ -874,6 +889,7 @@ static ERL_NIF_TERM parse_element_nif(ErlNifEnv* env, int argc,
874889
return enif_make_badarg(env);
875890

876891
state->send_env = env;
892+
state->use_maps = use_maps;
877893

878894
xmlel_stack_t *xmlel = enif_alloc(sizeof(xmlel_stack_t));
879895
if (!xmlel) {
@@ -1060,6 +1076,7 @@ static ErlNifFunc nif_funcs[] =
10601076
{"new", 3, new_nif},
10611077
{"parse", 2, parse_nif},
10621078
{"parse_element", 1, parse_element_nif},
1079+
{"parse_element", 2, parse_element_nif},
10631080
{"reset", 1, reset_nif},
10641081
{"close", 1, close_nif},
10651082
{"change_callback_pid", 2, change_callback_pid_nif}

src/fxml_stream.erl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
-on_load(init/0).
3131

3232
-export([new/1, new/2, new/3, parse/2, close/1, reset/1,
33-
change_callback_pid/2, parse_element/1]).
33+
change_callback_pid/2, parse_element/1, parse_element/2]).
3434

3535
-export([load_nif/0, load_nif/1]).
3636

@@ -113,3 +113,9 @@ close(_State) ->
113113

114114
parse_element(_Str) ->
115115
erlang:nif_error(nif_not_loaded).
116+
117+
-spec parse_element(binary(), [use_maps]) -> xmlel() |
118+
{error, atom()} |
119+
{error, {integer(), binary()}}.
120+
parse_element(_Str, _Options) ->
121+
erlang:nif_error(nif_not_loaded).

test/elixir/fast_xml_test.exs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,22 @@
1515
defmodule FastXMLTest do
1616
use ExUnit.Case
1717

18-
# TODO: we should be able to pass :use_maps option to :fxml_stream.parse_element/2
18+
test "Parse element can return Elixir structs" do
19+
assert %FastXML.El{name: "root"} == :fxml_stream.parse_element("<root></root>", [:use_maps])
20+
end
1921

2022
test "Stream parser can return Elixir structs" do
21-
s1 = :fxml_stream.new(self, :infinity, [:no_gen_server, :use_maps])
22-
s2 = :fxml_stream.parse(s1, "<root>")
23-
assert receive_stanza == %FastXML.StreamStart{name: "root"}
24-
s3 = :fxml_stream.parse(s2, "<xmlelement>content cdata</xmlelement>")
25-
assert receive_stanza == %FastXML.El{name: "xmlelement", children: ["content cdata"]}
26-
s4 = :fxml_stream.parse(s3, "<xmlelement><empty/><subelement attribute='true'>content cdata</subelement></xmlelement>")
27-
assert receive_stanza == %FastXML.El{name: "xmlelement", children: ["content cdata"]}
28-
s5 = :fxml_stream.parse(s4, "</root>")
29-
assert receive_stanza == %FastXML.StreamEnd{name: "root"}
30-
:fxml_stream.close(s5)
23+
:fxml_stream.new(self(), :infinity, [:no_gen_server, :use_maps])
24+
|> :fxml_stream.parse("<root>")
25+
|> :fxml_stream.parse("<xmlelement>content cdata</xmlelement>")
26+
|> :fxml_stream.parse("<xmlelement><empty/><subelement attribute='true'>content cdata</subelement></xmlelement>")
27+
|> :fxml_stream.parse("</root>")
28+
|> :fxml_stream.close()
29+
30+
assert receive_stanza() == %FastXML.StreamStart{name: "root"}
31+
assert receive_stanza() == %FastXML.El{name: "xmlelement", children: ["content cdata"]}
32+
assert receive_stanza() == %FastXML.El{name: "xmlelement", children: [%FastXML.El{name: "empty"}, %FastXML.El{name: "subelement", attrs: %{"attribute" => "true"}, children: ["content cdata"]}]}
33+
assert receive_stanza() == %FastXML.StreamEnd{name: "root"}
3134
end
3235

3336
test "Size of parsed stanza can be limited" do
@@ -49,7 +52,7 @@ defmodule FastXMLTest do
4952

5053
# TODO test mismatched tags
5154

52-
defp receive_stanza do
55+
defp receive_stanza() do
5356
receive do
5457
result ->
5558
result

test/fxml_test.erl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ tag_with_tags_test() ->
121121
{xmlcdata, <<"cdata2">>}]},
122122
fxml_stream:parse_element(<<"<root><a/>cdata1<b/>cdata2</root>">>)).
123123

124+
use_maps_test() ->
125+
?assertEqual(#{'__struct__' => 'Elixir.FastXML.El', name => <<"root">>, attrs => #{}, children => []}, fxml_stream:parse_element(<<"<root></root>">>, [use_maps])).
126+
124127
receiver(Acc) ->
125128
receive
126129
{'$gen_event', Msg} ->

0 commit comments

Comments
 (0)