diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/kit/dynamic_array.c | 1 | ||||
-rw-r--r-- | source/kit/dynamic_array.h | 15 | ||||
-rw-r--r-- | source/kit/string_ref.h | 9 | ||||
-rw-r--r-- | source/kit/xml.c | 324 |
4 files changed, 170 insertions, 179 deletions
diff --git a/source/kit/dynamic_array.c b/source/kit/dynamic_array.c index 2b17d07..ede817b 100644 --- a/source/kit/dynamic_array.c +++ b/source/kit/dynamic_array.c @@ -1,7 +1,6 @@ #include "dynamic_array.h" #include <assert.h> -#include <string.h> void kit_da_init(kit_da_void_t *array, i64 element_size, i64 size, kit_allocator_t *alloc) { diff --git a/source/kit/dynamic_array.h b/source/kit/dynamic_array.h index df7b933..e868917 100644 --- a/source/kit/dynamic_array.h +++ b/source/kit/dynamic_array.h @@ -3,6 +3,8 @@ #include "allocator.h" +#include <string.h> + #ifdef __cplusplus extern "C" { #endif @@ -46,11 +48,14 @@ void kit_da_resize_exact(kit_da_void_t *array, i64 element_size, /* Destroy dynamic array. */ -#define KIT_DA_DESTROY(array_) \ - do { \ - if ((array_).values != NULL) \ - kit_alloc_dispatch((array_).alloc, KIT_DEALLOCATE, 0, 0, \ - (array_).values); \ +#define KIT_DA_DESTROY(array_) \ + do { \ + if ((array_).values != NULL) \ + kit_alloc_dispatch((array_).alloc, KIT_DEALLOCATE, 0, \ + (array_).capacity * \ + sizeof((array_).values[0]), \ + (array_).values); \ + memset(&(array_), 0, sizeof(array_)); \ } while (0) /* Resize dynamic array. diff --git a/source/kit/string_ref.h b/source/kit/string_ref.h index 89c319b..38ade80 100644 --- a/source/kit/string_ref.h +++ b/source/kit/string_ref.h @@ -34,7 +34,8 @@ static char *kit_make_bs(kit_str_t s) { i64 n = s.size; if (n > 4095) n = 4095; - memcpy(buf[index], s.values, n); + if (n > 0) + memcpy(buf[index], s.values, n); buf[index][n] = '\0'; char *result = buf[index]; index = (index + 1) % 8; @@ -51,11 +52,11 @@ static char *kit_make_bs(kit_str_t s) { #define KIT_WRAP_BS(string_) kit_str(strlen(string_), (string_)) -#define KIT_WRAP_STR(string_) \ - kit_str((string_).size, (string_).values) +#define KIT_WRAP_STR(...) \ + kit_str((__VA_ARGS__).size, (__VA_ARGS__).values) #ifndef KIT_DISABLE_SHORT_NAMES -# define BS(string_) kit_make_bs(KIT_WRAP_STR(string_)) +# define BS(...) kit_make_bs(KIT_WRAP_STR(__VA_ARGS__)) # define str_t kit_str_t diff --git a/source/kit/xml.c b/source/kit/xml.c index 2bef6d5..ed11b18 100644 --- a/source/kit/xml.c +++ b/source/kit/xml.c @@ -4,8 +4,9 @@ #include <assert.h> typedef struct { - ib_t last; - kit_xml_t xml; + ib_t last; + kit_str_builder_t text; + kit_da_xml_t tags; } kit_xml_intermediate_t; static kit_xml_intermediate_t kit_xml_parse_buf_( @@ -17,210 +18,195 @@ static kit_xml_intermediate_t kit_xml_parse_buf_( memset(&last, 0, sizeof last); memset(&spaces, 0, sizeof spaces); - ib_t tag_open = ib_exact(begin, SZ("<")); - ib_t tag_name = ib_none(tag_open, SZ(" \t\r\n/>")); - last = ib_copy(tag_name); + ib_t tag_text = ib_until(begin, SZ("<")); + last = ib_copy(tag_text); - DA_INIT(res.xml.properties, 0, alloc); + DA_INIT(res.tags, 0, alloc); for (;;) { - spaces = ib_any(last, SZ(" \t\r\n")); - ib_t property = ib_none(spaces, SZ(" \t\r\n=/>")); - ib_destroy(spaces); - - if (property.status != KIT_OK || property.data.size == 0) { - ib_destroy(property); + ib_t tagend_open = ib_exact(last, SZ("</")); + ib_destroy(tagend_open); + if (tagend_open.status == KIT_OK) break; - } - - spaces = ib_any(property, SZ(" \t\r\n")); - ib_t equals = ib_exact(spaces, SZ("=")); - ib_destroy(spaces); - spaces = ib_any(equals, SZ(" \t\r\n")); - ib_t value_open = ib_exact(spaces, SZ("\"")); - ib_t value_text = ib_until(value_open, SZ("\"")); - ib_t value_close = ib_exact(value_text, SZ("\"")); - - if (value_close.status == KIT_OK) { - i64 n = res.xml.properties.size; - DA_RESIZE(res.xml.properties, n + 1); - - if (res.xml.properties.size != n + 1) { - res.last = value_close; - res.last.status = KIT_ERROR_BAD_ALLOC; - - ib_destroy(begin); - ib_destroy(tag_open); - ib_destroy(tag_name); - ib_destroy(last); - ib_destroy(spaces); - ib_destroy(property); - ib_destroy(equals); - ib_destroy(value_open); - ib_destroy(value_text); - - DA_DESTROY(res.xml.properties); - return res; - } - // move - res.xml.properties.values[n].name = property.data; - memset(&property.data, 0, sizeof property.data); + ib_t tag_open = ib_exact(last, SZ("<")); - // move - res.xml.properties.values[n].value = value_text.data; - memset(&value_text.data, 0, sizeof value_text.data); + if (tag_open.status != KIT_OK) { + ib_destroy(tag_open); + break; } - ib_destroy(last); - last = ib_copy(value_close); + xml_t tag; + memset(&tag, 0, sizeof tag); + spaces = ib_any(tag_open, SZ(" \t\r\n")); + ib_t tag_name = ib_none(spaces, SZ(" \t\r\n/>")); ib_destroy(spaces); - ib_destroy(property); - ib_destroy(equals); - ib_destroy(value_open); - ib_destroy(value_text); - ib_destroy(value_close); - if (value_close.status != KIT_OK) - break; - } - - spaces = ib_any(last, SZ(" \t\r\n")); - ib_t tag_close = ib_exact(spaces, SZ(">")); - ib_t tag_close_empty = ib_exact(spaces, SZ("/>")); + DA_INIT(tag.properties, 0, alloc); - ib_destroy(last); - ib_destroy(spaces); + ib_destroy(last); + last = ib_copy(tag_name); -#define return_ \ - ib_destroy(begin); \ - ib_destroy(tag_open); \ - ib_destroy(tag_name); \ - ib_destroy(tag_close); \ - ib_destroy(tag_close_empty); \ - return + for (;;) { + spaces = ib_any(last, SZ(" \t\r\n")); + ib_t property = ib_none(spaces, SZ(" \t\r\n=/>")); + ib_destroy(spaces); - if (tag_close_empty.status == KIT_OK) { - ib_t tag_tail = ib_until(tag_close_empty, SZ("<")); + if (property.status != KIT_OK || property.data.size == 0) { + ib_destroy(property); + break; + } - if (tag_tail.status != KIT_OK) { - res.last = tag_tail; + spaces = ib_any(property, SZ(" \t\r\n")); + ib_t equals = ib_exact(spaces, SZ("=")); + ib_destroy(spaces); + spaces = ib_any(equals, SZ(" \t\r\n")); + ib_t value_open = ib_exact(spaces, SZ("\"")); + ib_destroy(spaces); + ib_t value_text = ib_until(value_open, SZ("\"")); + ib_t value_close = ib_exact(value_text, SZ("\"")); + + ib_destroy(last); + last = value_close; + + if (last.status == KIT_OK) { + i64 n = tag.properties.size; + DA_RESIZE(tag.properties, n + 1); + + if (tag.properties.size != n + 1) { + last.status = KIT_ERROR_BAD_ALLOC; + DA_DESTROY(tag.properties); + } else { + // move + tag.properties.values[n].name = property.data; + memset(&property.data, 0, sizeof property.data); + + // move + tag.properties.values[n].value = value_text.data; + memset(&value_text.data, 0, sizeof value_text.data); + } + } - DA_DESTROY(res.xml.properties); - return_ res; + ib_destroy(property); + ib_destroy(equals); + ib_destroy(value_open); + ib_destroy(value_text); } - // move - res.xml.tag = tag_name.data; - memset(&tag_name.data, 0, sizeof tag_name.data); - - // move - res.xml.tail = tag_tail.data; - memset(&tag_tail.data, 0, sizeof tag_tail.data); - - DA_INIT(res.xml.text, 0, alloc); - DA_INIT(res.xml.children, 0, alloc); + spaces = ib_any(last, SZ(" \t\r\n")); + ib_t tag_close = ib_exact(spaces, SZ(">")); + ib_t tag_close_empty = ib_exact(spaces, SZ("/>")); + ib_destroy(spaces); - res.last = tag_tail; - return_ res; - } + if (tag_close.status == KIT_OK) { + kit_xml_intermediate_t im = kit_xml_parse_buf_(tag_close, + alloc); + tag.text = im.text; + tag.children = im.tags; + + tagend_open = ib_exact(im.last, SZ("</")); + ib_destroy(im.last); + spaces = ib_any(tagend_open, SZ(" \t\r\n")); + ib_t tagend_name = ib_exact(spaces, WRAP_STR(tag_name.data)); + ib_destroy(spaces); + spaces = ib_any(tagend_name, SZ(" \t\r\n")); + ib_t tagend_close = ib_exact(spaces, SZ(">")); + ib_destroy(spaces); + ib_destroy(tagend_open); + ib_destroy(tagend_name); + + ib_destroy(last); + last = tagend_close; + + } else if (tag_close_empty.status == KIT_OK) { + ib_destroy(last); + last = ib_copy(tag_close_empty); + + DA_INIT(tag.text, 0, alloc); + DA_INIT(tag.children, 0, alloc); + } else + last.status = KIT_ERROR_INTERNAL; + + ib_t tag_tail = ib_until(last, SZ("<")); - ib_t tag_text = ib_until(tag_close, SZ("<")); - last = ib_copy(tag_text); + ib_destroy(last); + last = ib_copy(tag_tail); - DA_INIT(res.xml.children, 0, alloc); + if (last.status == KIT_OK) { + i64 n = res.tags.size; + DA_RESIZE(res.tags, n + 1); - if (last.status == KIT_OK) - for (;;) { - // TODO - // Refactor: make this outer loop. - // + if (res.tags.size != n + 1) { + last.status = KIT_ERROR_BAD_ALLOC; + xml_destroy(&tag); + } else { + // move + tag.tag = tag_name.data; + memset(&tag_name.data, 0, sizeof tag_name.data); - ib_t next = ib_exact(last, SZ("</")); + // move + tag.tail = tag_tail.data; + memset(&tag_tail.data, 0, sizeof tag_tail.data); - if (next.status == KIT_OK) { - ib_destroy(last); - last = next; - break; + res.tags.values[n] = tag; } + } else + xml_destroy(&tag); + + ib_destroy(tag_open); + ib_destroy(tag_name); + ib_destroy(tag_close); + ib_destroy(tag_close_empty); + ib_destroy(tag_tail); + } - ib_destroy(next); - - kit_xml_intermediate_t im = kit_xml_parse_buf_(last, alloc); + if (last.status != KIT_OK) { + for (i64 i = 0; i < res.tags.size; i++) + xml_destroy(res.tags.values + i); + DA_DESTROY(res.text); + DA_DESTROY(res.tags); + } else { + // move + res.text = tag_text.data; + memset(&tag_text.data, 0, sizeof tag_text.data); + } - last = im.last; + ib_destroy(tag_text); - if (last.status != KIT_OK) - break; - - i64 n = res.xml.children.size; - DA_RESIZE(res.xml.children, n + 1); + res.last = last; + return res; +} - if (res.xml.children.size != n + 1) { - res.last = last; - res.last.status = KIT_ERROR_BAD_ALLOC; +kit_xml_parse_result_t kit_xml_parse(kit_is_handle_t is, + kit_allocator_t *alloc) { + ib_t ib = ib_wrap(is, alloc); + kit_xml_intermediate_t im = kit_xml_parse_buf_(ib, alloc); + ib_destroy(ib); - ib_destroy(tag_text); + kit_xml_parse_result_t res; + memset(&res, 0, sizeof res); - DA_DESTROY(res.xml.properties); - DA_DESTROY(res.xml.children); - return_ res; - } + res.status = im.last.status; + ib_destroy(im.last); - res.xml.children.values[n] = im.xml; - } + if (res.status != KIT_OK) + return res; - ib_t tagend_open = last; - ib_t tagend_name = ib_exact(tagend_open, WRAP_STR(tag_name.data)); - ib_t tagend_close = ib_exact(tagend_name, SZ(">")); - ib_t tag_tail = ib_until(tagend_close, SZ("<")); - -#undef return_ -#define return_ \ - ib_destroy(begin); \ - ib_destroy(tag_open); \ - ib_destroy(tag_name); \ - ib_destroy(tag_close); \ - ib_destroy(tag_close_empty); \ - ib_destroy(tag_text); \ - ib_destroy(tagend_open); \ - ib_destroy(tagend_name); \ - ib_destroy(tagend_close); \ - return - - if (tag_tail.status != KIT_OK) { - res.last = tag_tail; - - DA_DESTROY(res.xml.properties); - DA_DESTROY(res.xml.children); - return_ res; + if (im.text.size == 0 && im.tags.size == 1) { + res.xml = im.tags.values[0]; + DA_DESTROY(im.text); + DA_DESTROY(im.tags); + return res; } - // move - res.xml.tag = tag_name.data; - memset(&tag_name.data, 0, sizeof tag_name.data); - - // move - res.xml.text = tag_text.data; - memset(&tag_text.data, 0, sizeof tag_text.data); - - // move - res.xml.tail = tag_tail.data; - memset(&tag_tail.data, 0, sizeof tag_tail.data); + DA_INIT(res.xml.tag, 0, alloc); + DA_INIT(res.xml.tail, 0, alloc); + DA_INIT(res.xml.properties, 0, alloc); - res.last = tag_tail; - return_ res; -#undef return_ -} + res.xml.text = im.text; + res.xml.children = im.tags; -kit_xml_parse_result_t kit_xml_parse(kit_is_handle_t is, - kit_allocator_t *alloc) { - kit_xml_intermediate_t im = kit_xml_parse_buf_(ib_wrap(is, alloc), - alloc); - kit_xml_parse_result_t res = { .status = im.last.status, - .xml = im.xml }; - ib_destroy(im.last); return res; } |