svn commit: r279549 - in head: contrib/libucl contrib/libucl/cmake contrib/libucl/doc contrib/libucl/include contrib/libucl/klib contrib/libucl/m4 contrib/libucl/src contrib/libucl/tests contrib/li...
Baptiste Daroussin
bapt at FreeBSD.org
Mon Mar 2 21:41:16 UTC 2015
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 <vsevolod at 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 ***
More information about the svn-src-all
mailing list