From owner-svn-src-all@freebsd.org Sun Feb 19 17:37:18 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id A2059CE2867; Sun, 19 Feb 2017 17:37:18 +0000 (UTC) (envelope-from bapt@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 70A7114C3; Sun, 19 Feb 2017 17:37:18 +0000 (UTC) (envelope-from bapt@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v1JHbH20005535; Sun, 19 Feb 2017 17:37:17 GMT (envelope-from bapt@FreeBSD.org) Received: (from bapt@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v1JHbGWl005526; Sun, 19 Feb 2017 17:37:16 GMT (envelope-from bapt@FreeBSD.org) Message-Id: <201702191737.v1JHbGWl005526@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: bapt set sender to bapt@FreeBSD.org using -f From: Baptiste Daroussin Date: Sun, 19 Feb 2017 17:37:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r313953 - in head/contrib/libucl: . include lua src X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 19 Feb 2017 17:37:18 -0000 Author: bapt Date: Sun Feb 19 17:37:16 2017 New Revision: 313953 URL: https://svnweb.freebsd.org/changeset/base/313953 Log: Import libucl 20170219 MFC after: 3 days Modified: head/contrib/libucl/ChangeLog.md head/contrib/libucl/README.md head/contrib/libucl/configure.ac head/contrib/libucl/include/ucl.h head/contrib/libucl/lua/lua_ucl.c head/contrib/libucl/src/ucl_emitter_utils.c head/contrib/libucl/src/ucl_internal.h head/contrib/libucl/src/ucl_parser.c head/contrib/libucl/src/ucl_util.c Directory Properties: head/contrib/libucl/ (props changed) Modified: head/contrib/libucl/ChangeLog.md ============================================================================== --- head/contrib/libucl/ChangeLog.md Sun Feb 19 17:35:14 2017 (r313952) +++ head/contrib/libucl/ChangeLog.md Sun Feb 19 17:37:16 2017 (r313953) @@ -35,7 +35,7 @@ ### Libucl 0.7.3 -- Fixed a bug with macroes that come after an empty object +- Fixed a bug with macros that come after an empty object - Fixed a bug in include processing when an incorrect variable has been destroyed (use-after-free) ### Libucl 0.8.0 Modified: head/contrib/libucl/README.md ============================================================================== --- head/contrib/libucl/README.md Sun Feb 19 17:35:14 2017 (r313952) +++ head/contrib/libucl/README.md Sun Feb 19 17:37:16 2017 (r313953) @@ -1,6 +1,8 @@ # LIBUCL -[![Build Status](https://travis-ci.org/vstakhov/libucl.svg?branch=master)](https://travis-ci.org/vstakhov/libucl)[![Coverity](https://scan.coverity.com/projects/4138/badge.svg)](https://scan.coverity.com/projects/4138)[![Coverage Status](https://coveralls.io/repos/github/vstakhov/libucl/badge.svg?branch=master)](https://coveralls.io/github/vstakhov/libucl?branch=master) +[![Build Status](https://travis-ci.org/vstakhov/libucl.svg?branch=master)](https://travis-ci.org/vstakhov/libucl) +[![Coverity](https://scan.coverity.com/projects/4138/badge.svg)](https://scan.coverity.com/projects/4138) +[![Coverage Status](https://coveralls.io/repos/github/vstakhov/libucl/badge.svg?branch=master)](https://coveralls.io/github/vstakhov/libucl?branch=master) **Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)* @@ -217,8 +219,8 @@ Multiline comments may be nested: UCL supports external macros both multiline and single line ones: ```nginx -.macro "sometext"; -.macro { +.macro_name "sometext"; +.macro_name { Some long text .... }; @@ -229,12 +231,12 @@ arguments themselves are the UCL object options: ```nginx -.macro(param=value) "something"; -.macro(param={key=value}) "something"; -.macro(.include "params.conf") "something"; -.macro(#this is multiline macro +.macro_name(param=value) "something"; +.macro_name(param={key=value}) "something"; +.macro_name(.include "params.conf") "something"; +.macro_name(#this is multiline macro param = [value1, value2]) "something"; -.macro(key="()") "something"; +.macro_name(key="()") "something"; ``` UCL also provide a convenient `include` macro to load content from another files Modified: head/contrib/libucl/configure.ac ============================================================================== --- head/contrib/libucl/configure.ac Sun Feb 19 17:35:14 2017 (r313952) +++ head/contrib/libucl/configure.ac Sun Feb 19 17:37:16 2017 (r313953) @@ -39,6 +39,7 @@ AC_CHECK_HEADERS_ONCE([stdarg.h]) AC_CHECK_HEADERS_ONCE([stdbool.h]) AC_CHECK_HEADERS_ONCE([stdint.h]) AC_CHECK_HEADERS_ONCE([string.h]) +AC_CHECK_HEADERS_ONCE([strings.h]) AC_CHECK_HEADERS_ONCE([unistd.h]) AC_CHECK_HEADERS_ONCE([ctype.h]) AC_CHECK_HEADERS_ONCE([errno.h]) Modified: head/contrib/libucl/include/ucl.h ============================================================================== --- head/contrib/libucl/include/ucl.h Sun Feb 19 17:35:14 2017 (r313952) +++ head/contrib/libucl/include/ucl.h Sun Feb 19 17:37:16 2017 (r313953) @@ -154,7 +154,8 @@ typedef enum ucl_parser_flags { UCL_PARSER_NO_TIME = (1 << 2), /**< Do not parse time and treat time values as strings */ UCL_PARSER_NO_IMPLICIT_ARRAYS = (1 << 3), /** Create explicit arrays instead of implicit ones */ UCL_PARSER_SAVE_COMMENTS = (1 << 4), /** Save comments in the parser context */ - UCL_PARSER_DISABLE_MACRO = (1 << 5) /** Treat macros as comments */ + UCL_PARSER_DISABLE_MACRO = (1 << 5), /** Treat macros as comments */ + UCL_PARSER_NO_FILEVARS = (1 << 6) /** Do not set file vars */ } ucl_parser_flags_t; /** @@ -205,7 +206,8 @@ enum ucl_duplicate_strategy { enum ucl_parse_type { UCL_PARSE_UCL = 0, /**< Default ucl format */ UCL_PARSE_MSGPACK, /**< Message pack input format */ - UCL_PARSE_CSEXP /**< Canonical S-expressions */ + UCL_PARSE_CSEXP, /**< Canonical S-expressions */ + UCL_PARSE_AUTO /**< Try to detect parse type */ }; /** @@ -227,7 +229,7 @@ typedef struct ucl_object_s { const char *key; /**< Key of an object */ struct ucl_object_s *next; /**< Array handle */ struct ucl_object_s *prev; /**< Array handle */ - uint32_t keylen; /**< Lenght of a key */ + uint32_t keylen; /**< Length of a key */ uint32_t len; /**< Size of an object */ uint32_t ref; /**< Reference count */ uint16_t flags; /**< Object flags */ @@ -831,10 +833,29 @@ UCL_EXTERN ucl_object_iter_t ucl_object_ * Get the next object from the `obj`. This fucntion iterates over arrays, objects * and implicit arrays * @param iter safe iterator + * @param expand_values expand explicit arrays and objects * @return the next object in sequence */ UCL_EXTERN const ucl_object_t* ucl_object_iterate_safe (ucl_object_iter_t iter, bool expand_values); +/** + * Iteration type enumerator + */ +enum ucl_iterate_type { + UCL_ITERATE_EXPLICIT = 1 << 0, /**< Iterate just explicit arrays and objects */ + UCL_ITERATE_IMPLICIT = 1 << 1, /**< Iterate just implicit arrays */ + UCL_ITERATE_BOTH = (1 << 0) | (1 << 1), /**< Iterate both explicit and implicit arrays*/ +}; + +/** + * Get the next object from the `obj`. This fucntion iterates over arrays, objects + * and implicit arrays if needed + * @param iter safe iterator + * @param + * @return the next object in sequence + */ +UCL_EXTERN const ucl_object_t* ucl_object_iterate_full (ucl_object_iter_t iter, + enum ucl_iterate_type type); /** * Free memory associated with the safe iterator @@ -1016,6 +1037,7 @@ UCL_EXTERN bool ucl_parser_add_string_pr * Load and add data from a file * @param parser parser structure * @param filename the name of file + * @param err if *err is NULL it is set to parser error * @return true if chunk has been added and false in case of error */ UCL_EXTERN bool ucl_parser_add_file (struct ucl_parser *parser, @@ -1025,6 +1047,7 @@ UCL_EXTERN bool ucl_parser_add_file (str * Load and add data from a file * @param parser parser structure * @param filename the name of file + * @param err if *err is NULL it is set to parser error * @param priority the desired priority of a chunk (only 4 least significant bits * are considered for this parameter) * @return true if chunk has been added and false in case of error @@ -1069,6 +1092,21 @@ UCL_EXTERN bool ucl_parser_add_fd_priori int fd, unsigned priority); /** + * Load and add data from a file descriptor + * @param parser parser structure + * @param filename the name of file + * @param err if *err is NULL it is set to parser error + * @param priority the desired priority of a chunk (only 4 least significant bits + * are considered for this parameter) + * @param strat Merge strategy to use while parsing this file + * @param parse_type Parser type to use while parsing this file + * @return true if chunk has been added and false in case of error + */ +UCL_EXTERN bool ucl_parser_add_fd_full (struct ucl_parser *parser, int fd, + unsigned priority, enum ucl_duplicate_strategy strat, + enum ucl_parse_type parse_type); + +/** * Provide a UCL_ARRAY of paths to search for include files. The object is * copied so caller must unref the object. * @param parser parser structure Modified: head/contrib/libucl/lua/lua_ucl.c ============================================================================== --- head/contrib/libucl/lua/lua_ucl.c Sun Feb 19 17:35:14 2017 (r313952) +++ head/contrib/libucl/lua/lua_ucl.c Sun Feb 19 17:37:16 2017 (r313953) @@ -29,7 +29,6 @@ #include "ucl_internal.h" #include "lua_ucl.h" #include -#include /*** * @module ucl @@ -187,6 +186,8 @@ ucl_object_lua_push_array (lua_State *L, lua_rawseti (L, -2, i); i ++; } + + ucl_object_iterate_free (it); } else { /* Optimize allocation by preallocation of table */ @@ -482,7 +483,7 @@ static int lua_ucl_parser_init (lua_State *L) { struct ucl_parser *parser, **pparser; - int flags = 0; + int flags = UCL_PARSER_NO_FILEVARS; if (lua_gettop (L) >= 1) { flags = lua_tonumber (L, 1); @@ -524,6 +525,27 @@ lua_ucl_push_opaque (lua_State *L, ucl_o lua_setmetatable (L, -2); } +static inline enum ucl_parse_type +lua_ucl_str_to_parse_type (const char *str) +{ + enum ucl_parse_type type = UCL_PARSE_UCL; + + if (str != NULL) { + if (strcasecmp (str, "msgpack") == 0) { + type = UCL_PARSE_MSGPACK; + } + else if (strcasecmp (str, "sexp") == 0 || + strcasecmp (str, "csexp") == 0) { + type = UCL_PARSE_CSEXP; + } + else if (strcasecmp (str, "auto") == 0) { + type = UCL_PARSE_AUTO; + } + } + + return type; +} + /*** * @method parser:parse_file(name) * Parse UCL object from file. @@ -579,13 +601,19 @@ lua_ucl_parser_parse_string (lua_State * struct ucl_parser *parser; const char *string; size_t llen; + enum ucl_parse_type type = UCL_PARSE_UCL; int ret = 2; parser = lua_ucl_parser_get (L, 1); string = luaL_checklstring (L, 2, &llen); + if (lua_type (L, 3) == LUA_TSTRING) { + type = lua_ucl_str_to_parse_type (lua_tostring (L, 3)); + } + if (parser != NULL && string != NULL) { - if (ucl_parser_add_chunk (parser, (const unsigned char *)string, llen)) { + if (ucl_parser_add_chunk_full (parser, (const unsigned char *)string, + llen, 0, UCL_DUPLICATE_APPEND, type)) { lua_pushboolean (L, true); ret = 1; } @@ -761,6 +789,28 @@ lua_ucl_object_unwrap (lua_State *L) return 1; } +static inline enum ucl_emitter +lua_ucl_str_to_emit_type (const char *strtype) +{ + enum ucl_emitter format = UCL_EMIT_JSON_COMPACT; + + if (strcasecmp (strtype, "json") == 0) { + format = UCL_EMIT_JSON; + } + else if (strcasecmp (strtype, "json-compact") == 0) { + format = UCL_EMIT_JSON_COMPACT; + } + else if (strcasecmp (strtype, "yaml") == 0) { + format = UCL_EMIT_YAML; + } + else if (strcasecmp (strtype, "config") == 0 || + strcasecmp (strtype, "ucl") == 0) { + format = UCL_EMIT_CONFIG; + } + + return format; +} + /*** * @method object:tostring(type) * Unwraps opaque ucl object to string (json by default). Optionally you can @@ -787,19 +837,7 @@ lua_ucl_object_tostring (lua_State *L) if (lua_type (L, 2) == LUA_TSTRING) { const char *strtype = lua_tostring (L, 2); - if (strcasecmp (strtype, "json") == 0) { - format = UCL_EMIT_JSON; - } - else if (strcasecmp (strtype, "json-compact") == 0) { - format = UCL_EMIT_JSON_COMPACT; - } - else if (strcasecmp (strtype, "yaml") == 0) { - format = UCL_EMIT_YAML; - } - else if (strcasecmp (strtype, "config") == 0 || - strcasecmp (strtype, "ucl") == 0) { - format = UCL_EMIT_CONFIG; - } + format = lua_ucl_str_to_emit_type (strtype); } } @@ -1088,6 +1126,9 @@ lua_ucl_to_format (lua_State *L) strcasecmp (strtype, "ucl") == 0) { format = UCL_EMIT_CONFIG; } + else if (strcasecmp (strtype, "msgpack") == 0) { + format = UCL_EMIT_MSGPACK; + } } } Modified: head/contrib/libucl/src/ucl_emitter_utils.c ============================================================================== --- head/contrib/libucl/src/ucl_emitter_utils.c Sun Feb 19 17:35:14 2017 (r313952) +++ head/contrib/libucl/src/ucl_emitter_utils.c Sun Feb 19 17:37:16 2017 (r313953) @@ -102,7 +102,7 @@ ucl_elt_string_write_json (const char *s func->ucl_emitter_append_character ('"', 1, func->ud); while (size) { - if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) { + if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_DENIED)) { if (len > 0) { func->ucl_emitter_append_len (c, len, func->ud); } @@ -128,6 +128,10 @@ ucl_elt_string_write_json (const char *s case '"': func->ucl_emitter_append_len ("\\\"", 2, func->ud); break; + default: + /* Emit unicode unknown character */ + func->ucl_emitter_append_len ("\\uFFFD", 5, func->ud); + break; } len = 0; c = ++p; @@ -138,9 +142,11 @@ ucl_elt_string_write_json (const char *s } size --; } + if (len > 0) { func->ucl_emitter_append_len (c, len, func->ud); } + func->ucl_emitter_append_character ('"', 1, func->ud); } Modified: head/contrib/libucl/src/ucl_internal.h ============================================================================== --- head/contrib/libucl/src/ucl_internal.h Sun Feb 19 17:35:14 2017 (r313952) +++ head/contrib/libucl/src/ucl_internal.h Sun Feb 19 17:37:16 2017 (r313953) @@ -87,6 +87,9 @@ #ifdef HAVE_STRING_H #include #endif +#ifdef HAVE_STRINGS_H +#include +#endif #include "utlist.h" #include "utstring.h" @@ -127,19 +130,19 @@ enum ucl_parser_state { }; enum ucl_character_type { - UCL_CHARACTER_DENIED = 0, - UCL_CHARACTER_KEY = 1, - UCL_CHARACTER_KEY_START = 1 << 1, - UCL_CHARACTER_WHITESPACE = 1 << 2, - UCL_CHARACTER_WHITESPACE_UNSAFE = 1 << 3, - UCL_CHARACTER_VALUE_END = 1 << 4, - UCL_CHARACTER_VALUE_STR = 1 << 5, - UCL_CHARACTER_VALUE_DIGIT = 1 << 6, - UCL_CHARACTER_VALUE_DIGIT_START = 1 << 7, - UCL_CHARACTER_ESCAPE = 1 << 8, - UCL_CHARACTER_KEY_SEP = 1 << 9, - UCL_CHARACTER_JSON_UNSAFE = 1 << 10, - UCL_CHARACTER_UCL_UNSAFE = 1 << 11 + UCL_CHARACTER_DENIED = (1 << 0), + UCL_CHARACTER_KEY = (1 << 1), + UCL_CHARACTER_KEY_START = (1 << 2), + UCL_CHARACTER_WHITESPACE = (1 << 3), + UCL_CHARACTER_WHITESPACE_UNSAFE = (1 << 4), + UCL_CHARACTER_VALUE_END = (1 << 5), + UCL_CHARACTER_VALUE_STR = (1 << 6), + UCL_CHARACTER_VALUE_DIGIT = (1 << 7), + UCL_CHARACTER_VALUE_DIGIT_START = (1 << 8), + UCL_CHARACTER_ESCAPE = (1 << 9), + UCL_CHARACTER_KEY_SEP = (1 << 10), + UCL_CHARACTER_JSON_UNSAFE = (1 << 11), + UCL_CHARACTER_UCL_UNSAFE = (1 << 12) }; struct ucl_macro { @@ -568,4 +571,6 @@ bool ucl_parser_process_object_element ( */ bool ucl_parse_msgpack (struct ucl_parser *parser); +bool ucl_parse_csexp (struct ucl_parser *parser); + #endif /* UCL_INTERNAL_H_ */ Modified: head/contrib/libucl/src/ucl_parser.c ============================================================================== --- head/contrib/libucl/src/ucl_parser.c Sun Feb 19 17:35:14 2017 (r313952) +++ head/contrib/libucl/src/ucl_parser.c Sun Feb 19 17:37:16 2017 (r313953) @@ -2469,8 +2469,10 @@ ucl_parser_new (int flags) parser->comments = ucl_object_typed_new (UCL_OBJECT); } - /* Initial assumption about filevars */ - ucl_parser_set_filevars (parser, NULL, false); + if (!(flags & UCL_PARSER_NO_FILEVARS)) { + /* Initial assumption about filevars */ + ucl_parser_set_filevars (parser, NULL, false); + } return parser; } @@ -2617,6 +2619,19 @@ ucl_parser_add_chunk_full (struct ucl_pa return false; } + if (parse_type == UCL_PARSE_AUTO && len > 0) { + /* We need to detect parse type by the first symbol */ + if ((*data & 0x80) == 0x80 && (*data >= 0xdc && *data <= 0xdf)) { + parse_type = UCL_PARSE_MSGPACK; + } + else if (*data == '(') { + parse_type = UCL_PARSE_CSEXP; + } + else { + parse_type = UCL_PARSE_UCL; + } + } + chunk->begin = data; chunk->remain = len; chunk->pos = chunk->begin; @@ -2643,6 +2658,8 @@ ucl_parser_add_chunk_full (struct ucl_pa return ucl_state_machine (parser); case UCL_PARSE_MSGPACK: return ucl_parse_msgpack (parser); + case UCL_PARSE_CSEXP: + return ucl_parse_csexp (parser); } } else { Modified: head/contrib/libucl/src/ucl_util.c ============================================================================== --- head/contrib/libucl/src/ucl_util.c Sun Feb 19 17:35:14 2017 (r313952) +++ head/contrib/libucl/src/ucl_util.c Sun Feb 19 17:37:16 2017 (r313953) @@ -26,11 +26,17 @@ #include "ucl_internal.h" #include "ucl_chartable.h" #include "kvec.h" +#include #include #include /* for snprintf */ #ifndef _WIN32 #include +#include +#else +#ifndef NBBY +#define NBBY 8 +#endif #endif #ifdef HAVE_LIBGEN_H @@ -81,11 +87,6 @@ typedef kvec_t(ucl_object_t *) ucl_array #define MAP_FAILED ((void *) -1) #endif -#ifdef _WIN32 -#include -#define NBBY CHAR_BIT -#endif - static void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset) { void *map = NULL; @@ -1854,9 +1855,11 @@ ucl_parser_add_file (struct ucl_parser * UCL_PARSE_UCL); } + bool -ucl_parser_add_fd_priority (struct ucl_parser *parser, int fd, - unsigned priority) +ucl_parser_add_fd_full (struct ucl_parser *parser, int fd, + unsigned priority, enum ucl_duplicate_strategy strat, + enum ucl_parse_type parse_type) { unsigned char *buf; size_t len; @@ -1882,7 +1885,8 @@ ucl_parser_add_fd_priority (struct ucl_p } parser->cur_file = NULL; len = st.st_size; - ret = ucl_parser_add_chunk_priority (parser, buf, len, priority); + ret = ucl_parser_add_chunk_full (parser, buf, len, priority, strat, + parse_type); if (len > 0) { ucl_munmap (buf, len); @@ -1892,6 +1896,18 @@ ucl_parser_add_fd_priority (struct ucl_p } bool +ucl_parser_add_fd_priority (struct ucl_parser *parser, int fd, + unsigned priority) +{ + if (parser == NULL) { + return false; + } + + return ucl_parser_add_fd_full(parser, fd, parser->default_priority, + UCL_DUPLICATE_APPEND, UCL_PARSE_UCL); +} + +bool ucl_parser_add_fd (struct ucl_parser *parser, int fd) { if (parser == NULL) { @@ -2488,6 +2504,10 @@ ucl_object_iterate_reset (ucl_object_ite UCL_SAFE_ITER_CHECK (rit); + if (rit->expl_it != NULL) { + UCL_FREE (sizeof (*rit->expl_it), rit->expl_it); + } + rit->impl_it = obj; rit->expl_it = NULL; @@ -2497,6 +2517,13 @@ ucl_object_iterate_reset (ucl_object_ite const ucl_object_t* ucl_object_iterate_safe (ucl_object_iter_t it, bool expand_values) { + return ucl_object_iterate_full (it, expand_values ? UCL_ITERATE_BOTH : + UCL_ITERATE_IMPLICIT); +} + +const ucl_object_t* +ucl_object_iterate_full (ucl_object_iter_t it, enum ucl_iterate_type type) +{ struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it); const ucl_object_t *ret = NULL; @@ -2509,21 +2536,23 @@ ucl_object_iterate_safe (ucl_object_iter if (rit->impl_it->type == UCL_OBJECT || rit->impl_it->type == UCL_ARRAY) { ret = ucl_object_iterate (rit->impl_it, &rit->expl_it, true); - if (ret == NULL) { + if (ret == NULL && (type & UCL_ITERATE_IMPLICIT)) { /* Need to switch to another implicit object in chain */ rit->impl_it = rit->impl_it->next; rit->expl_it = NULL; - return ucl_object_iterate_safe (it, expand_values); + + return ucl_object_iterate_safe (it, type); } } else { /* Just iterate over the implicit array */ ret = rit->impl_it; rit->impl_it = rit->impl_it->next; - if (expand_values) { + + if (type & UCL_ITERATE_EXPLICIT) { /* We flatten objects if need to expand values */ if (ret->type == UCL_OBJECT || ret->type == UCL_ARRAY) { - return ucl_object_iterate_safe (it, expand_values); + return ucl_object_iterate_safe (it, type); } } } @@ -2538,6 +2567,10 @@ ucl_object_iterate_free (ucl_object_iter UCL_SAFE_ITER_CHECK (rit); + if (rit->expl_it != NULL) { + UCL_FREE (sizeof (*rit->expl_it), rit->expl_it); + } + UCL_FREE (sizeof (*rit), it); }