@@ -39,7 +39,6 @@ typedef struct
39 // when you commit, you copy over from end to front
39 // when you commit, you copy over from end to front
42− // Invariant: Always at least one free spot (to do copying from front to back)
44 int used_front; // front entries, stored for good
43 int used_front; // front entries, stored for good
45 int used_back; // back entries, stack based, copied into front on </close>
44 int used_back; // back entries, stack based, copied into front on </close>
@@ -214,9 +213,8 @@ node* hexml_node_child(const document* d, const node* parent, const node* prev,
215static inline node* node_alloc(node_buffer* b)
214static inline node* node_alloc(node_buffer* b)
217− // Invariant: node_commit requires at least one spare spot
218 int space = b->size - b->used_back - b->used_front;
216 int space = b->size - b->used_back - b->used_front;
219− if (space < 2)
217+ if (space < 1)
221 int size2 = (b->size + 1000) * 2;
219 int size2 = (b->size + 1000) * 2;
222 node* buf2 = malloc(size2 * sizeof(node));
220 node* buf2 = malloc(size2 * sizeof(node));
@@ -232,9 +230,59 @@ static inline node* node_alloc(node_buffer* b)
232 return &b->nodes[b->size - b->used_back - 1];
230 return &b->nodes[b->size - b->used_back - 1];
235−static inline void node_commit(node_buffer* b)
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+ int to = from + n - 1;
238+ for (int to = from + n - 1; to > from; from++, to--)
241+ node temp = buffer[to];
242+ buffer[to] = buffer[from];
243+ buffer[from] = temp;
247+// buffer[to .. to+n] = reverse (buffer[from .. from+n])
248+// The ranges may not overlap
249+static inline void memcpy_reverse(node* buffer, int from, int to, int n)
251+ int end = from + n - 1;
252+ for (int i = 0; i < n; i++)
253+ buffer[to+i] = buffer[end-i];
256+// buffer[to .. to+n] = reverse (buffer[from .. from+n])
257+// The ranges may overlap
258+static inline void memmove_reverse(node* buffer, int from, int to, int n)
260+ assert(from < to); // always the case in my usages
262+ memcpy_reverse(buffer, from, to, n);
265+ int overlap = from - to;
266+ memcpy_reverse(buffer, from, to + n - overlap, overlap);
267+ reverse(buffer, to, n - overlap);
271+static inline str node_commit(node_buffer* b)
273+ // first search for an "open" node (nodes.length == -1)
275+ for (open = b->size - b->used_back; open < b->size; open++)
277+ if (b->nodes[open].nodes.length == -1)
281+ int n = open - (b->size - b->used_back);
282+ memmove_reverse(b->nodes, b->used_front, b->used_back, n);
285+ return start_length(b->used_front - n, n);
240static inline attr* attr_alloc(attr_buffer* b)
288static inline attr* attr_alloc(attr_buffer* b)
@@ -287,7 +335,7 @@ static inline str gap(const char* ref, const char* start, const char* end)
287 attr->name = gap(d->body, name_start, name_end); \
335 attr->name = gap(d->body, name_start, name_end); \
288 attr->value = gap(d->body, quote_start, quote_end);
336 attr->value = gap(d->body, quote_start, quote_end);
289#define P_TagComment printf("TagComment %s\n", p)
337#define P_TagComment printf("TagComment %s\n", p)
290−#define P_TagOpen printf("TagOpen %s\n", p)
338+#define P_TagOpen printf("TagOpen - missed %s\n", p)
291#define P_TagClose printf("TagClose %s\n", p)
339#define P_TagClose printf("TagClose %s\n", p)
292#define P_TagOpenClose \
340#define P_TagOpenClose \
293 node->nodes = start_end(0, 0); \
341 node->nodes = start_end(0, 0); \
@@ -317,7 +365,6 @@ document* hexml_document_parse(const char* s, int slen)
318 if (slen == -1) slen = (int) strlen(s);
366 if (slen == -1) slen = (int) strlen(s);
319 assert(s[slen] == 0);
367 assert(s[slen] == 0);
320− // init_parse_table();
322 buffer* buf = malloc(sizeof(buffer));
369 buffer* buf = malloc(sizeof(buffer));
323 assert(buf);
370 assert(buf);
@@ -346,7 +393,7 @@ document* hexml_document_parse(const char* s, int slen)
346 if (res != NULL)
393 if (res != NULL)
347 d->error_message = strdup(res);
394 d->error_message = strdup(res);
349− d->nodes.nodes[0].nodes = start_end(1, d->nodes.used_front);
396+ d->nodes.nodes[0].nodes = node_commit(&d->nodes);
350 return d;
397 return d;