@@ -1,5 +1,5 @@
1#include "hexml.h"
1#include "hexml.h"
2−#include <stdlib.h>
2+#include <malloc.h>
3#include <string.h>
3#include <string.h>
4#include <assert.h>
4#include <assert.h>
5#include <ctype.h>
5#include <ctype.h>
@@ -40,7 +40,7 @@ typedef struct
40 // have a cursor at the end, which is stack scoped, so children write out, then I do
40 // have a cursor at the end, which is stack scoped, so children write out, then I do
41 // when you commit, you copy over from end to front
41 // when you commit, you copy over from end to front
45 int used_front; // front entries, stored for good
45 int used_front; // front entries, stored for good
46 int used_back; // back entries, stack based, copied into front
46 int used_back; // back entries, stack based, copied into front
@@ -97,16 +97,16 @@ static inline void bound_str(str s, int mn, int mx)
97 bound(end(s), mn, mx);
97 bound(end(s), mn, mx);
100−static void render_str(render* r, str s)
100+void render_str(render* r, str s)
102 bound_str(s, 0, doc_length(r->d));
102 bound_str(s, 0, doc_length(r->d));
103 for (int i = 0; i < s.length; i++)
103 for (int i = 0; i < s.length; i++)
104 render_char(r, r->d->body[s.start + i]);
104 render_char(r, r->d->body[s.start + i]);
107−static void render_tag(render* r, const node* n);
107+void render_tag(render* r, const node* n);
109−static void render_content(render* r, const node* n)
109+void render_content(render* r, const node* n)
111 bound_str(n->inner, 0, doc_length(r->d));
111 bound_str(n->inner, 0, doc_length(r->d));
112 bound_str(n->nodes, 0, r->d->nodes.used_front);
112 bound_str(n->nodes, 0, r->d->nodes.used_front);
@@ -123,7 +123,7 @@ static void render_content(render* r, const node* n)
123 render_str(r, start_end(done, end(n->inner)));
123 render_str(r, start_end(done, end(n->inner)));
126−static void render_tag(render* r, const node* n)
126+void render_tag(render* r, const node* n)
128 render_char(r, '<');
128 render_char(r, '<');
129 render_str(r, n->name);
129 render_str(r, n->name);
@@ -145,7 +145,7 @@ static void render_tag(render* r, const node* n)
145 render_char(r, '>');
145 render_char(r, '>');
148−int hexml_node_render(const document* d, const node* n, char* buffer, int length)
148+int node_render(const document* d, const node* n, char* buffer, int length)
150 render r;
150 render r;
@@ -164,10 +164,10 @@ int hexml_node_render(const document* d, const node* n, char* buffer, int length
164/////////////////////////////////////////////////////////////////////
164/////////////////////////////////////////////////////////////////////
165// NOT THE PARSER
165// NOT THE PARSER
167−char* hexml_document_error(const document* d){return d->error_message;}
167+char* document_error(const document* d){return d->error_message;}
168−node* hexml_document_node(const document* d){return &d->nodes.nodes[0];}
168+node* document_node(const document* d){return &d->nodes.nodes[0];}
170−void hexml_document_free(document* d)
170+void document_free(document* d)
172 free(d->error_message);
172 free(d->error_message);
173 free(d->nodes.alloc);
173 free(d->nodes.alloc);
@@ -175,20 +175,20 @@ void hexml_document_free(document* d)
178−node* hexml_node_children(const document* d, const node* n, int* res)
178+node* node_children(const document* d, const node* n, int* res)
180 *res = n->nodes.length;
180 *res = n->nodes.length;
181 return &d->nodes.nodes[n->nodes.start];
181 return &d->nodes.nodes[n->nodes.start];
184−attr* hexml_node_attributes(const document* d, const node* n, int* res)
184+attr* node_attributes(const document* d, const node* n, int* res)
186 *res = n->attrs.length;
186 *res = n->attrs.length;
187 return &d->attrs.attrs[n->attrs.start];
187 return &d->attrs.attrs[n->attrs.start];
191−attr* hexml_node_attribute(const document* d, const node* n, const char* s, int slen)
191+attr* node_attributeBy(const document* d, const node* n, const char* s, int slen)
193 if (slen == -1) slen = (int) strlen(s);
193 if (slen == -1) slen = (int) strlen(s);
194 const int limit = end(n->attrs);
194 const int limit = end(n->attrs);
@@ -202,7 +202,7 @@ attr* hexml_node_attribute(const document* d, const node* n, const char* s, int
204// Search for given strings within a node
204// Search for given strings within a node
205−node* hexml_node_child(const document* d, const node* parent, const node* prev, const char* s, int slen)
205+node* node_childBy(const document* d, const node* parent, const node* prev, const char* s, int slen)
207 if (slen == -1) slen = (int) strlen(s);
207 if (slen == -1) slen = (int) strlen(s);
208 int i = prev == NULL ? parent->nodes.start : (int) (prev + 1 - d->nodes.nodes);
208 int i = prev == NULL ? parent->nodes.start : (int) (prev + 1 - d->nodes.nodes);
@@ -220,27 +220,27 @@ node* hexml_node_child(const document* d, const node* parent, const node* prev,
220/////////////////////////////////////////////////////////////////////
220/////////////////////////////////////////////////////////////////////
221// PARSE TABLE
221// PARSE TABLE
223−static const char tag_name1 = 0x1;
223+const char tag_name1 = 0x1;
224−static const char tag_name = 0x2;
224+const char tag_name = 0x2;
225−static const char tag_space = 0x4;
225+const char tag_space = 0x4;
227−static char parse_table[256];
227+char parse_table[256];
229−static void init_parse_table()
229+void init_parse_table()
231 static bool done = 0;
231 static bool done = 0;
232 if (done) return;
232 if (done) return;
233 for (int i = 0; i < 256; i++)
233 for (int i = 0; i < 256; i++)
235 bool name1 = i == ':' || i == '_' || (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z');
235 bool name1 = i == ':' || i == '_' || (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z');
236− bool name = name1 || i == '-' || i == '.' || (i >= '0' && i <= '9');
236+ bool name = name1 || i == '-' || (i >= '0' && i <= '9');
237 bool space = i == ' ' || i == '\t' || i == '\r' || i == '\n';
237 bool space = i == ' ' || i == '\t' || i == '\r' || i == '\n';
238 parse_table[i] = (name1 ? tag_name1 : 0) | (name ? tag_name : 0) | (space ? tag_space : 0);
238 parse_table[i] = (name1 ? tag_name1 : 0) | (name ? tag_name : 0) | (space ? tag_space : 0);
240 done = 1;
240 done = 1;
243−static inline bool is(char c, char tag) { return parse_table[(unsigned char) c] & tag; }
243+static inline bool is(char c, char tag) { return parse_table[c] & tag; }
244static inline bool is_name1(char c) { return is(c, tag_name1); }
244static inline bool is_name1(char c) { return is(c, tag_name1); }
245static inline bool is_name(char c) { return is(c, tag_name); }
245static inline bool is_name(char c) { return is(c, tag_name); }
246static inline bool is_space(char c) { return is(c, tag_space); }
246static inline bool is_space(char c) { return is(c, tag_space); }
@@ -249,20 +249,20 @@ static inline bool is_space(char c) { return is(c, tag_space); }
249/////////////////////////////////////////////////////////////////////
249/////////////////////////////////////////////////////////////////////
250// PARSER COMBINATORS
250// PARSER COMBINATORS
252−static inline char peek_at(const document* d, int i) { return d->cursor[i]; }
252+char static inline peekAt(document* d, int i) { return d->cursor[i]; }
253−static inline char peek(const document* d) { return peek_at(d, 0); }
254−static inline void skip(document* d, int i) { d->cursor += i; }
253+void static inline skip(document* d, int i) { d->cursor += i; }
254+char static inline peek(document* d) { return peekAt(d, 0); }
255−static inline char get(document* d) { char c = peek(d); skip(d, 1); return c; }
255+char static inline get(document* d) { char c = peek(d); skip(d, 1); return c; }
257// Remove whitespace characters from the cursor while they are still whitespace
257// Remove whitespace characters from the cursor while they are still whitespace
258−static inline void trim(document* d)
258+void static inline trim(document* d)
260 while (is_space(peek(d)))
260 while (is_space(peek(d)))
261 skip(d, 1);
261 skip(d, 1);
264// Find this character form the cursor onwards, if true adjust the cursor to that char, otherwise leave it at the end
264// Find this character form the cursor onwards, if true adjust the cursor to that char, otherwise leave it at the end
265−static bool find(document* d, char c)
265+bool find(document* d, char c)
267 char* x = memchr(d->cursor, c, d->end - d->cursor);
267 char* x = memchr(d->cursor, c, d->end - d->cursor);
268 if (x == NULL)
268 if (x == NULL)
@@ -281,7 +281,7 @@ static bool find(document* d, char c)
281/////////////////////////////////////////////////////////////////////
281/////////////////////////////////////////////////////////////////////
282// PARSING CODE
282// PARSING CODE
284−static inline void node_alloc(node_buffer* b, int ask)
284+void static inline node_alloc(node_buffer* b, int ask)
286 int space = b->size - b->used_back - b->used_front;
286 int space = b->size - b->used_back - b->used_front;
287 if (space >= ask) return;
287 if (space >= ask) return;
@@ -296,7 +296,7 @@ static inline void node_alloc(node_buffer* b, int ask)
296 b->alloc = buf2;
296 b->alloc = buf2;
299−static inline void attr_alloc(attr_buffer* b, int ask)
299+void static inline attr_alloc(attr_buffer* b, int ask)
301 int space = b->size - b->used;
301 int space = b->size - b->used;
302 if (space >= ask) return;
302 if (space >= ask) return;
@@ -310,7 +310,7 @@ static inline void attr_alloc(attr_buffer* b, int ask)
310 b->alloc = buf2;
310 b->alloc = buf2;
313−static void set_error(document* d, const char* msg)
313+void set_error(document* d, char* msg)
315 if (d->error_message != NULL) return; // keep the first error message
315 if (d->error_message != NULL) return; // keep the first error message
316 d->error_message = malloc(strlen(msg)+1);
316 d->error_message = malloc(strlen(msg)+1);
@@ -334,12 +334,11 @@ static inline str parse_name(document* d)
334static inline str parse_attrval(document* d)
334static inline str parse_attrval(document* d)
337− if (peek(d) != '=')
337+ if (get(d) != '=')
339 set_error(d, "Expected = in attribute, but missing");
339 set_error(d, "Expected = in attribute, but missing");
340 return start_length(0, 0);
340 return start_length(0, 0);
344 char c = peek(d);
343 char c = peek(d);
345 if (c == '\"' || c == '\'')
344 if (c == '\"' || c == '\'')
@@ -368,7 +367,7 @@ static inline str parse_attrval(document* d)
368static inline str parse_attributes(document* d)
367static inline str parse_attributes(document* d)
370 int start = d->attrs.used;
369 int start = d->attrs.used;
371− while (d->error_message == NULL)
370+ for (;;)
374 str name = parse_name(d);
373 str name = parse_name(d);
@@ -381,7 +380,7 @@ static inline str parse_attributes(document* d)
381 return start_end(start, d->attrs.used);
380 return start_end(start, d->attrs.used);
384−static str parse_content(document* d);
383+str parse_content(document* d);
387// Add a new entry into tag, am at a '<'
386// Add a new entry into tag, am at a '<'
@@ -396,18 +395,12 @@ static inline void parse_tag(document* d)
396 assert(c == '<');
395 assert(c == '<');
397 if (peek(d) == '?') skip(d, 1);
396 if (peek(d) == '?') skip(d, 1);
398 me->name = parse_name(d);
397 me->name = parse_name(d);
399− if (me->name.length == 0)
401− set_error(d, "Missing tag name");
404 me->attrs = parse_attributes(d);
398 me->attrs = parse_attributes(d);
405− if (d->error_message != NULL) return;
407− c = peek(d);
400+ c = get(d);
408− if ((c == '/' || c == '?') && peek_at(d, 1) == '>')
401+ if ((c == '/' || c == '?') && peek(d) == '>')
410− skip(d, 2);
403+ skip(d, 1);
411 me->nodes = start_length(0, 0);
404 me->nodes = start_length(0, 0);
412 me->outer.length = start_end(me->outer.start, doc_position(d)).length;
405 me->outer.length = start_end(me->outer.start, doc_position(d)).length;
413 me->inner = start_length(doc_position(d), 0);
406 me->inner = start_length(doc_position(d), 0);
@@ -418,8 +411,6 @@ static inline void parse_tag(document* d)
418 set_error(d, "Gunk at the end of the tag");
411 set_error(d, "Gunk at the end of the tag");
423 me->inner.start = doc_position(d);
414 me->inner.start = doc_position(d);
424 str content = parse_content(d);
415 str content = parse_content(d);
@@ -429,7 +420,7 @@ static inline void parse_tag(document* d)
429 me->inner.length = start_end(me->inner.start, doc_position(d)).length;
420 me->inner.length = start_end(me->inner.start, doc_position(d)).length;
431 if (d->error_message != NULL) return;
422 if (d->error_message != NULL) return;
432− if (peek(d) == '<' && peek_at(d, 1) == '/')
423+ if (peek(d) == '<' && peekAt(d, 1) == '/')
434 skip(d, 2);
425 skip(d, 2);
435 if (d->end - d->cursor >= me->name.length &&
426 if (d->end - d->cursor >= me->name.length &&
@@ -451,7 +442,7 @@ static inline void parse_tag(document* d)
452// Parser until </, return the index of your node children
443// Parser until </, return the index of your node children
453// Not inline as it is recursive
444// Not inline as it is recursive
454−static str parse_content(document* d)
445+str parse_content(document* d)
456 int before = d->nodes.used_back;
447 int before = d->nodes.used_back;
457 while (d->error_message == NULL)
448 while (d->error_message == NULL)
@@ -461,16 +452,16 @@ static str parse_content(document* d)
464− else if (peek_at(d, 1) == '/')
455+ else if (peekAt(d, 1) == '/')
466 // have found a </
457 // have found a </
469− else if (peek_at(d, 1) == '!' && peek_at(d, 2) == '-' && peek_at(d, 3) == '-')
460+ else if (peekAt(d, 1) == '!' && peekAt(d, 2) == '-' && peekAt(d, 3) == '-')
471 skip(d, 3);
462 skip(d, 3);
472 // you can't reuse the two '-' characters for the closing as well
463 // you can't reuse the two '-' characters for the closing as well
473− if (peek_at(d, 0) == '\0' || peek_at(d, 1) == '\0')
464+ if (peekAt(d, 0) == '\0' || peekAt(d, 1) == '\0')
475 set_error(d, "Didn't get a closing comment");
466 set_error(d, "Didn't get a closing comment");
476 return start_end(0, 0);
467 return start_end(0, 0);
@@ -484,7 +475,7 @@ static str parse_content(document* d)
484 return start_end(0, 0);
475 return start_end(0, 0);
486 skip(d, 1);
477 skip(d, 1);
487− if (peek_at(d, -3) == '-' && peek_at(d, -2) == '-')
478+ if (peekAt(d, -3) == '-' && peekAt(d, -2))
@@ -512,7 +503,7 @@ typedef struct
512 node nodes[500];
503 node nodes[500];
515−document* hexml_document_parse(const char* s, int slen)
506+document* document_parse(const char* s, int slen)
517 if (slen == -1) slen = (int) strlen(s);
508 if (slen == -1) slen = (int) strlen(s);
518 assert(s[slen] == 0);
509 assert(s[slen] == 0);
@@ -539,13 +530,15 @@ document* hexml_document_parse(const char* s, int slen)
539 d->nodes.nodes[0].outer = start_length(0, slen);
530 d->nodes.nodes[0].outer = start_length(0, slen);
540 d->nodes.nodes[0].inner = start_length(0, slen);
531 d->nodes.nodes[0].inner = start_length(0, slen);
541 d->nodes.nodes[0].attrs = start_length(0, 0);
532 d->nodes.nodes[0].attrs = start_length(0, 0);
543 // Introduce an intermediate result, otherwise behaviour is undefined
534 // Introduce an intermediate result, otherwise behaviour is undefined
544 // because there is no guaranteed ordering between LHS and RHS evaluation
535 // because there is no guaranteed ordering between LHS and RHS evaluation
545 str content = parse_content(d);
536 str content = parse_content(d);
546 d->nodes.nodes[0].nodes = content;
537 d->nodes.nodes[0].nodes = content;
548− if (d->cursor < d->end)
539+ if (d->cursor < d->end && d->error_message == NULL)
549 set_error(d, "Trailing junk at the end of the document");
541 set_error(d, "Trailing junk at the end of the document");
550 return d;
543 return d;