@@ -3,8 +3,11 @@
3#include <stdlib.h>
3#include <stdlib.h>
4#include <string.h>
4#include <string.h>
5#include <assert.h>
5#include <assert.h>
6#include <stdio.h>
7#include <stdio.h>
8/////////////////////////////////////////////////////////////////////
11/////////////////////////////////////////////////////////////////////
@@ -41,8 +44,7 @@ typedef struct
43 int used_front; // front entries, stored for good
46 int used_front; // front entries, stored for good
44− int used_back; // back entries, stack based, copied into front on </close>
47+ int used_back; // back entries, stack based, copied into front
45− // back entries which haven't yet been closed have nodes.length == -1
46 node* nodes; // dynamically allocated buffer
48 node* nodes; // dynamically allocated buffer
47 node* alloc; // what to call free on
49 node* alloc; // what to call free on
48} node_buffer;
50} node_buffer;
@@ -51,24 +53,30 @@ typedef struct
51struct document
53struct document
53 const char* body; // pointer to initial argument, not owned by us
55 const char* body; // pointer to initial argument, not owned by us
54− int body_len; // length of the body
56+
57+ // things only used while parsing
58+ const char* cursor; // pointer to where we are in body
59+ const char* end; // pointer to one past the last char
60+ // if cursor is > end we have gone past the end
56 char* error_message;
62 char* error_message;
57 node_buffer nodes;
63 node_buffer nodes;
58 attr_buffer attrs;
64 attr_buffer attrs;
67+static inline int doc_length(const document* d) { return (int) (d->end - d->body); }
68+static inline int doc_position(const document* d) { return (int) (d->cursor - d->body); }
62/////////////////////////////////////////////////////////////////////
71/////////////////////////////////////////////////////////////////////
63// RENDER CODE
72// RENDER CODE
65typedef struct
74typedef struct
67− const document* d; // Document, used to get at the body
76+ const document* d;
68− char* buffer; // Buffer we are writing too
77+ char* buffer;
69− int length; // Length of buffer, do not write past the end.
78+ int length;
70− // No character is reserved for a NULL terminator.
79+ int cursor;
71− int cursor; // Cursor of where we are writing now
74static inline void render_char(render* r, char c)
82static inline void render_char(render* r, char c)
@@ -92,7 +100,7 @@ static inline void bound_str(str s, int mn, int mx)
93static void render_str(render* r, str s)
101static void render_str(render* r, str s)
95− bound_str(s, 0, r->d->body_len);
103+ bound_str(s, 0, doc_length(r->d));
96 for (int i = 0; i < s.length; i++)
104 for (int i = 0; i < s.length; i++)
97 render_char(r, r->d->body[s.start + i]);
105 render_char(r, r->d->body[s.start + i]);
@@ -101,7 +109,7 @@ static void render_tag(render* r, const node* n);
102static void render_content(render* r, const node* n)
110static void render_content(render* r, const node* n)
104− bound_str(n->inner, 0, r->d->body_len);
112+ bound_str(n->inner, 0, doc_length(r->d));
105 bound_str(n->nodes, 0, r->d->nodes.used_front);
113 bound_str(n->nodes, 0, r->d->nodes.used_front);
106 bound_str(n->attrs, 0, r->d->attrs.used);
114 bound_str(n->attrs, 0, r->d->attrs.used);
@@ -180,6 +188,7 @@ attr* hexml_node_attributes(const document* d, const node* n, int* res)
180 return &d->attrs.attrs[n->attrs.start];
188 return &d->attrs.attrs[n->attrs.start];
183attr* hexml_node_attribute(const document* d, const node* n, const char* s, int slen)
192attr* hexml_node_attribute(const document* d, const node* n, const char* s, int slen)
185 if (slen == -1) slen = (int) strlen(s);
194 if (slen == -1) slen = (int) strlen(s);
@@ -211,95 +220,33 @@ node* hexml_node_child(const document* d, const node* parent, const node* prev,
211/////////////////////////////////////////////////////////////////////
220/////////////////////////////////////////////////////////////////////
212// PARSING CODE
221// PARSING CODE
214−static inline node* node_alloc(node_buffer* b)
223+static inline void node_alloc(node_buffer* b, int ask)
216 int space = b->size - b->used_back - b->used_front;
225 int space = b->size - b->used_back - b->used_front;
217− if (space < 1)
226+ if (space >= ask) return;
219− int size2 = (b->size + 1000) * 2;
227+ int size2 = (b->size + 1000 + ask) * 2;
220− node* buf2 = malloc(size2 * sizeof(node));
228+ node* buf2 = malloc(size2 * sizeof(node));
221− assert(buf2);
229+ assert(buf2);
222− memcpy(buf2, b->nodes, b->used_front * sizeof(node));
230+ memcpy(buf2, b->nodes, b->used_front * sizeof(node));
223− memcpy(&buf2[size2 - b->used_back], &b->nodes[b->size - b->used_back], b->used_back * sizeof(node));
231+ memcpy(&buf2[size2 - b->used_back], &b->nodes[b->size - b->used_back], b->used_back * sizeof(node));
224− free(b->alloc);
232+ free(b->alloc);
225− b->size = size2;
233+ b->size = size2;
226− b->nodes = buf2;
234+ b->nodes = buf2;
227− b->alloc = buf2;
235+ b->alloc = buf2;
230− return &b->nodes[b->size - b->used_back];
233−// buffer[from .. from+n] = reverse (buffer[from .. from+n])
234−// The ranges completely overlap
235−static inline void reverse(node* buffer, int from, int n)
237− for (int to = from + n - 1; to > from; from++, to--)
239− node temp = buffer[to];
240− buffer[to] = buffer[from];
241− buffer[from] = temp;
245−// buffer[to .. to+n] = reverse (buffer[from .. from+n])
246−// The ranges may not overlap
247−static inline void memcpy_reverse(node* buffer, int from, int to, int n)
249− int end = from + n - 1;
250− for (int i = 0; i < n; i++)
251− buffer[to+i] = buffer[end-i];
254−// buffer[to .. to+n] = reverse (buffer[from .. from+n])
255−// The ranges may overlap
256−static inline void memmove_reverse(node* buffer, int from, int to, int n)
258− assert(from >= to); // always the case in my usages
260− memcpy_reverse(buffer, from, to, n);
263− int overlap = from - to;
264− memcpy_reverse(buffer, from, to + n - overlap, overlap);
265− reverse(buffer, to, n - overlap);
269−static inline str node_commit(node_buffer* b)
271− // first search for an "open" node (nodes.length == -1)
273− for (open = b->size - b->used_back; open < b->size; open++)
275− if (b->nodes[open].nodes.length == -1)
279− int n = open - (b->size - b->used_back);
280− memmove_reverse(b->nodes, b->size - b->used_back, b->used_front, n);
283− return start_length(b->used_front - n, n);
286−static inline attr* attr_alloc(attr_buffer* b)
238+static inline void attr_alloc(attr_buffer* b, int ask)
288− // Ensure there is at least one node left
289 int space = b->size - b->used;
240 int space = b->size - b->used;
290− if (space < 1)
241+ if (space >= ask) return;
292− int size2 = (b->size + 1000) * 2;
242+ int size2 = (b->size + 1000 + ask) * 2;
293− attr* buf2 = malloc(size2 * sizeof(attr));
243+ attr* buf2 = malloc(size2 * sizeof(attr));
294− assert(buf2);
244+ assert(buf2);
295− memcpy(buf2, b->attrs, b->used * sizeof(attr));
245+ memcpy(buf2, b->attrs, b->used * sizeof(attr));
296− free(b->alloc);
246+ free(b->alloc);
297− b->size = size2;
247+ b->size = size2;
298− b->attrs = buf2;
248+ b->attrs = buf2;
299− b->alloc = buf2;
249+ b->alloc = buf2;
302− return &b->attrs[b->used - 1];
305static void set_error(document* d, const char* msg)
252static void set_error(document* d, const char* msg)
@@ -316,49 +263,28 @@ static inline str gap(const char* ref, const char* start, const char* end)
318#define P_Abort(x) return x
265#define P_Abort(x) return x
319−#define P_Tag tag_start = p;
320#define P_NameStart name_start = p
266#define P_NameStart name_start = p
321#define P_NameEnd name_end = p
267#define P_NameEnd name_end = p
322−#define P_AttribsStart \
323− me = node_alloc(&d->nodes); \
324− me->attrs.start = d->attrs.used; \
325− me->name = gap(d->body, name_start, name_end);
326−#define P_AttribsEnd \
327− me->attrs = start_end(me->attrs.start, d->attrs.used);
328#define P_QuoteStart quote_start = p
268#define P_QuoteStart quote_start = p
329#define P_QuoteEnd \
269#define P_QuoteEnd \
330− attr* attr = attr_alloc(&d->attrs); \
271+ attr_alloc(&d->attrs, 1); \
331− attr->name = gap(d->body, name_start, name_end); \
272+ d->attrs.attrs[d->attrs.used].name = gap(d->body, name_start, name_end); \
332− attr->value = gap(d->body, quote_start, p);
273+ d->attrs.attrs[d->attrs.used].value = gap(d->body, quote_start, quote_end); \
275+#define P_AttribsStart printf("AttribsStart %s\n", p)
276+#define P_AttribsEnd printf("AttribsEnd %s\n", p)
277+#define P_Tag tag_start = p
333−#define P_TagComment \
278+#define P_TagComment printf("TagComment %s\n", p)
334− // No action required - comments just flow as normal text
335−#define P_TagOpen \
279+#define P_TagOpen printf("TagOpen %s\n", p)
336− me->nodes.length = -1; \
337− me->inner = gap(d->body, p, p); \
338− me->outer = gap(d->body, tag_start, tag_start);
339−#define P_TagClose \
280+#define P_TagClose printf("TagClose %s\n", p)
340− str nodes = node_commit(&d->nodes); \
341− if (d->nodes.used_back == 0) \
342− return "Closing tag with no openning"; \
343− me = &d->nodes.nodes[d->nodes.size - d->nodes.used_back]; \
344− me->nodes = nodes; \
345− if (me->name.length != gap(d->body, name_start, name_end).length || \
346− memcmp(&d->body[me->name.start], name_start, me->name.length) != 0) \
347− return "Mismatch in closing tag"; \
348− me->inner = gap(d->body, &d->body[me->inner.start], tag_start); \
349− me->outer = gap(d->body, &d->body[me->outer.start], p);
350#define P_TagOpenClose \
281#define P_TagOpenClose \
351− me->nodes = start_end(0, 0); \
352− me->inner = gap(d->body, p, p); \
353− me->outer = gap(d->body, tag_start, p);
282+ d->nodes.nodes[d->nodes.used_front].outer = gap(d->body, tag_start, p); \
283+ printf("TagOpenClose %s\n", p)
355−// Given the parsed string, return either NULL (success) or an error message (failure)
356static const char* parser(const char* p, document* d)
285static const char* parser(const char* p, document* d)
358− const char *tag_start; // Where the tag starts [<foo
287+ const char *tag_start, *name_start, *name_end, *quote_start, *quote_end;
359− const char *name_start, *name_end; // Where a name is <[foo] or <foo [bar]=
360− const char *quote_start; // Where an attribute quote is <foo bar='[123'>
361− node* me; // The current node I'm working on
362# include "test.h"
288# include "test.h"
363 return NULL;
289 return NULL;
@@ -376,12 +302,14 @@ document* hexml_document_parse(const char* s, int slen)
377 if (slen == -1) slen = (int) strlen(s);
303 if (slen == -1) slen = (int) strlen(s);
378 assert(s[slen] == 0);
304 assert(s[slen] == 0);
305+ // init_parse_table();
380 buffer* buf = malloc(sizeof(buffer));
307 buffer* buf = malloc(sizeof(buffer));
381 assert(buf);
308 assert(buf);
382 document* d = &buf->document;
309 document* d = &buf->document;
383 d->body = s;
310 d->body = s;
384− d->body_len = slen;
311+ d->cursor = s;
385 d->error_message = NULL;
313 d->error_message = NULL;
386 d->attrs.size = 1000;
314 d->attrs.size = 1000;
387 d->attrs.used = 0;
315 d->attrs.used = 0;
@@ -402,70 +330,21 @@ document* hexml_document_parse(const char* s, int slen)
402 // because there is no guaranteed ordering between LHS and RHS evaluation
330 // because there is no guaranteed ordering between LHS and RHS evaluation
403 const char* res = parser(s, d);
331 const char* res = parser(s, d);
404 if (res != NULL)
332 if (res != NULL)
405− set_error(d, res);
333+ d->error_message = strdup(res);
408− d->nodes.nodes[0].nodes = node_commit(&d->nodes);
334+ // d->nodes.nodes[0].nodes = content;
409− if (d->nodes.used_back != 0)
410− d->error_message = strdup("used_back failure");
412 return d;
335 return d;
415−/////////////////////////////////////////////////////////////////////
416−// TEST HARNESS (temporary)
420−static char* resolve(const document* d, str loc)
422− char* buf = malloc(loc.length + 3);
423− memcpy(&buf[1], &d->body[loc.start], loc.length);
425− buf[loc.length+1] = '\"';
426− buf[loc.length+2] = 0;
430−static char* disp(str loc)
432− char* buf = malloc(100);
433− if (loc.length == 0)
436− sprintf(buf, "[%i..%i]", loc.start, end(loc)-1);
440int main()
338int main()
442− setbuf(stdout, NULL);
443− const char* example = "<test foo='123 xyz' bar='t'><inner /> value</test>";
340+ const document* d = hexml_document_parse("<test foo='123 xyz'><inner /> value</test>", -1);
444− document* d = hexml_document_parse(example, -1);
445− if (d->error_message != NULL)
446− printf("Parse failure: %s\n", d->error_message);
449− char buf[1000];
341+ char buf[1000];
450− int len = hexml_node_render(d, hexml_document_node(d), buf, sizeof(buf));
342+ int len = hexml_node_render(d, hexml_document_node(d), buf, sizeof(buf));
451− buf[len] = 0;
343+ buf[len] = 0;
452− printf("Result = %s\n", buf);
344+ printf("Result = %s\n", buf);
453− printf("Used nodes = %i, attributes = %i\n", d->nodes.used_front, d->attrs.used);
455− for (int i = 0; i < d->attrs.used; i++)
456− printf("Attr %i: %s=%s\n", i, resolve(d, d->attrs.attrs[i].name), resolve(d, d->attrs.attrs[i].value));
457− for (int i = 0; i < d->nodes.used_front; i++)
459− printf("Node %i: %s attrs=%s, nodes=%s\n", i, resolve(d, d->nodes.nodes[i].name), disp(d->nodes.nodes[i].attrs), disp(d->nodes.nodes[i].nodes));
460− printf(" inner %s\n outer %s\n", resolve(d, d->nodes.nodes[i].inner), resolve(d, d->nodes.nodes[i].outer));
463− hexml_document_free(d);
464− return 0;
345+ return 0;
470void main()
349void main()