Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Update bundled libucl to 0.2.9
Baptiste Daroussin committed 12 years ago
commit ad016c2e888df5e3f8c9c6f0d70686c63880f419
parent 0a9bdd5
13 files changed +708 -463
modified external/libucl/Makefile.unix
@@ -4,7 +4,7 @@ LD ?= gcc
C_COMMON_FLAGS ?= -fPIC -Wall -W -Wno-unused-parameter -Wno-pointer-sign -I./include -I./uthash -I./src
MAJOR_VERSION = 0
MINOR_VERSION = 2
-
PATCH_VERSION = 8
+
PATCH_VERSION = 9
VERSION = "$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION)"
SONAME = libucl.so
SONAME_FULL = $(SONAME).$(MAJOR_VERSION)
modified external/libucl/Makefile.w32
@@ -4,7 +4,7 @@ LD ?= gcc
C_COMMON_FLAGS ?= -fPIC -Wall -W -Wno-unused-parameter -Wno-pointer-sign -I./include -I./uthash -I./src
MAJOR_VERSION = 0
MINOR_VERSION = 2
-
PATCH_VERSION = 8
+
PATCH_VERSION = 9
VERSION = "$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION)"
SONAME = libucl.dll
OBJDIR ?= .obj
modified external/libucl/doc/api.md
@@ -9,22 +9,26 @@ Description
Libucl is a parser and `C` API to parse and generate `ucl` objects. Libucl consist of several groups of functions:

### Parser functions
-
Used to parse `ucl` files and provide interface to extract `ucl` object
+
Used to parse `ucl` files and provide interface to extract `ucl` object. Currently, `libucl` can parse only full `ucl` documents, for instance, it is impossible to parse a part of document and therefore it is impossible to use `libucl` as a streaming parser. In future, this limitation can be removed.

### Emitting functions
-
Convert `ucl` objects to some textual or binary representation.
+
Convert `ucl` objects to some textual or binary representation. Currently, libucl supports the following exports:
+

+
- `JSON` - valid json format (can possibly loose some original data, such as implicit arrays)
+
- `Config` - human-readable configuration format (losseless)
+
- `YAML` - embedded yaml format (has the same limitations as `json` output)

### Conversion functions
-
Help to convert `ucl` objects to C types
+
Help to convert `ucl` objects to C types. These functions are used to convert `ucl_object_t` to C primitive types, such as numbers, strings or boolean values.

### Generation functions
-
Allow creating of `ucl` objects from C types
+
Allow creating of `ucl` objects from C types and creating of complex `ucl` objects, such as hashes or arrays from primitive `ucl` objects, such as numbers or strings.

### Iteration functions
-
Iterate over `ucl` objects
+
Iterate over `ucl` complex objects or over a chain of values, for example when a key in an object has multiple values (that can be treated as implicit array or implicit consolidation).

### Utility functions
-
Provide basic utilities to manage `ucl` objects
+
Provide basic utilities to manage `ucl` objects: creating, removing, retaining and releasing reference count and so on.

# Parser functions

@@ -40,6 +44,7 @@ Creates new parser with the specified flags:

- `UCL_PARSER_KEY_LOWERCASE` - lowercase keys parsed
- `UCL_PARSER_ZEROCOPY` - try to use zero-copy mode when reading files (in zero-copy mode text chunk being parsed without copying strings so it should exist till any object parsed is used)
+
- `UCL_PARSER_NO_TIME` - treat time values as strings without parsing them as floats

### ucl_parser_register_macro

@@ -87,6 +92,14 @@ while this one won't be parsed correctly:

This limitation may possible be removed in future.

+
### ucl_parser_add_string
+
~~~C
+
bool ucl_parser_add_string (struct ucl_parser *parser, 
+
    const char *data, size_t len);
+
~~~
+

+
This function acts exactly like `ucl_parser_add_chunk` does but if `len` argument is zero, then the string `data` must be zero-terminated and the actual length is calculated up to `\0` character. 
+

### ucl_parser_add_file

~~~C
@@ -314,8 +327,9 @@ This function is used to convert a string `str` of size `len` to an UCL objects
- `UCL_STRING_PARSE_BOOLEAN` - parse passed string and detect boolean
- `UCL_STRING_PARSE_INT` - parse passed string and detect integer number
- `UCL_STRING_PARSE_DOUBLE` - parse passed string and detect integer or float number
-
- `UCL_STRING_PARSE_NUMBER` - parse passed string and detect number (both float or integer types)
-
- `UCL_STRING_PARSE` - parse passed string (and detect booleans and numbers)
+
- `UCL_STRING_PARSE_TIME` - parse time values as floating point numbers
+
- `UCL_STRING_PARSE_NUMBER` - parse passed string and detect number (both float, integer and time types)
+
- `UCL_STRING_PARSE` - parse passed string (and detect booleans, numbers and time values)
- `UCL_STRING_PARSE_BYTES` - assume that numeric multipliers are in bytes notation, for example `10k` means `10*1024` and not `10*1000` as assumed without this flag

If parsing operations fail then the resulting UCL object will be a `UCL_STRING`. A caller should always check the type of the returned object and release it after using.
modified external/libucl/include/ucl.h
@@ -138,7 +138,8 @@ typedef enum ucl_emitter {
 */
typedef enum ucl_parser_flags {
	UCL_PARSER_KEY_LOWERCASE = 0x1, /**< Convert all keys to lower case */
-
	UCL_PARSER_ZEROCOPY = 0x2 /**< Parse input in zero-copy mode if possible */
+
	UCL_PARSER_ZEROCOPY = 0x2, /**< Parse input in zero-copy mode if possible */
+
	UCL_PARSER_NO_TIME = 0x4 /**< Do not parse time and treat time values as strings */
} ucl_parser_flags_t;

/**
@@ -150,11 +151,12 @@ typedef enum ucl_string_flags {
	UCL_STRING_PARSE_BOOLEAN = 0x4,    /**< Parse passed string and detect boolean */
	UCL_STRING_PARSE_INT = 0x8,    /**< Parse passed string and detect integer number */
	UCL_STRING_PARSE_DOUBLE = 0x10,    /**< Parse passed string and detect integer or float number */
-
	UCL_STRING_PARSE_NUMBER =  UCL_STRING_PARSE_INT|UCL_STRING_PARSE_DOUBLE ,  /**<
+
	UCL_STRING_PARSE_TIME = 0x20, /**< Parse time strings */
+
	UCL_STRING_PARSE_NUMBER =  UCL_STRING_PARSE_INT|UCL_STRING_PARSE_DOUBLE|UCL_STRING_PARSE_TIME,  /**<
									Parse passed string and detect number */
	UCL_STRING_PARSE =  UCL_STRING_PARSE_BOOLEAN|UCL_STRING_PARSE_NUMBER,   /**<
									Parse passed string (and detect booleans and numbers) */
-
	UCL_STRING_PARSE_BYTES = 0x20  /**< Treat numbers as bytes */
+
	UCL_STRING_PARSE_BYTES = 0x40  /**< Treat numbers as bytes */
} ucl_string_flags_t;

/**
@@ -219,38 +221,14 @@ UCL_EXTERN char* ucl_copy_value_trash (ucl_object_t *obj);
 * Creates a new object
 * @return new object
 */
-
static inline ucl_object_t* ucl_object_new (void) UCL_WARN_UNUSED_RESULT;
-
static inline ucl_object_t *
-
ucl_object_new (void)
-
{
-
	ucl_object_t *new;
-
	new = malloc (sizeof (ucl_object_t));
-
	if (new != NULL) {
-
		memset (new, 0, sizeof (ucl_object_t));
-
		new->ref = 1;
-
		new->type = UCL_NULL;
-
	}
-
	return new;
-
}
+
UCL_EXTERN ucl_object_t* ucl_object_new (void) UCL_WARN_UNUSED_RESULT;

/**
 * Create new object with type specified
 * @param type type of a new object
 * @return new object
 */
-
static inline ucl_object_t* ucl_object_typed_new (unsigned int type) UCL_WARN_UNUSED_RESULT;
-
static inline ucl_object_t *
-
ucl_object_typed_new (unsigned int type)
-
{
-
	ucl_object_t *new;
-
	new = malloc (sizeof (ucl_object_t));
-
	if (new != NULL) {
-
		memset (new, 0, sizeof (ucl_object_t));
-
		new->ref = 1;
-
		new->type = (type <= UCL_NULL ? type : UCL_NULL);
-
	}
-
	return new;
-
}
+
UCL_EXTERN ucl_object_t* ucl_object_typed_new (unsigned int type) UCL_WARN_UNUSED_RESULT;

/**
 * Convert any string to an ucl object making the specified transformations
@@ -267,11 +245,7 @@ UCL_EXTERN ucl_object_t * ucl_object_fromstring_common (const char *str, size_t
 * @param str NULL terminated string, will be json escaped
 * @return new object
 */
-
static inline ucl_object_t *
-
ucl_object_fromstring (const char *str)
-
{
-
	return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE);
-
}
+
UCL_EXTERN ucl_object_t *ucl_object_fromstring (const char *str);

/**
 * Create a UCL object from the specified string
@@ -279,68 +253,28 @@ ucl_object_fromstring (const char *str)
 * @param len length of a string
 * @return new object
 */
-
static inline ucl_object_t *
-
ucl_object_fromlstring (const char *str, size_t len)
-
{
-
	return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE);
-
}
+
UCL_EXTERN ucl_object_t *ucl_object_fromlstring (const char *str, size_t len);

/**
 * Create an object from an integer number
 * @param iv number
 * @return new object
 */
-
static inline ucl_object_t *
-
ucl_object_fromint (int64_t iv)
-
{
-
	ucl_object_t *obj;
-

-
	obj = ucl_object_new ();
-
	if (obj != NULL) {
-
		obj->type = UCL_INT;
-
		obj->value.iv = iv;
-
	}
-

-
	return obj;
-
}
+
UCL_EXTERN ucl_object_t* ucl_object_fromint (int64_t iv);

/**
 * Create an object from a float number
 * @param dv number
 * @return new object
 */
-
static inline ucl_object_t *
-
ucl_object_fromdouble (double dv)
-
{
-
	ucl_object_t *obj;
-

-
	obj = ucl_object_new ();
-
	if (obj != NULL) {
-
		obj->type = UCL_FLOAT;
-
		obj->value.dv = dv;
-
	}
-

-
	return obj;
-
}
+
UCL_EXTERN ucl_object_t* ucl_object_fromdouble (double dv);

/**
 * Create an object from a boolean
 * @param bv bool value
 * @return new object
 */
-
static inline ucl_object_t *
-
ucl_object_frombool (bool bv)
-
{
-
	ucl_object_t *obj;
-

-
	obj = ucl_object_new ();
-
	if (obj != NULL) {
-
		obj->type = UCL_BOOLEAN;
-
		obj->value.iv = bv;
-
	}
-

-
	return obj;
-
}
+
UCL_EXTERN ucl_object_t* ucl_object_frombool (bool bv);

/**
 * Insert a object 'elt' to the hash 'top' and associate it with key 'key'
@@ -382,6 +316,28 @@ UCL_EXTERN bool ucl_object_delete_keyl (ucl_object_t *top, const char *key, size
 */
UCL_EXTERN bool ucl_object_delete_key (ucl_object_t *top, const char *key);

+

+
/**
+
 * Delete key from `top` object returning the object deleted. This object is not
+
 * released
+
 * @param top object
+
 * @param key key to remove
+
 * @param keylen length of the key (or 0 for NULL terminated keys)
+
 * @return removed object or NULL if object has not been found
+
 */
+
UCL_EXTERN ucl_object_t* ucl_object_pop_keyl (ucl_object_t *top, const char *key,
+
		size_t keylen) UCL_WARN_UNUSED_RESULT;
+

+
/**
+
 * Delete key from `top` object returning the object deleted. This object is not
+
 * released
+
 * @param top object
+
 * @param key key to remove
+
 * @return removed object or NULL if object has not been found
+
 */
+
UCL_EXTERN ucl_object_t* ucl_object_pop_key (ucl_object_t *top, const char *key)
+
	UCL_WARN_UNUSED_RESULT;
+

/**
 * Insert a object 'elt' to the hash 'top' and associate it with key 'key', if the specified key exist,
 * try to merge its content
@@ -401,41 +357,8 @@ UCL_EXTERN ucl_object_t* ucl_object_insert_key_merged (ucl_object_t *top, ucl_ob
 * @param elt element to append (must NOT be NULL)
 * @return new value of top object
 */
-
static inline ucl_object_t * ucl_array_append (ucl_object_t *top,
+
UCL_EXTERN ucl_object_t* ucl_array_append (ucl_object_t *top,
		ucl_object_t *elt) UCL_WARN_UNUSED_RESULT;
-
static inline ucl_object_t *
-
ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
-
{
-
	ucl_object_t *head;
-

-
	if (elt == NULL) {
-
		return NULL;
-
	}
-

-
	if (top == NULL) {
-
		top = ucl_object_typed_new (UCL_ARRAY);
-
		top->value.av = elt;
-
		elt->next = NULL;
-
		elt->prev = elt;
-
		top->len = 1;
-
	}
-
	else {
-
		head = top->value.av;
-
		if (head == NULL) {
-
			top->value.av = elt;
-
			elt->prev = elt;
-
		}
-
		else {
-
			elt->prev = head->prev;
-
			head->prev->next = elt;
-
			head->prev = elt;
-
		}
-
		elt->next = NULL;
-
		top->len ++;
-
	}
-

-
	return top;
-
}

/**
 * Append an element to the start of array object
@@ -443,41 +366,8 @@ ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
 * @param elt element to append (must NOT be NULL)
 * @return new value of top object
 */
-
static inline ucl_object_t * ucl_array_prepend (ucl_object_t *top,
+
UCL_EXTERN ucl_object_t* ucl_array_prepend (ucl_object_t *top,
		ucl_object_t *elt) UCL_WARN_UNUSED_RESULT;
-
static inline ucl_object_t *
-
ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
-
{
-
	ucl_object_t *head;
-

-
	if (elt == NULL) {
-
		return NULL;
-
	}
-

-
	if (top == NULL) {
-
		top = ucl_object_typed_new (UCL_ARRAY);
-
		top->value.av = elt;
-
		elt->next = NULL;
-
		elt->prev = elt;
-
		top->len = 1;
-
	}
-
	else {
-
		head = top->value.av;
-
		if (head == NULL) {
-
			top->value.av = elt;
-
			elt->prev = elt;
-
		}
-
		else {
-
			elt->prev = head->prev;
-
			head->prev = elt;
-
		}
-
		elt->next = head;
-
		top->value.av = elt;
-
		top->len ++;
-
	}
-

-
	return top;
-
}

/**
 * Removes an element `elt` from the array `top`. Caller must unref the returned object when it is not
@@ -486,66 +376,21 @@ ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
 * @param elt element to remove
 * @return removed element or NULL if `top` is NULL or not an array
 */
-
static inline ucl_object_t *
-
ucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
-
{
-
	ucl_object_t *head;
-

-
	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
-
		return NULL;
-
	}
-
	head = top->value.av;
-

-
	if (elt->prev == elt) {
-
		top->value.av = NULL;
-
	}
-
	else if (elt == head) {
-
		elt->next->prev = elt->prev;
-
		top->value.av = elt->next;
-
	}
-
	else {
-
		elt->prev->next = elt->next;
-
		if (elt->next) {
-
			elt->next->prev = elt->prev;
-
		}
-
		else {
-
			head->prev = elt->prev;
-
		}
-
	}
-
	elt->next = NULL;
-
	elt->prev = elt;
-
	top->len --;
-

-
	return elt;
-
}
+
UCL_EXTERN ucl_object_t* ucl_array_delete (ucl_object_t *top, ucl_object_t *elt);

/**
 * Returns the first element of the array `top`
 * @param top array ucl object
 * @return element or NULL if `top` is NULL or not an array
 */
-
static inline ucl_object_t *
-
ucl_array_head (ucl_object_t *top)
-
{
-
	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
-
		return NULL;
-
	}
-
	return top->value.av;
-
}
+
UCL_EXTERN ucl_object_t* ucl_array_head (ucl_object_t *top);

/**
 * Returns the last element of the array `top`
 * @param top array ucl object
 * @return element or NULL if `top` is NULL or not an array
 */
-
static inline ucl_object_t *
-
ucl_array_tail (ucl_object_t *top)
-
{
-
	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
-
		return NULL;
-
	}
-
	return top->value.av->prev;
-
}
+
UCL_EXTERN ucl_object_t* ucl_array_tail (ucl_object_t *top);

/**
 * Removes the last element from the array `top`. Caller must unref the returned object when it is not
@@ -553,11 +398,7 @@ ucl_array_tail (ucl_object_t *top)
 * @param top array ucl object
 * @return removed element or NULL if `top` is NULL or not an array
 */
-
static inline ucl_object_t *
-
ucl_array_pop_last (ucl_object_t *top)
-
{
-
	return ucl_array_delete (top, ucl_array_tail (top));
-
}
+
UCL_EXTERN ucl_object_t* ucl_array_pop_last (ucl_object_t *top);

/**
 * Removes the first element from the array `top`. Caller must unref the returned object when it is not
@@ -565,11 +406,7 @@ ucl_array_pop_last (ucl_object_t *top)
 * @param top array ucl object
 * @return removed element or NULL if `top` is NULL or not an array
 */
-
static inline ucl_object_t *
-
ucl_array_pop_first (ucl_object_t *top)
-
{
-
	return ucl_array_delete (top, ucl_array_head (top));
-
}
+
UCL_EXTERN ucl_object_t* ucl_array_pop_first (ucl_object_t *top);

/**
 * Append a element to another element forming an implicit array
@@ -577,26 +414,8 @@ ucl_array_pop_first (ucl_object_t *top)
 * @param elt new element
 * @return new head if applicable
 */
-
static inline ucl_object_t * ucl_elt_append (ucl_object_t *head,
+
UCL_EXTERN ucl_object_t* ucl_elt_append (ucl_object_t *head,
		ucl_object_t *elt) UCL_WARN_UNUSED_RESULT;
-
static inline ucl_object_t *
-
ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
-
{
-

-
	if (head == NULL) {
-
		elt->next = NULL;
-
		elt->prev = elt;
-
		head = elt;
-
	}
-
	else {
-
		elt->prev = head->prev;
-
		head->prev->next = elt;
-
		head->prev = elt;
-
		elt->next = NULL;
-
	}
-

-
	return head;
-
}

/**
 * Converts an object to double value
@@ -604,40 +423,14 @@ ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
 * @param target target double variable
 * @return true if conversion was successful
 */
-
static inline bool
-
ucl_object_todouble_safe (ucl_object_t *obj, double *target)
-
{
-
	if (obj == NULL) {
-
		return false;
-
	}
-
	switch (obj->type) {
-
	case UCL_INT:
-
		*target = obj->value.iv; /* Probaly could cause overflow */
-
		break;
-
	case UCL_FLOAT:
-
	case UCL_TIME:
-
		*target = obj->value.dv;
-
		break;
-
	default:
-
		return false;
-
	}
-

-
	return true;
-
}
+
UCL_EXTERN bool ucl_object_todouble_safe (ucl_object_t *obj, double *target);

/**
 * Unsafe version of \ref ucl_obj_todouble_safe
 * @param obj CL object
 * @return double value
 */
-
static inline double
-
ucl_object_todouble (ucl_object_t *obj)
-
{
-
	double result = 0.;
-

-
	ucl_object_todouble_safe (obj, &result);
-
	return result;
-
}
+
UCL_EXTERN double ucl_object_todouble (ucl_object_t *obj);

/**
 * Converts an object to integer value
@@ -645,40 +438,14 @@ ucl_object_todouble (ucl_object_t *obj)
 * @param target target integer variable
 * @return true if conversion was successful
 */
-
static inline bool
-
ucl_object_toint_safe (ucl_object_t *obj, int64_t *target)
-
{
-
	if (obj == NULL) {
-
		return false;
-
	}
-
	switch (obj->type) {
-
	case UCL_INT:
-
		*target = obj->value.iv;
-
		break;
-
	case UCL_FLOAT:
-
	case UCL_TIME:
-
		*target = obj->value.dv; /* Loosing of decimal points */
-
		break;
-
	default:
-
		return false;
-
	}
-

-
	return true;
-
}
+
UCL_EXTERN bool ucl_object_toint_safe (ucl_object_t *obj, int64_t *target);

/**
 * Unsafe version of \ref ucl_obj_toint_safe
 * @param obj CL object
 * @return int value
 */
-
static inline int64_t
-
ucl_object_toint (ucl_object_t *obj)
-
{
-
	int64_t result = 0;
-

-
	ucl_object_toint_safe (obj, &result);
-
	return result;
-
}
+
UCL_EXTERN int64_t ucl_object_toint (ucl_object_t *obj);

/**
 * Converts an object to boolean value
@@ -686,36 +453,14 @@ ucl_object_toint (ucl_object_t *obj)
 * @param target target boolean variable
 * @return true if conversion was successful
 */
-
static inline bool
-
ucl_object_toboolean_safe (ucl_object_t *obj, bool *target)
-
{
-
	if (obj == NULL) {
-
		return false;
-
	}
-
	switch (obj->type) {
-
	case UCL_BOOLEAN:
-
		*target = (obj->value.iv == true);
-
		break;
-
	default:
-
		return false;
-
	}
-

-
	return true;
-
}
+
UCL_EXTERN bool ucl_object_toboolean_safe (ucl_object_t *obj, bool *target);

/**
 * Unsafe version of \ref ucl_obj_toboolean_safe
 * @param obj CL object
 * @return boolean value
 */
-
static inline bool
-
ucl_object_toboolean (ucl_object_t *obj)
-
{
-
	bool result = false;
-

-
	ucl_object_toboolean_safe (obj, &result);
-
	return result;
-
}
+
UCL_EXTERN bool ucl_object_toboolean (ucl_object_t *obj);

/**
 * Converts an object to string value
@@ -723,48 +468,21 @@ ucl_object_toboolean (ucl_object_t *obj)
 * @param target target string variable, no need to free value
 * @return true if conversion was successful
 */
-
static inline bool
-
ucl_object_tostring_safe (ucl_object_t *obj, const char **target)
-
{
-
	if (obj == NULL) {
-
		return false;
-
	}
-

-
	switch (obj->type) {
-
	case UCL_STRING:
-
		*target = ucl_copy_value_trash (obj);
-
		break;
-
	default:
-
		return false;
-
	}
-

-
	return true;
-
}
+
UCL_EXTERN bool ucl_object_tostring_safe (ucl_object_t *obj, const char **target);

/**
 * Unsafe version of \ref ucl_obj_tostring_safe
 * @param obj CL object
 * @return string value
 */
-
static inline const char *
-
ucl_object_tostring (ucl_object_t *obj)
-
{
-
	const char *result = NULL;
-

-
	ucl_object_tostring_safe (obj, &result);
-
	return result;
-
}
+
UCL_EXTERN const char* ucl_object_tostring (ucl_object_t *obj);

/**
 * Convert any object to a string in JSON notation if needed
 * @param obj CL object
 * @return string value
 */
-
static inline const char *
-
ucl_object_tostring_forced (ucl_object_t *obj)
-
{
-
	return ucl_copy_value_trash (obj);
-
}
+
UCL_EXTERN const char* ucl_object_tostring_forced (ucl_object_t *obj);

/**
 * Return string as char * and len, string may be not zero terminated, more efficient that \ref ucl_obj_tostring as it
@@ -774,37 +492,15 @@ ucl_object_tostring_forced (ucl_object_t *obj)
 * @param tlen target length
 * @return true if conversion was successful
 */
-
static inline bool
-
ucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen)
-
{
-
	if (obj == NULL) {
-
		return false;
-
	}
-
	switch (obj->type) {
-
	case UCL_STRING:
-
		*target = obj->value.sv;
-
		*tlen = obj->len;
-
		break;
-
	default:
-
		return false;
-
	}
-

-
	return true;
-
}
+
UCL_EXTERN bool ucl_object_tolstring_safe (ucl_object_t *obj,
+
		const char **target, size_t *tlen);

/**
 * Unsafe version of \ref ucl_obj_tolstring_safe
 * @param obj CL object
 * @return string value
 */
-
static inline const char *
-
ucl_object_tolstring (ucl_object_t *obj, size_t *tlen)
-
{
-
	const char *result = NULL;
-

-
	ucl_object_tolstring_safe (obj, &result, tlen);
-
	return result;
-
}
+
UCL_EXTERN const char* ucl_object_tolstring (ucl_object_t *obj, size_t *tlen);

/**
 * Return object identified by a key in the specified object
@@ -812,7 +508,7 @@ ucl_object_tolstring (ucl_object_t *obj, size_t *tlen)
 * @param key key to search
 * @return object matched the specified key or NULL if key is not found
 */
-
UCL_EXTERN ucl_object_t * ucl_object_find_key (ucl_object_t *obj, const char *key);
+
UCL_EXTERN ucl_object_t* ucl_object_find_key (ucl_object_t *obj, const char *key);

/**
 * Return object identified by a fixed size key in the specified object
@@ -821,18 +517,14 @@ UCL_EXTERN ucl_object_t * ucl_object_find_key (ucl_object_t *obj, const char *ke
 * @param klen length of a key
 * @return object matched the specified key or NULL if key is not found
 */
-
UCL_EXTERN ucl_object_t *ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen);
+
UCL_EXTERN ucl_object_t* ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen);

/**
 * Returns a key of an object as a NULL terminated string
 * @param obj CL object
 * @return key or NULL if there is no key
 */
-
static inline const char *
-
ucl_object_key (ucl_object_t *obj)
-
{
-
	return ucl_copy_key_trash (obj);
-
}
+
UCL_EXTERN const char* ucl_object_key (ucl_object_t *obj);

/**
 * Returns a key of an object as a fixed size string (may be more efficient)
@@ -840,12 +532,7 @@ ucl_object_key (ucl_object_t *obj)
 * @param len target key length
 * @return key pointer
 */
-
static inline const char *
-
ucl_object_keyl (ucl_object_t *obj, size_t *len)
-
{
-
	*len = obj->keylen;
-
	return obj->key;
-
}
+
UCL_EXTERN const char* ucl_object_keyl (ucl_object_t *obj, size_t *len);

/**
 * Free ucl object
@@ -857,22 +544,13 @@ UCL_EXTERN void ucl_object_free (ucl_object_t *obj);
 * Increase reference count for an object
 * @param obj object to ref
 */
-
static inline ucl_object_t *
-
ucl_object_ref (ucl_object_t *obj) {
-
	obj->ref ++;
-
	return obj;
-
}
+
UCL_EXTERN ucl_object_t* ucl_object_ref (ucl_object_t *obj);

/**
 * Decrease reference count for an object
 * @param obj object to unref
 */
-
static inline void
-
ucl_object_unref (ucl_object_t *obj) {
-
	if (obj != NULL && --obj->ref <= 0) {
-
		ucl_object_free (obj);
-
	}
-
}
+
UCL_EXTERN void ucl_object_unref (ucl_object_t *obj);
/**
 * Opaque iterator object
 */
@@ -944,7 +622,18 @@ UCL_EXTERN void ucl_parser_register_variable (struct ucl_parser *parser, const c
 * @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_chunk (struct ucl_parser *parser, const unsigned char *data, size_t len);
+
UCL_EXTERN bool ucl_parser_add_chunk (struct ucl_parser *parser,
+
		const unsigned char *data, size_t len);
+

+
/**
+
 * Load ucl object from a string
+
 * @param parser parser structure
+
 * @param data the pointer to the string
+
 * @param len the length of the string, if `len` is 0 then `data` must be zero-terminated string
+
 * @return true if string has been added and false in case of error
+
 */
+
UCL_EXTERN bool ucl_parser_add_string (struct ucl_parser *parser,
+
		const char *data,size_t len);

/**
 * Load and add data from a file
modified external/libucl/src/ucl_internal.h
@@ -261,7 +261,8 @@ ucl_maybe_parse_boolean (ucl_object_t *obj, const unsigned char *start, size_t l
 * @return 0 if string is numeric and error code (EINVAL or ERANGE) in case of conversion error
 */
int ucl_maybe_parse_number (ucl_object_t *obj,
-
		const char *start, const char *end, const char **pos, bool allow_double, bool number_bytes);
+
		const char *start, const char *end, const char **pos,
+
		bool allow_double, bool number_bytes, bool allow_time);


static inline ucl_object_t *
modified external/libucl/src/ucl_parser.c
@@ -544,6 +544,10 @@ ucl_add_parser_stack (ucl_object_t *obj, struct ucl_parser *parser, bool is_arra
	}

	st = UCL_ALLOC (sizeof (struct ucl_stack));
+
	if (st == NULL) {
+
		ucl_set_err (parser->chunks, 0, "cannot allocate memory for an object", &parser->err);
+
		return NULL;
+
	}
	st->obj = obj;
	st->level = level;
	LL_PREPEND (parser->stack, st);
@@ -554,12 +558,13 @@ ucl_add_parser_stack (ucl_object_t *obj, struct ucl_parser *parser, bool is_arra

int
ucl_maybe_parse_number (ucl_object_t *obj,
-
		const char *start, const char *end, const char **pos, bool allow_double, bool number_bytes)
+
		const char *start, const char *end, const char **pos,
+
		bool allow_double, bool number_bytes, bool allow_time)
{
	const char *p = start, *c = start;
	char *endptr;
	bool got_dot = false, got_exp = false, need_double = false,
-
			is_date = false, valid_start = false, is_hex = false,
+
			is_time = false, valid_start = false, is_hex = false,
			is_neg = false;
	double dv = 0;
	int64_t lv = 0;
@@ -678,7 +683,7 @@ ucl_maybe_parse_number (ucl_object_t *obj,
						need_double = true;
						dv = lv;
					}
-
					is_date = true;
+
					is_time = true;
					if (p[0] == 'm' || p[0] == 'M') {
						dv /= 1000.;
					}
@@ -708,7 +713,7 @@ ucl_maybe_parse_number (ucl_object_t *obj,
					p ++;
					goto set_obj;
				}
-
				else if (end - p >= 3) {
+
				else if (allow_time && end - p >= 3) {
					if (tolower (p[0]) == 'm' &&
							tolower (p[1]) == 'i' &&
							tolower (p[2]) == 'n') {
@@ -717,7 +722,7 @@ ucl_maybe_parse_number (ucl_object_t *obj,
							need_double = true;
							dv = lv;
						}
-
						is_date = true;
+
						is_time = true;
						dv *= 60.;
						p += 3;
						goto set_obj;
@@ -737,13 +742,14 @@ ucl_maybe_parse_number (ucl_object_t *obj,
			break;
		case 'S':
		case 's':
-
			if (p == end - 1 || ucl_lex_is_atom_end (p[1])) {
+
			if (allow_time &&
+
					(p == end - 1 || ucl_lex_is_atom_end (p[1]))) {
				if (!need_double) {
					need_double = true;
					dv = lv;
				}
				p ++;
-
				is_date = true;
+
				is_time = true;
				goto set_obj;
			}
			break;
@@ -755,12 +761,13 @@ ucl_maybe_parse_number (ucl_object_t *obj,
		case 'W':
		case 'Y':
		case 'y':
-
			if (p == end - 1 || ucl_lex_is_atom_end (p[1])) {
+
			if (allow_time &&
+
					(p == end - 1 || ucl_lex_is_atom_end (p[1]))) {
				if (!need_double) {
					need_double = true;
					dv = lv;
				}
-
				is_date = true;
+
				is_time = true;
				dv *= ucl_lex_time_multiplier (*p);
				p ++;
				goto set_obj;
@@ -773,8 +780,8 @@ ucl_maybe_parse_number (ucl_object_t *obj,
	return EINVAL;

	set_obj:
-
	if (allow_double && (need_double || is_date)) {
-
		if (!is_date) {
+
	if (allow_double && (need_double || is_time)) {
+
		if (!is_time) {
			obj->type = UCL_FLOAT;
		}
		else {
@@ -803,7 +810,8 @@ ucl_lex_number (struct ucl_parser *parser,
	const unsigned char *pos;
	int ret;

-
	ret = ucl_maybe_parse_number (obj, chunk->pos, chunk->end, (const char **)&pos, true, false);
+
	ret = ucl_maybe_parse_number (obj, chunk->pos, chunk->end, (const char **)&pos,
+
			true, false, ((parser->flags & UCL_PARSER_NO_TIME) == 0));

	if (ret == 0) {
		chunk->remain -= pos - chunk->pos;
@@ -1308,6 +1316,9 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
			obj = ucl_get_value_object (parser);
			/* We have a new object */
			obj = ucl_add_parser_stack (obj, parser, false, parser->stack->level);
+
			if (obj == NULL) {
+
				return false;
+
			}

			ucl_chunk_skipc (chunk, p);
			return true;
@@ -1316,6 +1327,9 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
			obj = ucl_get_value_object (parser);
			/* We have a new array */
			obj = ucl_add_parser_stack (obj, parser, true, parser->stack->level);
+
			if (obj == NULL) {
+
				return false;
+
			}

			ucl_chunk_skipc (chunk, p);
			return true;
@@ -1608,6 +1622,9 @@ ucl_state_machine (struct ucl_parser *parser)
		else {
			obj = ucl_add_parser_stack (NULL, parser, false, 0);
		}
+
		if (obj == NULL) {
+
			return false;
+
		}
		parser->top_obj = obj;
		parser->cur_obj = obj;
		parser->state = UCL_STATE_INIT;
@@ -1673,7 +1690,11 @@ ucl_state_machine (struct ucl_parser *parser)
			else if (parser->state != UCL_STATE_MACRO_NAME) {
				if (next_key && parser->stack->obj->type == UCL_OBJECT) {
					/* Parse more keys and nest objects accordingly */
-
					obj = ucl_add_parser_stack (parser->cur_obj, parser, false, parser->stack->level + 1);
+
					obj = ucl_add_parser_stack (parser->cur_obj, parser, false,
+
							parser->stack->level + 1);
+
					if (obj == NULL) {
+
						return false;
+
					}
				}
				else {
					parser->state = UCL_STATE_VALUE;
@@ -1787,6 +1808,9 @@ ucl_parser_new (int flags)
	struct ucl_parser *new;

	new = UCL_ALLOC (sizeof (struct ucl_parser));
+
	if (new == NULL) {
+
		return NULL;
+
	}
	memset (new, 0, sizeof (struct ucl_parser));

	ucl_parser_register_macro (new, "include", ucl_include_handler, new);
@@ -1808,7 +1832,13 @@ ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
{
	struct ucl_macro *new;

+
	if (macro == NULL || handler == NULL) {
+
		return;
+
	}
	new = UCL_ALLOC (sizeof (struct ucl_macro));
+
	if (new == NULL) {
+
		return;
+
	}
	memset (new, 0, sizeof (struct ucl_macro));
	new->handler = handler;
	new->name = strdup (macro);
@@ -1851,6 +1881,9 @@ ucl_parser_register_variable (struct ucl_parser *parser, const char *var,
	else {
		if (new == NULL) {
			new = UCL_ALLOC (sizeof (struct ucl_variable));
+
			if (new == NULL) {
+
				return;
+
			}
			memset (new, 0, sizeof (struct ucl_variable));
			new->var = strdup (var);
			new->var_len = strlen (var);
@@ -1873,8 +1906,16 @@ ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data,
{
	struct ucl_chunk *chunk;

+
	if (data == NULL || len == 0) {
+
		ucl_create_err (&parser->err, "invalid chunk added");
+
		return false;
+
	}
	if (parser->state != UCL_STATE_ERROR) {
		chunk = UCL_ALLOC (sizeof (struct ucl_chunk));
+
		if (chunk == NULL) {
+
			ucl_create_err (&parser->err, "cannot allocate chunk structure");
+
			return false;
+
		}
		chunk->begin = data;
		chunk->remain = len;
		chunk->pos = chunk->begin;
@@ -1895,3 +1936,18 @@ ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data,

	return false;
}
+

+
bool
+
ucl_parser_add_string (struct ucl_parser *parser, const char *data,
+
		size_t len)
+
{
+
	if (data == NULL) {
+
		ucl_create_err (&parser->err, "invalid string added");
+
		return false;
+
	}
+
	if (len == 0) {
+
		len = strlen (data);
+
	}
+

+
	return ucl_parser_add_chunk (parser, (const unsigned char *)data, len);
+
}
modified external/libucl/src/ucl_util.c
@@ -38,14 +38,26 @@
#ifdef _WIN32
#include <windows.h>

+
#ifndef PROT_READ
#define PROT_READ       1
+
#endif
+
#ifndef PROT_WRITE
#define PROT_WRITE      2
+
#endif
+
#ifndef PROT_READWRITE
#define PROT_READWRITE  3
+
#endif
+
#ifndef MAP_SHARED
#define MAP_SHARED      1
+
#endif
+
#ifndef MAP_PRIVATE
#define MAP_PRIVATE     2
+
#endif
+
#ifndef MAP_FAILED
#define MAP_FAILED      ((void *) -1)
+
#endif

-
static void *mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
+
static void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
{
	void *map = NULL;
	HANDLE handle = INVALID_HANDLE_VALUE;
@@ -83,7 +95,7 @@ static void *mmap(char *addr, size_t length, int prot, int access, int fd, off_t
	return (void *) ((char *) map + offset);
}

-
static int munmap(void *map,size_t length)
+
static int ucl_munmap(void *map,size_t length)
{
	if (!UnmapViewOfFile(map)) {
		return(-1);
@@ -91,7 +103,7 @@ static int munmap(void *map,size_t length)
	return(0);
}

-
static char* realpath(const char *path, char *resolved_path) {
+
static char* ucl_realpath(const char *path, char *resolved_path) {
    char *p;
    char tmp[MAX_PATH + 1];
    strncpy(tmp, path, sizeof(tmp)-1);
@@ -102,6 +114,10 @@ static char* realpath(const char *path, char *resolved_path) {
    }
    return _fullpath(resolved_path, tmp, MAX_PATH);
}
+
#else
+
#define ucl_mmap mmap
+
#define ucl_munmap munmap
+
#define ucl_realpath realpath
#endif

/**
@@ -158,6 +174,9 @@ ucl_unescape_json_string (char *str, size_t len)
	char *t = str, *h = str;
	int i, uval;

+
	if (len <= 1) {
+
		return len;
+
	}
	/* t is target (tortoise), h is source (hare) */

	while (len) {
@@ -188,45 +207,53 @@ ucl_unescape_json_string (char *str, size_t len)
			case 'u':
				/* Unicode escape */
				uval = 0;
-
				for (i = 0; i < 4; i++) {
-
					uval <<= 4;
-
					if (isdigit (h[i])) {
-
						uval += h[i] - '0';
+
				if (len > 3) {
+
					for (i = 0; i < 4; i++) {
+
						uval <<= 4;
+
						if (isdigit (h[i])) {
+
							uval += h[i] - '0';
+
						}
+
						else if (h[i] >= 'a' && h[i] <= 'f') {
+
							uval += h[i] - 'a' + 10;
+
						}
+
						else if (h[i] >= 'A' && h[i] <= 'F') {
+
							uval += h[i] - 'A' + 10;
+
						}
+
						else {
+
							break;
+
						}
					}
-
					else if (h[i] >= 'a' && h[i] <= 'f') {
-
						uval += h[i] - 'a' + 10;
+
					h += 3;
+
					len -= 3;
+
					/* Encode */
+
					if(uval < 0x80) {
+
						t[0] = (char)uval;
+
						t ++;
					}
-
					else if (h[i] >= 'A' && h[i] <= 'F') {
-
						uval += h[i] - 'A' + 10;
+
					else if(uval < 0x800) {
+
						t[0] = 0xC0 + ((uval & 0x7C0) >> 6);
+
						t[1] = 0x80 + ((uval & 0x03F));
+
						t += 2;
+
					}
+
					else if(uval < 0x10000) {
+
						t[0] = 0xE0 + ((uval & 0xF000) >> 12);
+
						t[1] = 0x80 + ((uval & 0x0FC0) >> 6);
+
						t[2] = 0x80 + ((uval & 0x003F));
+
						t += 3;
+
					}
+
					else if(uval <= 0x10FFFF) {
+
						t[0] = 0xF0 + ((uval & 0x1C0000) >> 18);
+
						t[1] = 0x80 + ((uval & 0x03F000) >> 12);
+
						t[2] = 0x80 + ((uval & 0x000FC0) >> 6);
+
						t[3] = 0x80 + ((uval & 0x00003F));
+
						t += 4;
+
					}
+
					else {
+
						*t++ = '?';
					}
-
				}
-
				h += 3;
-
				len -= 3;
-
				/* Encode */
-
				if(uval < 0x80) {
-
					t[0] = (char)uval;
-
					t ++;
-
				}
-
				else if(uval < 0x800) {
-
					t[0] = 0xC0 + ((uval & 0x7C0) >> 6);
-
					t[1] = 0x80 + ((uval & 0x03F));
-
					t += 2;
-
				}
-
				else if(uval < 0x10000) {
-
					t[0] = 0xE0 + ((uval & 0xF000) >> 12);
-
					t[1] = 0x80 + ((uval & 0x0FC0) >> 6);
-
					t[2] = 0x80 + ((uval & 0x003F));
-
					t += 3;
-
				}
-
				else if(uval <= 0x10FFFF) {
-
					t[0] = 0xF0 + ((uval & 0x1C0000) >> 18);
-
					t[1] = 0x80 + ((uval & 0x03F000) >> 12);
-
					t[2] = 0x80 + ((uval & 0x000FC0) >> 6);
-
					t[3] = 0x80 + ((uval & 0x00003F));
-
					t += 4;
				}
				else {
-
					*t++ = '?';
+
					*t++ = 'u';
				}
				break;
			default:
@@ -249,6 +276,9 @@ ucl_unescape_json_string (char *str, size_t len)
UCL_EXTERN char *
ucl_copy_key_trash (ucl_object_t *obj)
{
+
	if (obj == NULL) {
+
		return NULL;
+
	}
	if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) {
		obj->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1);
		if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
@@ -265,6 +295,9 @@ ucl_copy_key_trash (ucl_object_t *obj)
UCL_EXTERN char *
ucl_copy_value_trash (ucl_object_t *obj)
{
+
	if (obj == NULL) {
+
		return NULL;
+
	}
	if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) {
		if (obj->type == UCL_STRING) {
			/* Special case for strings */
@@ -304,6 +337,10 @@ ucl_parser_free (struct ucl_parser *parser)
	struct ucl_pubkey *key, *ktmp;
	struct ucl_variable *var, *vtmp;

+
	if (parser == NULL) {
+
		return;
+
	}
+

	if (parser->top_obj != NULL) {
		ucl_object_unref (parser->top_obj);
	}
@@ -338,6 +375,10 @@ ucl_parser_free (struct ucl_parser *parser)
UCL_EXTERN const char *
ucl_parser_get_error(struct ucl_parser *parser)
{
+
	if (parser == NULL) {
+
		return NULL;
+
	}
+

	if (parser->err == NULL)
		return NULL;

@@ -360,6 +401,10 @@ ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)

	mem = BIO_new_mem_buf ((void *)key, len);
	nkey = UCL_ALLOC (sizeof (struct ucl_pubkey));
+
	if (nkey == NULL) {
+
		ucl_create_err (&parser->err, "cannot allocate memory for key");
+
		return false;
+
	}
	nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL);
	BIO_free (mem);
	if (nkey->key == NULL) {
@@ -527,7 +572,7 @@ ucl_fetch_file (const unsigned char *filename, unsigned char **buf, size_t *bufl
					filename, strerror (errno));
			return false;
		}
-
		if ((*buf = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
+
		if ((*buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
			close (fd);
			ucl_create_err (err, "cannot mmap file %s: %s",
					filename, strerror (errno));
@@ -629,12 +674,12 @@ ucl_include_url (const unsigned char *data, size_t len,
							urlbuf,
							ERR_error_string (ERR_get_error (), NULL));
			if (siglen > 0) {
-
				munmap (sigbuf, siglen);
+
				ucl_munmap (sigbuf, siglen);
			}
			return false;
		}
		if (siglen > 0) {
-
			munmap (sigbuf, siglen);
+
			ucl_munmap (sigbuf, siglen);
		}
#endif
	}
@@ -678,7 +723,7 @@ ucl_include_file (const unsigned char *data, size_t len,
	int prev_state;

	snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
-
	if (realpath (filebuf, realbuf) == NULL) {
+
	if (ucl_realpath (filebuf, realbuf) == NULL) {
		if (!must_exist) {
			return true;
		}
@@ -706,12 +751,12 @@ ucl_include_file (const unsigned char *data, size_t len,
							filebuf,
							ERR_error_string (ERR_get_error (), NULL));
			if (siglen > 0) {
-
				munmap (sigbuf, siglen);
+
				ucl_munmap (sigbuf, siglen);
			}
			return false;
		}
		if (siglen > 0) {
-
			munmap (sigbuf, siglen);
+
			ucl_munmap (sigbuf, siglen);
		}
#endif
	}
@@ -734,7 +779,7 @@ ucl_include_file (const unsigned char *data, size_t len,
	parser->state = prev_state;

	if (buflen > 0) {
-
		munmap (buf, buflen);
+
		ucl_munmap (buf, buflen);
	}

	return res;
@@ -803,7 +848,7 @@ ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool n

	if (filename != NULL) {
		if (need_expand) {
-
			if (realpath (filename, realbuf) == NULL) {
+
			if (ucl_realpath (filename, realbuf) == NULL) {
				return false;
			}
		}
@@ -834,7 +879,7 @@ ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
	bool ret;
	char realbuf[PATH_MAX];

-
	if (realpath (filename, realbuf) == NULL) {
+
	if (ucl_realpath (filename, realbuf) == NULL) {
		ucl_create_err (&parser->err, "cannot open file %s: %s",
				filename,
				strerror (errno));
@@ -849,7 +894,7 @@ ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
	ret = ucl_parser_add_chunk (parser, buf, len);

	if (len > 0) {
-
		munmap (buf, len);
+
		ucl_munmap (buf, len);
	}

	return ret;
@@ -1014,13 +1059,15 @@ ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags
				if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) {
					ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
							flags & UCL_STRING_PARSE_DOUBLE,
-
							flags & UCL_STRING_PARSE_BYTES);
+
							flags & UCL_STRING_PARSE_BYTES,
+
							flags & UCL_STRING_PARSE_TIME);
				}
			}
			else {
				ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
						flags & UCL_STRING_PARSE_DOUBLE,
-
						flags & UCL_STRING_PARSE_BYTES);
+
						flags & UCL_STRING_PARSE_BYTES,
+
						flags & UCL_STRING_PARSE_TIME);
			}
		}
	}
@@ -1129,10 +1176,15 @@ ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen)
{
	ucl_object_t *found;

+
	if (top == NULL || key == NULL) {
+
		return false;
+
	}
+

	found = ucl_object_find_keyl(top, key, keylen);

-
	if (found == NULL)
+
	if (found == NULL) {
		return false;
+
	}

	ucl_hash_delete(top->value.ov, found);
	ucl_object_unref (found);
@@ -1147,6 +1199,31 @@ ucl_object_delete_key(ucl_object_t *top, const char *key)
	return ucl_object_delete_keyl(top, key, 0);
}

+
ucl_object_t*
+
ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen)
+
{
+
	ucl_object_t *found;
+

+
	if (top == NULL || key == NULL) {
+
		return false;
+
	}
+
	found = ucl_object_find_keyl(top, key, keylen);
+

+
	if (found == NULL) {
+
		return NULL;
+
	}
+
	ucl_hash_delete(top->value.ov, found);
+
	top->len --;
+

+
	return found;
+
}
+

+
ucl_object_t*
+
ucl_object_pop_key (ucl_object_t *top, const char *key)
+
{
+
	return ucl_object_pop_keyl (top, key, 0);
+
}
+

ucl_object_t *
ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
		const char *key, size_t keylen, bool copy_key)
@@ -1247,3 +1324,415 @@ ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_valu
	/* Not reached */
	return NULL;
}
+

+

+
ucl_object_t *
+
ucl_object_new (void)
+
{
+
	ucl_object_t *new;
+
	new = malloc (sizeof (ucl_object_t));
+
	if (new != NULL) {
+
		memset (new, 0, sizeof (ucl_object_t));
+
		new->ref = 1;
+
		new->type = UCL_NULL;
+
	}
+
	return new;
+
}
+

+
ucl_object_t *
+
ucl_object_typed_new (unsigned int type)
+
{
+
	ucl_object_t *new;
+
	new = malloc (sizeof (ucl_object_t));
+
	if (new != NULL) {
+
		memset (new, 0, sizeof (ucl_object_t));
+
		new->ref = 1;
+
		new->type = (type <= UCL_NULL ? type : UCL_NULL);
+
	}
+
	return new;
+
}
+

+
ucl_object_t*
+
ucl_object_fromstring (const char *str)
+
{
+
	return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE);
+
}
+

+
ucl_object_t *
+
ucl_object_fromlstring (const char *str, size_t len)
+
{
+
	return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE);
+
}
+

+
ucl_object_t *
+
ucl_object_fromint (int64_t iv)
+
{
+
	ucl_object_t *obj;
+

+
	obj = ucl_object_new ();
+
	if (obj != NULL) {
+
		obj->type = UCL_INT;
+
		obj->value.iv = iv;
+
	}
+

+
	return obj;
+
}
+

+
ucl_object_t *
+
ucl_object_fromdouble (double dv)
+
{
+
	ucl_object_t *obj;
+

+
	obj = ucl_object_new ();
+
	if (obj != NULL) {
+
		obj->type = UCL_FLOAT;
+
		obj->value.dv = dv;
+
	}
+

+
	return obj;
+
}
+

+
ucl_object_t*
+
ucl_object_frombool (bool bv)
+
{
+
	ucl_object_t *obj;
+

+
	obj = ucl_object_new ();
+
	if (obj != NULL) {
+
		obj->type = UCL_BOOLEAN;
+
		obj->value.iv = bv;
+
	}
+

+
	return obj;
+
}
+

+
ucl_object_t *
+
ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
+
{
+
	ucl_object_t *head;
+

+
	if (elt == NULL) {
+
		return NULL;
+
	}
+

+
	if (top == NULL) {
+
		top = ucl_object_typed_new (UCL_ARRAY);
+
		top->value.av = elt;
+
		elt->next = NULL;
+
		elt->prev = elt;
+
		top->len = 1;
+
	}
+
	else {
+
		head = top->value.av;
+
		if (head == NULL) {
+
			top->value.av = elt;
+
			elt->prev = elt;
+
		}
+
		else {
+
			elt->prev = head->prev;
+
			head->prev->next = elt;
+
			head->prev = elt;
+
		}
+
		elt->next = NULL;
+
		top->len ++;
+
	}
+

+
	return top;
+
}
+

+
ucl_object_t *
+
ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
+
{
+
	ucl_object_t *head;
+

+
	if (elt == NULL) {
+
		return NULL;
+
	}
+

+
	if (top == NULL) {
+
		top = ucl_object_typed_new (UCL_ARRAY);
+
		top->value.av = elt;
+
		elt->next = NULL;
+
		elt->prev = elt;
+
		top->len = 1;
+
	}
+
	else {
+
		head = top->value.av;
+
		if (head == NULL) {
+
			top->value.av = elt;
+
			elt->prev = elt;
+
		}
+
		else {
+
			elt->prev = head->prev;
+
			head->prev = elt;
+
		}
+
		elt->next = head;
+
		top->value.av = elt;
+
		top->len ++;
+
	}
+

+
	return top;
+
}
+

+
ucl_object_t *
+
ucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
+
{
+
	ucl_object_t *head;
+

+
	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
+
		return NULL;
+
	}
+
	head = top->value.av;
+

+
	if (elt->prev == elt) {
+
		top->value.av = NULL;
+
	}
+
	else if (elt == head) {
+
		elt->next->prev = elt->prev;
+
		top->value.av = elt->next;
+
	}
+
	else {
+
		elt->prev->next = elt->next;
+
		if (elt->next) {
+
			elt->next->prev = elt->prev;
+
		}
+
		else {
+
			head->prev = elt->prev;
+
		}
+
	}
+
	elt->next = NULL;
+
	elt->prev = elt;
+
	top->len --;
+

+
	return elt;
+
}
+

+
ucl_object_t *
+
ucl_array_head (ucl_object_t *top)
+
{
+
	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
+
		return NULL;
+
	}
+
	return top->value.av;
+
}
+

+
ucl_object_t *
+
ucl_array_tail (ucl_object_t *top)
+
{
+
	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
+
		return NULL;
+
	}
+
	return top->value.av->prev;
+
}
+

+
ucl_object_t *
+
ucl_array_pop_last (ucl_object_t *top)
+
{
+
	return ucl_array_delete (top, ucl_array_tail (top));
+
}
+

+
ucl_object_t *
+
ucl_array_pop_first (ucl_object_t *top)
+
{
+
	return ucl_array_delete (top, ucl_array_head (top));
+
}
+

+
ucl_object_t *
+
ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
+
{
+

+
	if (head == NULL) {
+
		elt->next = NULL;
+
		elt->prev = elt;
+
		head = elt;
+
	}
+
	else {
+
		elt->prev = head->prev;
+
		head->prev->next = elt;
+
		head->prev = elt;
+
		elt->next = NULL;
+
	}
+

+
	return head;
+
}
+

+
bool
+
ucl_object_todouble_safe (ucl_object_t *obj, double *target)
+
{
+
	if (obj == NULL || target == NULL) {
+
		return false;
+
	}
+
	switch (obj->type) {
+
	case UCL_INT:
+
		*target = obj->value.iv; /* Probaly could cause overflow */
+
		break;
+
	case UCL_FLOAT:
+
	case UCL_TIME:
+
		*target = obj->value.dv;
+
		break;
+
	default:
+
		return false;
+
	}
+

+
	return true;
+
}
+

+
double
+
ucl_object_todouble (ucl_object_t *obj)
+
{
+
	double result = 0.;
+

+
	ucl_object_todouble_safe (obj, &result);
+
	return result;
+
}
+

+
bool
+
ucl_object_toint_safe (ucl_object_t *obj, int64_t *target)
+
{
+
	if (obj == NULL || target == NULL) {
+
		return false;
+
	}
+
	switch (obj->type) {
+
	case UCL_INT:
+
		*target = obj->value.iv;
+
		break;
+
	case UCL_FLOAT:
+
	case UCL_TIME:
+
		*target = obj->value.dv; /* Loosing of decimal points */
+
		break;
+
	default:
+
		return false;
+
	}
+

+
	return true;
+
}
+

+
int64_t
+
ucl_object_toint (ucl_object_t *obj)
+
{
+
	int64_t result = 0;
+

+
	ucl_object_toint_safe (obj, &result);
+
	return result;
+
}
+

+
bool
+
ucl_object_toboolean_safe (ucl_object_t *obj, bool *target)
+
{
+
	if (obj == NULL || target == NULL) {
+
		return false;
+
	}
+
	switch (obj->type) {
+
	case UCL_BOOLEAN:
+
		*target = (obj->value.iv == true);
+
		break;
+
	default:
+
		return false;
+
	}
+

+
	return true;
+
}
+

+
bool
+
ucl_object_toboolean (ucl_object_t *obj)
+
{
+
	bool result = false;
+

+
	ucl_object_toboolean_safe (obj, &result);
+
	return result;
+
}
+

+
bool
+
ucl_object_tostring_safe (ucl_object_t *obj, const char **target)
+
{
+
	if (obj == NULL || target == NULL) {
+
		return false;
+
	}
+

+
	switch (obj->type) {
+
	case UCL_STRING:
+
		*target = ucl_copy_value_trash (obj);
+
		break;
+
	default:
+
		return false;
+
	}
+

+
	return true;
+
}
+

+
const char *
+
ucl_object_tostring (ucl_object_t *obj)
+
{
+
	const char *result = NULL;
+

+
	ucl_object_tostring_safe (obj, &result);
+
	return result;
+
}
+

+
const char *
+
ucl_object_tostring_forced (ucl_object_t *obj)
+
{
+
	return ucl_copy_value_trash (obj);
+
}
+

+
bool
+
ucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen)
+
{
+
	if (obj == NULL || target == NULL) {
+
		return false;
+
	}
+
	switch (obj->type) {
+
	case UCL_STRING:
+
		*target = obj->value.sv;
+
		if (tlen != NULL) {
+
			*tlen = obj->len;
+
		}
+
		break;
+
	default:
+
		return false;
+
	}
+

+
	return true;
+
}
+

+
const char *
+
ucl_object_tolstring (ucl_object_t *obj, size_t *tlen)
+
{
+
	const char *result = NULL;
+

+
	ucl_object_tolstring_safe (obj, &result, tlen);
+
	return result;
+
}
+

+
const char *
+
ucl_object_key (ucl_object_t *obj)
+
{
+
	return ucl_copy_key_trash (obj);
+
}
+

+
const char *
+
ucl_object_keyl (ucl_object_t *obj, size_t *len)
+
{
+
	if (len == NULL || obj == NULL) {
+
		return NULL;
+
	}
+
	*len = obj->keylen;
+
	return obj->key;
+
}
+

+
ucl_object_t *
+
ucl_object_ref (ucl_object_t *obj)
+
{
+
	if (obj != NULL) {
+
		obj->ref ++;
+
	}
+
	return obj;
+
}
+

+
void
+
ucl_object_unref (ucl_object_t *obj)
+
{
+
	if (obj != NULL && --obj->ref <= 0) {
+
		ucl_object_free (obj);
+
	}
+
}
deleted external/libucl/tests/5.in
@@ -1 +0,0 @@
-
# test
deleted external/libucl/tests/5.res
@@ -1 +0,0 @@
-

deleted external/libucl/tests/7.in
deleted external/libucl/tests/7.res
@@ -1 +0,0 @@
-

modified external/libucl/tests/9.in
@@ -1,5 +1,4 @@
.include "$CURDIR/9.inc"
-
.include "$CURDIR/9-empty.inc"
.include "$CURDIR/9-comment.inc"
#.include "$CURDIR/9.inc"
.include "$CURDIR/9.inc"
modified external/libucl/tests/test_basic.c
@@ -97,7 +97,7 @@ main (int argc, char **argv)
	else {
		out = stdout;
	}
-
	if (ucl_parser_get_error(parser) != NULL) {
+
	if (ucl_parser_get_error (parser) != NULL) {
		fprintf (out, "Error occurred: %s\n", ucl_parser_get_error(parser));
		ret = 1;
		goto end;
@@ -112,7 +112,7 @@ main (int argc, char **argv)
	ucl_parser_free (parser);
	ucl_object_unref (obj);
	parser2 = ucl_parser_new (UCL_PARSER_KEY_LOWERCASE);
-
	ucl_parser_add_chunk (parser2, emitted, strlen (emitted));
+
	ucl_parser_add_string (parser2, emitted, 0);

	if (ucl_parser_get_error(parser2) != NULL) {
		fprintf (out, "Error occurred: %s\n", ucl_parser_get_error(parser2));