aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/expat_erl.c152
-rw-r--r--src/stringprep/stringprep.erl8
-rw-r--r--src/xml_stream.erl10
3 files changed, 94 insertions, 76 deletions
diff --git a/src/expat_erl.c b/src/expat_erl.c
index 2df857d8f..8cc9f2903 100644
--- a/src/expat_erl.c
+++ b/src/expat_erl.c
@@ -106,6 +106,9 @@ int ei_x_encode_string_fixed(ei_x_buff* x, const char* s)
#define XML_CDATA 2
#define XML_ERROR 3
+#define PARSE_COMMAND 0
+
+ei_x_buff event_buf;
typedef struct {
ErlDrvPort port;
@@ -117,44 +120,39 @@ void *erlXML_StartElementHandler(expat_data *d,
const XML_Char **atts)
{
int i;
- ei_x_buff buf;
-
- ei_x_new_with_version(&buf);
- ei_x_encode_tuple_header(&buf, 2);
- ei_x_encode_long(&buf, XML_START);
- ei_x_encode_tuple_header(&buf, 2);
- ei_x_encode_string_fixed(&buf, name);
-
+
+ ei_x_encode_list_header(&event_buf, 1);
+ ei_x_encode_tuple_header(&event_buf, 2);
+ ei_x_encode_long(&event_buf, XML_START);
+ ei_x_encode_tuple_header(&event_buf, 2);
+ ei_x_encode_string_fixed(&event_buf, name);
+
for (i = 0; atts[i]; i += 2) {}
- ei_x_encode_list_header(&buf, i/2);
-
- for (i = 0; atts[i]; i += 2)
+ if (i > 0)
{
- ei_x_encode_tuple_header(&buf, 2);
- ei_x_encode_string_fixed(&buf, atts[i]);
- ei_x_encode_string_fixed(&buf, atts[i+1]);
+ ei_x_encode_list_header(&event_buf, i/2);
+
+ for (i = 0; atts[i]; i += 2)
+ {
+ ei_x_encode_tuple_header(&event_buf, 2);
+ ei_x_encode_string_fixed(&event_buf, atts[i]);
+ ei_x_encode_string_fixed(&event_buf, atts[i+1]);
+ }
}
-
- ei_x_encode_empty_list(&buf);
-
- driver_output(d->port, buf.buff, buf.index);
- ei_x_free(&buf);
+
+ ei_x_encode_empty_list(&event_buf);
+
return NULL;
}
void *erlXML_EndElementHandler(expat_data *d,
const XML_Char *name)
{
- ei_x_buff buf;
-
- ei_x_new_with_version(&buf);
- ei_x_encode_tuple_header(&buf, 2);
- ei_x_encode_long(&buf, XML_END);
- ei_x_encode_string_fixed(&buf, name);
-
- driver_output(d->port, buf.buff, buf.index);
- ei_x_free(&buf);
+ ei_x_encode_list_header(&event_buf, 1);
+ ei_x_encode_tuple_header(&event_buf, 2);
+ ei_x_encode_long(&event_buf, XML_END);
+ ei_x_encode_string_fixed(&event_buf, name);
return NULL;
}
@@ -162,15 +160,10 @@ void *erlXML_CharacterDataHandler(expat_data *d,
const XML_Char *s,
int len)
{
- ei_x_buff buf;
-
- ei_x_new_with_version(&buf);
- ei_x_encode_tuple_header(&buf, 2);
- ei_x_encode_long(&buf, XML_CDATA);
- ei_x_encode_string_len_fixed(&buf, s, len);
-
- driver_output(d->port, buf.buff, buf.index);
- ei_x_free(&buf);
+ ei_x_encode_list_header(&event_buf, 1);
+ ei_x_encode_tuple_header(&event_buf, 2);
+ ei_x_encode_long(&event_buf, XML_CDATA);
+ ei_x_encode_string_len_fixed(&event_buf, s, len);
return NULL;
}
@@ -182,6 +175,8 @@ static ErlDrvData expat_erl_start(ErlDrvPort port, char *buff)
d->parser = XML_ParserCreate("UTF-8");
XML_SetUserData(d->parser, d);
+ set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
+
XML_SetStartElementHandler(
d->parser, (XML_StartElementHandler)erlXML_StartElementHandler);
XML_SetEndElementHandler(
@@ -199,48 +194,65 @@ static void expat_erl_stop(ErlDrvData handle)
driver_free((char*)handle);
}
-static void expat_erl_output(ErlDrvData handle, char *buff, int bufflen)
+static int expat_erl_control(ErlDrvData drv_data,
+ unsigned int command,
+ char *buf, int len,
+ char **rbuf, int rlen)
{
- expat_data* d = (expat_data*)handle;
+ expat_data* d = (expat_data*)drv_data;
int res, errcode;
char *errstring;
- ei_x_buff buf;
-
- res = XML_Parse(d->parser, buff, bufflen, 0);
+ ErlDrvBinary *b;
+ size_t size;
- if(!res)
+ switch (command)
{
- errcode = XML_GetErrorCode(d->parser);
- errstring = (char *)XML_ErrorString(errcode);
-
- ei_x_new_with_version(&buf);
- ei_x_encode_tuple_header(&buf, 2);
- ei_x_encode_long(&buf, XML_ERROR);
- ei_x_encode_tuple_header(&buf, 2);
- ei_x_encode_long(&buf, errcode);
- ei_x_encode_string_fixed(&buf, errstring);
-
- driver_output(d->port, buf.buff, buf.index);
- ei_x_free(&buf);
+ case PARSE_COMMAND:
+ ei_x_new_with_version(&event_buf);
+ res = XML_Parse(d->parser, buf, len, 0);
+
+ if(!res)
+ {
+ errcode = XML_GetErrorCode(d->parser);
+ errstring = (char *)XML_ErrorString(errcode);
+
+ ei_x_encode_list_header(&event_buf, 1);
+ ei_x_encode_tuple_header(&event_buf, 2);
+ ei_x_encode_long(&event_buf, XML_ERROR);
+ ei_x_encode_tuple_header(&event_buf, 2);
+ ei_x_encode_long(&event_buf, errcode);
+ ei_x_encode_string_fixed(&event_buf, errstring);
+ }
+
+ ei_x_encode_empty_list(&event_buf);
+
+ size = event_buf.index;
+
+ b = driver_alloc_binary(size);
+ memcpy(b->orig_bytes, event_buf.buff, size);
+
+ ei_x_free(&event_buf);
+
+ *rbuf = (char *)b;
+ return size;
+ default:
+ return 0;
}
-
- //driver_output(d->port, &res, 1);
}
-
-
ErlDrvEntry expat_driver_entry = {
- NULL, /* F_PTR init, N/A */
- expat_erl_start, /* L_PTR start, called when port is opened */
- expat_erl_stop, /* F_PTR stop, called when port is closed */
- expat_erl_output, /* F_PTR output, called when erlang has sent */
- NULL, /* F_PTR ready_input, called when input descriptor ready */
- NULL, /* F_PTR ready_output, called when output descriptor ready */
- "expat_erl", /* char *driver_name, the argument to open_port */
- NULL, /* F_PTR finish, called when unloaded */
- NULL, /* F_PTR control, port_command callback */
- NULL, /* F_PTR timeout, reserved */
- NULL /* F_PTR outputv, reserved */
+ NULL, /* F_PTR init, N/A */
+ expat_erl_start, /* L_PTR start, called when port is opened */
+ expat_erl_stop, /* F_PTR stop, called when port is closed */
+ NULL, /* F_PTR output, called when erlang has sent */
+ NULL, /* F_PTR ready_input, called when input descriptor ready */
+ NULL, /* F_PTR ready_output, called when output descriptor ready */
+ "expat_erl", /* char *driver_name, the argument to open_port */
+ NULL, /* F_PTR finish, called when unloaded */
+ NULL, /* handle */
+ expat_erl_control, /* F_PTR control, port_command callback */
+ NULL, /* F_PTR timeout, reserved */
+ NULL /* F_PTR outputv, reserved */
};
DRIVER_INIT(expat_erl) /* must match name in driver_entry */
diff --git a/src/stringprep/stringprep.erl b/src/stringprep/stringprep.erl
index 58360b292..ac06a0965 100644
--- a/src/stringprep/stringprep.erl
+++ b/src/stringprep/stringprep.erl
@@ -26,6 +26,8 @@
code_change/3,
terminate/2]).
+-define(STRINGPREP_PORT, stringprep_port).
+
-define(NAMEPREP_COMMAND, 1).
-define(NODEPREP_COMMAND, 2).
-define(RESOURCEPREP_COMMAND, 3).
@@ -39,8 +41,7 @@ start_link() ->
init([]) ->
ok = erl_ddll:load_driver(ejabberd:get_so_path(), stringprep_drv),
Port = open_port({spawn, stringprep_drv}, []),
- ets:new(stringprep_table, [set, public, named_table]),
- ets:insert(stringprep_table, {port, Port}),
+ register(?STRINGPREP_PORT, Port),
{ok, Port}.
@@ -84,8 +85,7 @@ resourceprep(String) ->
control(?RESOURCEPREP_COMMAND, String).
control(Command, String) ->
- [{port, Port} | _] = ets:lookup(stringprep_table, port),
- case port_control(Port, Command, String) of
+ case port_control(?STRINGPREP_PORT, Command, String) of
[0 | _] -> error;
[1 | Res] -> Res
end.
diff --git a/src/xml_stream.erl b/src/xml_stream.erl
index b81575a44..8a892bf30 100644
--- a/src/xml_stream.erl
+++ b/src/xml_stream.erl
@@ -17,6 +17,8 @@
-define(XML_CDATA, 2).
-define(XML_ERROR, 3).
+-define(PARSE_COMMAND, 0).
+
start(CallbackPid) ->
spawn(?MODULE, init, [CallbackPid]).
@@ -38,8 +40,12 @@ loop(CallbackPid, Port, Stack) ->
Data = binary_to_term(Bin),
loop(CallbackPid, Port, process_data(CallbackPid, Stack, Data));
{_From, {send, Str}} ->
- Port ! {self(), {command, Str}},
- loop(CallbackPid, Port, Stack);
+ Res = port_control(Port, ?PARSE_COMMAND, Str),
+ NewStack = lists:foldl(
+ fun(Data, St) ->
+ process_data(CallbackPid, St, Data)
+ end, Stack, binary_to_term(Res)),
+ loop(CallbackPid, Port, NewStack);
{'DOWN', _Ref, _Type, _Object, _Info} ->
ok
end.