on master help sign in
Switch to using a null terminated string
6691cb4Neil Mitchell
hexml.c+32−36
@@ -62,15 +62,18 @@ struct document
62 char* body; // pointer to initial argument, not owned by us
62 char* body; // pointer to initial argument, not owned by us
63
63
64 // things only used while parsing
64 // things only used while parsing
65− int cursor; // pointer to where we are in body
65+ char* cursor; // pointer to where we are in body
66− int length; // total length of body
66+ char* end; // pointer to one past the last char
67− // if cursor is >= length we have gone past the end
67+ // if cursor is > end we have gone past the end
68
68
69 char* error_message;
69 char* error_message;
70 node_buffer nodes;
70 node_buffer nodes;
71 attr_buffer attrs;
71 attr_buffer attrs;
72};
72};
73
73
74+int static inline doc_length(document* d) { return d->end - d->body; }
75+int static inline doc_position(document* d) { return d->cursor - d->body; }
76+
74
77
75/////////////////////////////////////////////////////////////////////
78/////////////////////////////////////////////////////////////////////
76// RENDER CODE
79// RENDER CODE
@@ -108,7 +111,7 @@ void static inline bound_str(char* msg, str s, int mn, int mx)
108
111
109void render_str(render* r, str s)
112void render_str(render* r, str s)
110{
113{
111− bound_str("render_str", s, 0, r->d->length);
114+ bound_str("render_str", s, 0, doc_length(r->d));
112 render_char(r, '[');
115 render_char(r, '[');
113 for (int i = 0; i < s.length; i++)
116 for (int i = 0; i < s.length; i++)
114 render_char(r, r->d->body[s.start + i]);
117 render_char(r, r->d->body[s.start + i]);
@@ -119,7 +122,7 @@ void render_tag(render* r, node* n);
119
122
120void render_content(render* r, node* n)
123void render_content(render* r, node* n)
121{
124{
122− bound_str("render_conent inner", n->inner, 0, r->d->length);
125+ bound_str("render_conent inner", n->inner, 0, doc_length(r->d));
123 bound_str("render_conent nodes", n->nodes, 0, r->d->nodes.used_front);
126 bound_str("render_conent nodes", n->nodes, 0, r->d->nodes.used_front);
124 bound_str("render_conent attrs", n->attrs, 0, r->d->attrs.used);
127 bound_str("render_conent attrs", n->attrs, 0, r->d->attrs.used);
125
128
@@ -257,15 +260,10 @@ bool static inline is_space(char c) { return is(c, tag_space); }
257/////////////////////////////////////////////////////////////////////
260/////////////////////////////////////////////////////////////////////
258// PARSER COMBINATORS
261// PARSER COMBINATORS
259
262
260−char static inline peekAt(document* d, int i)
263+char static inline peekAt(document* d, int i) { return d->cursor[i]; }
261−{
262− int j = d->cursor + i;
263− return j >= d->length ? 0 : d->body[j];
264−}
265−
266−void static inline skip(document* d, int i){d->cursor += i;}
264+void static inline skip(document* d, int i) { d->cursor += i; }
267−char static inline peek(document* d){return peekAt(d, 0);}
265+char static inline peek(document* d) { return peekAt(d, 0); }
268−char static inline get(document* d){char c = peek(d); skip(d, 1); return c;}
266+char static inline get(document* d) { char c = peek(d); skip(d, 1); return c; }
269
267
270// Remove whitespace characters from the cursor while they are still whitespace
268// Remove whitespace characters from the cursor while they are still whitespace
271void static inline trim(document* d)
269void static inline trim(document* d)
@@ -277,16 +275,15 @@ void static inline trim(document* d)
277// Find this character form the cursor onwards, if true adjust the cursor to that char, otherwise leave it at the end
275// Find this character form the cursor onwards, if true adjust the cursor to that char, otherwise leave it at the end
278bool find(document* d, char c)
276bool find(document* d, char c)
279{
277{
280− char* start = &d->body[d->cursor];
281− char* end = memchr(start, c, d->length - d->cursor);
278+ char* x = memchr(d->cursor, c, d->end - d->cursor);
282− if (end == NULL)
279+ if (x == NULL)
283 {
280 {
284− d->cursor = d->length;
281+ d->cursor = d->end;
285 return 0;
282 return 0;
286 }
283 }
287 else
284 else
288 {
285 {
289− d->cursor += end - start;
286+ d->cursor = x;
290 return 1;
287 return 1;
291 }
288 }
292}
289}
@@ -318,15 +315,13 @@ void attr_alloc(attr_buffer* b, int ask)
318str parse_name(document* d)
315str parse_name(document* d)
319{
316{
320 trim(d);
317 trim(d);
321− str res;
318+ int start = doc_position(d);
322− res.start = d->cursor;
323 if (!is_name1(peek(d)))
319 if (!is_name1(peek(d)))
324− return start_length(d->cursor, 0);
320+ return start_length(start, 0);
325 skip(d, 1);
321 skip(d, 1);
326 while (is_name(peek(d)))
322 while (is_name(peek(d)))
327 skip(d, 1);
323 skip(d, 1);
328− res.length = d->cursor - res.start;
324+ return start_end(start, doc_position(d));
329− return res;
330}
325}
331
326
332str parse_attrval(document* d)
327str parse_attrval(document* d)
@@ -346,7 +341,7 @@ str parse_attrval(document* d)
346 return start_length(0, 0);
341 return start_length(0, 0);
347 }
342 }
348 skip(d, 1);
343 skip(d, 1);
349− return start_end(start, d->cursor - 1);
344+ return start_end(start, doc_position(d) - 1);
350 }
345 }
351 else
346 else
352 return parse_name(d);
347 return parse_name(d);
@@ -383,7 +378,7 @@ void parse_tag(document* d)
383 d->nodes.used_back++;
378 d->nodes.used_back++;
384 int me = d->nodes.size - d->nodes.used_back;
379 int me = d->nodes.size - d->nodes.used_back;
385
380
386− d->nodes.nodes[me].outer.start = d->cursor;
381+ d->nodes.nodes[me].outer.start = doc_position(d);
387 char c = get(d);
382 char c = get(d);
388 assert(c == '<');
383 assert(c == '<');
389 if (peek(d) == '?') skip(d, 1);
384 if (peek(d) == '?') skip(d, 1);
@@ -395,8 +390,8 @@ void parse_tag(document* d)
395 {
390 {
396 skip(d, 1);
391 skip(d, 1);
397 d->nodes.nodes[me].nodes = start_length(0, 0);
392 d->nodes.nodes[me].nodes = start_length(0, 0);
398− d->nodes.nodes[me].outer.length = start_end(d->nodes.nodes[me].outer.start, d->cursor).length;
393+ d->nodes.nodes[me].outer.length = start_end(d->nodes.nodes[me].outer.start, doc_position(d)).length;
399− d->nodes.nodes[me].inner = start_length(d->cursor, 0);
394+ d->nodes.nodes[me].inner = start_length(doc_position(d), 0);
400 return;
395 return;
401 }
396 }
402 else if (c != '>')
397 else if (c != '>')
@@ -404,23 +399,23 @@ void parse_tag(document* d)
404 d->error_message = _strdup("Gunk at the end of the tag");
399 d->error_message = _strdup("Gunk at the end of the tag");
405 return;
400 return;
406 }
401 }
407− d->nodes.nodes[me].inner.start = d->cursor;
402+ d->nodes.nodes[me].inner.start = doc_position(d);
408 d->nodes.nodes[me].nodes = parse_content(d);
403 d->nodes.nodes[me].nodes = parse_content(d);
409− d->nodes.nodes[me].inner.length = start_end(d->nodes.nodes[me].inner.start, d->cursor).length;
404+ d->nodes.nodes[me].inner.length = start_end(d->nodes.nodes[me].inner.start, doc_position(d)).length;
410
405
411 if (d->error_message != NULL) return;
406 if (d->error_message != NULL) return;
412 if (peek(d) == '<' && peekAt(d, 1) == '/')
407 if (peek(d) == '<' && peekAt(d, 1) == '/')
413 {
408 {
414 skip(d, 2);
409 skip(d, 2);
415 trim(d);
410 trim(d);
416− if (d->length - d->cursor >= d->nodes.nodes[me].name.length &&
411+ if (d->end - d->cursor >= d->nodes.nodes[me].name.length &&
417− memcmp(&d->body[d->cursor], &d->body[d->nodes.nodes[me].name.start], d->nodes.nodes[me].name.length) == 0)
412+ memcmp(d->cursor, &d->body[d->nodes.nodes[me].name.start], d->nodes.nodes[me].name.length) == 0)
418 {
413 {
419 skip(d, d->nodes.nodes[me].name.length);
414 skip(d, d->nodes.nodes[me].name.length);
420 trim(d);
415 trim(d);
421 if (get(d) == '>')
416 if (get(d) == '>')
422 {
417 {
423− d->nodes.nodes[me].outer.length = start_end(d->nodes.nodes[me].outer.start, d->cursor).length;
418+ d->nodes.nodes[me].outer.length = start_end(d->nodes.nodes[me].outer.start, doc_position(d)).length;
424 return;
419 return;
425 }
420 }
426 }
421 }
@@ -464,12 +459,13 @@ str parse_content(document* d)
464document* document_parse(char* s, int slen)
459document* document_parse(char* s, int slen)
465{
460{
466 if (slen == -1) slen = strlen(s);
461 if (slen == -1) slen = strlen(s);
462+ assert(s[slen] == 0);
467 init_parse_table();
463 init_parse_table();
468
464
469 document* d = malloc(sizeof(document));
465 document* d = malloc(sizeof(document));
470 d->body = s;
466 d->body = s;
471− d->cursor = 0;
467+ d->cursor = s;
472− d->length = slen;
468+ d->end = &s[slen];
473 d->error_message = NULL;
469 d->error_message = NULL;
474 d->attrs.size = 0;
470 d->attrs.size = 0;
475 d->attrs.used = 0;
471 d->attrs.used = 0;
@@ -485,7 +481,7 @@ document* document_parse(char* s, int slen)
485 d->nodes.nodes[0].attrs = start_length(0, 0);
481 d->nodes.nodes[0].attrs = start_length(0, 0);
486 d->nodes.nodes[0].nodes = parse_content(d);
482 d->nodes.nodes[0].nodes = parse_content(d);
487
483
488− if (d->cursor < d->length && d->error_message == NULL)
484+ if (d->cursor < d->end && d->error_message == NULL)
489 {
485 {
490 d->error_message = _strdup("Trailing junk at the end of the document");
486 d->error_message = _strdup("Trailing junk at the end of the document");
491 }
487 }