summaryrefslogtreecommitdiff
path: root/src/expat_erl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/expat_erl.c')
-rw-r--r--src/expat_erl.c128
1 files changed, 112 insertions, 16 deletions
diff --git a/src/expat_erl.c b/src/expat_erl.c
index a1a950e3..82be2307 100644
--- a/src/expat_erl.c
+++ b/src/expat_erl.c
@@ -5,6 +5,107 @@
#include <ei.h>
#include <expat.h>
+#define EI_ENCODE_STRING_BUG
+
+#ifdef EI_ENCODE_STRING_BUG
+
+/*
+ * Workaround for EI encode_string bug
+ */
+
+#define put8(s,n) do { \
+ (s)[0] = (char)((n) & 0xff); \
+ (s) += 1; \
+} while (0)
+
+#define put16be(s,n) do { \
+ (s)[0] = ((n) >> 8) & 0xff; \
+ (s)[1] = (n) & 0xff; \
+ (s) += 2; \
+} while (0)
+
+#define put32be(s,n) do { \
+ (s)[0] = ((n) >> 24) & 0xff; \
+ (s)[1] = ((n) >> 16) & 0xff; \
+ (s)[2] = ((n) >> 8) & 0xff; \
+ (s)[3] = (n) & 0xff; \
+ (s) += 4; \
+} while (0)
+
+int ei_encode_string_len_fixed(char *buf, int *index, const char *p, int len)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+ int i;
+
+ if (len <= 0xffff) {
+ if (!buf) s += 3;
+ else {
+ put8(s,ERL_STRING_EXT);
+ put16be(s,len);
+ memmove(s,p,len); /* unterminated string */
+ }
+ s += len;
+ }
+ else {
+ if (!buf) s += 6 + (2*len);
+ else {
+ /* strings longer than 65535 are encoded as lists */
+ put8(s,ERL_LIST_EXT);
+ put32be(s,len);
+
+ for (i=0; i<len; i++) {
+ put8(s,ERL_SMALL_INTEGER_EXT);
+ put8(s,p[i]);
+ }
+
+ put8(s,ERL_NIL_EXT);
+ }
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
+
+int ei_encode_string_fixed(char *buf, int *index, const char *p)
+{
+ return ei_encode_string_len_fixed(buf, index, p, strlen(p));
+}
+
+int ei_x_encode_string_len_fixed(ei_x_buff* x, const char* s, int len)
+{
+ int i = x->index;
+ ei_encode_string_len_fixed(NULL, &i, s, len);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_string_len_fixed(x->buff, &x->index, s, len);
+}
+
+int ei_x_encode_string_fixed(ei_x_buff* x, const char* s)
+{
+ return ei_x_encode_string_len_fixed(x, s, strlen(s));
+}
+
+#else
+
+#define ei_encode_string_len_fixed(buf, index, p, len) \
+ ei_encode_string_len(buf, index, p, len)
+#define ei_encode_string_fixed(buf, index, p) \
+ ei_encode_string(buf, index, p)
+#define ei_x_encode_string_len_fixed(x, s, len) \
+ ei_x_encode_string_len(x, s, len)
+#define ei_x_encode_string_fixed(x, s) \
+ ei_x_encode_string(x, s)
+
+#endif
+
+#define XML_START 0
+#define XML_END 1
+#define XML_CDATA 2
+#define XML_ERROR 3
+
+
typedef struct {
ErlDrvPort port;
XML_Parser parser;
@@ -19,19 +120,19 @@ void *erlXML_StartElementHandler(expat_data *d,
ei_x_new_with_version(&buf);
ei_x_encode_tuple_header(&buf, 2);
- ei_x_encode_atom(&buf, "xmlstart");
+ ei_x_encode_long(&buf, XML_START);
ei_x_encode_tuple_header(&buf, 2);
- ei_x_encode_string(&buf, name);
+ ei_x_encode_string_fixed(&buf, name);
for (i = 0; atts[i]; i += 2) {}
ei_x_encode_list_header(&buf, i/2);
-
+
for (i = 0; atts[i]; i += 2)
{
ei_x_encode_tuple_header(&buf, 2);
- ei_x_encode_string(&buf, atts[i]);
- ei_x_encode_string(&buf, atts[i+1]);
+ ei_x_encode_string_fixed(&buf, atts[i]);
+ ei_x_encode_string_fixed(&buf, atts[i+1]);
}
ei_x_encode_empty_list(&buf);
@@ -48,8 +149,8 @@ void *erlXML_EndElementHandler(expat_data *d,
ei_x_new_with_version(&buf);
ei_x_encode_tuple_header(&buf, 2);
- ei_x_encode_atom(&buf, "xmlend");
- ei_x_encode_string(&buf, name);
+ 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);
@@ -64,8 +165,8 @@ void *erlXML_CharacterDataHandler(expat_data *d,
ei_x_new_with_version(&buf);
ei_x_encode_tuple_header(&buf, 2);
- ei_x_encode_atom(&buf, "xmlcdata");
- ei_x_encode_string_len(&buf, s, len);
+ 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);
@@ -104,11 +205,6 @@ static void expat_erl_output(ErlDrvData handle, char *buff, int bufflen)
char *errstring;
ei_x_buff buf;
- /*buff[bufflen] = 0;
-
- fprintf(stderr, "RCVD: '%s'\n", buff);
- fflush(stderr);*/
-
res = XML_Parse(d->parser, buff, bufflen, 0);
if(!res)
@@ -118,10 +214,10 @@ static void expat_erl_output(ErlDrvData handle, char *buff, int bufflen)
ei_x_new_with_version(&buf);
ei_x_encode_tuple_header(&buf, 2);
- ei_x_encode_atom(&buf, "xmlerror");
+ ei_x_encode_long(&buf, XML_ERROR);
ei_x_encode_tuple_header(&buf, 2);
ei_x_encode_long(&buf, errcode);
- ei_x_encode_string(&buf, errstring);
+ ei_x_encode_string_fixed(&buf, errstring);
driver_output(d->port, buf.buff, buf.index);
ei_x_free(&buf);