aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMuhammad Moinur Rahman <bofh@FreeBSD.org>2026-07-22 01:49:53 +0000
committerMuhammad Moinur Rahman <bofh@FreeBSD.org>2026-07-22 01:49:53 +0000
commit6433ec43c802d56ef615b44c435f8dd229d55695 (patch)
tree3da7618b1e6f3c75e3a970270740d876bde78584
parent5001af647b3b263aeb3d4fa7a6c2690399265202 (diff)
parentd7ea4aaa3e204e5c22dadb94078f3638f6b3b505 (diff)
contrib/libucl: Import libucl 0.9.4
Differential Revision: https://reviews.freebsd.org/D58333 Approved by: ivy MFC after: 3 days Changelog: https://github.com/vstakhov/libucl/releases/tag/0.9.4
-rw-r--r--contrib/libucl/FREEBSD-Xlist1
-rw-r--r--contrib/libucl/FREEBSD-upgrade2
-rw-r--r--contrib/libucl/include/ucl.h23
-rw-r--r--contrib/libucl/src/ucl_emitter.c12
-rw-r--r--contrib/libucl/src/ucl_hash.c11
-rw-r--r--contrib/libucl/src/ucl_hash.h6
-rw-r--r--contrib/libucl/src/ucl_util.c31
-rw-r--r--contrib/libucl/tests/CMakeLists.txt12
-rw-r--r--contrib/libucl/tests/basic/issue312.in4
-rw-r--r--contrib/libucl/tests/basic/issue312.res13
10 files changed, 103 insertions, 12 deletions
diff --git a/contrib/libucl/FREEBSD-Xlist b/contrib/libucl/FREEBSD-Xlist
index 6d8cb4ff8f5b..ae8e77059488 100644
--- a/contrib/libucl/FREEBSD-Xlist
+++ b/contrib/libucl/FREEBSD-Xlist
@@ -1,5 +1,6 @@
.github
.gitignore
+CLAUDE.md
CMakeLists.txt
ChangeLog.md
Makefile.am
diff --git a/contrib/libucl/FREEBSD-upgrade b/contrib/libucl/FREEBSD-upgrade
index b80736d7877b..6305899797f7 100644
--- a/contrib/libucl/FREEBSD-upgrade
+++ b/contrib/libucl/FREEBSD-upgrade
@@ -33,7 +33,7 @@
# 3. Merge vendor tree
#
# $ git subtree merge -P contrib/libucl vendor/libucl/<REF_BRANCH_TO_BE_IMPORTED>
-# $ sh -c 'for F in `cat FREEBSD-Xlist | grep -v FreeBSD`; do rm -rf ./$F ; done'
+# $ sh -c 'for F in `cat FREEBSD-Xlist | grep -v FreeBSD`; do git rm -rf ./$F ; done'
#
# Recheck if there were any new files were added which are not necessary in the
# contrib tree. If so, remove them and also add them to the FREEBSD-Xlist file.
diff --git a/contrib/libucl/include/ucl.h b/contrib/libucl/include/ucl.h
index 96ddaa9cb987..bb75ae94810f 100644
--- a/contrib/libucl/include/ucl.h
+++ b/contrib/libucl/include/ucl.h
@@ -862,6 +862,29 @@ UCL_EXTERN const ucl_object_t *ucl_object_iterate_with_error(const ucl_object_t
#define ucl_object_iterate(ob, it, ev) ucl_object_iterate_with_error((ob), (it), (ev), NULL)
/**
+ * Free resources associated with an inline iterator when iteration is
+ * abandoned before completion. Only needed for UCL_OBJECT iteration where
+ * internal heap state is allocated. Safe to call with a NULL iterator or
+ * on non-object types.
+ *
+ * Example usage:
+ * ucl_object_iter_t it = NULL;
+ * while ((cur = ucl_iterate_object(obj, &it, true))) {
+ * if (error) {
+ * ucl_object_iterate_end(obj, &it);
+ * return;
+ * }
+ * }
+ *
+ * @param obj the object being iterated
+ * @param iter pointer to the iterator to free
+ */
+UCL_EXTERN void ucl_object_iterate_end(const ucl_object_t *obj,
+ ucl_object_iter_t *iter);
+
+#define ucl_iterate_object_end ucl_object_iterate_end
+
+/**
* 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
diff --git a/contrib/libucl/src/ucl_emitter.c b/contrib/libucl/src/ucl_emitter.c
index 84c1b13e1865..bcea5b037e70 100644
--- a/contrib/libucl/src/ucl_emitter.c
+++ b/contrib/libucl/src/ucl_emitter.c
@@ -353,10 +353,16 @@ ucl_emitter_common_start_object(struct ucl_emitter_context *ctx,
else {
/* Expand implicit arrays */
if (cur->next != NULL) {
- if (first_key) {
- ucl_add_tabs(func, ctx->indent, compact);
+ if (!first_key) {
+ if (compact) {
+ func->ucl_emitter_append_character(',', 1, func->ud);
+ }
+ else {
+ func->ucl_emitter_append_len(",\n", 2, func->ud);
+ }
}
- ucl_emitter_common_start_array(ctx, cur, first_key, true, compact);
+ ucl_add_tabs(func, ctx->indent, compact);
+ ucl_emitter_common_start_array(ctx, cur, true, true, compact);
ucl_emitter_common_end_array(ctx, cur, compact);
}
else {
diff --git a/contrib/libucl/src/ucl_hash.c b/contrib/libucl/src/ucl_hash.c
index d648f405951b..3fd9b29c23ca 100644
--- a/contrib/libucl/src/ucl_hash.c
+++ b/contrib/libucl/src/ucl_hash.c
@@ -443,6 +443,14 @@ bool ucl_hash_iter_has_next(ucl_hash_t *hashlin, ucl_hash_iter_t iter)
return it->cur != NULL;
}
+void ucl_hash_iterate_free(ucl_hash_iter_t iter)
+{
+ struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *) (iter);
+
+ if (it != NULL) {
+ UCL_FREE(sizeof(*it), it);
+ }
+}
const ucl_object_t *
ucl_hash_search(ucl_hash_t *hashlin, const char *key, unsigned keylen)
@@ -610,6 +618,9 @@ ucl_hash_cmp_case_sens(const void *a, const void *b)
void ucl_hash_sort(ucl_hash_t *hashlin, enum ucl_object_keys_sort_flags fl)
{
+ if (hashlin == NULL) {
+ return;
+ }
if (fl & UCL_SORT_KEYS_ICASE) {
DL_SORT(hashlin->head, ucl_hash_cmp_icase);
diff --git a/contrib/libucl/src/ucl_hash.h b/contrib/libucl/src/ucl_hash.h
index 95fe206b677e..ca77e208e2ac 100644
--- a/contrib/libucl/src/ucl_hash.h
+++ b/contrib/libucl/src/ucl_hash.h
@@ -98,6 +98,12 @@ const void *ucl_hash_iterate2(ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *e
bool ucl_hash_iter_has_next(ucl_hash_t *hashlin, ucl_hash_iter_t iter);
/**
+ * Free a hash iterator (used when iteration is abandoned early)
+ * @param iter iterator to free, may be NULL
+ */
+void ucl_hash_iterate_free(ucl_hash_iter_t iter);
+
+/**
* Reserves space in hash
* @return true on sucess, false on failure (e.g. ENOMEM)
* @param hashlin
diff --git a/contrib/libucl/src/ucl_util.c b/contrib/libucl/src/ucl_util.c
index 3566632275a5..a56d8b27ad65 100644
--- a/contrib/libucl/src/ucl_util.c
+++ b/contrib/libucl/src/ucl_util.c
@@ -2435,9 +2435,7 @@ ucl_object_insert_key_common(ucl_object_t *top, ucl_object_t *elt,
if (found == NULL) {
top->value.ov = ucl_hash_insert_object(top->value.ov, elt, false);
top->len++;
- if (replace) {
- ret = false;
- }
+ /* Key was inserted - return true regardless of replace flag */
}
else {
if (replace) {
@@ -2767,6 +2765,20 @@ ucl_object_iterate_with_error(const ucl_object_t *obj, ucl_object_iter_t *iter,
return NULL;
}
+void
+ucl_object_iterate_end(const ucl_object_t *obj, ucl_object_iter_t *iter)
+{
+ if (iter == NULL || *iter == NULL) {
+ return;
+ }
+
+ if (obj != NULL && obj->type == UCL_OBJECT) {
+ ucl_hash_iterate_free(*iter);
+ }
+
+ *iter = NULL;
+}
+
enum ucl_safe_iter_flags {
UCL_ITERATE_FLAG_UNDEFINED = 0,
UCL_ITERATE_FLAG_INSIDE_ARRAY,
@@ -3028,6 +3040,16 @@ bool ucl_object_reserve(ucl_object_t *obj, size_t reserved)
if (obj->type == UCL_ARRAY) {
UCL_ARRAY_GET(vec, obj);
+ if (vec == NULL) {
+ /* Allocate array storage if not present (e.g., copied empty array) */
+ vec = UCL_ALLOC(sizeof(*vec));
+ if (vec == NULL) {
+ return false;
+ }
+ kv_init(*vec);
+ obj->value.av = (void *)vec;
+ }
+
if (vec->m < reserved) {
/* Preallocate some space for arrays */
kv_resize_safe(ucl_object_t *, *vec, reserved, e0);
@@ -3657,8 +3679,9 @@ ucl_object_copy_internal(const ucl_object_t *other, bool allow_array)
}
if (other->type == UCL_ARRAY || other->type == UCL_OBJECT) {
- /* reset old value */
+ /* reset old value and length since we will re-add elements below */
memset(&new->value, 0, sizeof(new->value));
+ new->len = 0;
while ((cur = ucl_object_iterate(other, &it, true)) != NULL) {
if (other->type == UCL_ARRAY) {
diff --git a/contrib/libucl/tests/CMakeLists.txt b/contrib/libucl/tests/CMakeLists.txt
index e66c3d10a60a..4d91bfa49cbb 100644
--- a/contrib/libucl/tests/CMakeLists.txt
+++ b/contrib/libucl/tests/CMakeLists.txt
@@ -22,10 +22,14 @@ macro(add_ucl_test testname sourcefile wrapper)
ENDIF()
endmacro()
-# Build test binaries always (not just for testing)
-add_ucl_test(test_basic test_basic.c basic.test)
-add_ucl_test(test_speed test_speed.c speed.test)
-add_ucl_test(test_schema test_schema.c schema.test)
+# Tests using POSIX APIs (mmap, STDIN_FILENO, etc.) - skip on Windows
+IF(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ add_ucl_test(test_basic test_basic.c basic.test)
+ add_ucl_test(test_speed test_speed.c speed.test)
+ add_ucl_test(test_schema test_schema.c schema.test)
+ENDIF()
+
+# Portable tests
add_ucl_test(test_msgpack test_msgpack.c msgpack.test)
add_ucl_test(test_generate test_generate.c generate.test)
diff --git a/contrib/libucl/tests/basic/issue312.in b/contrib/libucl/tests/basic/issue312.in
new file mode 100644
index 000000000000..ec46cbe804da
--- /dev/null
+++ b/contrib/libucl/tests/basic/issue312.in
@@ -0,0 +1,4 @@
+section_a { key_1 = "value_1"; }
+section_a { key_2 = "value_2"; }
+section_b { key_3 = "value_3"; }
+section_b { key_4 = "value_4"; }
diff --git a/contrib/libucl/tests/basic/issue312.res b/contrib/libucl/tests/basic/issue312.res
new file mode 100644
index 000000000000..739174f9f230
--- /dev/null
+++ b/contrib/libucl/tests/basic/issue312.res
@@ -0,0 +1,13 @@
+section_a {
+ key_1 = "value_1";
+}
+section_a {
+ key_2 = "value_2";
+}
+section_b {
+ key_3 = "value_3";
+}
+section_b {
+ key_4 = "value_4";
+}
+