Author: bapt Date: Mon Mar 2 21:41:09 2015 New Revision: 279549 URL: https://svnweb.freebsd.org/changeset/base/279549
Log: Update libucl to git version 8d3b186 Added: head/contrib/libucl/klib/ - copied from r279548, vendor/libucl/dist/klib/ head/contrib/libucl/tests/basic/14.in - copied unchanged from r279548, vendor/libucl/dist/tests/basic/14.in head/contrib/libucl/tests/basic/14.res - copied unchanged from r279548, vendor/libucl/dist/tests/basic/14.res Deleted: head/contrib/libucl/m4/ Modified: head/contrib/libucl/ChangeLog.md head/contrib/libucl/Makefile.am head/contrib/libucl/README.md head/contrib/libucl/cmake/CMakeLists.txt head/contrib/libucl/configure.ac head/contrib/libucl/doc/Makefile.am head/contrib/libucl/doc/api.md head/contrib/libucl/doc/libucl.3 head/contrib/libucl/doc/pandoc.template head/contrib/libucl/include/ucl.h head/contrib/libucl/src/Makefile.am head/contrib/libucl/src/ucl_emitter.c head/contrib/libucl/src/ucl_emitter_utils.c head/contrib/libucl/src/ucl_hash.c head/contrib/libucl/src/ucl_hash.h head/contrib/libucl/src/ucl_internal.h head/contrib/libucl/src/ucl_parser.c head/contrib/libucl/src/ucl_schema.c head/contrib/libucl/src/ucl_util.c head/contrib/libucl/tests/schema.test head/contrib/libucl/tests/test_generate.c head/contrib/libucl/tests/test_schema.c head/contrib/libucl/uthash/utstring.h head/contrib/libucl/utils/objdump.c head/lib/libucl/Makefile Directory Properties: head/contrib/libucl/ (props changed) Modified: head/contrib/libucl/ChangeLog.md ============================================================================== --- head/contrib/libucl/ChangeLog.md Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/ChangeLog.md Mon Mar 2 21:41:09 2015 (r279549) @@ -20,3 +20,15 @@ ### Libucl 0.6.1 - Various utilities fixes + +### Libucl 0.7.0 + +- Move to klib library from uthash to reduce memory overhead and increase performance + +### Libucl 0.7.1 + +- Added safe iterators API + +### Libucl 0.7.2 + +- Fixed serious bugs in schema and arrays iteration Modified: head/contrib/libucl/Makefile.am ============================================================================== --- head/contrib/libucl/Makefile.am Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/Makefile.am Mon Mar 2 21:41:09 2015 (r279549) @@ -1,5 +1,5 @@ ACLOCAL_AMFLAGS = -I m4 -EXTRA_DIST = uthash README.md +EXTRA_DIST = uthash klib README.md pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libucl.pc Modified: head/contrib/libucl/README.md ============================================================================== --- head/contrib/libucl/README.md Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/README.md Mon Mar 2 21:41:09 2015 (r279549) @@ -1,6 +1,6 @@ # LIBUCL -[](https://travis-ci.org/vstakhov/libucl) +[](https://travis-ci.org/vstakhov/libucl)[](https://scan.coverity.com/projects/4138) **Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)* @@ -156,10 +156,10 @@ is converted to the following object: ```nginx section { blah { - key = value; + key = value; } foo { - key = value; + key = value; } } ``` @@ -177,9 +177,9 @@ is presented as: ```nginx section { blah { - foo { - key = value; - } + foo { + key = value; + } } } ``` @@ -219,8 +219,8 @@ UCL supports external macros both multil ```nginx .macro "sometext"; .macro { - Some long text - .... + Some long text + .... }; ``` Modified: head/contrib/libucl/cmake/CMakeLists.txt ============================================================================== --- head/contrib/libucl/cmake/CMakeLists.txt Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/cmake/CMakeLists.txt Mon Mar 2 21:41:09 2015 (r279549) @@ -82,6 +82,7 @@ ENDIF(ENABLE_URL_SIGN MATCHES "ON") INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../src") INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../include") INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../uthash") +INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../klib") SET(UCLSRC ../src/ucl_util.c ../src/ucl_parser.c Modified: head/contrib/libucl/configure.ac ============================================================================== --- head/contrib/libucl/configure.ac Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/configure.ac Mon Mar 2 21:41:09 2015 (r279549) @@ -1,7 +1,7 @@ m4_define([maj_ver], [0]) -m4_define([med_ver], [6]) -m4_define([min_ver], [1]) -m4_define([so_version], [3:0:1]) +m4_define([med_ver], [7]) +m4_define([min_ver], [2]) +m4_define([so_version], [5:0:1]) m4_define([ucl_version], [maj_ver.med_ver.min_ver]) AC_INIT([libucl],[ucl_version],[https://github.com/vstakhov/libucl],[libucl]) Modified: head/contrib/libucl/doc/Makefile.am ============================================================================== --- head/contrib/libucl/doc/Makefile.am Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/doc/Makefile.am Mon Mar 2 21:41:09 2015 (r279549) @@ -4,5 +4,6 @@ dist_man_MANS = libucl.3 gen-man: @PANDOC@ tail -n +$$(grep -n '# Synopsis' api.md | cut -d':' -f1) api.md | \ - cat pandoc.template - | sed -e 's/^# \(.*\)/# \U\1/' | \ + cat pandoc.template - | sed -e 's/^# \(.*\)/# \U\1/' \ + -e "s/%%date%%/$$(LANG=C date +'%d %B, %Y')/" | \ @PANDOC@ -s -f markdown -t man -o libucl.3 Modified: head/contrib/libucl/doc/api.md ============================================================================== --- head/contrib/libucl/doc/api.md Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/doc/api.md Mon Mar 2 21:41:09 2015 (r279549) @@ -377,7 +377,9 @@ If parsing operations fail then the resu # Iteration functions -Iteration are used to iterate over UCL compound types: arrays and objects. Moreover, iterations could be performed over the keys with multiple values (implicit arrays). To iterate over an object, an array or a key with multiple values there is a function `ucl_iterate_object`. +Iteration are used to iterate over UCL compound types: arrays and objects. Moreover, iterations could be performed over the keys with multiple values (implicit arrays). +There are two types of iterators API: old and unsafe one via `ucl_iterate_object` and the proposed interface of safe iterators. + ## ucl_iterate_object ~~~C @@ -402,6 +404,60 @@ while ((obj = ucl_iterate_object (top, & } ~~~ +## Safe iterators API + +Safe iterators are defined to clarify iterating over UCL objects and simplify flattening of UCL objects in non-trivial cases. +For example, if there is an implicit array that contains another array and a boolean value it is extremely unclear how to iterate over +such an object. Safe iterators are desinged to define two sorts of iteration: + +1. Iteration over complex objects with expanding all values +2. Iteration over complex objects without expanding of values + +The following example demonstrates the difference between these two types of iteration: + +~~~ +key = 1; +key = [2, 3, 4]; + +Iteration with expansion: + +1, 2, 3, 4 + +Iteration without expansion: + +1, [2, 3, 4] +~~~ + +UCL defines the following functions to manage safe iterators: + +- `ucl_object_iterate_new` - creates new safe iterator +- `ucl_object_iterate_reset` - resets iterator to a new object +- `ucl_object_iterate_safe` - safely iterate the object inside iterator +- `ucl_object_iterate_free` - free memory associated with the safe iterator + +Please note that unlike unsafe iterators, safe iterators *must* be explicitly initialized and freed. +An assert is likely generated if you use uninitialized or `NULL` iterator in all safe iterators functions. + +~~~C +ucl_object_iter_t it; +const ucl_object_t *cur; + +it = ucl_object_iterate_new (obj); + +while ((cur = ucl_object_iterate_safe (it, true)) != NULL) { + /* Do something */ +} + +/* Switch to another object */ +it = ucl_object_iterate_reset (it, another_obj); + +while ((cur = ucl_object_iterate_safe (it, true)) != NULL) { + /* Do something else */ +} + +ucl_object_iterate_free (it); +~~~ + # Validation functions Currently, there is only one validation function called `ucl_object_validate`. It performs validation of object using the specified schema. This function is defined as following: Modified: head/contrib/libucl/doc/libucl.3 ============================================================================== --- head/contrib/libucl/doc/libucl.3 Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/doc/libucl.3 Mon Mar 2 21:41:09 2015 (r279549) @@ -1,4 +1,4 @@ -.TH "LIBUCL" "3" "July 26, 2014" "Libucl manual" "" +.TH "LIBUCL" "3" "27 December, 2014" "Libucl manual" "" .SH NAME .PP \f[B]ucl_parser_new\f[], \f[B]ucl_parser_register_macro\f[], @@ -528,8 +528,9 @@ Iteration are used to iterate over UCL c objects. Moreover, iterations could be performed over the keys with multiple values (implicit arrays). -To iterate over an object, an array or a key with multiple values there -is a function \f[C]ucl_iterate_object\f[]. +There are two types of iterators API: old and unsafe one via +\f[C]ucl_iterate_object\f[] and the proposed interface of safe +iterators. .SS ucl_iterate_object .IP .nf @@ -578,6 +579,75 @@ while\ ((obj\ =\ ucl_iterate_object\ (to } \f[] .fi +.SS Safe iterators API +.PP +Safe iterators are defined to clarify iterating over UCL objects and +simplify flattening of UCL objects in non\-trivial cases. +For example, if there is an implicit array that contains another array +and a boolean value it is extremely unclear how to iterate over such an +object. +Safe iterators are desinged to define two sorts of iteration: +.IP "1." 3 +Iteration over complex objects with expanding all values +.IP "2." 3 +Iteration over complex objects without expanding of values +.PP +The following example demonstrates the difference between these two +types of iteration: +.IP +.nf +\f[C] +key\ =\ 1; +key\ =\ [2,\ 3,\ 4]; + +Iteration\ with\ expansion: + +1,\ 2,\ 3,\ 4 + +Iteration\ without\ expansion: + +1,\ [2,\ 3,\ 4] +\f[] +.fi +.PP +UCL defines the following functions to manage safe iterators: +.IP \[bu] 2 +\f[C]ucl_object_iterate_new\f[] \- creates new safe iterator +.IP \[bu] 2 +\f[C]ucl_object_iterate_reset\f[] \- resets iterator to a new object +.IP \[bu] 2 +\f[C]ucl_object_iterate_safe\f[] \- safely iterate the object inside +iterator +.IP \[bu] 2 +\f[C]ucl_object_iterate_free\f[] \- free memory associated with the safe +iterator +.PP +Please note that unlike unsafe iterators, safe iterators \f[I]must\f[] +be explicitly initialized and freed. +An assert is likely generated if you use uninitialized or \f[C]NULL\f[] +iterator in all safe iterators functions. +.IP +.nf +\f[C] +ucl_object_iter_t\ it; +const\ ucl_object_t\ *cur; + +it\ =\ ucl_object_iterate_new\ (obj); + +while\ ((cur\ =\ ucl_object_iterate_safe\ (it,\ true))\ !=\ NULL)\ { +\ \ \ \ /*\ Do\ something\ */ +} + +/*\ Switch\ to\ another\ object\ */ +it\ =\ ucl_object_iterate_reset\ (it,\ another_obj); + +while\ ((cur\ =\ ucl_object_iterate_safe\ (it,\ true))\ !=\ NULL)\ { +\ \ \ \ /*\ Do\ something\ else\ */ +} + +ucl_object_iterate_free\ (it); +\f[] +.fi .SH VALIDATION FUNCTIONS .PP Currently, there is only one validation function called Modified: head/contrib/libucl/doc/pandoc.template ============================================================================== --- head/contrib/libucl/doc/pandoc.template Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/doc/pandoc.template Mon Mar 2 21:41:09 2015 (r279549) @@ -1,6 +1,6 @@ % LIBUCL(3) Libucl manual % Vsevolod Stakhov <vsevo...@highsecure.ru> -% July 26, 2014 +% %%date%% # Name Modified: head/contrib/libucl/include/ucl.h ============================================================================== --- head/contrib/libucl/include/ucl.h Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/include/ucl.h Mon Mar 2 21:41:09 2015 (r279549) @@ -192,7 +192,7 @@ 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 *av; /**< Array */ + void *av; /**< Array */ void *ov; /**< Object */ void* ud; /**< Opaque user data */ } value; @@ -715,6 +715,37 @@ typedef void* ucl_object_iter_t; */ UCL_EXTERN const ucl_object_t* ucl_iterate_object (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values); + +/** + * Create new safe iterator for the specified object + * @param obj object to iterate + * @return new iterator object that should be used with safe iterators API only + */ +UCL_EXTERN ucl_object_iter_t ucl_object_iterate_new (const ucl_object_t *obj) + UCL_WARN_UNUSED_RESULT; +/** + * Reset initialized iterator to a new object + * @param obj new object to iterate + * @return modified iterator object + */ +UCL_EXTERN ucl_object_iter_t ucl_object_iterate_reset (ucl_object_iter_t it, + const ucl_object_t *obj); + +/** + * Get the next object from the `obj`. This fucntion iterates over arrays, objects + * and implicit arrays + * @param iter safe iterator + * @return the next object in sequence + */ +UCL_EXTERN const ucl_object_t* ucl_object_iterate_safe (ucl_object_iter_t iter, + bool expand_values); + +/** + * Free memory associated with the safe iterator + * @param it safe iterator object + */ +UCL_EXTERN void ucl_object_iterate_free (ucl_object_iter_t it); + /** @} */ @@ -854,6 +885,13 @@ UCL_EXTERN ucl_object_t* ucl_parser_get_ * @param parser parser object */ UCL_EXTERN const char *ucl_parser_get_error(struct ucl_parser *parser); + +/** + * Clear the error in the parser + * @param parser parser object + */ +UCL_EXTERN void ucl_parser_clear_error(struct ucl_parser *parser); + /** * Free ucl parser object * @param parser parser object Modified: head/contrib/libucl/src/Makefile.am ============================================================================== --- head/contrib/libucl/src/Makefile.am Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/src/Makefile.am Mon Mar 2 21:41:09 2015 (r279549) @@ -1,6 +1,7 @@ libucl_common_cflags= -I$(top_srcdir)/src \ -I$(top_srcdir)/include \ -I$(top_srcdir)/uthash \ + -I$(top_srcdir)/klib \ -Wall -W -Wno-unused-parameter -Wno-pointer-sign lib_LTLIBRARIES= libucl.la libucl_la_SOURCES= ucl_emitter.c \ Modified: head/contrib/libucl/src/ucl_emitter.c ============================================================================== --- head/contrib/libucl/src/ucl_emitter.c Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/src/ucl_emitter.c Mon Mar 2 21:41:09 2015 (r279549) @@ -250,6 +250,7 @@ ucl_emitter_common_start_array (struct u const ucl_object_t *obj, bool print_key, bool compact) { const ucl_object_t *cur; + ucl_object_iter_t iter = NULL; const struct ucl_emitter_functions *func = ctx->func; bool first = true; @@ -266,18 +267,22 @@ ucl_emitter_common_start_array (struct u if (obj->type == UCL_ARRAY) { /* explicit array */ - cur = obj->value.av; + while ((cur = ucl_iterate_object (obj, &iter, true)) != NULL) { + ucl_emitter_common_elt (ctx, cur, first, false, compact); + first = false; + } } else { /* implicit array */ cur = obj; + while (cur) { + ucl_emitter_common_elt (ctx, cur, first, false, compact); + first = false; + cur = cur->next; + } } - while (cur) { - ucl_emitter_common_elt (ctx, cur, first, false, compact); - first = false; - cur = cur->next; - } + } /** Modified: head/contrib/libucl/src/ucl_emitter_utils.c ============================================================================== --- head/contrib/libucl/src/ucl_emitter_utils.c Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/src/ucl_emitter_utils.c Mon Mar 2 21:41:09 2015 (r279549) @@ -289,6 +289,7 @@ ucl_fd_append_character (unsigned char c else { memset (buf, c, len); if (write (fd, buf, len) == -1) { + free(buf); return -1; } free (buf); Modified: head/contrib/libucl/src/ucl_hash.c ============================================================================== --- head/contrib/libucl/src/ucl_hash.c Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/src/ucl_hash.c Mon Mar 2 21:41:09 2015 (r279549) @@ -23,119 +23,331 @@ #include "ucl_internal.h" #include "ucl_hash.h" -#include "utlist.h" +#include "khash.h" +#include "kvec.h" + +struct ucl_hash_elt { + const ucl_object_t *obj; + size_t ar_idx; +}; + +struct ucl_hash_struct { + void *hash; + kvec_t(const ucl_object_t *) ar; + bool caseless; +}; + +static inline uint32_t +ucl_hash_func (const ucl_object_t *o) +{ + return XXH32 (o->key, o->keylen, 0xdeadbeef); +} + +static inline int +ucl_hash_equal (const ucl_object_t *k1, const ucl_object_t *k2) +{ + if (k1->keylen == k2->keylen) { + return strncmp (k1->key, k2->key, k1->keylen) == 0; + } + + return 0; +} + +KHASH_INIT (ucl_hash_node, const ucl_object_t *, struct ucl_hash_elt, 1, + ucl_hash_func, ucl_hash_equal) + +static inline uint32_t +ucl_hash_caseless_func (const ucl_object_t *o) +{ + void *xxh = XXH32_init (0xdeadbeef); + char hash_buf[64], *c; + const char *p; + ssize_t remain = o->keylen; + + p = o->key; + c = &hash_buf[0]; + + while (remain > 0) { + *c++ = tolower (*p++); + + if (c - &hash_buf[0] == sizeof (hash_buf)) { + XXH32_update (xxh, hash_buf, sizeof (hash_buf)); + c = &hash_buf[0]; + } + remain --; + } + + if (c - &hash_buf[0] != 0) { + XXH32_update (xxh, hash_buf, c - &hash_buf[0]); + } + + return XXH32_digest (xxh); +} + +static inline int +ucl_hash_caseless_equal (const ucl_object_t *k1, const ucl_object_t *k2) +{ + if (k1->keylen == k2->keylen) { + return strncasecmp (k1->key, k2->key, k1->keylen) == 0; + } + + return 0; +} + +KHASH_INIT (ucl_hash_caseless_node, const ucl_object_t *, struct ucl_hash_elt, 1, + ucl_hash_caseless_func, ucl_hash_caseless_equal) ucl_hash_t* -ucl_hash_create (void) +ucl_hash_create (bool ignore_case) { ucl_hash_t *new; new = UCL_ALLOC (sizeof (ucl_hash_t)); if (new != NULL) { - new->buckets = NULL; + kv_init (new->ar); + + new->caseless = ignore_case; + if (ignore_case) { + khash_t(ucl_hash_caseless_node) *h = kh_init (ucl_hash_caseless_node); + new->hash = (void *)h; + } + else { + khash_t(ucl_hash_node) *h = kh_init (ucl_hash_node); + new->hash = (void *)h; + } } return new; } 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; + const ucl_object_t *cur, *tmp; + + if (hashlin == NULL) { + return; + } - HASH_ITER (hh, hashlin->buckets, elt, tmp) { - HASH_DELETE (hh, hashlin->buckets, elt); - if (func) { - DL_FOREACH_SAFE (elt->data, cur, otmp) { - /* Need to deconst here */ - func (__DECONST (ucl_object_t *, cur)); + if (func != NULL) { + /* Iterate over the hash first */ + khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *) + hashlin->hash; + khiter_t k; + + for (k = kh_begin (h); k != kh_end (h); ++k) { + if (kh_exist (h, k)) { + cur = (kh_value (h, k)).obj; + while (cur != NULL) { + tmp = cur->next; + func (__DECONST (ucl_object_t *, cur)); + cur = tmp; + } } } - UCL_FREE (sizeof (ucl_hash_node_t), elt); } - UCL_FREE (sizeof (ucl_hash_t), hashlin); + + if (hashlin->caseless) { + khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *) + hashlin->hash; + kh_destroy (ucl_hash_caseless_node, h); + } + else { + khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *) + hashlin->hash; + kh_destroy (ucl_hash_node, h); + } + + kv_destroy (hashlin->ar); + UCL_FREE (sizeof (*hashlin), hashlin); } void ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj, const char *key, unsigned keylen) { - ucl_hash_node_t *node; + khiter_t k; + int ret; + struct ucl_hash_elt *elt; - node = UCL_ALLOC (sizeof (ucl_hash_node_t)); - node->data = obj; - HASH_ADD_KEYPTR (hh, hashlin->buckets, key, keylen, node); + if (hashlin == NULL) { + return; + } + + if (hashlin->caseless) { + khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *) + hashlin->hash; + k = kh_put (ucl_hash_caseless_node, h, obj, &ret); + if (ret > 0) { + elt = &kh_value (h, k); + kv_push (const ucl_object_t *, hashlin->ar, obj); + elt->obj = obj; + elt->ar_idx = kv_size (hashlin->ar) - 1; + } + } + else { + khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *) + hashlin->hash; + k = kh_put (ucl_hash_node, h, obj, &ret); + if (ret > 0) { + elt = &kh_value (h, k); + kv_push (const ucl_object_t *, hashlin->ar, obj); + elt->obj = obj; + elt->ar_idx = kv_size (hashlin->ar) - 1; + } + } } void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old, const ucl_object_t *new) { - ucl_hash_node_t *node; + khiter_t k; + int ret; + struct ucl_hash_elt elt, *pelt; - HASH_FIND (hh, hashlin->buckets, old->key, old->keylen, node); - if (node != NULL) { - /* Direct replacement */ - node->data = new; - node->hh.key = new->key; - node->hh.keylen = new->keylen; + if (hashlin == NULL) { + return; + } + + if (hashlin->caseless) { + khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *) + hashlin->hash; + k = kh_put (ucl_hash_caseless_node, h, old, &ret); + if (ret == 0) { + elt = kh_value (h, k); + kh_del (ucl_hash_caseless_node, h, k); + k = kh_put (ucl_hash_caseless_node, h, new, &ret); + pelt = &kh_value (h, k); + pelt->obj = new; + pelt->ar_idx = elt.ar_idx; + kv_A (hashlin->ar, elt.ar_idx) = new; + } + } + else { + khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *) + hashlin->hash; + k = kh_put (ucl_hash_node, h, old, &ret); + if (ret == 0) { + elt = kh_value (h, k); + kh_del (ucl_hash_node, h, k); + k = kh_put (ucl_hash_node, h, new, &ret); + pelt = &kh_value (h, k); + pelt->obj = new; + pelt->ar_idx = elt.ar_idx; + kv_A (hashlin->ar, elt.ar_idx) = new; + } } } +struct ucl_hash_real_iter { + const ucl_object_t **cur; + const ucl_object_t **end; +}; + const void* ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter) { - ucl_hash_node_t *elt = *iter; + struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *)(*iter); + const ucl_object_t *ret = NULL; - if (elt == NULL) { - if (hashlin == NULL || hashlin->buckets == NULL) { - return NULL; - } - elt = hashlin->buckets; - if (elt == NULL) { - return NULL; - } + if (hashlin == NULL) { + return NULL; + } + + if (it == NULL) { + it = UCL_ALLOC (sizeof (*it)); + it->cur = &hashlin->ar.a[0]; + it->end = it->cur + hashlin->ar.n; + } + + if (it->cur < it->end) { + ret = *it->cur++; } - else if (elt == hashlin->buckets) { + else { + UCL_FREE (sizeof (*it), it); + *iter = NULL; return NULL; } - *iter = elt->hh.next ? elt->hh.next : hashlin->buckets; - return elt->data; + *iter = it; + + return ret; } bool -ucl_hash_iter_has_next (ucl_hash_iter_t iter) +ucl_hash_iter_has_next (ucl_hash_t *hashlin, ucl_hash_iter_t iter) { - ucl_hash_node_t *elt = iter; + struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *)(iter); - return (elt == NULL || elt->hh.prev != NULL); + return it->cur < it->end - 1; } const ucl_object_t* ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen) { - ucl_hash_node_t *found; + khiter_t k; + const ucl_object_t *ret = NULL; + ucl_object_t search; + struct ucl_hash_elt *elt; + + search.key = key; + search.keylen = keylen; if (hashlin == NULL) { return NULL; } - HASH_FIND (hh, hashlin->buckets, key, keylen, found); - if (found) { - return found->data; + if (hashlin->caseless) { + khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *) + hashlin->hash; + + k = kh_get (ucl_hash_caseless_node, h, &search); + if (k != kh_end (h)) { + elt = &kh_value (h, k); + ret = elt->obj; + } } - return NULL; + else { + khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *) + hashlin->hash; + k = kh_get (ucl_hash_node, h, &search); + if (k != kh_end (h)) { + elt = &kh_value (h, k); + ret = elt->obj; + } + } + + return ret; } void ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj) { - ucl_hash_node_t *found; + khiter_t k; + struct ucl_hash_elt *elt; - HASH_FIND (hh, hashlin->buckets, obj->key, obj->keylen, found); + if (hashlin == NULL) { + return; + } - if (found) { - HASH_DELETE (hh, hashlin->buckets, found); - UCL_FREE (sizeof (ucl_hash_node_t), found); + if (hashlin->caseless) { + khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *) + hashlin->hash; + + k = kh_get (ucl_hash_caseless_node, h, obj); + if (k != kh_end (h)) { + elt = &kh_value (h, k); + kv_A (hashlin->ar, elt->ar_idx) = NULL; + kh_del (ucl_hash_caseless_node, h, k); + } + } + else { + khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *) + hashlin->hash; + k = kh_get (ucl_hash_node, h, obj); + if (k != kh_end (h)) { + elt = &kh_value (h, k); + kv_A (hashlin->ar, elt->ar_idx) = NULL; + kh_del (ucl_hash_node, h, k); + } } } Modified: head/contrib/libucl/src/ucl_hash.h ============================================================================== --- head/contrib/libucl/src/ucl_hash.h Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/src/ucl_hash.h Mon Mar 2 21:41:09 2015 (r279549) @@ -25,15 +25,11 @@ #define __UCL_HASH_H #include "ucl.h" -#include "uthash.h" /******************************************************************************/ -typedef struct ucl_hash_node_s -{ - const ucl_object_t *data; - UT_hash_handle hh; -} ucl_hash_node_t; +struct ucl_hash_node_s; +typedef struct ucl_hash_node_s ucl_hash_node_t; typedef int ucl_hash_cmp_func (const void* void_a, const void* void_b); typedef void ucl_hash_free_func (void *ptr); @@ -43,16 +39,14 @@ typedef void* ucl_hash_iter_t; /** * Linear chained hashtable. */ -typedef struct ucl_hash_struct -{ - ucl_hash_node_t *buckets; /**< array of hash buckets. One list for each hash modulus. */ -} ucl_hash_t; +struct ucl_hash_struct; +typedef struct ucl_hash_struct ucl_hash_t; /** * Initializes the hashtable. */ -ucl_hash_t* ucl_hash_create (void); +ucl_hash_t* ucl_hash_create (bool ignore_case); /** * Deinitializes the hashtable. @@ -94,6 +88,6 @@ const void* ucl_hash_iterate (ucl_hash_t /** * Check whether an iterator has next element */ -bool ucl_hash_iter_has_next (ucl_hash_iter_t iter); +bool ucl_hash_iter_has_next (ucl_hash_t *hashlin, ucl_hash_iter_t iter); #endif Modified: head/contrib/libucl/src/ucl_internal.h ============================================================================== --- head/contrib/libucl/src/ucl_internal.h Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/src/ucl_internal.h Mon Mar 2 21:41:09 2015 (r279549) @@ -339,14 +339,17 @@ ucl_hash_search_obj (ucl_hash_t* hashlin 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, const ucl_object_t *obj) UCL_WARN_UNUSED_RESULT; +static inline ucl_hash_t * ucl_hash_insert_object (ucl_hash_t *hashlin, + const ucl_object_t *obj, + bool ignore_case) UCL_WARN_UNUSED_RESULT; static inline ucl_hash_t * -ucl_hash_insert_object (ucl_hash_t *hashlin, const ucl_object_t *obj) +ucl_hash_insert_object (ucl_hash_t *hashlin, + const ucl_object_t *obj, + bool ignore_case) { if (hashlin == NULL) { - hashlin = ucl_hash_create (); + hashlin = ucl_hash_create (ignore_case); } ucl_hash_insert (hashlin, obj, obj->key, obj->keylen); Modified: head/contrib/libucl/src/ucl_parser.c ============================================================================== --- head/contrib/libucl/src/ucl_parser.c Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/src/ucl_parser.c Mon Mar 2 21:41:09 2015 (r279549) @@ -570,7 +570,7 @@ ucl_add_parser_stack (ucl_object_t *obj, else { obj->type = UCL_OBJECT; } - obj->value.ov = ucl_hash_create (); + obj->value.ov = ucl_hash_create (parser->flags & UCL_PARSER_KEY_LOWERCASE); parser->state = UCL_STATE_KEY; } else { @@ -975,7 +975,7 @@ ucl_parser_append_elt (struct ucl_parser else { if ((top->flags & UCL_OBJECT_MULTIVALUE) != 0) { /* Just add to the explicit array */ - DL_APPEND (top->value.av, elt); + ucl_array_append (top, elt); } else { /* Convert to an array */ @@ -984,8 +984,8 @@ ucl_parser_append_elt (struct ucl_parser nobj->key = top->key; nobj->keylen = top->keylen; nobj->flags |= UCL_OBJECT_MULTIVALUE; - DL_APPEND (nobj->value.av, top); - DL_APPEND (nobj->value.av, elt); + ucl_array_append (nobj, top); + ucl_array_append (nobj, elt); ucl_hash_insert (cont, nobj, nobj->key, nobj->keylen); } } @@ -1016,6 +1016,7 @@ ucl_parse_key (struct ucl_parser *parser ucl_chunk_skipc (chunk, p); parser->prev_state = parser->state; parser->state = UCL_STATE_MACRO_NAME; + *end_of_object = false; return true; } while (p < chunk->end) { @@ -1195,7 +1196,8 @@ ucl_parse_key (struct ucl_parser *parser nobj->keylen = keylen; tobj = __DECONST (ucl_object_t *, ucl_hash_search_obj (container, nobj)); if (tobj == NULL) { - container = ucl_hash_insert_object (container, nobj); + container = ucl_hash_insert_object (container, nobj, + parser->flags & UCL_PARSER_KEY_LOWERCASE); nobj->prev = nobj; nobj->next = NULL; parser->stack->obj->len ++; @@ -1363,14 +1365,16 @@ ucl_get_value_object (struct ucl_parser { ucl_object_t *t, *obj = NULL; + if (parser == NULL || parser->stack == NULL || parser->stack->obj == NULL) { + return NULL; + } + if (parser->stack->obj->type == UCL_ARRAY) { /* Object must be allocated */ obj = ucl_object_new_full (UCL_NULL, parser->chunks->priority); - t = parser->stack->obj->value.av; - DL_APPEND (t, obj); + t = parser->stack->obj; + ucl_array_append (t, obj); parser->cur_obj = obj; - parser->stack->obj->value.av = t; - parser->stack->obj->len ++; } else { /* Object has been already allocated */ Modified: head/contrib/libucl/src/ucl_schema.c ============================================================================== --- head/contrib/libucl/src/ucl_schema.c Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/src/ucl_schema.c Mon Mar 2 21:41:09 2015 (r279549) @@ -525,15 +525,16 @@ ucl_schema_validate_array (const ucl_obj ucl_object_iter_t iter = NULL, piter = NULL; bool ret = true, allow_additional = true, need_unique = false; int64_t minmax; + unsigned int idx = 0; while (ret && (elt = ucl_iterate_object (schema, &iter, true)) != NULL) { if (strcmp (ucl_object_key (elt), "items") == 0) { if (elt->type == UCL_ARRAY) { - found = obj->value.av; + found = ucl_array_head (obj); while (ret && (it = ucl_iterate_object (elt, &piter, true)) != NULL) { if (found) { ret = ucl_schema_validate (it, found, false, err, root); - found = found->next; + found = ucl_array_find_index (obj, ++idx); } } if (found != NULL) { @@ -608,14 +609,14 @@ ucl_schema_validate_array (const ucl_obj ret = false; } else if (additional_schema != NULL) { - elt = first_unvalidated; + elt = ucl_array_find_index (obj, idx); while (elt) { if (!ucl_schema_validate (additional_schema, elt, false, err, root)) { ret = false; break; } - elt = elt->next; + elt = ucl_array_find_index (obj, idx ++); } } } @@ -741,7 +742,7 @@ ucl_schema_resolve_ref_component (const "reference %s is invalid, invalid item number", refc); return NULL; } - res = cur->value.av; + res = ucl_array_head (cur); i = 0; while (res != NULL) { if (i == num) { Modified: head/contrib/libucl/src/ucl_util.c ============================================================================== --- head/contrib/libucl/src/ucl_util.c Mon Mar 2 21:37:55 2015 (r279548) +++ head/contrib/libucl/src/ucl_util.c Mon Mar 2 21:41:09 2015 (r279549) @@ -24,13 +24,21 @@ #include "ucl.h" #include "ucl_internal.h" #include "ucl_chartable.h" +#include "kvec.h" +#ifndef _WIN32 #include <glob.h> +#endif #ifdef HAVE_LIBGEN_H #include <libgen.h> /* For dirname */ #endif +typedef kvec_t(ucl_object_t *) ucl_array_t; + +#define UCL_ARRAY_GET(ar, obj) ucl_array_t *ar = \ *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"