Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 19 Feb 2017 17:31:53 +0000 (UTC)
From:      Baptiste Daroussin <bapt@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org
Subject:   svn commit: r313950 - in vendor/libucl/dist: . include lua src
Message-ID:  <201702191731.v1JHVrYc002379@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bapt
Date: Sun Feb 19 17:31:53 2017
New Revision: 313950
URL: https://svnweb.freebsd.org/changeset/base/313950

Log:
  Import libucl snapshot 20170219

Modified:
  vendor/libucl/dist/ChangeLog.md
  vendor/libucl/dist/README.md
  vendor/libucl/dist/configure.ac
  vendor/libucl/dist/include/ucl.h
  vendor/libucl/dist/lua/lua_ucl.c
  vendor/libucl/dist/src/ucl_emitter_utils.c
  vendor/libucl/dist/src/ucl_internal.h
  vendor/libucl/dist/src/ucl_parser.c
  vendor/libucl/dist/src/ucl_util.c

Modified: vendor/libucl/dist/ChangeLog.md
==============================================================================
--- vendor/libucl/dist/ChangeLog.md	Sun Feb 19 17:27:58 2017	(r313949)
+++ vendor/libucl/dist/ChangeLog.md	Sun Feb 19 17:31:53 2017	(r313950)
@@ -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: vendor/libucl/dist/README.md
==============================================================================
--- vendor/libucl/dist/README.md	Sun Feb 19 17:27:58 2017	(r313949)
+++ vendor/libucl/dist/README.md	Sun Feb 19 17:31:53 2017	(r313950)
@@ -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: vendor/libucl/dist/configure.ac
==============================================================================
--- vendor/libucl/dist/configure.ac	Sun Feb 19 17:27:58 2017	(r313949)
+++ vendor/libucl/dist/configure.ac	Sun Feb 19 17:31:53 2017	(r313950)
@@ -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: vendor/libucl/dist/include/ucl.h
==============================================================================
--- vendor/libucl/dist/include/ucl.h	Sun Feb 19 17:27:58 2017	(r313949)
+++ vendor/libucl/dist/include/ucl.h	Sun Feb 19 17:31:53 2017	(r313950)
@@ -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: vendor/libucl/dist/lua/lua_ucl.c
==============================================================================
--- vendor/libucl/dist/lua/lua_ucl.c	Sun Feb 19 17:27:58 2017	(r313949)
+++ vendor/libucl/dist/lua/lua_ucl.c	Sun Feb 19 17:31:53 2017	(r313950)
@@ -29,7 +29,6 @@
 #include "ucl_internal.h"
 #include "lua_ucl.h"
 #include <strings.h>
-#include <zconf.h>
 
 /***
  * @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: vendor/libucl/dist/src/ucl_emitter_utils.c
==============================================================================
--- vendor/libucl/dist/src/ucl_emitter_utils.c	Sun Feb 19 17:27:58 2017	(r313949)
+++ vendor/libucl/dist/src/ucl_emitter_utils.c	Sun Feb 19 17:31:53 2017	(r313950)
@@ -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: vendor/libucl/dist/src/ucl_internal.h
==============================================================================
--- vendor/libucl/dist/src/ucl_internal.h	Sun Feb 19 17:27:58 2017	(r313949)
+++ vendor/libucl/dist/src/ucl_internal.h	Sun Feb 19 17:31:53 2017	(r313950)
@@ -87,6 +87,9 @@
 #ifdef HAVE_STRING_H
 #include <string.h>
 #endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#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: vendor/libucl/dist/src/ucl_parser.c
==============================================================================
--- vendor/libucl/dist/src/ucl_parser.c	Sun Feb 19 17:27:58 2017	(r313949)
+++ vendor/libucl/dist/src/ucl_parser.c	Sun Feb 19 17:31:53 2017	(r313950)
@@ -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: vendor/libucl/dist/src/ucl_util.c
==============================================================================
--- vendor/libucl/dist/src/ucl_util.c	Sun Feb 19 17:27:58 2017	(r313949)
+++ vendor/libucl/dist/src/ucl_util.c	Sun Feb 19 17:31:53 2017	(r313950)
@@ -26,11 +26,17 @@
 #include "ucl_internal.h"
 #include "ucl_chartable.h"
 #include "kvec.h"
+#include <limits.h>
 #include <stdarg.h>
 #include <stdio.h> /* for snprintf */
 
 #ifndef _WIN32
 #include <glob.h>
+#include <sys/param.h>
+#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 <limits.h>
-#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);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201702191731.v1JHVrYc002379>