Radish alpha
H
HardenedBSD Package Manager
Radicle
Git (anonymous pull)
Log in to clone via SSH
Update bundled libucl to 0.2.9
Baptiste Daroussin committed 12 years ago
commit ad016c2e888df5e3f8c9c6f0d70686c63880f419
parent 0a9bdd57e46fb1cb62f619f78867ac54084a535b
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));