diff options
| author | Muhammad Moinur Rahman <bofh@FreeBSD.org> | 2026-07-22 01:49:53 +0000 |
|---|---|---|
| committer | Muhammad Moinur Rahman <bofh@FreeBSD.org> | 2026-07-22 01:49:53 +0000 |
| commit | 6433ec43c802d56ef615b44c435f8dd229d55695 (patch) | |
| tree | 3da7618b1e6f3c75e3a970270740d876bde78584 | |
| parent | 5001af647b3b263aeb3d4fa7a6c2690399265202 (diff) | |
| parent | d7ea4aaa3e204e5c22dadb94078f3638f6b3b505 (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-Xlist | 1 | ||||
| -rw-r--r-- | contrib/libucl/FREEBSD-upgrade | 2 | ||||
| -rw-r--r-- | contrib/libucl/include/ucl.h | 23 | ||||
| -rw-r--r-- | contrib/libucl/src/ucl_emitter.c | 12 | ||||
| -rw-r--r-- | contrib/libucl/src/ucl_hash.c | 11 | ||||
| -rw-r--r-- | contrib/libucl/src/ucl_hash.h | 6 | ||||
| -rw-r--r-- | contrib/libucl/src/ucl_util.c | 31 | ||||
| -rw-r--r-- | contrib/libucl/tests/CMakeLists.txt | 12 | ||||
| -rw-r--r-- | contrib/libucl/tests/basic/issue312.in | 4 | ||||
| -rw-r--r-- | contrib/libucl/tests/basic/issue312.res | 13 |
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"; +} + |
