diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2013-11-02 22:12:39 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2013-11-02 22:12:39 +0000 |
commit | bbf9405abd6caff16f7680e2d8918c71579e2161 (patch) | |
tree | 2c834e6e1b35231d809d5d0edfc0f5af4410fecf /src/ucl | |
parent | ebaf611123e405af3fcf1f59aa542198bc5c95b3 (diff) | |
download | rspamd-bbf9405abd6caff16f7680e2d8918c71579e2161.tar.gz rspamd-bbf9405abd6caff16f7680e2d8918c71579e2161.zip |
Sync with libucl.
Diffstat (limited to 'src/ucl')
-rw-r--r-- | src/ucl/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/ucl/include/ucl.h | 110 | ||||
-rw-r--r-- | src/ucl/src/ucl_emitter.c | 81 | ||||
-rw-r--r-- | src/ucl/src/ucl_internal.h | 25 | ||||
-rw-r--r-- | src/ucl/src/ucl_parser.c | 45 | ||||
-rw-r--r-- | src/ucl/src/ucl_util.c | 124 |
6 files changed, 272 insertions, 117 deletions
diff --git a/src/ucl/CMakeLists.txt b/src/ucl/CMakeLists.txt index 73937d199..d4254aafb 100644 --- a/src/ucl/CMakeLists.txt +++ b/src/ucl/CMakeLists.txt @@ -1,6 +1,8 @@ SET(UCLSRC src/ucl_util.c src/ucl_parser.c - src/ucl_emitter.c) + src/ucl_emitter.c + src/ucl_hash.c + src/xxhash.c) ADD_LIBRARY(rspamd-ucl ${LINK_TYPE} ${UCLSRC}) SET_TARGET_PROPERTIES(rspamd-ucl PROPERTIES VERSION ${RSPAMD_VERSION}) diff --git a/src/ucl/include/ucl.h b/src/ucl/include/ucl.h index fe56a04da..aaad4a9a9 100644 --- a/src/ucl/include/ucl.h +++ b/src/ucl/include/ucl.h @@ -31,10 +31,7 @@ #include <stdbool.h> #include <stdarg.h> #include <stdio.h> - #include "config.h" -#include "uthash.h" -#include "utlist.h" /** * @file rcl.h @@ -77,6 +74,13 @@ #define UCL_FREE(size, ptr) free(ptr) #endif +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define UCL_WARN_UNUSED_RESULT \ + __attribute__((warn_unused_result)) +#else +#define UCL_WARN_UNUSED_RESULT +#endif + enum ucl_error { UCL_EOK = 0, //!< UCL_EOK UCL_ESYNTAX, //!< UCL_ESYNTAX @@ -153,17 +157,19 @@ typedef struct ucl_object_s { int64_t iv; /**< int value of an object */ const char *sv; /**< string value of an object */ double dv; /**< double value of an object */ - struct ucl_object_s *ov; /**< array or hash */ + struct ucl_object_s *av; /**< array */ + void *ov; /**< object */ void* ud; /**< opaque user data */ } value; - enum ucl_type type; /**< real type */ - short int ref; /**< reference count */ - short int flags; /**< object flags */ - size_t len; /**< size of an object */ + const char *key; /**< key of an object */ struct ucl_object_s *next; /**< array handle */ struct ucl_object_s *prev; /**< array handle */ unsigned char* trash_stack[2]; /**< pointer to allocated chunks */ - UT_hash_handle hh; /**< hash handle */ + unsigned keylen; /**< lenght of a key */ + unsigned len; /**< size of an object */ + enum ucl_type type; /**< real type */ + uint16_t ref; /**< reference count */ + uint16_t flags; /**< object flags */ } ucl_object_t; @@ -185,6 +191,7 @@ char* ucl_copy_value_trash (ucl_object_t *obj); * Creates a new object * @return new object */ +static inline ucl_object_t* ucl_object_new (void) UCL_WARN_UNUSED_RESULT; static inline ucl_object_t * ucl_object_new (void) { @@ -204,7 +211,8 @@ ucl_object_new (void) * @param flags conversion flags * @return new object */ -ucl_object_t * ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags); +ucl_object_t * ucl_object_fromstring_common (const char *str, size_t len, + enum ucl_string_flags flags) UCL_WARN_UNUSED_RESULT; /** * Create a UCL object from the specified string @@ -296,7 +304,7 @@ ucl_object_frombool (bool bv) * @return new value of top object */ ucl_object_t* ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, - const char *key, size_t keylen, bool copy_key); + const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; /** * Append an element to the array object @@ -304,9 +312,13 @@ ucl_object_t* ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, * @param eltelement to append (must NOT be NULL) * @return new value of top object */ +static inline ucl_object_t * ucl_array_append (ucl_object_t *top, + ucl_object_t *elt) UCL_WARN_UNUSED_RESULT; static inline ucl_object_t * ucl_array_append (ucl_object_t *top, ucl_object_t *elt) { + ucl_object_t *head; + if (elt == NULL) { return NULL; } @@ -314,9 +326,17 @@ ucl_array_append (ucl_object_t *top, ucl_object_t *elt) if (top == NULL) { top = ucl_object_new (); top->type = UCL_ARRAY; + top->value.av = elt; + elt->next = NULL; + elt->prev = elt; + } + else { + head = top->value.av; + elt->prev = head->prev; + head->prev->next = elt; + head->prev = elt; + elt->next = NULL; } - - DL_APPEND (top->value.ov, elt); return top; } @@ -327,10 +347,24 @@ ucl_array_append (ucl_object_t *top, ucl_object_t *elt) * @param elt new element * @return new head if applicable */ +static inline ucl_object_t * ucl_elt_append (ucl_object_t *head, + ucl_object_t *elt) UCL_WARN_UNUSED_RESULT; static inline ucl_object_t * ucl_elt_append (ucl_object_t *head, ucl_object_t *elt) { - DL_APPEND (head, elt); + + if (head == NULL) { + elt->next = NULL; + elt->prev = elt; + head = elt; + } + else { + elt->prev = head->prev; + head->prev->next = elt; + head->prev = elt; + elt->next = NULL; + } + return head; } @@ -497,7 +531,7 @@ ucl_obj_tostring (ucl_object_t *obj) * @return string value */ static inline const char * -ucl_obj_tostring_forced (ucl_object_t *obj) +ucl_object_tostring_forced (ucl_object_t *obj) { return ucl_copy_value_trash (obj); } @@ -548,21 +582,7 @@ ucl_obj_tolstring (ucl_object_t *obj, size_t *tlen) * @param key key to search * @return object matched the specified key or NULL if key is not found */ -static inline ucl_object_t * -ucl_obj_get_key (ucl_object_t *obj, const char *key) -{ - size_t keylen; - ucl_object_t *ret; - - if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) { - return NULL; - } - - keylen = strlen (key); - HASH_FIND (hh, obj->value.ov, key, keylen, ret); - - return ret; -} +ucl_object_t * ucl_obj_get_key (ucl_object_t *obj, const char *key); /** * Return object identified by a fixed size key in the specified object @@ -571,19 +591,7 @@ ucl_obj_get_key (ucl_object_t *obj, const char *key) * @param klen length of a key * @return object matched the specified key or NULL if key is not found */ -static inline ucl_object_t * -ucl_obj_get_keyl (ucl_object_t *obj, const char *key, size_t klen) -{ - ucl_object_t *ret; - - if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) { - return NULL; - } - - HASH_FIND (hh, obj->value.ov, key, klen, ret); - - return ret; -} +ucl_object_t *ucl_obj_get_keyl (ucl_object_t *obj, const char *key, size_t klen); /** * Returns a key of an object as a NULL terminated string @@ -605,8 +613,8 @@ ucl_object_key (ucl_object_t *obj) static inline const char * ucl_object_keyl (ucl_object_t *obj, size_t *len) { - *len = obj->hh.keylen; - return obj->hh.key; + *len = obj->keylen; + return obj->key; } /** @@ -723,4 +731,16 @@ unsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type); */ bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len); +typedef void* ucl_object_iter_t; + +/** + * Get next key from an object + * @param obj object to iterate + * @param iter opaque iterator, must be set to NULL on the first call: + * ucl_object_iter_t it = NULL; + * while ((cur = ucl_iterate_object (obj, &it)) != NULL) ... + * @return the next object or NULL + */ +ucl_object_t* ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values); + #endif /* RCL_H_ */ diff --git a/src/ucl/src/ucl_emitter.c b/src/ucl/src/ucl_emitter.c index 1cf7f2798..2973f1da2 100644 --- a/src/ucl/src/ucl_emitter.c +++ b/src/ucl/src/ucl_emitter.c @@ -141,7 +141,8 @@ ucl_print_float (UT_string *buf, double val) static void ucl_elt_obj_write_json (ucl_object_t *obj, UT_string *buf, unsigned int tabs, bool start_tabs, bool compact) { - ucl_object_t *cur, *tmp; + ucl_object_t *cur; + ucl_hash_iter_t it = NULL; if (start_tabs) { ucl_add_tabs (buf, tabs, compact); @@ -152,10 +153,10 @@ ucl_elt_obj_write_json (ucl_object_t *obj, UT_string *buf, unsigned int tabs, bo else { utstring_append_len (buf, "{\n", 2); } - HASH_ITER (hh, obj, cur, tmp) { + while ((cur = ucl_hash_iterate (obj->value.ov, &it))) { ucl_add_tabs (buf, tabs + 1, compact); - if (cur->hh.keylen > 0) { - ucl_elt_string_write_json (cur->hh.key, cur->hh.keylen, buf); + if (cur->keylen > 0) { + ucl_elt_string_write_json (cur->key, cur->keylen, buf); } else { utstring_append_len (buf, "null", 4); @@ -167,7 +168,7 @@ ucl_elt_obj_write_json (ucl_object_t *obj, UT_string *buf, unsigned int tabs, bo utstring_append_len (buf, ": ", 2); } ucl_obj_write_json (cur, buf, tabs + 1, false, compact); - if (cur->hh.next != NULL) { + if (ucl_hash_iter_has_next (it)) { if (compact) { utstring_append_c (buf, ','); } @@ -256,10 +257,10 @@ ucl_elt_write_json (ucl_object_t *obj, UT_string *buf, unsigned int tabs, bool s ucl_elt_string_write_json (obj->value.sv, obj->len, buf); break; case UCL_OBJECT: - ucl_elt_obj_write_json (obj->value.ov, buf, tabs, start_tabs, compact); + ucl_elt_obj_write_json (obj, buf, tabs, start_tabs, compact); break; case UCL_ARRAY: - ucl_elt_array_write_json (obj->value.ov, buf, tabs, start_tabs, compact); + ucl_elt_array_write_json (obj->value.av, buf, tabs, start_tabs, compact); break; case UCL_USERDATA: break; @@ -335,7 +336,8 @@ ucl_object_emit_json (ucl_object_t *obj, bool compact) static void ucl_elt_obj_write_rcl (ucl_object_t *obj, UT_string *buf, unsigned int tabs, bool start_tabs, bool is_top) { - ucl_object_t *cur, *tmp; + ucl_object_t *cur, *cur_obj; + ucl_hash_iter_t it = NULL; if (start_tabs) { ucl_add_tabs (buf, tabs, is_top); @@ -344,26 +346,28 @@ ucl_elt_obj_write_rcl (ucl_object_t *obj, UT_string *buf, unsigned int tabs, boo utstring_append_len (buf, "{\n", 2); } - HASH_ITER (hh, obj, cur, tmp) { - ucl_add_tabs (buf, tabs + 1, is_top); - if (cur->flags & UCL_OBJECT_NEED_KEY_ESCAPE) { - ucl_elt_string_write_json (cur->hh.key, cur->hh.keylen, buf); - } - else { - utstring_append_len (buf, cur->hh.key, cur->hh.keylen); - } - if (cur->type != UCL_OBJECT && cur->type != UCL_ARRAY) { - utstring_append_len (buf, " = ", 3); - } - else { - utstring_append_c (buf, ' '); - } - ucl_elt_write_rcl (cur, buf, is_top ? tabs : tabs + 1, false, false, true); - if (cur->type != UCL_OBJECT && cur->type != UCL_ARRAY) { - utstring_append_len (buf, ";\n", 2); - } - else { - utstring_append_c (buf, '\n'); + while ((cur = ucl_hash_iterate (obj->value.ov, &it))) { + LL_FOREACH (cur, cur_obj) { + ucl_add_tabs (buf, tabs + 1, is_top); + if (cur_obj->flags & UCL_OBJECT_NEED_KEY_ESCAPE) { + ucl_elt_string_write_json (cur_obj->key, cur_obj->keylen, buf); + } + else { + utstring_append_len (buf, cur_obj->key, cur_obj->keylen); + } + if (cur_obj->type != UCL_OBJECT && cur_obj->type != UCL_ARRAY) { + utstring_append_len (buf, " = ", 3); + } + else { + utstring_append_c (buf, ' '); + } + ucl_elt_write_rcl (cur_obj, buf, is_top ? tabs : tabs + 1, false, false, false); + if (cur_obj->type != UCL_OBJECT && cur_obj->type != UCL_ARRAY) { + utstring_append_len (buf, ";\n", 2); + } + else { + utstring_append_c (buf, '\n'); + } } } @@ -437,10 +441,10 @@ ucl_elt_write_rcl (ucl_object_t *obj, UT_string *buf, unsigned int tabs, ucl_elt_string_write_json (obj->value.sv, obj->len, buf); break; case UCL_OBJECT: - ucl_elt_obj_write_rcl (obj->value.ov, buf, tabs, start_tabs, is_top); + ucl_elt_obj_write_rcl (obj, buf, tabs, start_tabs, is_top); break; case UCL_ARRAY: - ucl_elt_array_write_rcl (obj->value.ov, buf, tabs, start_tabs, is_top); + ucl_elt_array_write_rcl (obj->value.av, buf, tabs, start_tabs, is_top); break; case UCL_USERDATA: break; @@ -475,7 +479,8 @@ ucl_object_emit_rcl (ucl_object_t *obj) static void ucl_elt_obj_write_yaml (ucl_object_t *obj, UT_string *buf, unsigned int tabs, bool start_tabs, bool is_top) { - ucl_object_t *cur, *tmp; + ucl_object_t *cur; + ucl_hash_iter_t it = NULL; if (start_tabs) { ucl_add_tabs (buf, tabs, is_top); @@ -484,13 +489,13 @@ ucl_elt_obj_write_yaml (ucl_object_t *obj, UT_string *buf, unsigned int tabs, bo utstring_append_len (buf, ": {\n", 4); } - HASH_ITER (hh, obj, cur, tmp) { + while ((cur = ucl_hash_iterate (obj->value.ov, &it))) { ucl_add_tabs (buf, tabs + 1, is_top); if (cur->flags & UCL_OBJECT_NEED_KEY_ESCAPE) { - ucl_elt_string_write_json (cur->hh.key, cur->hh.keylen, buf); + ucl_elt_string_write_json (cur->key, cur->keylen, buf); } else { - utstring_append_len (buf, cur->hh.key, cur->hh.keylen); + utstring_append_len (buf, cur->key, cur->keylen); } if (cur->type != UCL_OBJECT && cur->type != UCL_ARRAY) { utstring_append_len (buf, " : ", 3); @@ -582,10 +587,10 @@ ucl_elt_write_yaml (ucl_object_t *obj, UT_string *buf, unsigned int tabs, ucl_elt_string_write_json (obj->value.sv, obj->len, buf); break; case UCL_OBJECT: - ucl_elt_obj_write_yaml (obj->value.ov, buf, tabs, start_tabs, is_top); + ucl_elt_obj_write_yaml (obj, buf, tabs, start_tabs, is_top); break; case UCL_ARRAY: - ucl_elt_array_write_yaml (obj->value.ov, buf, tabs, start_tabs, is_top); + ucl_elt_array_write_yaml (obj->value.av, buf, tabs, start_tabs, is_top); break; case UCL_USERDATA: break; @@ -617,6 +622,10 @@ ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type) UT_string *buf = NULL; unsigned char *res = NULL; + if (obj == NULL) { + return NULL; + } + if (emit_type == UCL_EMIT_JSON) { buf = ucl_object_emit_json (obj, false); } diff --git a/src/ucl/src/ucl_internal.h b/src/ucl/src/ucl_internal.h index 393ecf85a..a6d8e096b 100644 --- a/src/ucl/src/ucl_internal.h +++ b/src/ucl/src/ucl_internal.h @@ -37,7 +37,10 @@ #include "utlist.h" #include "utstring.h" +#include "uthash.h" #include "ucl.h" +#include "ucl_hash.h" +#include "xxhash.h" #ifdef HAVE_OPENSSL #include <openssl/evp.h> @@ -249,4 +252,26 @@ ucl_maybe_parse_boolean (ucl_object_t *obj, const unsigned char *start, size_t l int ucl_maybe_parse_number (ucl_object_t *obj, const char *start, const char *end, const char **pos, bool allow_double); + +static inline ucl_object_t * +ucl_hash_search_obj (ucl_hash_t* hashlin, ucl_object_t *obj) +{ + return (ucl_object_t *)ucl_hash_search (hashlin, obj->key, obj->keylen); +} + +static inline ucl_hash_t * +ucl_hash_insert_object (ucl_hash_t *hashlin, ucl_object_t *obj) UCL_WARN_UNUSED_RESULT; + +static inline ucl_hash_t * +ucl_hash_insert_object (ucl_hash_t *hashlin, ucl_object_t *obj) +{ + if (hashlin == NULL) { + hashlin = ucl_hash_create (); + } + ucl_hash_insert (hashlin, obj, obj->key, obj->keylen); + + return hashlin; +} + + #endif /* UCL_INTERNAL_H_ */ diff --git a/src/ucl/src/ucl_parser.c b/src/ucl/src/ucl_parser.c index e125caee4..dd0ac4896 100644 --- a/src/ucl/src/ucl_parser.c +++ b/src/ucl/src/ucl_parser.c @@ -233,13 +233,13 @@ ucl_lex_is_comment (const unsigned char c1, const unsigned char c2) return false; } -static inline size_t +static inline ssize_t ucl_copy_or_store_ptr (struct ucl_parser *parser, const unsigned char *src, unsigned char **dst, const char **dst_const, size_t in_len, bool need_unescape, bool need_lowercase) { - size_t ret = 0; + ssize_t ret = -1; if (need_unescape || need_lowercase || !(parser->flags & UCL_PARSER_ZEROCOPY)) { /* Copy string */ @@ -275,8 +275,8 @@ ucl_maybe_parse_number (ucl_object_t *obj, const char *p = start, *c = start; char *endptr; bool got_dot = false, got_exp = false, need_double = false, is_date = false, valid_start = false; - double dv; - int64_t lv; + double dv = 0; + int64_t lv = 0; if (*p == '-') { p ++; @@ -604,8 +604,9 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk) const char *key; bool got_quote = false, got_eq = false, got_semicolon = false, need_unescape = false, ucl_escape = false; - ucl_object_t *nobj, *tobj, *container; - size_t keylen; + ucl_object_t *nobj, *tobj; + ucl_hash_t *container; + ssize_t keylen; p = chunk->pos; @@ -724,15 +725,22 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk) nobj = ucl_object_new (); keylen = ucl_copy_or_store_ptr (parser, c, &nobj->trash_stack[UCL_TRASH_KEY], &key, end - c, need_unescape, parser->flags & UCL_PARSER_KEY_LOWERCASE); - if (keylen == 0) { + if (keylen == -1) { + return false; + } + else if (keylen == 0) { + ucl_set_err (chunk, UCL_ESYNTAX, "empty keys are not allowed", &parser->err); return false; } container = parser->stack->obj->value.ov; - HASH_FIND (hh, container, key, keylen, tobj); + nobj->key = key; + nobj->keylen = keylen; + tobj = ucl_hash_search_obj (container, nobj); if (tobj == NULL) { - DL_APPEND (tobj, nobj); - HASH_ADD_KEYPTR (hh, container, key, keylen, nobj); + container = ucl_hash_insert_object (container, nobj); + nobj->prev = nobj; + nobj->next = NULL; } else { DL_APPEND (tobj, nobj); @@ -879,10 +887,10 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk) if (parser->stack->obj->type == UCL_ARRAY) { /* Object must be allocated */ obj = ucl_object_new (); - t = parser->stack->obj->value.ov; + t = parser->stack->obj->value.av; DL_APPEND (t, obj); parser->cur_obj = obj; - parser->stack->obj->value.ov = t; + parser->stack->obj->value.av = t; } else { /* Object has been already allocated */ @@ -899,7 +907,7 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk) str_len = chunk->pos - c - 2; obj->type = UCL_STRING; if ((str_len = ucl_copy_or_store_ptr (parser, c + 1, &obj->trash_stack[UCL_TRASH_VALUE], - &obj->value.sv, str_len, need_unescape, false)) == 0) { + &obj->value.sv, str_len, need_unescape, false)) == -1) { return false; } obj->len = str_len; @@ -910,7 +918,7 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk) case '{': /* We have a new object */ obj->type = UCL_OBJECT; - + obj->value.ov = ucl_hash_create (); parser->state = UCL_STATE_KEY; st = UCL_ALLOC (sizeof (struct ucl_stack)); st->obj = obj; @@ -957,7 +965,7 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk) } obj->type = UCL_STRING; if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE], - &obj->value.sv, str_len - 1, false, false)) == 0) { + &obj->value.sv, str_len - 1, false, false)) == -1) { return false; } obj->len = str_len; @@ -1003,7 +1011,7 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk) } obj->type = UCL_STRING; if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE], - &obj->value.sv, str_len, false, false)) == 0) { + &obj->value.sv, str_len, false, false)) == -1) { return false; } obj->len = str_len; @@ -1035,7 +1043,7 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk) } obj->type = UCL_STRING; if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE], - &obj->value.sv, str_len, false, false)) == 0) { + &obj->value.sv, str_len, false, false)) == -1) { return false; } obj->len = str_len; @@ -1217,7 +1225,7 @@ ucl_state_machine (struct ucl_parser *parser) ucl_object_t *obj; struct ucl_chunk *chunk = parser->chunks; struct ucl_stack *st; - const unsigned char *p, *c, *macro_start = NULL; + const unsigned char *p, *c = NULL, *macro_start = NULL; size_t macro_len = 0; struct ucl_macro *macro = NULL; @@ -1246,6 +1254,7 @@ ucl_state_machine (struct ucl_parser *parser) else { parser->state = UCL_STATE_KEY; obj->type = UCL_OBJECT; + obj->value.ov = ucl_hash_create (); if (*p == '{') { ucl_chunk_skipc (chunk, p); } diff --git a/src/ucl/src/ucl_util.c b/src/ucl/src/ucl_util.c index 09123e91e..10377e295 100644 --- a/src/ucl/src/ucl_util.c +++ b/src/ucl/src/ucl_util.c @@ -53,7 +53,7 @@ ucl_object_free_internal (ucl_object_t *obj, bool allow_rec) } if (obj->type == UCL_ARRAY) { - sub = obj->value.ov; + sub = obj->value.av; while (sub != NULL) { tmp = sub->next; ucl_object_free_internal (sub, false); @@ -61,10 +61,7 @@ ucl_object_free_internal (ucl_object_t *obj, bool allow_rec) } } else if (obj->type == UCL_OBJECT) { - HASH_ITER (hh, obj->value.ov, sub, tmp) { - HASH_DELETE (hh, obj->value.ov, sub); - ucl_object_free_internal (sub, true); - } + ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)ucl_obj_free); } tmp = obj->next; UCL_FREE (sizeof (ucl_object_t), obj); @@ -179,13 +176,13 @@ ucl_unescape_json_string (char *str, size_t len) char * ucl_copy_key_trash (ucl_object_t *obj) { - if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->hh.key != NULL) { - obj->trash_stack[UCL_TRASH_KEY] = malloc (obj->hh.keylen + 1); + if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) { + obj->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1); if (obj->trash_stack[UCL_TRASH_KEY] != NULL) { - memcpy (obj->trash_stack[UCL_TRASH_KEY], obj->hh.key, obj->hh.keylen); - obj->trash_stack[UCL_TRASH_KEY][obj->hh.keylen] = '\0'; + memcpy (obj->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen); + obj->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0'; } - obj->hh.key = obj->trash_stack[UCL_TRASH_KEY]; + obj->key = obj->trash_stack[UCL_TRASH_KEY]; obj->flags |= UCL_OBJECT_ALLOCATED_KEY; } @@ -278,7 +275,6 @@ ucl_parser_get_error(struct ucl_parser *parser) bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len) { - struct ucl_pubkey *nkey; #ifndef HAVE_OPENSSL ucl_create_err (&parser->err, "cannot check signatures without openssl"); return false; @@ -287,6 +283,7 @@ ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len) ucl_create_err (err, "cannot check signatures, openssl version is unsupported"); return EXIT_FAILURE; # else + struct ucl_pubkey *nkey; BIO *mem; mem = BIO_new_mem_buf ((void *)key, len); @@ -519,8 +516,8 @@ ucl_include_url (const unsigned char *data, size_t len, { bool res; - unsigned char *buf = NULL, *sigbuf = NULL; - size_t buflen = 0, siglen = 0; + unsigned char *buf = NULL; + size_t buflen = 0; struct ucl_chunk *chunk; char urlbuf[PATH_MAX]; @@ -532,6 +529,8 @@ ucl_include_url (const unsigned char *data, size_t len, if (check_signature) { #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L) + unsigned char *sigbuf = NULL; + size_t siglen = 0; /* We need to check signature first */ snprintf (urlbuf, sizeof (urlbuf), "%.*s.sig", (int)len, data); if (!ucl_fetch_file (urlbuf, &sigbuf, &siglen, &parser->err)) { @@ -576,8 +575,8 @@ ucl_include_file (const unsigned char *data, size_t len, { bool res; struct ucl_chunk *chunk; - unsigned char *buf = NULL, *sigbuf = NULL; - size_t buflen, siglen; + unsigned char *buf = NULL; + size_t buflen; char filebuf[PATH_MAX], realbuf[PATH_MAX]; snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data); @@ -594,6 +593,8 @@ ucl_include_file (const unsigned char *data, size_t len, if (check_signature) { #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L) + unsigned char *sigbuf = NULL; + size_t siglen = 0; /* We need to check signature first */ snprintf (filebuf, sizeof (filebuf), "%s.sig", realbuf); if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err)) { @@ -870,6 +871,11 @@ ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, top = ucl_object_new (); top->type = UCL_OBJECT; } + + if (top->value.ov == NULL) { + top->value.ov = ucl_hash_create (); + } + if (keylen == 0) { keylen = strlen (key); } @@ -881,11 +887,15 @@ ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, } } - HASH_FIND (hh, top->value.ov, key, keylen, found); + elt->key = key; + elt->keylen = keylen; + + found = ucl_hash_search_obj (top->value.ov, elt); if (!found) { - HASH_ADD_KEYPTR (hh, top->value.ov, key, keylen, elt); + top->value.ov = ucl_hash_insert_object (top->value.ov, elt); } + DL_APPEND (found, elt); if (copy_key) { @@ -894,3 +904,83 @@ ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, return top; } + +ucl_object_t * +ucl_obj_get_keyl (ucl_object_t *obj, const char *key, size_t klen) +{ + ucl_object_t *ret, srch; + + if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) { + return NULL; + } + + srch.key = key; + srch.keylen = klen; + ret = ucl_hash_search_obj (obj->value.ov, &srch); + + return ret; +} + +ucl_object_t * +ucl_obj_get_key (ucl_object_t *obj, const char *key) +{ + size_t klen; + ucl_object_t *ret, srch; + + if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) { + return NULL; + } + + klen = strlen (key); + srch.key = key; + srch.keylen = klen; + ret = ucl_hash_search_obj (obj->value.ov, &srch); + + return ret; +} + +ucl_object_t* +ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values) +{ + ucl_object_t *elt; + + if (expand_values) { + switch (obj->type) { + case UCL_OBJECT: + return (ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter); + break; + case UCL_ARRAY: + elt = *iter; + if (elt == NULL) { + elt = obj->value.av; + if (elt == NULL) { + return NULL; + } + } + else if (elt == obj->value.av) { + return NULL; + } + *iter = elt->next ? elt->next : obj->value.av; + return elt; + default: + /* Go to linear iteration */ + break; + } + } + /* Treat everything as a linear list */ + elt = *iter; + if (elt == NULL) { + elt = obj; + if (elt == NULL) { + return NULL; + } + } + else if (elt == obj) { + return NULL; + } + *iter = elt->next ? elt->next : obj; + return elt; + + /* Not reached */ + return NULL; +} |