From 00ab80826c865daabdb5655ba251d6445a98d0b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Fri, 27 May 2022 16:31:41 +0000 Subject: [PATCH] adt: api refactor --- CHANGELOG | 5 + code/apps/examples/json.c | 2 +- code/apps/examples/json_create.c | 2 +- code/apps/examples/json_create_string.c | 2 +- code/header/adt.h | 284 +++++++++++++++++++++--- code/source/adt.c | 107 +++++---- code/source/parsers/csv.c | 6 +- code/source/parsers/json.c | 4 +- code/tests/cases/adt.h | 88 ++++---- code/tests/cases/csv.h | 40 ++-- code/tests/cases/json.h | 24 +- 11 files changed, 409 insertions(+), 155 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6020c6fb..52ec10cd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +17.0.0 - ADT API changes + zpl_adt_inset_* -> zpl_adt_append_* + zpl_adt_node now holds a parent field, methods no longer require a pointer to the parent + methods are now documented + 16.1.1 - fix scientific notation parsing 16.1.0 - introduce ZPL_PARSER_DISABLE_ANALYSIS that disables extra parsing capabilities to offer better raw performance at a cost of lack of node metadata. diff --git a/code/apps/examples/json.c b/code/apps/examples/json.c index 6f23cc86..45a3293a 100644 --- a/code/apps/examples/json.c +++ b/code/apps/examples/json.c @@ -21,7 +21,7 @@ int main(void) { zpl_adt_set_arr(replace, "i_am_replaced", zpl_heap()); for (size_t i = 0; i < 5; i++) - zpl_adt_inset_int(replace, NULL, (zpl_i64)i+1); + zpl_adt_append_int(replace, NULL, (zpl_i64)i+1); } zpl_json_object *first = zpl_adt_alloc_at(&root, 0); diff --git a/code/apps/examples/json_create.c b/code/apps/examples/json_create.c index 811bc5b5..97c255b5 100644 --- a/code/apps/examples/json_create.c +++ b/code/apps/examples/json_create.c @@ -6,7 +6,7 @@ int main(void) { zpl_json_object root = {0}; root.cfg_mode = 1; - zpl_adt_make_branch(&root, zpl_heap(), "" /* unused for root object */, ZPL_ADT_TYPE_OBJECT); + zpl_adt_make_branch(&root, zpl_heap(), "" /* unused for root object */, 0); zpl_random rng={0}; zpl_random_init(&rng); diff --git a/code/apps/examples/json_create_string.c b/code/apps/examples/json_create_string.c index 5eefa1e2..9881fec9 100644 --- a/code/apps/examples/json_create_string.c +++ b/code/apps/examples/json_create_string.c @@ -5,7 +5,7 @@ int main(void) { zpl_json_object root = {0}; - zpl_adt_make_branch(&root, zpl_heap(), "" /* unused for root object */, ZPL_ADT_TYPE_OBJECT); + zpl_adt_make_branch(&root, zpl_heap(), "" /* unused for root object */, 0); zpl_random rng={0}; zpl_random_init(&rng); diff --git a/code/header/adt.h b/code/header/adt.h index 94fe1d53..2f90d02e 100644 --- a/code/header/adt.h +++ b/code/header/adt.h @@ -46,8 +46,16 @@ typedef enum zpl_adt_delim_style { ZPL_ADT_DELIM_STYLE_NEWLINE, } zpl_adt_delim_style; +typedef enum zpl_adt_error { + ZPL_ADT_ERROR_NONE, + ZPL_ADT_ERROR_INTERNAL, + ZPL_ADT_ERROR_ALREADY_CONVERTED, + ZPL_ADT_ERROR_INVALID_TYPE, +} zpl_adt_error; + typedef struct zpl_adt_node { char const *name; + struct zpl_adt_node *parent; /* properties */ zpl_u8 type :4; @@ -90,9 +98,33 @@ typedef struct zpl_adt_node { * real number exponent is limited to 64 digits. */ -ZPL_DEF zpl_u8 zpl_adt_make_branch(zpl_adt_node *node, zpl_allocator backing, char const *name, zpl_u8 type); +/** + * @brief Initialise an ADT object or array + * + * @param node + * @param backing Memory allocator used for descendants + * @param name Node's name + * @param is_array + * @return error code + */ +ZPL_DEF zpl_u8 zpl_adt_make_branch(zpl_adt_node *node, zpl_allocator backing, char const *name, zpl_b32 is_array); + +/** + * @brief Destroy an ADT branch and its descendants + * + * @param node + * @return error code + */ ZPL_DEF zpl_u8 zpl_adt_destroy_branch(zpl_adt_node *node); +/** + * @brief Initialise an ADT leaf + * + * @param node + * @param name Node's name + * @param type Node's type (use zpl_adt_make_branch for container nodes) + * @return error code + */ ZPL_DEF zpl_u8 zpl_adt_make_leaf(zpl_adt_node *node, char const *name, zpl_u8 type); @@ -101,10 +133,11 @@ ZPL_DEF zpl_u8 zpl_adt_make_leaf(zpl_adt_node *node, char const *name, zpl_u8 ty * * This method uses a basic syntax to fetch a node from the ADT. The following features are available * to retrieve the data: - * 1) "a/b/c" navigates through objects "a" and "b" to get to "c" - * 2) "arr/[foo=123]/bar" iterates over "arr" to find any object with param "foo" that matches the value "123", then gets its field called "bar" - * 3) "arr/3" retrieves the 4th element in "arr" - * 4) "arr/[apple]" retrieves the first element of value "apple" in "arr" + * + * - "a/b/c" navigates through objects "a" and "b" to get to "c" + * - "arr/[foo=123]/bar" iterates over "arr" to find any object with param "foo" that matches the value "123", then gets its field called "bar" + * - "arr/3" retrieves the 4th element in "arr" + * - "arr/[apple]" retrieves the first element of value "apple" in "arr" * * @param node ADT node * @param uri Locator string as described above @@ -114,44 +147,220 @@ ZPL_DEF zpl_u8 zpl_adt_make_leaf(zpl_adt_node *node, char const *name, zpl_u8 ty */ ZPL_DEF zpl_adt_node *zpl_adt_get(zpl_adt_node *node, char const *uri); +/** + * @brief Find a field node within an object by the given name. + * + * @param node + * @param name + * @param deep_search Perform search recursively + * @return zpl_adt_node * node + */ ZPL_DEF zpl_adt_node *zpl_adt_find(zpl_adt_node *node, char const *name, zpl_b32 deep_search); +/** + * @brief Allocate an unitialised node within a container at a specified index. + * + * @param parent + * @param index + * @return zpl_adt_node * node + */ ZPL_DEF zpl_adt_node *zpl_adt_alloc_at(zpl_adt_node *parent, zpl_isize index); + +/** + * @brief Allocate an unitialised node within a container. + * + * @param parent + * @return zpl_adt_node * node + */ ZPL_DEF zpl_adt_node *zpl_adt_alloc(zpl_adt_node *parent); -ZPL_DEF zpl_adt_node *zpl_adt_move_node_at(zpl_adt_node *node, zpl_adt_node *old_parent, zpl_adt_node *new_parent, zpl_isize index); -ZPL_DEF zpl_adt_node *zpl_adt_move_node(zpl_adt_node *node, zpl_adt_node *old_parent, zpl_adt_node *new_parent); -ZPL_DEF void zpl_adt_swap_nodes(zpl_adt_node *node, zpl_adt_node *other_node, zpl_adt_node *parent); -ZPL_DEF void zpl_adt_swap_nodes_between_parents(zpl_adt_node *node, zpl_adt_node *other_node, zpl_adt_node *parent, zpl_adt_node *other_parent); -ZPL_DEF void zpl_adt_remove_node(zpl_adt_node *node, zpl_adt_node *parent); +/** + * @brief Move an existing node to a new container at a specified index. + * + * @param node + * @param new_parent + * @param index + * @return zpl_adt_node * node + */ +ZPL_DEF zpl_adt_node *zpl_adt_move_node_at(zpl_adt_node *node, zpl_adt_node *new_parent, zpl_isize index); +/** + * @brief Move an existing node to a new container. + * + * @param node + * @param new_parent + * @return zpl_adt_node * node + */ +ZPL_DEF zpl_adt_node *zpl_adt_move_node(zpl_adt_node *node, zpl_adt_node *new_parent); + +/** + * @brief Swap two nodes. + * + * @param node + * @param other_node + * @return + */ +ZPL_DEF void zpl_adt_swap_nodes(zpl_adt_node *node, zpl_adt_node *other_node); + +/** + * @brief Remove node from container. + * + * @param node + * @return + */ +ZPL_DEF void zpl_adt_remove_node(zpl_adt_node *node); + +/** + * @brief Initialise a node as an object + * + * @param obj + * @param name + * @param backing + * @return + */ ZPL_DEF void zpl_adt_set_obj(zpl_adt_node *obj, char const *name, zpl_allocator backing); + +/** + * @brief Initialise a node as an array + * + * @param obj + * @param name + * @param backing + * @return + */ ZPL_DEF void zpl_adt_set_arr(zpl_adt_node *obj, char const *name, zpl_allocator backing); + +/** + * @brief Initialise a node as a string + * + * @param obj + * @param name + * @param value + * @return + */ ZPL_DEF void zpl_adt_set_str(zpl_adt_node *obj, char const *name, char const *value); + +/** + * @brief Initialise a node as a float + * + * @param obj + * @param name + * @param value + * @return + */ ZPL_DEF void zpl_adt_set_flt(zpl_adt_node *obj, char const *name, zpl_f64 value); + +/** + * @brief Initialise a node as a signed integer + * + * @param obj + * @param name + * @param value + * @return + */ ZPL_DEF void zpl_adt_set_int(zpl_adt_node *obj, char const *name, zpl_i64 value); -ZPL_DEF zpl_adt_node *zpl_adt_inset_obj(zpl_adt_node *parent, char const *name); -ZPL_DEF zpl_adt_node *zpl_adt_inset_arr(zpl_adt_node *parent, char const *name); -ZPL_DEF zpl_adt_node *zpl_adt_inset_str(zpl_adt_node *parent, char const *name, char const *value); -ZPL_DEF zpl_adt_node *zpl_adt_inset_flt(zpl_adt_node *parent, char const *name, zpl_f64 value); -ZPL_DEF zpl_adt_node *zpl_adt_inset_int(zpl_adt_node *parent, char const *name, zpl_i64 value); +/** + * @brief Append a new node to a container as an object + * + * @param parent + * @param name + * @return* + */ +ZPL_DEF zpl_adt_node *zpl_adt_append_obj(zpl_adt_node *parent, char const *name); + +/** + * @brief Append a new node to a container as an array + * + * @param parent + * @param name + * @return* + */ +ZPL_DEF zpl_adt_node *zpl_adt_append_arr(zpl_adt_node *parent, char const *name); + +/** + * @brief Append a new node to a container as a string + * + * @param parent + * @param name + * @param value + * @return* + */ +ZPL_DEF zpl_adt_node *zpl_adt_append_str(zpl_adt_node *parent, char const *name, char const *value); + +/** + * @brief Append a new node to a container as a float + * + * @param parent + * @param name + * @param value + * @return* + */ +ZPL_DEF zpl_adt_node *zpl_adt_append_flt(zpl_adt_node *parent, char const *name, zpl_f64 value); + +/** + * @brief Append a new node to a container as a signed integer + * + * @param parent + * @param name + * @param value + * @return* + */ +ZPL_DEF zpl_adt_node *zpl_adt_append_int(zpl_adt_node *parent, char const *name, zpl_i64 value); /* parser helpers */ -ZPL_DEF char *zpl_adt_parse_number(zpl_adt_node *node, char* base); -ZPL_DEF void zpl_adt_str_to_number(zpl_adt_node *node); -ZPL_DEF void zpl_adt_print_number(zpl_file *file, zpl_adt_node *node); -ZPL_DEF void zpl_adt_print_string(zpl_file *file, zpl_adt_node *node, char const* escaped_chars, char escape_symbol); +/** + * @brief Parses a text and stores the result into an unitialised node. + * + * @param node + * @param base + * @return* + */ +ZPL_DEF char *zpl_adt_parse_number(zpl_adt_node *node, char* base); + +/** + * @brief Parses and converts an existing string node into a number. + * + * @param node + * @return + */ +ZPL_DEF zpl_adt_error zpl_adt_str_to_number(zpl_adt_node *node); + +/** + * @brief Prints a number into a file stream. + * + * The provided file handle can also be a memory mapped stream. + * + * @see zpl_file_stream_new + * @param file + * @param node + * @return + */ +ZPL_DEF zpl_adt_error zpl_adt_print_number(zpl_file *file, zpl_adt_node *node); + +/** + * @brief Prints a string into a file stream. + * + * The provided file handle can also be a memory mapped stream. + * + * @see zpl_file_stream_new + * @param file + * @param node + * @param escaped_chars + * @param escape_symbol + * @return + */ +ZPL_DEF zpl_adt_error zpl_adt_print_string(zpl_file *file, zpl_adt_node *node, char const *escaped_chars, char const *escape_symbol); /* extensions */ #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L -#define zpl_adt_inset(parent, name, value) _Generic((value), \ - char*: zpl_adt_inset_str, \ - char const*: zpl_adt_inset_str, \ - zpl_f64: zpl_adt_inset_flt, \ - default: zpl_adt_inset_int)(parent, name, value) +#define zpl_adt_append(parent, name, value) _Generic((value), \ + char*: zpl_adt_append_str, \ + char const*: zpl_adt_append_str, \ + zpl_f64: zpl_adt_append_flt, \ + default: zpl_adt_append_int)(parent, name, value) #define zpl_adt_set(obj, name, value) _Generic((value), \ char*: zpl_adt_set_str, \ char const*: zpl_adt_set_str, \ @@ -163,7 +372,32 @@ ZPL_DEF void zpl_adt_print_string(zpl_file *file, zpl_adt_node *node, char const ZPL_DEPRECATED_FOR(13.3.0, zpl_adt_str_to_number) ZPL_IMPL_INLINE void zpl_adt_str_to_flt(zpl_adt_node *node) { - zpl_adt_str_to_number(node); + (void)zpl_adt_str_to_number(node); +} + +ZPL_DEPRECATED_FOR(17.0.0, zpl_adt_append_obj) +ZPL_IMPL_INLINE zpl_adt_node *zpl_adt_inset_obj(zpl_adt_node *parent, char const *name) { + return zpl_adt_append_obj(parent, name); +} + +ZPL_DEPRECATED_FOR(17.0.0, zpl_adt_append_arr) +ZPL_IMPL_INLINE zpl_adt_node *zpl_adt_inset_arr(zpl_adt_node *parent, char const *name) { + return zpl_adt_append_arr(parent, name); +} + +ZPL_DEPRECATED_FOR(17.0.0, zpl_adt_append_str) +ZPL_IMPL_INLINE zpl_adt_node *zpl_adt_inset_str(zpl_adt_node *parent, char const *name, char const *value) { + return zpl_adt_append_str(parent, name, value); +} + +ZPL_DEPRECATED_FOR(17.0.0, zpl_adt_append_flt) +ZPL_IMPL_INLINE zpl_adt_node *zpl_adt_inset_flt(zpl_adt_node *parent, char const *name, zpl_f64 value) { + return zpl_adt_append_flt(parent, name, value); +} + +ZPL_DEPRECATED_FOR(17.0.0, zpl_adt_append_int) +ZPL_IMPL_INLINE zpl_adt_node *zpl_adt_inset_int(zpl_adt_node *parent, char const *name, zpl_i64 value) { + return zpl_adt_append_int(parent, name, value); } ZPL_END_C_DECLS diff --git a/code/source/adt.c b/code/source/adt.c index 1d90a70f..ee8d6162 100644 --- a/code/source/adt.c +++ b/code/source/adt.c @@ -2,11 +2,16 @@ ZPL_BEGIN_C_DECLS -zpl_u8 zpl_adt_make_branch(zpl_adt_node *node, zpl_allocator backing, char const *name, zpl_u8 type) { - ZPL_ASSERT(type == ZPL_ADT_TYPE_OBJECT || type == ZPL_ADT_TYPE_ARRAY); +zpl_u8 zpl_adt_make_branch(zpl_adt_node *node, zpl_allocator backing, char const *name, zpl_b32 is_array) { + zpl_u8 type = ZPL_ADT_TYPE_OBJECT; + if (is_array) { + type = ZPL_ADT_TYPE_ARRAY; + } + zpl_adt_node *parent = node->parent; zpl_zero_item(node); node->type = type; node->name = name; + node->parent = parent; zpl_array_init(node->nodes, backing); return 0; } @@ -23,9 +28,11 @@ zpl_u8 zpl_adt_destroy_branch(zpl_adt_node *node) { zpl_u8 zpl_adt_make_leaf(zpl_adt_node *node, char const *name, zpl_u8 type) { ZPL_ASSERT(type != ZPL_ADT_TYPE_OBJECT && type != ZPL_ADT_TYPE_ARRAY); + zpl_adt_node *parent = node->parent; zpl_zero_item(node); node->type = type; node->name = name; + node->parent = parent; return 0; } @@ -215,6 +222,7 @@ zpl_adt_node *zpl_adt_alloc_at(zpl_adt_node *parent, zpl_isize index) { return NULL; zpl_adt_node o = {0}; + o.parent = parent; zpl_array_append_at(parent->nodes, o, index); return parent->nodes + index; @@ -233,10 +241,10 @@ zpl_adt_node *zpl_adt_alloc(zpl_adt_node *parent) { void zpl_adt_set_obj(zpl_adt_node *obj, char const *name, zpl_allocator backing) { - zpl_adt_make_branch(obj, backing, name, ZPL_ADT_TYPE_OBJECT); + zpl_adt_make_branch(obj, backing, name, 0); } void zpl_adt_set_arr(zpl_adt_node *obj, char const *name, zpl_allocator backing) { - zpl_adt_make_branch(obj, backing, name, ZPL_ADT_TYPE_ARRAY); + zpl_adt_make_branch(obj, backing, name, 1); } void zpl_adt_set_str(zpl_adt_node *obj, char const *name, char const *value) { zpl_adt_make_leaf(obj, name, ZPL_ADT_TYPE_STRING); @@ -251,75 +259,70 @@ void zpl_adt_set_int(zpl_adt_node *obj, char const *name, zpl_i64 value) { obj->integer = value; } -zpl_adt_node *zpl_adt_move_node_at(zpl_adt_node *node, zpl_adt_node *old_parent, zpl_adt_node *new_parent, zpl_isize index) { +zpl_adt_node *zpl_adt_move_node_at(zpl_adt_node *node, zpl_adt_node *new_parent, zpl_isize index) { ZPL_ASSERT_NOT_NULL(node); - ZPL_ASSERT_NOT_NULL(old_parent); ZPL_ASSERT_NOT_NULL(new_parent); - ZPL_ASSERT(new_parent->type == ZPL_ADT_TYPE_ARRAY || new_parent->type == ZPL_ADT_TYPE_OBJECT); - ZPL_ASSERT(node >= old_parent->nodes); - ZPL_ASSERT(node <= zpl_array_end(old_parent->nodes)); - ZPL_ASSERT(index >= 0 && index <= zpl_array_count(new_parent->nodes)); + zpl_adt_node *old_parent = node->parent; zpl_adt_node *new_node = zpl_adt_alloc_at(new_parent, index); *new_node = *node; - zpl_adt_remove_node(node, old_parent); + new_node->parent = new_parent; + if (old_parent) { + zpl_adt_remove_node(node); + } return new_node; } -zpl_adt_node *zpl_adt_move_node(zpl_adt_node *node, zpl_adt_node *old_parent, zpl_adt_node *new_parent) { +zpl_adt_node *zpl_adt_move_node(zpl_adt_node *node, zpl_adt_node *new_parent) { + ZPL_ASSERT_NOT_NULL(node); ZPL_ASSERT_NOT_NULL(new_parent); ZPL_ASSERT(new_parent->type == ZPL_ADT_TYPE_ARRAY || new_parent->type == ZPL_ADT_TYPE_OBJECT); - return zpl_adt_move_node_at(node, old_parent, new_parent, zpl_array_count(new_parent->nodes)); -} - -void zpl_adt_swap_nodes(zpl_adt_node *node, zpl_adt_node *other_node, zpl_adt_node *parent) { - zpl_adt_swap_nodes_between_parents(node, other_node, parent, parent); + return zpl_adt_move_node_at(node, new_parent, zpl_array_count(new_parent->nodes)); } -void zpl_adt_swap_nodes_between_parents(zpl_adt_node *node, zpl_adt_node *other_node, zpl_adt_node *parent, zpl_adt_node *other_parent) { +void zpl_adt_swap_nodes(zpl_adt_node *node, zpl_adt_node *other_node) { ZPL_ASSERT_NOT_NULL(node); ZPL_ASSERT_NOT_NULL(other_node); - ZPL_ASSERT_NOT_NULL(parent); - ZPL_ASSERT_NOT_NULL(other_parent); - ZPL_ASSERT(node >= parent->nodes && node <= zpl_array_end(parent->nodes)); - ZPL_ASSERT(other_node >= other_parent->nodes && other_node <= zpl_array_end(other_parent->nodes)); + zpl_adt_node *parent = node->parent; + zpl_adt_node *other_parent = other_node->parent; zpl_isize index = (zpl_pointer_diff(parent->nodes, node) / zpl_size_of(zpl_adt_node)); zpl_isize index2 = (zpl_pointer_diff(other_parent->nodes, other_node) / zpl_size_of(zpl_adt_node)); zpl_adt_node temp = parent->nodes[index]; + temp.parent = other_parent; + other_parent->nodes[index2].parent = parent; parent->nodes[index] = other_parent->nodes[index2]; other_parent->nodes[index2] = temp; } -void zpl_adt_remove_node(zpl_adt_node *node, zpl_adt_node *parent) { +void zpl_adt_remove_node(zpl_adt_node *node) { ZPL_ASSERT_NOT_NULL(node); - ZPL_ASSERT_NOT_NULL(parent); - ZPL_ASSERT(node >= parent->nodes); - ZPL_ASSERT(node <= zpl_array_end(parent->nodes)); + ZPL_ASSERT_NOT_NULL(node->parent); + zpl_adt_node *parent = node->parent; zpl_isize index = (zpl_pointer_diff(parent->nodes, node) / zpl_size_of(zpl_adt_node)); zpl_array_remove_at(parent->nodes, index); } -zpl_adt_node *zpl_adt_inset_obj(zpl_adt_node *parent, char const *name) { +zpl_adt_node *zpl_adt_append_obj(zpl_adt_node *parent, char const *name) { zpl_adt_node *o = zpl_adt_alloc(parent); zpl_adt_set_obj(o, name, ZPL_ARRAY_HEADER(parent->nodes)->allocator); return o; } -zpl_adt_node *zpl_adt_inset_arr(zpl_adt_node *parent, char const *name) { +zpl_adt_node *zpl_adt_append_arr(zpl_adt_node *parent, char const *name) { zpl_adt_node *o = zpl_adt_alloc(parent); zpl_adt_set_arr(o, name, ZPL_ARRAY_HEADER(parent->nodes)->allocator); return o; } -zpl_adt_node *zpl_adt_inset_str(zpl_adt_node *parent, char const *name, char const *value) { +zpl_adt_node *zpl_adt_append_str(zpl_adt_node *parent, char const *name, char const *value) { zpl_adt_node *o = zpl_adt_alloc(parent); zpl_adt_set_str(o, name, value); return o; } -zpl_adt_node *zpl_adt_inset_flt(zpl_adt_node *parent, char const *name, zpl_f64 value) { +zpl_adt_node *zpl_adt_append_flt(zpl_adt_node *parent, char const *name, zpl_f64 value) { zpl_adt_node *o = zpl_adt_alloc(parent); zpl_adt_set_flt(o, name, value); return o; } -zpl_adt_node *zpl_adt_inset_int(zpl_adt_node *parent, char const *name, zpl_i64 value) { +zpl_adt_node *zpl_adt_append_int(zpl_adt_node *parent, char const *name, zpl_i64 value) { zpl_adt_node *o = zpl_adt_alloc(parent); zpl_adt_set_int(o, name, value); return o; @@ -410,15 +413,15 @@ char *zpl_adt_parse_number(zpl_adt_node *node, char* base_str) { node->real = zpl_str_to_f64(buf, 0); #ifndef ZPL_PARSER_DISABLE_ANALYSIS - char *q = buf, *base_str = q, *base_str2 = q; - base_str = cast(char *)zpl_str_skip(base_str, '.'); - *base_str = '\0'; - base_str2 = base_str + 1; - char *base_str_off = base_str2; - while (*base_str_off++ == '0') base2_offset++; + char *q = buf, *base_string = q, *base_string2 = q; + base_string = cast(char *)zpl_str_skip(base_string, '.'); + *base_string = '\0'; + base_string2 = base_string + 1; + char *base_string_off = base_string2; + while (*base_string_off++ == '0') base2_offset++; base = (zpl_i32)zpl_str_to_i64(q, 0, 0); - base2 = (zpl_i32)zpl_str_to_i64(base_str2, 0, 0); + base2 = (zpl_i32)zpl_str_to_i64(base_string2, 0, 0); if (exp) { exp = exp * (!(eb == 10.0f) ? -1 : 1); node->props = ZPL_ADT_PROPS_IS_EXP; @@ -450,10 +453,12 @@ char *zpl_adt_parse_number(zpl_adt_node *node, char* base_str) { return e; } -void zpl_adt_print_number(zpl_file *file, zpl_adt_node *node) { +zpl_adt_error zpl_adt_print_number(zpl_file *file, zpl_adt_node *node) { ZPL_ASSERT_NOT_NULL(file); ZPL_ASSERT_NOT_NULL(node); - ZPL_ASSERT(node->type == ZPL_ADT_TYPE_INTEGER || node->type == ZPL_ADT_TYPE_REAL); + if (node->type != ZPL_ADT_TYPE_INTEGER && node->type != ZPL_ADT_TYPE_REAL) { + return ZPL_ADT_ERROR_INVALID_TYPE; + } #ifndef ZPL_PARSER_DISABLE_ANALYSIS if (node->neg_zero) { @@ -499,13 +504,17 @@ void zpl_adt_print_number(zpl_file *file, zpl_adt_node *node) { } } break; } + + return ZPL_ADT_ERROR_NONE; } -void zpl_adt_print_string(zpl_file *file, zpl_adt_node *node, char const* escaped_chars, char escape_symbol) { +zpl_adt_error zpl_adt_print_string(zpl_file *file, zpl_adt_node *node, char const *escaped_chars, char const *escape_symbol) { ZPL_ASSERT_NOT_NULL(file); ZPL_ASSERT_NOT_NULL(node); ZPL_ASSERT_NOT_NULL(escaped_chars); - ZPL_ASSERT(node->type == ZPL_ADT_TYPE_STRING || node->type == ZPL_ADT_TYPE_MULTISTRING); + if (node->type != ZPL_ADT_TYPE_STRING && node->type != ZPL_ADT_TYPE_MULTISTRING) { + return ZPL_ADT_ERROR_INVALID_TYPE; + } /* escape string */ char const* p = node->string, *b = p; @@ -513,19 +522,25 @@ void zpl_adt_print_string(zpl_file *file, zpl_adt_node *node, char const* escape p = zpl_str_skip_any(p, escaped_chars); zpl_fprintf(file, "%.*s", zpl_ptr_diff(b, p), b); if (*p && !!zpl_strchr(escaped_chars, *p)) { - zpl_fprintf(file, "%c%c", escape_symbol, *p); + zpl_fprintf(file, "%s%c", escape_symbol, *p); p++; } b = p; } while (*p); + + return ZPL_ADT_ERROR_NONE; } -void zpl_adt_str_to_number(zpl_adt_node *node) { +zpl_adt_error zpl_adt_str_to_number(zpl_adt_node *node) { ZPL_ASSERT(node); - if (node->type == ZPL_ADT_TYPE_REAL || node->type == ZPL_ADT_TYPE_INTEGER) return; /* this is already converted/parsed */ - ZPL_ASSERT(node->type == ZPL_ADT_TYPE_STRING || node->type == ZPL_ADT_TYPE_MULTISTRING); + if (node->type == ZPL_ADT_TYPE_REAL || node->type == ZPL_ADT_TYPE_INTEGER) return ZPL_ADT_ERROR_ALREADY_CONVERTED; /* this is already converted/parsed */ + if (node->type != ZPL_ADT_TYPE_STRING && node->type != ZPL_ADT_TYPE_MULTISTRING) { + return ZPL_ADT_ERROR_INVALID_TYPE; + } zpl_adt_parse_number(node, (char *)node->string); + + return ZPL_ADT_ERROR_NONE; } ZPL_END_C_DECLS diff --git a/code/source/parsers/csv.c b/code/source/parsers/csv.c index c75b8cac..688ec532 100644 --- a/code/source/parsers/csv.c +++ b/code/source/parsers/csv.c @@ -15,7 +15,7 @@ zpl_u8 zpl_csv_parse_delimiter(zpl_csv_object *root, char *text, zpl_allocator a ZPL_ASSERT_NOT_NULL(root); ZPL_ASSERT_NOT_NULL(text); zpl_zero_item(root); - zpl_adt_make_branch(root, allocator, NULL, has_header ? ZPL_ADT_TYPE_OBJECT : ZPL_ADT_TYPE_ARRAY); + zpl_adt_make_branch(root, allocator, NULL, has_header ? false : true); char *p = text, *b = p, *e = p; zpl_isize colc = 0, total_colc = 0; @@ -101,7 +101,7 @@ zpl_u8 zpl_csv_parse_delimiter(zpl_csv_object *root, char *text, zpl_allocator a } if (colc >= zpl_array_count(root->nodes)) { - zpl_adt_inset_arr(root, NULL); + zpl_adt_append_arr(root, NULL); } zpl_array_append(root->nodes[colc].nodes, row_item); @@ -152,7 +152,7 @@ void zpl__csv_write_record(zpl_file *file, zpl_csv_object *node) { switch (node->name_style) { case ZPL_ADT_NAME_STYLE_DOUBLE_QUOTE: { zpl_fprintf(file, "\""); - zpl_adt_print_string(file, node, "\"", '"'); + zpl_adt_print_string(file, node, "\"", "\""); zpl_fprintf(file, "\""); } break; diff --git a/code/source/parsers/json.c b/code/source/parsers/json.c index 8bce5fd7..b0e8f344 100644 --- a/code/source/parsers/json.c +++ b/code/source/parsers/json.c @@ -414,13 +414,13 @@ void zpl__json_write_value(zpl_file *f, zpl_adt_node *o, zpl_adt_node *t, zpl_is switch (node->type) { case ZPL_ADT_TYPE_STRING: { zpl_fprintf(f, "\""); - zpl_adt_print_string(f, node, "\"", '\\'); + zpl_adt_print_string(f, node, "\"", "\\"); zpl_fprintf(f, "\""); } break; case ZPL_ADT_TYPE_MULTISTRING: { zpl_fprintf(f, "`"); - zpl_adt_print_string(f, node, "`", '\\'); + zpl_adt_print_string(f, node, "`", "\\"); zpl_fprintf(f, "`"); } break; diff --git a/code/tests/cases/adt.h b/code/tests/cases/adt.h index 0b711e8d..52d6d3dc 100644 --- a/code/tests/cases/adt.h +++ b/code/tests/cases/adt.h @@ -2,31 +2,31 @@ MODULE(adt, { IT("can build an ADT tree", { zpl_adt_node root; zpl_adt_set_obj(&root, "root", mem_alloc); - zpl_adt_inset_int(&root, "foo", 42); - zpl_adt_inset_str(&root, "bar", "life"); + zpl_adt_append_int(&root, "foo", 42); + zpl_adt_append_str(&root, "bar", "life"); EQUALS(root.nodes[0].integer, 42); STREQUALS(root.nodes[1].string, "life"); }); IT("can build a deeper ADT tree", { zpl_adt_node root; zpl_adt_set_obj(&root, "root", mem_alloc); - zpl_adt_inset_int(&root, "foo", 42); - zpl_adt_inset_str(&root, "bar", "life"); + zpl_adt_append_int(&root, "foo", 42); + zpl_adt_append_str(&root, "bar", "life"); EQUALS(root.nodes[0].integer, 42); STREQUALS(root.nodes[1].string, "life"); - zpl_adt_node *array = zpl_adt_inset_arr(&root, "numbers"); - zpl_adt_inset_int(array, NULL, 1); - zpl_adt_inset_int(array, NULL, 2); - zpl_adt_inset_int(array, NULL, 3); + zpl_adt_node *array = zpl_adt_append_arr(&root, "numbers"); + zpl_adt_append_int(array, NULL, 1); + zpl_adt_append_int(array, NULL, 2); + zpl_adt_append_int(array, NULL, 3); EQUALS(root.nodes[2].nodes[2].integer, 3); }); IT("can find a node within ADT tree", { zpl_adt_node root; zpl_adt_set_obj(&root, "root", mem_alloc); - zpl_adt_inset_int(&root, "foo", 42); - zpl_adt_inset_str(&root, "bar", "life"); - zpl_adt_inset_str(&root, "question", "answer"); + zpl_adt_append_int(&root, "foo", 42); + zpl_adt_append_str(&root, "bar", "life"); + zpl_adt_append_str(&root, "question", "answer"); EQUALS(root.nodes[0].integer, 42); STREQUALS(root.nodes[1].string, "life"); @@ -37,13 +37,13 @@ MODULE(adt, { IT("can find a node buried deep within ADT tree", { zpl_adt_node root; zpl_adt_set_obj(&root, "root", mem_alloc); - zpl_adt_inset_int(&root, "foo", 42); - zpl_adt_inset_str(&root, "bar", "life"); + zpl_adt_append_int(&root, "foo", 42); + zpl_adt_append_str(&root, "bar", "life"); zpl_adt_node *level1, *level2; - level1 = zpl_adt_inset_obj(&root, "level1"); - level2 = zpl_adt_inset_obj(level1, "level2"); - zpl_adt_inset_str(level2, "question", "answer"); + level1 = zpl_adt_append_obj(&root, "level1"); + level2 = zpl_adt_append_obj(level1, "level2"); + zpl_adt_append_str(level2, "question", "answer"); EQUALS(root.nodes[0].integer, 42); STREQUALS(root.nodes[1].string, "life"); @@ -54,9 +54,9 @@ MODULE(adt, { IT("can swap 2 nodes", { zpl_adt_node root; zpl_adt_set_obj(&root, "root", mem_alloc); - zpl_adt_node *n1 = zpl_adt_inset_int(&root, "foo", 42); - zpl_adt_node *n2 = zpl_adt_inset_str(&root, "bar", "life"); - zpl_adt_swap_nodes(n1, n2, &root); + zpl_adt_node *n1 = zpl_adt_append_int(&root, "foo", 42); + zpl_adt_node *n2 = zpl_adt_append_str(&root, "bar", "life"); + zpl_adt_swap_nodes(n1, n2); EQUALS(root.nodes[1].integer, 42); STREQUALS(root.nodes[0].string, "life"); }); @@ -64,36 +64,36 @@ MODULE(adt, { zpl_adt_node root, root2; zpl_adt_set_obj(&root, "root", mem_alloc); zpl_adt_set_obj(&root2, "root2", mem_alloc); - zpl_adt_node *n1 = zpl_adt_inset_int(&root, "foo", 42); - zpl_adt_node *n2 = zpl_adt_inset_str(&root2, "bar", "life"); - zpl_adt_swap_nodes_between_parents(n1, n2, &root, &root2); + zpl_adt_node *n1 = zpl_adt_append_int(&root, "foo", 42); + zpl_adt_node *n2 = zpl_adt_append_str(&root2, "bar", "life"); + zpl_adt_swap_nodes(n1, n2); EQUALS(root2.nodes[0].integer, 42); STREQUALS(root.nodes[0].string, "life"); }); IT("can remove a node from tree", { zpl_adt_node root; zpl_adt_set_obj(&root, "root", mem_alloc); - zpl_adt_node *n1 = zpl_adt_inset_int(&root, "foo", 42); - zpl_adt_remove_node(n1, &root); + zpl_adt_node *n1 = zpl_adt_append_int(&root, "foo", 42); + zpl_adt_remove_node(n1); EQUALS(zpl_array_count(root.nodes), 0); }); IT("can move a node from one parent to another", { zpl_adt_node root, root2; zpl_adt_set_obj(&root, "root", mem_alloc); zpl_adt_set_obj(&root2, "root2", mem_alloc); - zpl_adt_node *n1 = zpl_adt_inset_int(&root, "foo", 42); + zpl_adt_node *n1 = zpl_adt_append_int(&root, "foo", 42); EQUALS(root.nodes[0].integer, 42); EQUALS(zpl_array_count(root2.nodes), 0); - zpl_adt_move_node(n1, &root, &root2); + zpl_adt_move_node(n1, &root2); EQUALS(root2.nodes[0].integer, 42); EQUALS(zpl_array_count(root.nodes), 0); }); IT("can find a nested node in a tree", { zpl_adt_node root; zpl_adt_set_obj(&root, "root", mem_alloc); - zpl_adt_node *a = zpl_adt_inset_obj(&root, "a"); - zpl_adt_node *b = zpl_adt_inset_obj(a, "b"); - zpl_adt_node *c = zpl_adt_inset_obj(b, "c"); + zpl_adt_node *a = zpl_adt_append_obj(&root, "a"); + zpl_adt_node *b = zpl_adt_append_obj(a, "b"); + zpl_adt_node *c = zpl_adt_append_obj(b, "c"); zpl_adt_node *node = zpl_adt_get(&root, "a/b/c"); @@ -102,14 +102,14 @@ MODULE(adt, { IT("can find a node in an array where an object matches param=value", { zpl_adt_node root; zpl_adt_set_obj(&root, "root", mem_alloc); - zpl_adt_node *arr = zpl_adt_inset_arr(&root, "arr"); + zpl_adt_node *arr = zpl_adt_append_arr(&root, "arr"); - zpl_adt_node *a = zpl_adt_inset_obj(arr, 0); - zpl_adt_inset_int(a, "foo", 456); - zpl_adt_node *a2 = zpl_adt_inset_obj(arr, 0); - zpl_adt_inset_int(a2, "foo", 123); - zpl_adt_node *a3 = zpl_adt_inset_obj(arr, 0); - zpl_adt_inset_int(a3, "foo", 789); + zpl_adt_node *a = zpl_adt_append_obj(arr, 0); + zpl_adt_append_int(a, "foo", 456); + zpl_adt_node *a2 = zpl_adt_append_obj(arr, 0); + zpl_adt_append_int(a2, "foo", 123); + zpl_adt_node *a3 = zpl_adt_append_obj(arr, 0); + zpl_adt_append_int(a3, "foo", 789); zpl_adt_node *node = zpl_adt_get(&root, "arr/[foo=123]"); EQUALS(a2, node); @@ -117,11 +117,11 @@ MODULE(adt, { IT("can retrieve a node in an array at a specific index", { zpl_adt_node root; zpl_adt_set_obj(&root, "root", mem_alloc); - zpl_adt_node *arr = zpl_adt_inset_arr(&root, "arr"); + zpl_adt_node *arr = zpl_adt_append_arr(&root, "arr"); - zpl_adt_inset_int(arr, 0, 1); - zpl_adt_inset_int(arr, 0, 2); - zpl_adt_inset_int(arr, 0, 3); + zpl_adt_append_int(arr, 0, 1); + zpl_adt_append_int(arr, 0, 2); + zpl_adt_append_int(arr, 0, 3); zpl_adt_node *node = zpl_adt_get(&root, "arr/1"); EQUALS(2, node->integer); @@ -129,11 +129,11 @@ MODULE(adt, { IT("can find a node in an array of a specific value", { zpl_adt_node root; zpl_adt_set_obj(&root, "root", mem_alloc); - zpl_adt_node *arr = zpl_adt_inset_arr(&root, "arr"); + zpl_adt_node *arr = zpl_adt_append_arr(&root, "arr"); - zpl_adt_inset_int(arr, "1", 1); - zpl_adt_inset_int(arr, "2", 2); - zpl_adt_inset_int(arr, "3", 3); + zpl_adt_append_int(arr, "1", 1); + zpl_adt_append_int(arr, "2", 2); + zpl_adt_append_int(arr, "3", 3); zpl_adt_node *node = zpl_adt_get(&root, "arr/[2]"); EQUALS(2, node->integer); diff --git a/code/tests/cases/csv.h b/code/tests/cases/csv.h index 0629a4e9..819d4b85 100644 --- a/code/tests/cases/csv.h +++ b/code/tests/cases/csv.h @@ -108,22 +108,22 @@ MODULE(csv_parser, { zpl_json_object doc, *foo, *bar, *baz; zpl_adt_set_obj(&doc, NULL, mem_alloc); { - foo = zpl_adt_inset_arr(&doc, "foo"); + foo = zpl_adt_append_arr(&doc, "foo"); foo->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; { - zpl_adt_node *n = zpl_adt_inset_str(foo, NULL, "1"); + zpl_adt_node *n = zpl_adt_append_str(foo, NULL, "1"); n->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; } - bar = zpl_adt_inset_arr(&doc, "bar"); + bar = zpl_adt_append_arr(&doc, "bar"); bar->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; { - zpl_adt_node *n = zpl_adt_inset_str(bar, NULL, "2"); + zpl_adt_node *n = zpl_adt_append_str(bar, NULL, "2"); n->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; } - baz = zpl_adt_inset_arr(&doc, "baz"); + baz = zpl_adt_append_arr(&doc, "baz"); baz->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; { - zpl_adt_node *n = zpl_adt_inset_str(baz, NULL, "3"); + zpl_adt_node *n = zpl_adt_append_str(baz, NULL, "3"); n->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; } } @@ -137,22 +137,22 @@ MODULE(csv_parser, { zpl_json_object doc, *foo, *bar, *baz; zpl_adt_set_obj(&doc, NULL, mem_alloc); { - foo = zpl_adt_inset_arr(&doc, "foo"); + foo = zpl_adt_append_arr(&doc, "foo"); foo->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; { - zpl_adt_node *n = zpl_adt_inset_str(foo, NULL, "1"); + zpl_adt_node *n = zpl_adt_append_str(foo, NULL, "1"); n->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; } - bar = zpl_adt_inset_arr(&doc, "bar"); + bar = zpl_adt_append_arr(&doc, "bar"); bar->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; { - zpl_adt_node *n = zpl_adt_inset_str(bar, NULL, ""); + zpl_adt_node *n = zpl_adt_append_str(bar, NULL, ""); n->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; } - baz = zpl_adt_inset_arr(&doc, "baz"); + baz = zpl_adt_append_arr(&doc, "baz"); baz->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; { - zpl_adt_node *n = zpl_adt_inset_str(baz, NULL, "3"); + zpl_adt_node *n = zpl_adt_append_str(baz, NULL, "3"); n->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; } } @@ -166,22 +166,22 @@ MODULE(csv_parser, { zpl_json_object doc, *foo, *bar, *baz; zpl_adt_set_obj(&doc, NULL, mem_alloc); { - foo = zpl_adt_inset_arr(&doc, "foo"); + foo = zpl_adt_append_arr(&doc, "foo"); foo->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; { - zpl_adt_node *n = zpl_adt_inset_str(foo, NULL, "1"); + zpl_adt_node *n = zpl_adt_append_str(foo, NULL, "1"); n->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; } - bar = zpl_adt_inset_arr(&doc, "bar"); + bar = zpl_adt_append_arr(&doc, "bar"); bar->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; { - zpl_adt_node *n = zpl_adt_inset_str(bar, NULL, ""); + zpl_adt_node *n = zpl_adt_append_str(bar, NULL, ""); n->name_style = ZPL_ADT_NAME_STYLE_DOUBLE_QUOTE; } - baz = zpl_adt_inset_arr(&doc, "baz"); + baz = zpl_adt_append_arr(&doc, "baz"); baz->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; { - zpl_adt_node *n = zpl_adt_inset_str(baz, NULL, "3"); + zpl_adt_node *n = zpl_adt_append_str(baz, NULL, "3"); n->name_style = ZPL_ADT_NAME_STYLE_NO_QUOTES; } } @@ -195,9 +195,9 @@ MODULE(csv_parser, { zpl_json_object doc, *node; zpl_adt_set_arr(&doc, NULL, mem_alloc); { - node = zpl_adt_inset_arr(&doc, NULL); + node = zpl_adt_append_arr(&doc, NULL); { - zpl_adt_node *n = zpl_adt_inset_str(node, NULL, "x \"test\" x"); + zpl_adt_node *n = zpl_adt_append_str(node, NULL, "x \"test\" x"); n->name_style = ZPL_ADT_NAME_STYLE_DOUBLE_QUOTE; } } diff --git a/code/tests/cases/json.h b/code/tests/cases/json.h index cc5e0abd..8ed9b642 100644 --- a/code/tests/cases/json.h +++ b/code/tests/cases/json.h @@ -228,24 +228,24 @@ MODULE(json5_parser, { zpl_json_object doc, *o, *o2; zpl_adt_set_obj(&doc, NULL, mem_alloc); - o = zpl_adt_inset_str(&doc, "$api", "opengl"); - o = zpl_adt_inset_str(&doc, "name", "Diffuse shader"); - o = zpl_adt_inset_int(&doc, "version", 150); - o = zpl_adt_inset_str(&doc, "type", "fragment"); - o = zpl_adt_inset_arr(&doc, "uniforms"); + o = zpl_adt_append_str(&doc, "$api", "opengl"); + o = zpl_adt_append_str(&doc, "name", "Diffuse shader"); + o = zpl_adt_append_int(&doc, "version", 150); + o = zpl_adt_append_str(&doc, "type", "fragment"); + o = zpl_adt_append_arr(&doc, "uniforms"); { - o2 = zpl_adt_inset_obj(o, NULL); + o2 = zpl_adt_append_obj(o, NULL); { - zpl_adt_inset_str(o2, "name", "l_pos"); - zpl_adt_inset_str(o2, "type", "vec3"); + zpl_adt_append_str(o2, "name", "l_pos"); + zpl_adt_append_str(o2, "type", "vec3"); } - o2 = zpl_adt_inset_obj(o, NULL); + o2 = zpl_adt_append_obj(o, NULL); { - zpl_adt_inset_str(o2, "name", "l_mat"); - zpl_adt_inset_str(o2, "type", "mat4"); + zpl_adt_append_str(o2, "name", "l_mat"); + zpl_adt_append_str(o2, "type", "mat4"); } } - o = zpl_adt_inset_str(&doc, "_meta", "0 0 -34 2.34 123 2.34e-4"); + o = zpl_adt_append_str(&doc, "_meta", "0 0 -34 2.34 123 2.34e-4"); zpl_string a = zpl_json_write_string(mem_alloc, &doc, 0); STREQUALS(original, a);