summaryrefslogtreecommitdiffstats
path: root/src/ucl
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2013-11-02 22:12:39 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2013-11-02 22:12:39 +0000
commitbbf9405abd6caff16f7680e2d8918c71579e2161 (patch)
tree2c834e6e1b35231d809d5d0edfc0f5af4410fecf /src/ucl
parentebaf611123e405af3fcf1f59aa542198bc5c95b3 (diff)
downloadrspamd-bbf9405abd6caff16f7680e2d8918c71579e2161.tar.gz
rspamd-bbf9405abd6caff16f7680e2d8918c71579e2161.zip
Sync with libucl.
Diffstat (limited to 'src/ucl')
-rw-r--r--src/ucl/CMakeLists.txt4
-rw-r--r--src/ucl/include/ucl.h110
-rw-r--r--src/ucl/src/ucl_emitter.c81
-rw-r--r--src/ucl/src/ucl_internal.h25
-rw-r--r--src/ucl/src/ucl_parser.c45
-rw-r--r--src/ucl/src/ucl_util.c124
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;
+}