From d4fc17b1e5ff64ea70cfb02594ae87f599f81c29 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Tue, 22 Apr 2014 21:56:27 +0000 Subject: Import libucl 0.4.0 --- src/Makefile.am | 2 + src/ucl_emitter.c | 59 +++++----- src/ucl_hash.c | 15 ++- src/ucl_hash.h | 12 +- src/ucl_internal.h | 18 ++- src/ucl_parser.c | 34 +----- src/ucl_schema.c | 102 +++++++++-------- src/ucl_util.c | 320 +++++++++++++++++++++++++++++++---------------------- 8 files changed, 305 insertions(+), 257 deletions(-) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 499d640508a2..76391cd044f0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,6 +13,8 @@ libucl_la_CFLAGS= $(libucl_common_cflags) \ @CURL_CFLAGS@ libucl_la_LDFLAGS = -version-info @SO_VERSION@ libucl_la_LIBADD= @LIBFETCH_LIBS@ \ + @LIBCRYPTO_LIB@ \ + @LIBREGEX_LIB@ \ @CURL_LIBS@ include_HEADERS= $(top_srcdir)/include/ucl.h diff --git a/src/ucl_emitter.c b/src/ucl_emitter.c index eb314ac21cd7..04c3d4b13232 100644 --- a/src/ucl_emitter.c +++ b/src/ucl_emitter.c @@ -41,29 +41,29 @@ */ -static void ucl_obj_write_json (ucl_object_t *obj, +static void ucl_obj_write_json (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool compact); -static void ucl_elt_write_json (ucl_object_t *obj, +static void ucl_elt_write_json (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool compact); -static void ucl_elt_write_config (ucl_object_t *obj, +static void ucl_elt_write_config (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool is_top, bool expand_array); -static void ucl_elt_write_yaml (ucl_object_t *obj, +static void ucl_elt_write_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool compact, bool expand_array); -static void ucl_elt_array_write_yaml (ucl_object_t *obj, +static void ucl_elt_array_write_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, @@ -144,10 +144,10 @@ ucl_elt_string_write_json (const char *str, size_t size, * @param buf target buffer */ static void -ucl_elt_obj_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, +ucl_elt_obj_write_json (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool compact) { - ucl_object_t *cur; + const ucl_object_t *cur; ucl_hash_iter_t it = NULL; if (start_tabs) { @@ -196,10 +196,10 @@ ucl_elt_obj_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, * @param buf target buffer */ static void -ucl_elt_array_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, +ucl_elt_array_write_json (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool compact) { - ucl_object_t *cur = obj; + const ucl_object_t *cur = obj; if (start_tabs) { ucl_add_tabs (func, tabs, compact); @@ -235,7 +235,7 @@ ucl_elt_array_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, * @param buf buffer */ static void -ucl_elt_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, +ucl_elt_write_json (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool compact) { bool flag; @@ -295,10 +295,10 @@ ucl_elt_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, * @param buf target buffer */ static void -ucl_obj_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, +ucl_obj_write_json (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool compact) { - ucl_object_t *cur; + const ucl_object_t *cur; bool is_array = (obj->next != NULL); if (is_array) { @@ -339,7 +339,8 @@ ucl_obj_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, * @return json output (should be freed after using) */ static void -ucl_object_emit_json (ucl_object_t *obj, bool compact, struct ucl_emitter_functions *func) +ucl_object_emit_json (const ucl_object_t *obj, bool compact, + struct ucl_emitter_functions *func) { ucl_obj_write_json (obj, func, 0, false, compact); } @@ -350,10 +351,10 @@ ucl_object_emit_json (ucl_object_t *obj, bool compact, struct ucl_emitter_functi * @param buf target buffer */ static void -ucl_elt_obj_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func, +ucl_elt_obj_write_config (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool is_top) { - ucl_object_t *cur, *cur_obj; + const ucl_object_t *cur, *cur_obj; ucl_hash_iter_t it = NULL; if (start_tabs) { @@ -402,10 +403,10 @@ ucl_elt_obj_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func, * @param buf target buffer */ static void -ucl_elt_array_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func, +ucl_elt_array_write_config (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool is_top) { - ucl_object_t *cur = obj; + const ucl_object_t *cur = obj; if (start_tabs) { ucl_add_tabs (func, tabs, false); @@ -427,7 +428,7 @@ ucl_elt_array_write_config (ucl_object_t *obj, struct ucl_emitter_functions *fun * @param buf buffer */ static void -ucl_elt_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func, +ucl_elt_write_config (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool is_top, bool expand_array) { bool flag; @@ -492,14 +493,14 @@ ucl_elt_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func, * @return rcl output (should be freed after using) */ static void -ucl_object_emit_config (ucl_object_t *obj, struct ucl_emitter_functions *func) +ucl_object_emit_config (const ucl_object_t *obj, struct ucl_emitter_functions *func) { ucl_elt_write_config (obj, func, 0, false, true, true); } static void -ucl_obj_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, +ucl_obj_write_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs) { bool is_array = (obj->next != NULL); @@ -518,10 +519,10 @@ ucl_obj_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, * @param buf target buffer */ static void -ucl_elt_obj_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, +ucl_elt_obj_write_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool is_top) { - ucl_object_t *cur; + const ucl_object_t *cur; ucl_hash_iter_t it = NULL; if (start_tabs) { @@ -566,10 +567,10 @@ ucl_elt_obj_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, * @param buf target buffer */ static void -ucl_elt_array_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, +ucl_elt_array_write_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool is_top) { - ucl_object_t *cur = obj; + const ucl_object_t *cur = obj; if (start_tabs) { ucl_add_tabs (func, tabs, false); @@ -591,7 +592,7 @@ ucl_elt_array_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, * @param buf buffer */ static void -ucl_elt_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, +ucl_elt_write_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool is_top, bool expand_array) { bool flag; @@ -656,7 +657,7 @@ ucl_elt_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func, * @return rcl output (should be freed after using) */ static void -ucl_object_emit_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func) +ucl_object_emit_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func) { ucl_elt_write_yaml (obj, func, 0, false, true, true); } @@ -723,7 +724,7 @@ ucl_utstring_append_double (double val, void *ud) unsigned char * -ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type) +ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type) { UT_string *buf = NULL; unsigned char *res = NULL; @@ -763,7 +764,7 @@ ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type) } bool -ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type, +ucl_object_emit_full (const ucl_object_t *obj, enum ucl_emitter emit_type, struct ucl_emitter_functions *emitter) { if (emit_type == UCL_EMIT_JSON) { @@ -785,7 +786,7 @@ ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type, unsigned char * -ucl_object_emit_single_json (ucl_object_t *obj) +ucl_object_emit_single_json (const ucl_object_t *obj) { UT_string *buf = NULL; unsigned char *res = NULL; diff --git a/src/ucl_hash.c b/src/ucl_hash.c index 0ab962a42009..c2e80cb4b252 100644 --- a/src/ucl_hash.c +++ b/src/ucl_hash.c @@ -40,11 +40,15 @@ ucl_hash_create (void) void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func) { ucl_hash_node_t *elt, *tmp; + const ucl_object_t *cur, *otmp; HASH_ITER (hh, hashlin->buckets, elt, tmp) { HASH_DELETE (hh, hashlin->buckets, elt); if (func) { - func (elt->data); + DL_FOREACH_SAFE (elt->data, cur, otmp) { + /* Need to deconst here */ + func (__DECONST (ucl_object_t *, cur)); + } } UCL_FREE (sizeof (ucl_hash_node_t), elt); } @@ -52,7 +56,8 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func) } void -ucl_hash_insert (ucl_hash_t* hashlin, ucl_object_t *obj, const char *key, unsigned keylen) +ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj, + const char *key, unsigned keylen) { ucl_hash_node_t *node; @@ -61,7 +66,7 @@ ucl_hash_insert (ucl_hash_t* hashlin, ucl_object_t *obj, const char *key, unsign HASH_ADD_KEYPTR (hh, hashlin->buckets, key, keylen, node); } -void* +const void* ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter) { ucl_hash_node_t *elt = *iter; @@ -92,7 +97,7 @@ ucl_hash_iter_has_next (ucl_hash_iter_t iter) } -ucl_object_t* +const ucl_object_t* ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen) { ucl_hash_node_t *found; @@ -109,7 +114,7 @@ ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen) } void -ucl_hash_delete (ucl_hash_t* hashlin, ucl_object_t *obj) +ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj) { ucl_hash_node_t *found; diff --git a/src/ucl_hash.h b/src/ucl_hash.h index 5c9b851b9f29..cbbf005240bd 100644 --- a/src/ucl_hash.h +++ b/src/ucl_hash.h @@ -31,7 +31,7 @@ typedef struct ucl_hash_node_s { - ucl_object_t *data; + const ucl_object_t *data; UT_hash_handle hh; } ucl_hash_node_t; @@ -62,17 +62,19 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func); /** * Inserts an element in the the hashtable. */ -void ucl_hash_insert (ucl_hash_t* hashlin, ucl_object_t *obj, const char *key, unsigned keylen); +void ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj, const char *key, + unsigned keylen); /** * Delete an element from the the hashtable. */ -void ucl_hash_delete (ucl_hash_t* hashlin, ucl_object_t *obj); +void ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj); /** * Searches an element in the hashtable. */ -ucl_object_t* ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen); +const ucl_object_t* ucl_hash_search (ucl_hash_t* hashlin, const char *key, + unsigned keylen); /** @@ -81,7 +83,7 @@ ucl_object_t* ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned ke * @param iter iterator (must be NULL on first iteration) * @return the next object */ -void* ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter); +const void* ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter); /** * Check whether an iterator has next element diff --git a/src/ucl_internal.h b/src/ucl_internal.h index a55d747dbfcc..9a35dcec40be 100644 --- a/src/ucl_internal.h +++ b/src/ucl_internal.h @@ -45,7 +45,9 @@ #define HAVE_STDBOOL_H #define HAVE_STDINT_H #define HAVE_STDARG_H -#define HAVE_REGEX_H +#ifndef _WIN32 +# define HAVE_REGEX_H +#endif #endif #ifdef HAVE_SYS_TYPES_H @@ -97,6 +99,10 @@ #include #endif +#ifndef __DECONST +#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) +#endif + /** * @file rcl_internal.h * Internal structures and functions of UCL library @@ -314,17 +320,17 @@ int ucl_maybe_parse_number (ucl_object_t *obj, bool allow_double, bool number_bytes, bool allow_time); -static inline ucl_object_t * +static inline const 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); + return (const 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; +ucl_hash_insert_object (ucl_hash_t *hashlin, const 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) +ucl_hash_insert_object (ucl_hash_t *hashlin, const ucl_object_t *obj) { if (hashlin == NULL) { hashlin = ucl_hash_create (); @@ -339,6 +345,6 @@ ucl_hash_insert_object (ucl_hash_t *hashlin, ucl_object_t *obj) * @param obj * @return */ -unsigned char * ucl_object_emit_single_json (ucl_object_t *obj); +unsigned char * ucl_object_emit_single_json (const ucl_object_t *obj); #endif /* UCL_INTERNAL_H_ */ diff --git a/src/ucl_parser.c b/src/ucl_parser.c index a067286df40c..d5a085ebf829 100644 --- a/src/ucl_parser.c +++ b/src/ucl_parser.c @@ -55,34 +55,6 @@ struct ucl_parser_saved_state { (chunk)->remain --; \ } while (0) -/** - * Save parser state - * @param chunk - * @param s - */ -static inline void -ucl_chunk_save_state (struct ucl_chunk *chunk, struct ucl_parser_saved_state *s) -{ - s->column = chunk->column; - s->pos = chunk->pos; - s->line = chunk->line; - s->remain = chunk->remain; -} - -/** - * Restore parser state - * @param chunk - * @param s - */ -static inline void -ucl_chunk_restore_state (struct ucl_chunk *chunk, struct ucl_parser_saved_state *s) -{ - chunk->column = s->column; - chunk->pos = s->pos; - chunk->line = s->line; - chunk->remain = s->remain; -} - static inline void ucl_set_err (struct ucl_chunk *chunk, int code, const char *str, UT_string **err) { @@ -1086,19 +1058,19 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke 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, false); if (keylen == -1) { - ucl_object_free(nobj); + ucl_object_unref (nobj); return false; } else if (keylen == 0) { ucl_set_err (chunk, UCL_ESYNTAX, "empty keys are not allowed", &parser->err); - ucl_object_free(nobj); + ucl_object_unref (nobj); return false; } container = parser->stack->obj->value.ov; nobj->key = key; nobj->keylen = keylen; - tobj = ucl_hash_search_obj (container, nobj); + tobj = __DECONST (ucl_object_t *, ucl_hash_search_obj (container, nobj)); if (tobj == NULL) { container = ucl_hash_insert_object (container, nobj); nobj->prev = nobj; diff --git a/src/ucl_schema.c b/src/ucl_schema.c index a74ed0f527a1..faffe8613ce7 100644 --- a/src/ucl_schema.c +++ b/src/ucl_schema.c @@ -40,10 +40,10 @@ #include #endif -static bool ucl_schema_validate (ucl_object_t *schema, - ucl_object_t *obj, bool try_array, +static bool ucl_schema_validate (const ucl_object_t *schema, + const ucl_object_t *obj, bool try_array, struct ucl_schema_error *err, - ucl_object_t *root); + const ucl_object_t *root); static bool ucl_string_to_type (const char *input, ucl_type_t *res) @@ -115,7 +115,7 @@ ucl_object_type_to_string (ucl_type_t type) */ static void ucl_schema_create_error (struct ucl_schema_error *err, - enum ucl_schema_error_code code, ucl_object_t *obj, + enum ucl_schema_error_code code, const ucl_object_t *obj, const char *fmt, ...) { va_list va; @@ -132,11 +132,13 @@ ucl_schema_create_error (struct ucl_schema_error *err, /* * Check whether we have a pattern specified */ -static ucl_object_t * -ucl_schema_test_pattern (ucl_object_t *obj, const char *pattern) +static const ucl_object_t * +ucl_schema_test_pattern (const ucl_object_t *obj, const char *pattern) { + const ucl_object_t *res = NULL; +#ifdef HAVE_REGEX_H regex_t reg; - ucl_object_t *res = NULL, *elt; + const ucl_object_t *elt; ucl_object_iter_t iter = NULL; if (regcomp (®, pattern, REG_EXTENDED | REG_NOSUB) == 0) { @@ -148,7 +150,7 @@ ucl_schema_test_pattern (ucl_object_t *obj, const char *pattern) } regfree (®); } - +#endif return res; } @@ -156,11 +158,11 @@ ucl_schema_test_pattern (ucl_object_t *obj, const char *pattern) * Check dependencies for an object */ static bool -ucl_schema_validate_dependencies (ucl_object_t *deps, - ucl_object_t *obj, struct ucl_schema_error *err, - ucl_object_t *root) +ucl_schema_validate_dependencies (const ucl_object_t *deps, + const ucl_object_t *obj, struct ucl_schema_error *err, + const ucl_object_t *root) { - ucl_object_t *elt, *cur, *cur_dep; + const ucl_object_t *elt, *cur, *cur_dep; ucl_object_iter_t iter = NULL, piter; bool ret = true; @@ -193,11 +195,11 @@ ucl_schema_validate_dependencies (ucl_object_t *deps, * Validate object */ static bool -ucl_schema_validate_object (ucl_object_t *schema, - ucl_object_t *obj, struct ucl_schema_error *err, - ucl_object_t *root) +ucl_schema_validate_object (const ucl_object_t *schema, + const ucl_object_t *obj, struct ucl_schema_error *err, + const ucl_object_t *root) { - ucl_object_t *elt, *prop, *found, *additional_schema = NULL, + const ucl_object_t *elt, *prop, *found, *additional_schema = NULL, *required = NULL, *pat, *pelt; ucl_object_iter_t iter = NULL, piter = NULL; bool ret = true, allow_additional = true; @@ -334,10 +336,10 @@ ucl_schema_validate_object (ucl_object_t *schema, } static bool -ucl_schema_validate_number (ucl_object_t *schema, - ucl_object_t *obj, struct ucl_schema_error *err) +ucl_schema_validate_number (const ucl_object_t *schema, + const ucl_object_t *obj, struct ucl_schema_error *err) { - ucl_object_t *elt, *test; + const ucl_object_t *elt, *test; ucl_object_iter_t iter = NULL; bool ret = true, exclusive = false; double constraint, val; @@ -400,14 +402,16 @@ ucl_schema_validate_number (ucl_object_t *schema, } static bool -ucl_schema_validate_string (ucl_object_t *schema, - ucl_object_t *obj, struct ucl_schema_error *err) +ucl_schema_validate_string (const ucl_object_t *schema, + const ucl_object_t *obj, struct ucl_schema_error *err) { - ucl_object_t *elt; + const ucl_object_t *elt; ucl_object_iter_t iter = NULL; bool ret = true; int64_t constraint; +#ifdef HAVE_REGEX_H regex_t re; +#endif while (ret && (elt = ucl_iterate_object (schema, &iter, true)) != NULL) { if (elt->type == UCL_INT && @@ -432,6 +436,7 @@ ucl_schema_validate_string (ucl_object_t *schema, break; } } +#ifdef HAVE_REGEX_H else if (elt->type == UCL_STRING && strcmp (ucl_object_key (elt), "pattern") == 0) { if (regcomp (&re, ucl_object_tostring (elt), @@ -449,13 +454,14 @@ ucl_schema_validate_string (ucl_object_t *schema, } regfree (&re); } +#endif } return ret; } struct ucl_compare_node { - ucl_object_t *obj; + const ucl_object_t *obj; TREE_ENTRY(ucl_compare_node) link; struct ucl_compare_node *next; }; @@ -467,17 +473,17 @@ TREE_DEFINE(ucl_compare_node, link) static int ucl_schema_elt_compare (struct ucl_compare_node *n1, struct ucl_compare_node *n2) { - ucl_object_t *o1 = n1->obj, *o2 = n2->obj; + const ucl_object_t *o1 = n1->obj, *o2 = n2->obj; return ucl_object_compare (o1, o2); } static bool -ucl_schema_array_is_unique (ucl_object_t *obj, struct ucl_schema_error *err) +ucl_schema_array_is_unique (const ucl_object_t *obj, struct ucl_schema_error *err) { ucl_compare_tree_t tree = TREE_INITIALIZER (ucl_schema_elt_compare); ucl_object_iter_t iter = NULL; - ucl_object_t *elt; + const ucl_object_t *elt; struct ucl_compare_node *node, test, *nodes = NULL, *tmp; bool ret = true; @@ -510,11 +516,11 @@ ucl_schema_array_is_unique (ucl_object_t *obj, struct ucl_schema_error *err) } static bool -ucl_schema_validate_array (ucl_object_t *schema, - ucl_object_t *obj, struct ucl_schema_error *err, - ucl_object_t *root) +ucl_schema_validate_array (const ucl_object_t *schema, + const ucl_object_t *obj, struct ucl_schema_error *err, + const ucl_object_t *root) { - ucl_object_t *elt, *it, *found, *additional_schema = NULL, + const ucl_object_t *elt, *it, *found, *additional_schema = NULL, *first_unvalidated = NULL; ucl_object_iter_t iter = NULL, piter = NULL; bool ret = true, allow_additional = true, need_unique = false; @@ -627,11 +633,11 @@ ucl_schema_validate_array (ucl_object_t *schema, * Returns whether this object is allowed for this type */ static bool -ucl_schema_type_is_allowed (ucl_object_t *type, ucl_object_t *obj, +ucl_schema_type_is_allowed (const ucl_object_t *type, const ucl_object_t *obj, struct ucl_schema_error *err) { ucl_object_iter_t iter = NULL; - ucl_object_t *elt; + const ucl_object_t *elt; const char *type_str; ucl_type_t t; @@ -683,11 +689,11 @@ ucl_schema_type_is_allowed (ucl_object_t *type, ucl_object_t *obj, * Check if object is equal to one of elements of enum */ static bool -ucl_schema_validate_enum (ucl_object_t *en, ucl_object_t *obj, +ucl_schema_validate_enum (const ucl_object_t *en, const ucl_object_t *obj, struct ucl_schema_error *err) { ucl_object_iter_t iter = NULL; - ucl_object_t *elt; + const ucl_object_t *elt; bool ret = false; while ((elt = ucl_iterate_object (en, &iter, true)) != NULL) { @@ -709,12 +715,12 @@ ucl_schema_validate_enum (ucl_object_t *en, ucl_object_t *obj, /* * Check a single ref component */ -static ucl_object_t * -ucl_schema_resolve_ref_component (ucl_object_t *cur, +static const ucl_object_t * +ucl_schema_resolve_ref_component (const ucl_object_t *cur, const char *refc, int len, struct ucl_schema_error *err) { - ucl_object_t *res = NULL; + const ucl_object_t *res = NULL; char *err_str; int num, i; @@ -762,12 +768,12 @@ ucl_schema_resolve_ref_component (ucl_object_t *cur, /* * Find reference schema */ -static ucl_object_t * -ucl_schema_resolve_ref (ucl_object_t *root, const char *ref, +static const ucl_object_t * +ucl_schema_resolve_ref (const ucl_object_t *root, const char *ref, struct ucl_schema_error *err) { const char *p, *c; - ucl_object_t *res = NULL; + const ucl_object_t *res = NULL; if (ref[0] != '#') { @@ -822,10 +828,10 @@ ucl_schema_resolve_ref (ucl_object_t *root, const char *ref, } static bool -ucl_schema_validate_values (ucl_object_t *schema, ucl_object_t *obj, +ucl_schema_validate_values (const ucl_object_t *schema, const ucl_object_t *obj, struct ucl_schema_error *err) { - ucl_object_t *elt, *cur; + const ucl_object_t *elt, *cur; int64_t constraint, i; elt = ucl_object_find_key (schema, "maxValues"); @@ -868,12 +874,12 @@ ucl_schema_validate_values (ucl_object_t *schema, ucl_object_t *obj, } static bool -ucl_schema_validate (ucl_object_t *schema, - ucl_object_t *obj, bool try_array, +ucl_schema_validate (const ucl_object_t *schema, + const ucl_object_t *obj, bool try_array, struct ucl_schema_error *err, - ucl_object_t *root) + const ucl_object_t *root) { - ucl_object_t *elt, *cur; + const ucl_object_t *elt, *cur; ucl_object_iter_t iter = NULL; bool ret; @@ -1001,8 +1007,8 @@ ucl_schema_validate (ucl_object_t *schema, } bool -ucl_object_validate (ucl_object_t *schema, - ucl_object_t *obj, struct ucl_schema_error *err) +ucl_object_validate (const ucl_object_t *schema, + const ucl_object_t *obj, struct ucl_schema_error *err) { return ucl_schema_validate (schema, obj, true, err, schema); } diff --git a/src/ucl_util.c b/src/ucl_util.c index f96c23cd6129..9178795d9446 100644 --- a/src/ucl_util.c +++ b/src/ucl_util.c @@ -134,35 +134,76 @@ static char* ucl_realpath(const char *path, char *resolved_path) { * Utilities for rcl parsing */ +typedef void (*ucl_object_dtor) (ucl_object_t *obj); +static void ucl_object_free_internal (ucl_object_t *obj, bool allow_rec, + ucl_object_dtor dtor); +static void ucl_object_dtor_unref (ucl_object_t *obj); static void -ucl_object_free_internal (ucl_object_t *obj, bool allow_rec) +ucl_object_dtor_free (ucl_object_t *obj) { - ucl_object_t *sub, *tmp; + if (obj->trash_stack[UCL_TRASH_KEY] != NULL) { + UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]); + } + if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) { + UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]); + } + UCL_FREE (sizeof (ucl_object_t), obj); +} - while (obj != NULL) { - if (obj->trash_stack[UCL_TRASH_KEY] != NULL) { - UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]); - } - if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) { - UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]); +/* + * This is a helper function that performs exactly the same as + * `ucl_object_unref` but it doesn't iterate over elements allowing + * to use it for individual elements of arrays and multiple values + */ +static void +ucl_object_dtor_unref_single (ucl_object_t *obj) +{ + if (obj != NULL) { +#ifdef HAVE_ATOMIC_BUILTINS + unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1); + if (rc == 0) { +#else + if (--obj->ref == 0) { +#endif + ucl_object_free_internal (obj, false, ucl_object_dtor_unref); } + } +} + +static void +ucl_object_dtor_unref (ucl_object_t *obj) +{ + if (obj->ref == 0) { + ucl_object_dtor_free (obj); + } + else { + /* This may cause dtor unref being called one more time */ + ucl_object_dtor_unref_single (obj); + } +} + +static void +ucl_object_free_internal (ucl_object_t *obj, bool allow_rec, ucl_object_dtor dtor) +{ + ucl_object_t *sub, *tmp; + while (obj != NULL) { if (obj->type == UCL_ARRAY) { sub = obj->value.av; while (sub != NULL) { tmp = sub->next; - ucl_object_free_internal (sub, false); + dtor (sub); sub = tmp; } } else if (obj->type == UCL_OBJECT) { if (obj->value.ov != NULL) { - ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)ucl_object_unref); + ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)dtor); } } tmp = obj->next; - UCL_FREE (sizeof (ucl_object_t), obj); + dtor (obj); obj = tmp; if (!allow_rec) { @@ -174,7 +215,7 @@ ucl_object_free_internal (ucl_object_t *obj, bool allow_rec) void ucl_object_free (ucl_object_t *obj) { - ucl_object_free_internal (obj, true); + ucl_object_free_internal (obj, true, ucl_object_dtor_free); } size_t @@ -282,47 +323,54 @@ ucl_unescape_json_string (char *str, size_t len) return (t - str); } -UCL_EXTERN char * -ucl_copy_key_trash (ucl_object_t *obj) +char * +ucl_copy_key_trash (const ucl_object_t *obj) { + ucl_object_t *deconst; + if (obj == NULL) { return NULL; } 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->key, obj->keylen); - obj->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0'; + deconst = __DECONST (ucl_object_t *, obj); + deconst->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1); + if (deconst->trash_stack[UCL_TRASH_KEY] != NULL) { + memcpy (deconst->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen); + deconst->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0'; } - obj->key = obj->trash_stack[UCL_TRASH_KEY]; - obj->flags |= UCL_OBJECT_ALLOCATED_KEY; + deconst->key = obj->trash_stack[UCL_TRASH_KEY]; + deconst->flags |= UCL_OBJECT_ALLOCATED_KEY; } return obj->trash_stack[UCL_TRASH_KEY]; } -UCL_EXTERN char * -ucl_copy_value_trash (ucl_object_t *obj) +char * +ucl_copy_value_trash (const ucl_object_t *obj) { + ucl_object_t *deconst; + if (obj == NULL) { return NULL; } if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) { + deconst = __DECONST (ucl_object_t *, obj); if (obj->type == UCL_STRING) { + /* Special case for strings */ - obj->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1); - if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) { - memcpy (obj->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len); - obj->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0'; - obj->value.sv = obj->trash_stack[UCL_TRASH_VALUE]; + deconst->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1); + if (deconst->trash_stack[UCL_TRASH_VALUE] != NULL) { + memcpy (deconst->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len); + deconst->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0'; + deconst->value.sv = obj->trash_stack[UCL_TRASH_VALUE]; } } else { /* Just emit value in json notation */ - obj->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj); - obj->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]); + deconst->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj); + deconst->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]); } - obj->flags |= UCL_OBJECT_ALLOCATED_VALUE; + deconst->flags |= UCL_OBJECT_ALLOCATED_VALUE; } return obj->trash_stack[UCL_TRASH_VALUE]; } @@ -1084,21 +1132,22 @@ ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags return obj; } -static ucl_object_t * +static bool ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, const char *key, size_t keylen, bool copy_key, bool merge, bool replace) { - ucl_object_t *found, *cur; + ucl_object_t *found, *tmp; + const ucl_object_t *cur; ucl_object_iter_t it = NULL; const char *p; + int ret = true; if (elt == NULL || key == NULL) { - return NULL; + return false; } if (top == NULL) { - top = ucl_object_new (); - top->type = UCL_OBJECT; + return false; } if (top->type != UCL_OBJECT) { @@ -1108,7 +1157,7 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, } else { /* Refuse converting of other object types */ - return top; + return false; } } @@ -1134,12 +1183,15 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, ucl_copy_key_trash (elt); } - found = ucl_hash_search_obj (top->value.ov, elt); + found = __DECONST (ucl_object_t *, ucl_hash_search_obj (top->value.ov, elt)); if (!found) { top->value.ov = ucl_hash_insert_object (top->value.ov, elt); DL_APPEND (found, elt); top->len ++; + if (replace) { + ret = false; + } } else { if (replace) { @@ -1152,19 +1204,22 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, else if (merge) { if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) { /* Insert old elt to new one */ - elt = ucl_object_insert_key_common (elt, found, found->key, found->keylen, copy_key, false, false); + ucl_object_insert_key_common (elt, found, found->key, + found->keylen, copy_key, false, false); ucl_hash_delete (top->value.ov, found); top->value.ov = ucl_hash_insert_object (top->value.ov, elt); } else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) { /* Insert new to old */ - found = ucl_object_insert_key_common (found, elt, elt->key, elt->keylen, copy_key, false, false); + ucl_object_insert_key_common (found, elt, elt->key, + elt->keylen, copy_key, false, false); } else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) { /* Mix two hashes */ while ((cur = ucl_iterate_object (elt, &it, true)) != NULL) { - ucl_object_ref (cur); - found = ucl_object_insert_key_common (found, cur, cur->key, cur->keylen, copy_key, false, false); + tmp = ucl_object_ref (cur); + ucl_object_insert_key_common (found, tmp, cur->key, + cur->keylen, copy_key, false, false); } ucl_object_unref (elt); } @@ -1178,11 +1233,11 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, } } - return top; + return ret; } bool -ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen) +ucl_object_delete_keyl (ucl_object_t *top, const char *key, size_t keylen) { ucl_object_t *found; @@ -1190,13 +1245,13 @@ ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen) return false; } - found = ucl_object_find_keyl(top, key, keylen); + found = __DECONST (ucl_object_t *, ucl_object_find_keyl (top, key, keylen)); if (found == NULL) { return false; } - ucl_hash_delete(top->value.ov, found); + ucl_hash_delete (top->value.ov, found); ucl_object_unref (found); top->len --; @@ -1204,61 +1259,62 @@ ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen) } bool -ucl_object_delete_key(ucl_object_t *top, const char *key) +ucl_object_delete_key (ucl_object_t *top, const char *key) { - return ucl_object_delete_keyl(top, key, 0); + return ucl_object_delete_keyl (top, key, strlen(key)); } ucl_object_t* ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen) { - ucl_object_t *found; + const ucl_object_t *found; if (top == NULL || key == NULL) { return false; } - found = ucl_object_find_keyl(top, key, keylen); + found = ucl_object_find_keyl (top, key, keylen); if (found == NULL) { return NULL; } - ucl_hash_delete(top->value.ov, found); + ucl_hash_delete (top->value.ov, found); top->len --; - return found; + return __DECONST (ucl_object_t *, found); } ucl_object_t* ucl_object_pop_key (ucl_object_t *top, const char *key) { - return ucl_object_pop_keyl (top, key, 0); + return ucl_object_pop_keyl (top, key, strlen(key)); } -ucl_object_t * +bool ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, const char *key, size_t keylen, bool copy_key) { return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false); } -ucl_object_t * +bool ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, const char *key, size_t keylen, bool copy_key) { return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false); } -ucl_object_t * +bool ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, const char *key, size_t keylen, bool copy_key) { return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true); } -ucl_object_t * -ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen) +const ucl_object_t * +ucl_object_find_keyl (const ucl_object_t *obj, const char *key, size_t klen) { - ucl_object_t *ret, srch; + const ucl_object_t *ret; + ucl_object_t srch; if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) { return NULL; @@ -1271,11 +1327,12 @@ ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen) return ret; } -ucl_object_t * -ucl_object_find_key (ucl_object_t *obj, const char *key) +const ucl_object_t * +ucl_object_find_key (const ucl_object_t *obj, const char *key) { size_t klen; - ucl_object_t *ret, srch; + const ucl_object_t *ret; + ucl_object_t srch; if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) { return NULL; @@ -1289,10 +1346,10 @@ ucl_object_find_key (ucl_object_t *obj, const char *key) return ret; } -ucl_object_t* -ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values) +const ucl_object_t* +ucl_iterate_object (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values) { - ucl_object_t *elt; + const ucl_object_t *elt; if (obj == NULL || iter == NULL) { return NULL; @@ -1301,7 +1358,7 @@ ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_valu if (expand_values) { switch (obj->type) { case UCL_OBJECT: - return (ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter); + return (const ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter); break; case UCL_ARRAY: elt = *iter; @@ -1332,7 +1389,7 @@ ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_valu else if (elt == obj) { return NULL; } - *iter = elt->next ? elt->next : obj; + *iter = __DECONST (void *, elt->next ? elt->next : obj); return elt; /* Not reached */ @@ -1420,72 +1477,55 @@ ucl_object_frombool (bool bv) return obj; } -ucl_object_t * +bool ucl_array_append (ucl_object_t *top, ucl_object_t *elt) { ucl_object_t *head; - if (elt == NULL) { - return NULL; + if (elt == NULL || top == NULL) { + return false; } - if (top == NULL) { - top = ucl_object_typed_new (UCL_ARRAY); + head = top->value.av; + if (head == NULL) { top->value.av = elt; - elt->next = NULL; elt->prev = elt; - top->len = 1; } else { - head = top->value.av; - if (head == NULL) { - top->value.av = elt; - elt->prev = elt; - } - else { - elt->prev = head->prev; - head->prev->next = elt; - head->prev = elt; - } - elt->next = NULL; - top->len ++; + elt->prev = head->prev; + head->prev->next = elt; + head->prev = elt; } + elt->next = NULL; + top->len ++; - return top; + return true; } -ucl_object_t * +bool ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt) { ucl_object_t *head; - if (elt == NULL) { - return NULL; + if (elt == NULL || top == NULL) { + return false; } - if (top == NULL) { - top = ucl_object_typed_new (UCL_ARRAY); + + head = top->value.av; + if (head == NULL) { top->value.av = elt; - elt->next = NULL; elt->prev = elt; - top->len = 1; } else { - head = top->value.av; - if (head == NULL) { - top->value.av = elt; - elt->prev = elt; - } - else { - elt->prev = head->prev; - head->prev = elt; - } - elt->next = head; - top->value.av = elt; - top->len ++; + elt->prev = head->prev; + head->prev = elt; } + elt->next = head; + top->value.av = elt; + top->len ++; - return top; + return true; } ucl_object_t * @@ -1521,8 +1561,8 @@ ucl_array_delete (ucl_object_t *top, ucl_object_t *elt) return elt; } -ucl_object_t * -ucl_array_head (ucl_object_t *top) +const ucl_object_t * +ucl_array_head (const ucl_object_t *top) { if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) { return NULL; @@ -1530,8 +1570,8 @@ ucl_array_head (ucl_object_t *top) return top->value.av; } -ucl_object_t * -ucl_array_tail (ucl_object_t *top) +const ucl_object_t * +ucl_array_tail (const ucl_object_t *top) { if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) { return NULL; @@ -1542,13 +1582,13 @@ ucl_array_tail (ucl_object_t *top) ucl_object_t * ucl_array_pop_last (ucl_object_t *top) { - return ucl_array_delete (top, ucl_array_tail (top)); + return ucl_array_delete (top, __DECONST(ucl_object_t *, ucl_array_tail (top))); } ucl_object_t * ucl_array_pop_first (ucl_object_t *top) { - return ucl_array_delete (top, ucl_array_head (top)); + return ucl_array_delete (top, __DECONST(ucl_object_t *, ucl_array_head (top))); } ucl_object_t * @@ -1571,7 +1611,7 @@ ucl_elt_append (ucl_object_t *head, ucl_object_t *elt) } bool -ucl_object_todouble_safe (ucl_object_t *obj, double *target) +ucl_object_todouble_safe (const ucl_object_t *obj, double *target) { if (obj == NULL || target == NULL) { return false; @@ -1592,7 +1632,7 @@ ucl_object_todouble_safe (ucl_object_t *obj, double *target) } double -ucl_object_todouble (ucl_object_t *obj) +ucl_object_todouble (const ucl_object_t *obj) { double result = 0.; @@ -1601,7 +1641,7 @@ ucl_object_todouble (ucl_object_t *obj) } bool -ucl_object_toint_safe (ucl_object_t *obj, int64_t *target) +ucl_object_toint_safe (const ucl_object_t *obj, int64_t *target) { if (obj == NULL || target == NULL) { return false; @@ -1622,7 +1662,7 @@ ucl_object_toint_safe (ucl_object_t *obj, int64_t *target) } int64_t -ucl_object_toint (ucl_object_t *obj) +ucl_object_toint (const ucl_object_t *obj) { int64_t result = 0; @@ -1631,7 +1671,7 @@ ucl_object_toint (ucl_object_t *obj) } bool -ucl_object_toboolean_safe (ucl_object_t *obj, bool *target) +ucl_object_toboolean_safe (const ucl_object_t *obj, bool *target) { if (obj == NULL || target == NULL) { return false; @@ -1648,7 +1688,7 @@ ucl_object_toboolean_safe (ucl_object_t *obj, bool *target) } bool -ucl_object_toboolean (ucl_object_t *obj) +ucl_object_toboolean (const ucl_object_t *obj) { bool result = false; @@ -1657,7 +1697,7 @@ ucl_object_toboolean (ucl_object_t *obj) } bool -ucl_object_tostring_safe (ucl_object_t *obj, const char **target) +ucl_object_tostring_safe (const ucl_object_t *obj, const char **target) { if (obj == NULL || target == NULL) { return false; @@ -1675,7 +1715,7 @@ ucl_object_tostring_safe (ucl_object_t *obj, const char **target) } const char * -ucl_object_tostring (ucl_object_t *obj) +ucl_object_tostring (const ucl_object_t *obj) { const char *result = NULL; @@ -1684,13 +1724,13 @@ ucl_object_tostring (ucl_object_t *obj) } const char * -ucl_object_tostring_forced (ucl_object_t *obj) +ucl_object_tostring_forced (const ucl_object_t *obj) { return ucl_copy_value_trash (obj); } bool -ucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen) +ucl_object_tolstring_safe (const ucl_object_t *obj, const char **target, size_t *tlen) { if (obj == NULL || target == NULL) { return false; @@ -1710,7 +1750,7 @@ ucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen) } const char * -ucl_object_tolstring (ucl_object_t *obj, size_t *tlen) +ucl_object_tolstring (const ucl_object_t *obj, size_t *tlen) { const char *result = NULL; @@ -1719,13 +1759,13 @@ ucl_object_tolstring (ucl_object_t *obj, size_t *tlen) } const char * -ucl_object_key (ucl_object_t *obj) +ucl_object_key (const ucl_object_t *obj) { return ucl_copy_key_trash (obj); } const char * -ucl_object_keyl (ucl_object_t *obj, size_t *len) +ucl_object_keyl (const ucl_object_t *obj, size_t *len) { if (len == NULL || obj == NULL) { return NULL; @@ -1735,26 +1775,40 @@ ucl_object_keyl (ucl_object_t *obj, size_t *len) } ucl_object_t * -ucl_object_ref (ucl_object_t *obj) +ucl_object_ref (const ucl_object_t *obj) { + ucl_object_t *res = NULL; + if (obj != NULL) { - obj->ref ++; + res = __DECONST (ucl_object_t *, obj); +#ifdef HAVE_ATOMIC_BUILTINS + (void)__sync_add_and_fetch (&res->ref, 1); +#else + res->ref ++; +#endif } - return obj; + return res; } void ucl_object_unref (ucl_object_t *obj) { - if (obj != NULL && --obj->ref <= 0) { - ucl_object_free (obj); + if (obj != NULL) { +#ifdef HAVE_ATOMIC_BUILTINS + unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1); + if (rc == 0) { +#else + if (--obj->ref == 0) { +#endif + ucl_object_free_internal (obj, true, ucl_object_dtor_unref); + } } } int -ucl_object_compare (ucl_object_t *o1, ucl_object_t *o2) +ucl_object_compare (const ucl_object_t *o1, const ucl_object_t *o2) { - ucl_object_t *it1, *it2; + const ucl_object_t *it1, *it2; ucl_object_iter_t iter = NULL; int ret = 0; @@ -1825,7 +1879,7 @@ ucl_object_compare (ucl_object_t *o1, ucl_object_t *o2) void ucl_object_array_sort (ucl_object_t *ar, - int (*cmp)(ucl_object_t *o1, ucl_object_t *o2)) + int (*cmp)(const ucl_object_t *o1, const ucl_object_t *o2)) { if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) { return; -- cgit v1.2.3