Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Update libucl to latest version
Baptiste Daroussin committed 10 years ago
commit 69206ba10d0c7731680be601ef7c1bc139583737
parent 7236e35
22 files changed +3018 -826
modified external/libucl/ChangeLog.md
@@ -32,3 +32,8 @@
### Libucl 0.7.2

- Fixed serious bugs in schema and arrays iteration
+

+
### Libucl 0.7.3
+

+
- Fixed a bug with macroes that come after an empty object
+
- Fixed a bug in include processing when an incorrect variable has been destroyed (use-after-free)
modified external/libucl/README.md
@@ -1,6 +1,6 @@
# LIBUCL

-
[![Build Status](https://travis-ci.org/vstakhov/libucl.svg?branch=master)](https://travis-ci.org/vstakhov/libucl)
+
[![Build Status](https://travis-ci.org/vstakhov/libucl.svg?branch=master)](https://travis-ci.org/vstakhov/libucl)[![Coverity](https://scan.coverity.com/projects/4138/badge.svg)](https://scan.coverity.com/projects/4138)

**Table of Contents**  *generated with [DocToc](http://doctoc.herokuapp.com/)*

@@ -262,6 +262,14 @@ parser is created but before any configurations are parsed.
all files that matches the specified pattern (normally the format of patterns is defined in `glob` manual page
for your operating system). This option is meaningless for URL includes.
* `url` (default: **true**) - allow URL includes.
+
* `path` (default: empty) - A UCL_ARRAY of directories to search for the include file.
+
Search ends after the first patch, unless `glob` is true, then all matches are included.
+
* `prefix` (default false) - Put included contents inside an object, instead
+
of loading them into the root. If no `key` is provided, one is automatically generated based on each files basename()
+
* `key` (default: <empty string>) - Key to load contents of include into. If
+
the key already exists, it must be the correct type
+
* `target` (default: object) - Specify if the `prefix` `key` should be an
+
object or an array.
* `priority` (default: 0) - specify priority for the include (see below).

Priorities are used by UCL parser to manage the policy of objects rewriting during including other files
modified external/libucl/configure.ac
@@ -1,7 +1,7 @@
m4_define([maj_ver], [0])
m4_define([med_ver], [7])
-
m4_define([min_ver], [2])
-
m4_define([so_version], [5:0:1])
+
m4_define([min_ver], [3])
+
m4_define([so_version], [5:0:2])
m4_define([ucl_version], [maj_ver.med_ver.min_ver])

AC_INIT([libucl],[ucl_version],[https://github.com/vstakhov/libucl],[libucl])
@@ -47,6 +47,7 @@ AC_CHECK_HEADERS_ONCE([libgen.h])
AC_CHECK_HEADERS_ONCE([stdio.h])
AC_CHECK_HEADERS_ONCE([float.h])
AC_CHECK_HEADERS_ONCE([math.h])
+
AC_CHECK_HEADERS_ONCE([endian.h sys/endian.h machine/endian.h])

dnl Example of default-disabled feature
AC_ARG_ENABLE([urls], AS_HELP_STRING([--enable-urls], 
modified external/libucl/doc/lua_api.md
@@ -16,7 +16,7 @@ if not res then
else
	local obj = parser:get_object()
	local got = ucl.to_format(obj, 'json')
-
endif
+
end

local table = {
  str = 'value',
@@ -25,6 +25,7 @@ local table = {
  func = function ()
    return 'huh'
  end
+
}


print(ucl.to_format(table, 'ucl'))
@@ -115,6 +116,7 @@ local table = {
  func = function ()
    return 'huh'
  end
+
}


print(ucl.to_format(table, 'ucl'))
modified external/libucl/include/ucl.h
@@ -135,7 +135,9 @@ typedef enum ucl_emitter {
	UCL_EMIT_JSON = 0, /**< Emit fine formatted JSON */
	UCL_EMIT_JSON_COMPACT, /**< Emit compacted JSON */
	UCL_EMIT_CONFIG, /**< Emit human readable config format */
-
	UCL_EMIT_YAML /**< Emit embedded YAML format */
+
	UCL_EMIT_YAML, /**< Emit embedded YAML format */
+
	UCL_EMIT_MSGPACK, /**< Emit msgpack output */
+
	UCL_EMIT_MAX /**< Unsupported emitter type */
} ucl_emitter_t;

/**
@@ -145,6 +147,7 @@ typedef enum ucl_emitter {
 * UCL still has to perform copying implicitly.
 */
typedef enum ucl_parser_flags {
+
	UCL_PARSER_DEFAULT = 0x0,       /**< No special 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_NO_TIME = 0x4, /**< Do not parse time and treat time values as strings */
@@ -155,6 +158,7 @@ typedef enum ucl_parser_flags {
 * String conversion flags, that are used in #ucl_object_fromstring_common function.
 */
typedef enum ucl_string_flags {
+
	UCL_STRING_RAW = 0x0,     /**< Treat string as is */
	UCL_STRING_ESCAPE = 0x1,  /**< Perform JSON escape */
	UCL_STRING_TRIM = 0x2,    /**< Trim leading and trailing whitespaces */
	UCL_STRING_PARSE_BOOLEAN = 0x4,    /**< Parse passed string and detect boolean */
@@ -172,12 +176,13 @@ typedef enum ucl_string_flags {
 * Basic flags for an object
 */
typedef enum ucl_object_flags {
-
	UCL_OBJECT_ALLOCATED_KEY = 0x1, /**< An object has key allocated internally */
-
	UCL_OBJECT_ALLOCATED_VALUE = 0x2, /**< An object has a string value allocated internally */
-
	UCL_OBJECT_NEED_KEY_ESCAPE = 0x4, /**< The key of an object need to be escaped on output */
-
	UCL_OBJECT_EPHEMERAL = 0x8, /**< Temporary object that does not need to be freed really */
-
	UCL_OBJECT_MULTILINE = 0x10, /**< String should be displayed as multiline string */
-
	UCL_OBJECT_MULTIVALUE = 0x20 /**< Object is a key with multiple values */
+
	UCL_OBJECT_ALLOCATED_KEY = (1 << 0), /**< An object has key allocated internally */
+
	UCL_OBJECT_ALLOCATED_VALUE = (1 << 1), /**< An object has a string value allocated internally */
+
	UCL_OBJECT_NEED_KEY_ESCAPE = (1 << 2), /**< The key of an object need to be escaped on output */
+
	UCL_OBJECT_EPHEMERAL = (1 << 3), /**< Temporary object that does not need to be freed really */
+
	UCL_OBJECT_MULTILINE = (1 << 4), /**< String should be displayed as multiline string */
+
	UCL_OBJECT_MULTIVALUE = (1 << 5), /**< Object is a key with multiple values */
+
	UCL_OBJECT_INHERITED = (1 << 6) /**< Object has been inherited from another */
} ucl_object_flags_t;

/**
@@ -496,6 +501,15 @@ UCL_EXTERN const ucl_object_t* ucl_array_find_index (const ucl_object_t *top,
		unsigned int index);

/**
+
 * Return the index of `elt` in the array `top`
+
 * @param top object to get a key from (must be of type UCL_ARRAY)
+
 * @param elt element to find index of (must NOT be NULL)
+
 * @return index of `elt` in the array `top or (unsigned int)-1 if `elt` is not found
+
 */
+
UCL_EXTERN unsigned int ucl_array_index_of (ucl_object_t *top,
+
		ucl_object_t *elt);
+

+
/**
 * Replace an element in an array with a different element, returning the object
 * that was replaced. This object is not released, caller must unref the
 * returned object when it is no longer needed.
@@ -612,6 +626,19 @@ UCL_EXTERN const ucl_object_t* ucl_object_find_key (const ucl_object_t *obj,
		const char *key);

/**
+
 * Return object identified by a key in the specified object, if the first key is
+
 * not found then look for the next one. This process is repeated unless
+
 * the next argument in the list is not NULL. So, `ucl_object_find_any_key(obj, key, NULL)`
+
 * is equal to `ucl_object_find_key(obj, key)`
+
 * @param obj object to get a key from (must be of type UCL_OBJECT)
+
 * @param key key to search
+
 * @param ... list of alternative keys to search (NULL terminated)
+
 * @return object matching the specified key or NULL if key was not found
+
 */
+
UCL_EXTERN const ucl_object_t* ucl_object_find_any_key (const ucl_object_t *obj,
+
		const char *key, ...);
+

+
/**
 * Return object identified by a fixed size key in the specified object
 * @param obj object to get a key from (must be of type UCL_OBJECT)
 * @param key key to search
@@ -631,6 +658,16 @@ UCL_EXTERN const ucl_object_t *ucl_lookup_path (const ucl_object_t *obj,
		const char *path);

/**
+
 * Return object identified by object notation string using arbitrary delimiter
+
 * @param obj object to search in
+
 * @param path dot.notation.path to the path to lookup. May use numeric .index on arrays
+
 * @param sep the sepatorator to use in place of . (incase keys have . in them)
+
 * @return object matched the specified path or NULL if path is not found
+
 */
+
UCL_EXTERN const ucl_object_t *ucl_lookup_path_char (const ucl_object_t *obj,
+
		const char *path, char sep);
+

+
/**
 * Returns a key of an object as a NULL terminated string
 * @param obj CL object
 * @return key or NULL if there is no key
@@ -769,6 +806,21 @@ typedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len,
		const ucl_object_t *arguments,
		void* ud);

+
/**
+
 * Context dependent macro handler for a parser
+
 * @param data the content of macro
+
 * @param len the length of content
+
 * @param arguments arguments object
+
 * @param context previously parsed context
+
 * @param ud opaque user data
+
 * @param err error pointer
+
 * @return true if macro has been parsed
+
 */
+
typedef bool (*ucl_context_macro_handler) (const unsigned char *data, size_t len,
+
		const ucl_object_t *arguments,
+
		const ucl_object_t *context,
+
		void* ud);
+

/* Opaque parser */
struct ucl_parser;

@@ -780,16 +832,38 @@ struct ucl_parser;
UCL_EXTERN struct ucl_parser* ucl_parser_new (int flags);

/**
+
 * Sets the default priority for the parser applied to chunks that does not
+
 * specify priority explicitly
+
 * @param parser parser object
+
 * @param prio default priority (0 .. 16)
+
 * @return true if parser's default priority was set
+
 */
+
UCL_EXTERN bool ucl_parser_set_default_priority (struct ucl_parser *parser,
+
		unsigned prio);
+
/**
 * Register new handler for a macro
 * @param parser parser object
 * @param macro macro name (without leading dot)
 * @param handler handler (it is called immediately after macro is parsed)
 * @param ud opaque user data for a handler
 */
-
UCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
+
UCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser,
+
		const char *macro,
		ucl_macro_handler handler, void* ud);

/**
+
 * Register new context dependent handler for a macro
+
 * @param parser parser object
+
 * @param macro macro name (without leading dot)
+
 * @param handler handler (it is called immediately after macro is parsed)
+
 * @param ud opaque user data for a handler
+
 */
+
UCL_EXTERN void ucl_parser_register_context_macro (struct ucl_parser *parser,
+
		const char *macro,
+
		ucl_context_macro_handler handler,
+
		void* ud);
+

+
/**
 * Handler to detect unregistered variables
 * @param data variable data
 * @param len length of variable
@@ -853,6 +927,18 @@ UCL_EXTERN bool ucl_parser_add_string (struct ucl_parser *parser,
		const 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
+
 * @param priority the desired priority of a chunk (only 4 least significant bits
+
 * are considered for this parameter)
+
 * @return true if string has been added and false in case of error
+
 */
+
UCL_EXTERN bool ucl_parser_add_string_priority (struct ucl_parser *parser,
+
		const char *data, size_t len, unsigned priority);
+

+
/**
 * Load and add data from a file
 * @param parser parser structure
 * @param filename the name of file
@@ -863,6 +949,18 @@ UCL_EXTERN bool ucl_parser_add_file (struct ucl_parser *parser,
		const char *filename);

/**
+
 * Load and add data from a file
+
 * @param parser parser structure
+
 * @param filename the name of file
+
 * @param err if *err is NULL it is set to parser error
+
 * @param priority the desired priority of a chunk (only 4 least significant bits
+
 * are considered for this parameter)
+
 * @return true if chunk has been added and false in case of error
+
 */
+
UCL_EXTERN bool ucl_parser_add_file_priority (struct ucl_parser *parser,
+
		const char *filename, unsigned priority);
+

+
/**
 * Load and add data from a file descriptor
 * @param parser parser structure
 * @param filename the name of file
@@ -873,6 +971,28 @@ UCL_EXTERN bool ucl_parser_add_fd (struct ucl_parser *parser,
		int fd);

/**
+
 * Load and add data from a file descriptor
+
 * @param parser parser structure
+
 * @param filename the name of file
+
 * @param err if *err is NULL it is set to parser error
+
 * @param priority the desired priority of a chunk (only 4 least significant bits
+
 * are considered for this parameter)
+
 * @return true if chunk has been added and false in case of error
+
 */
+
UCL_EXTERN bool ucl_parser_add_fd_priority (struct ucl_parser *parser,
+
		int fd, unsigned priority);
+

+
/**
+
 * Provide a UCL_ARRAY of paths to search for include files. The object is
+
 * copied so caller must unref the object.
+
 * @param parser parser structure
+
 * @param paths UCL_ARRAY of paths to search
+
 * @return true if the path search array was replaced in the parser
+
 */
+
UCL_EXTERN bool ucl_set_include_path (struct ucl_parser *parser,
+
		ucl_object_t *paths);
+

+
/**
 * Get a top object for a parser (refcount is increased)
 * @param parser parser structure
 * @param err if *err is NULL it is set to parser error
@@ -881,12 +1001,34 @@ UCL_EXTERN bool ucl_parser_add_fd (struct ucl_parser *parser,
UCL_EXTERN ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser);

/**
-
 * Get the error string if failing
+
 * Get the error string if parsing has been failed
 * @param parser parser object
+
 * @return error description
 */
UCL_EXTERN const char *ucl_parser_get_error(struct ucl_parser *parser);

/**
+
 * Get the code of the last error
+
 * @param parser parser object
+
 * @return error code
+
 */
+
UCL_EXTERN int ucl_parser_get_error_code(struct ucl_parser *parser);
+

+
/**
+
 * Get the current column number within parser
+
 * @param parser parser object
+
 * @return current column number
+
 */
+
UCL_EXTERN unsigned ucl_parser_get_column(struct ucl_parser *parser);
+

+
/**
+
 * Get the current line number within parser
+
 * @param parser parser object
+
 * @return current line number
+
 */
+
UCL_EXTERN unsigned ucl_parser_get_linenum(struct ucl_parser *parser);
+

+
/**
 * Clear the error in the parser
 * @param parser parser object
 */
@@ -994,6 +1136,17 @@ UCL_EXTERN unsigned char *ucl_object_emit (const ucl_object_t *obj,
		enum ucl_emitter emit_type);

/**
+
 * Emit object to a string that can contain `\0` inside
+
 * @param obj object
+
 * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is
+
 * #UCL_EMIT_CONFIG then emit config like object
+
 * @param len the resulting length
+
 * @return dump of an object (must be freed after using) or NULL in case of error
+
 */
+
UCL_EXTERN unsigned char *ucl_object_emit_len (const ucl_object_t *obj,
+
		enum ucl_emitter emit_type, size_t *len);
+

+
/**
 * Emit object to a string
 * @param obj object
 * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is
modified external/libucl/klib/kvec.h
@@ -89,7 +89,7 @@ int main() {

#define kv_concat(type, v1, v0) do {										\
	if ((v1).m < (v0).n + (v1).n) kv_resize(type, v1, (v0).n + (v1).n);		\
-
		memcpy((v1).a + (v1).n, (v0).a, sizeof(type) * ((v0).n + (v1).n));	\
+
		memcpy((v1).a + (v1).n, (v0).a, sizeof(type) * (v0).n);	\
		(v1).n = (v0).n + (v1).n;											\
	} while (0)

modified external/libucl/lua/lua_ucl.c
@@ -172,19 +172,33 @@ static int
ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj)
{
	const ucl_object_t *cur;
+
	ucl_object_iter_t it;
	int i = 1, nelt = 0;

-
	/* Optimize allocation by preallocation of table */
-
	LL_FOREACH (obj, cur) {
-
		nelt ++;
+
	if (obj->type == UCL_ARRAY) {
+
		nelt = obj->len;
+
		it = ucl_object_iterate_new (obj);
+
		lua_createtable (L, nelt, 0);
+

+
		while ((cur = ucl_object_iterate_safe (it, true))) {
+
			ucl_object_push_lua (L, cur, false);
+
			lua_rawseti (L, -2, i);
+
			i ++;
+
		}
	}
+
	else {
+
		/* Optimize allocation by preallocation of table */
+
		LL_FOREACH (obj, cur) {
+
			nelt ++;
+
		}

-
	lua_createtable (L, nelt, 0);
+
		lua_createtable (L, nelt, 0);

-
	LL_FOREACH (obj, cur) {
-
		ucl_object_push_lua (L, cur, false);
-
		lua_rawseti (L, -2, i);
-
		i ++;
+
		LL_FOREACH (obj, cur) {
+
			ucl_object_push_lua (L, cur, false);
+
			lua_rawseti (L, -2, i);
+
			i ++;
+
		}
	}

	return 1;
@@ -259,7 +273,7 @@ ucl_object_push_lua (lua_State *L, const ucl_object_t *obj, bool allow_array)
	case UCL_OBJECT:
		return ucl_object_lua_push_object (L, obj, allow_array);
	case UCL_ARRAY:
-
		return ucl_object_lua_push_array (L, obj->value.av);
+
		return ucl_object_lua_push_array (L, obj);
	default:
		return ucl_object_lua_push_scalar (L, obj, allow_array);
	}
@@ -322,6 +336,7 @@ ucl_object_lua_fromtable (lua_State *L, int idx)
			if (obj != NULL) {
				ucl_array_append (top, obj);
			}
+
			lua_pop (L, 1);
		}
	}
	else {
modified external/libucl/src/Makefile.am
@@ -11,6 +11,7 @@ libucl_la_SOURCES= ucl_emitter.c \
					ucl_parser.c \
					ucl_schema.c \
					ucl_util.c \
+
					ucl_msgpack.c \
					xxhash.c
libucl_la_CFLAGS=	$(libucl_common_cflags) \
					@CURL_CFLAGS@
@@ -20,7 +21,8 @@ libucl_la_LIBADD= @LIBFETCH_LIBS@ \
					@LIBREGEX_LIB@ \
					@CURL_LIBS@

-
include_HEADERS=	$(top_srcdir)/include/ucl.h
+
include_HEADERS=	$(top_srcdir)/include/ucl.h \
+
					$(top_srcdir)/include/ucl++.h
noinst_HEADERS=	ucl_internal.h \
				xxhash.h \
				ucl_hash.h \
modified external/libucl/src/tree.h
@@ -44,6 +44,13 @@


#define TREE_DELTA_MAX	1
+
#ifndef _HU_FUNCTION
+
# if defined(__GNUC__) || defined(__clang__)
+
#   define _HU_FUNCTION(x) __attribute__((__unused__)) x
+
# else
+
#   define _HU_FUNCTION(x) x
+
# endif
+
#endif

#define TREE_ENTRY(type)			\
  struct {					\
@@ -68,9 +75,9 @@

#define TREE_DEFINE(node, field)									\
													\
-
  struct node *TREE_BALANCE_##node##_##field(struct node *);						\
+
  static struct node *_HU_FUNCTION(TREE_BALANCE_##node##_##field)(struct node *);						\
													\
-
  struct node *TREE_ROTL_##node##_##field(struct node *self)						\
+
  static struct node *_HU_FUNCTION(TREE_ROTL_##node##_##field)(struct node *self)						\
  {													\
    struct node *r= self->field.avl_right;								\
    self->field.avl_right= r->field.avl_left;								\
@@ -78,7 +85,7 @@
    return TREE_BALANCE_##node##_##field(r);								\
  }													\
													\
-
  struct node *TREE_ROTR_##node##_##field(struct node *self)						\
+
  static struct node *_HU_FUNCTION(TREE_ROTR_##node##_##field)(struct node *self)						\
  {													\
    struct node *l= self->field.avl_left;								\
    self->field.avl_left= l->field.avl_right;								\
@@ -86,7 +93,7 @@
    return TREE_BALANCE_##node##_##field(l);								\
  }													\
													\
-
  struct node *TREE_BALANCE_##node##_##field(struct node *self)						\
+
  static struct node *_HU_FUNCTION(TREE_BALANCE_##node##_##field)(struct node *self)						\
  {													\
    int delta= TREE_DELTA(self, field);									\
													\
@@ -111,7 +118,7 @@
    return self;											\
  }													\
													\
-
  struct node *TREE_INSERT_##node##_##field								\
+
  static struct node *_HU_FUNCTION(TREE_INSERT_##node##_##field)								\
    (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))		\
  {													\
    if (!self)												\
@@ -123,7 +130,7 @@
    return TREE_BALANCE_##node##_##field(self);								\
  }													\
													\
-
  struct node *TREE_FIND_##node##_##field								\
+
  static struct node *_HU_FUNCTION(TREE_FIND_##node##_##field)								\
    (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))		\
  {													\
    if (!self)												\
@@ -136,7 +143,7 @@
      return TREE_FIND_##node##_##field(self->field.avl_right, elm, compare);				\
  }													\
													\
-
  struct node *TREE_MOVE_RIGHT(struct node *self, struct node *rhs)					\
+
  static struct node *_HU_FUNCTION(TREE_MOVE_RIGHT)(struct node *self, struct node *rhs)					\
  {													\
    if (!self)												\
      return rhs;											\
@@ -144,7 +151,7 @@
    return TREE_BALANCE_##node##_##field(self);								\
  }													\
													\
-
  struct node *TREE_REMOVE_##node##_##field								\
+
  static struct node *_HU_FUNCTION(TREE_REMOVE_##node##_##field)								\
    (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))		\
  {													\
    if (!self) return 0;										\
@@ -163,7 +170,7 @@
    return TREE_BALANCE_##node##_##field(self);								\
  }													\
													\
-
  void TREE_FORWARD_APPLY_ALL_##node##_##field								\
+
  static void _HU_FUNCTION(TREE_FORWARD_APPLY_ALL_##node##_##field)								\
    (struct node *self, void (*function)(struct node *node, void *data), void *data)			\
  {													\
    if (self)												\
@@ -174,7 +181,7 @@
      }													\
  }													\
													\
-
  void TREE_REVERSE_APPLY_ALL_##node##_##field								\
+
  static void _HU_FUNCTION(TREE_REVERSE_APPLY_ALL_##node##_##field)								\
    (struct node *self, void (*function)(struct node *node, void *data), void *data)			\
  {													\
    if (self)												\
modified external/libucl/src/ucl_emitter.c
@@ -62,6 +62,7 @@ UCL_EMIT_TYPE_OPS(json);
UCL_EMIT_TYPE_OPS(json_compact);
UCL_EMIT_TYPE_OPS(config);
UCL_EMIT_TYPE_OPS(yaml);
+
UCL_EMIT_TYPE_OPS(msgpack);

#define UCL_EMIT_TYPE_CONTENT(type) {	\
	.ucl_emitter_write_elt = ucl_emit_ ## type ## _elt,	\
@@ -71,12 +72,12 @@ UCL_EMIT_TYPE_OPS(yaml);
	.ucl_emitter_end_array = ucl_emit_ ## type ##_end_array	\
}

-

const struct ucl_emitter_operations ucl_standartd_emitter_ops[] = {
	[UCL_EMIT_JSON] = UCL_EMIT_TYPE_CONTENT(json),
	[UCL_EMIT_JSON_COMPACT] = UCL_EMIT_TYPE_CONTENT(json_compact),
	[UCL_EMIT_CONFIG] = UCL_EMIT_TYPE_CONTENT(config),
-
	[UCL_EMIT_YAML] = UCL_EMIT_TYPE_CONTENT(yaml)
+
	[UCL_EMIT_YAML] = UCL_EMIT_TYPE_CONTENT(yaml),
+
	[UCL_EMIT_MSGPACK] = UCL_EMIT_TYPE_CONTENT(msgpack)
};

/*
@@ -469,19 +470,139 @@ UCL_EMIT_TYPE_IMPL(json_compact, true)
UCL_EMIT_TYPE_IMPL(config, false)
UCL_EMIT_TYPE_IMPL(yaml, false)

+
static void
+
ucl_emit_msgpack_elt (struct ucl_emitter_context *ctx,
+
		const ucl_object_t *obj, bool first, bool print_key)
+
{
+
	ucl_object_iter_t it;
+
	struct ucl_object_userdata *ud;
+
	const char *ud_out;
+
	const ucl_object_t *cur, *celt;
+

+
	switch (obj->type) {
+
	case UCL_INT:
+
		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+
		ucl_emitter_print_int_msgpack (ctx, ucl_object_toint (obj));
+
		break;
+

+
	case UCL_FLOAT:
+
	case UCL_TIME:
+
		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+
		ucl_emitter_print_double_msgpack (ctx, ucl_object_todouble (obj));
+
		break;
+

+
	case UCL_BOOLEAN:
+
		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+
		ucl_emitter_print_bool_msgpack (ctx, ucl_object_toboolean (obj));
+
		break;
+

+
	case UCL_STRING:
+
		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+
		ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len);
+
		break;
+

+
	case UCL_NULL:
+
		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+
		ucl_emitter_print_null_msgpack (ctx);
+
		break;
+

+
	case UCL_OBJECT:
+
		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+
		ucl_emit_msgpack_start_obj (ctx, obj, print_key);
+
		it = ucl_object_iterate_new (obj);
+

+
		while ((cur = ucl_object_iterate_safe (it, true)) != NULL) {
+
			LL_FOREACH (cur, celt) {
+
				ucl_emit_msgpack_elt (ctx, celt, false, true);
+
			}
+
		}
+

+
		ucl_object_iterate_free (it);
+
		break;
+

+
	case UCL_ARRAY:
+
		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+
		ucl_emit_msgpack_start_array (ctx, obj, print_key);
+
		it = ucl_object_iterate_new (obj);
+

+
		while ((cur = ucl_object_iterate_safe (it, true)) != NULL) {
+
			ucl_emit_msgpack_elt (ctx, cur, false, false);
+
		}
+

+
		ucl_object_iterate_free (it);
+
		break;
+

+
	case UCL_USERDATA:
+
		ud = (struct ucl_object_userdata *)obj;
+
		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+

+
		if (ud->emitter) {
+
			ud_out = ud->emitter (obj->value.ud);
+
			if (ud_out == NULL) {
+
				ud_out = "null";
+
			}
+
		}
+
		ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len);
+
		break;
+
	}
+
}
+

+
static void
+
ucl_emit_msgpack_start_obj (struct ucl_emitter_context *ctx,
+
		const ucl_object_t *obj, bool print_key)
+
{
+
	ucl_emitter_print_object_msgpack (ctx, obj->len);
+
}
+

+
static void
+
ucl_emit_msgpack_start_array (struct ucl_emitter_context *ctx,
+
		const ucl_object_t *obj, bool print_key)
+
{
+
	ucl_emitter_print_array_msgpack (ctx, obj->len);
+
}
+

+
static void
+
ucl_emit_msgpack_end_object (struct ucl_emitter_context *ctx,
+
		const ucl_object_t *obj)
+
{
+

+
}
+

+
static void
+
ucl_emit_msgpack_end_array (struct ucl_emitter_context *ctx,
+
		const ucl_object_t *obj)
+
{
+

+
}
+

unsigned char *
ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type)
{
+
	return ucl_object_emit_len (obj, emit_type, NULL);
+
}
+

+
unsigned char *
+
ucl_object_emit_len (const ucl_object_t *obj, enum ucl_emitter emit_type,
+
		size_t *outlen)
+
{
	unsigned char *res = NULL;
	struct ucl_emitter_functions *func;
+
	UT_string *s;
+

	if (obj == NULL) {
		return NULL;
	}

	func = ucl_object_emit_memory_funcs ((void **)&res);
+
	s = func->ud;

	if (func != NULL) {
		ucl_object_emit_full (obj, emit_type, func);
+

+
		if (outlen != NULL) {
+
			*outlen = s->i;
+
		}
+

		ucl_object_emit_funcs_free (func);
	}

modified external/libucl/src/ucl_emitter_utils.c
@@ -62,6 +62,12 @@ static const struct ucl_emitter_context ucl_standard_emitters[] = {
		.id = UCL_EMIT_YAML,
		.func = NULL,
		.ops = &ucl_standartd_emitter_ops[UCL_EMIT_YAML]
+
	},
+
	[UCL_EMIT_MSGPACK] = {
+
		.name = "msgpack",
+
		.id = UCL_EMIT_MSGPACK,
+
		.func = NULL,
+
		.ops = &ucl_standartd_emitter_ops[UCL_EMIT_MSGPACK]
	}
};

@@ -73,7 +79,7 @@ static const struct ucl_emitter_context ucl_standard_emitters[] = {
const struct ucl_emitter_context *
ucl_emit_get_standard_context (enum ucl_emitter emit_type)
{
-
	if (emit_type >= UCL_EMIT_JSON && emit_type <= UCL_EMIT_YAML) {
+
	if (emit_type >= UCL_EMIT_JSON && emit_type < UCL_EMIT_MAX) {
		return &ucl_standard_emitters[emit_type];
	}

modified external/libucl/src/ucl_hash.c
@@ -26,6 +26,9 @@
#include "khash.h"
#include "kvec.h"

+
#include <time.h>
+
#include <limits.h>
+

struct ucl_hash_elt {
	const ucl_object_t *obj;
	size_t ar_idx;
@@ -37,11 +40,78 @@ struct ucl_hash_struct {
	bool caseless;
};

+
static uint64_t
+
ucl_hash_seed (void)
+
{
+
	static uint64_t seed;
+

+
	if (seed == 0) {
+
#ifdef UCL_RANDOM_FUNCTION
+
		seed = UCL_RANDOM_FUNCTION;
+
#else
+
		/* Not very random but can be useful for our purposes */
+
		seed = time (NULL);
+
#endif
+
	}
+

+
	return seed;
+
}
+

+
static const unsigned char lc_map[256] = {
+
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+
		0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+
		0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+
		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+
		0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+
		0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+
		0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+
		0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+
		0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+
		0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+
		0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+
		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+
		0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+
		0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+
		0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+
		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+
		0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+
		0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+
		0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+
		0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+
		0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+
		0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+
		0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+
		0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+
		0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+
		0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+
		0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+
		0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+
		0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+
		0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+
		0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+
};
+

+
#if (defined(WORD_BIT) && WORD_BIT == 64) || \
+
	(defined(__WORDSIZE) && __WORDSIZE == 64) || \
+
	defined(__x86_64__) || \
+
	defined(__amd64__)
+
#define UCL64_BIT_HASH 1
+
#endif
+

+
#ifdef UCL64_BIT_HASH
+
static inline uint32_t
+
ucl_hash_func (const ucl_object_t *o)
+
{
+
	return XXH64 (o->key, o->keylen, ucl_hash_seed ());
+
}
+
#else
static inline uint32_t
ucl_hash_func (const ucl_object_t *o)
{
-
	return XXH32 (o->key, o->keylen, 0xdeadbeef);
+
	return XXH32 (o->key, o->keylen, ucl_hash_seed ());
}
+
#endif

static inline int
ucl_hash_equal (const ucl_object_t *k1, const ucl_object_t *k2)
@@ -56,33 +126,91 @@ ucl_hash_equal (const ucl_object_t *k1, const ucl_object_t *k2)
KHASH_INIT (ucl_hash_node, const ucl_object_t *, struct ucl_hash_elt, 1,
		ucl_hash_func, ucl_hash_equal)

+
#ifdef UCL64_BIT_HASH
static inline uint32_t
ucl_hash_caseless_func (const ucl_object_t *o)
{
-
	void *xxh = XXH32_init (0xdeadbeef);
-
	char hash_buf[64], *c;
-
	const char *p;
-
	ssize_t remain = o->keylen;
-

-
	p = o->key;
-
	c = &hash_buf[0];
+
	unsigned len = o->keylen;
+
	unsigned leftover = o->keylen % 4;
+
	unsigned fp, i;
+
	const uint8_t* s = (const uint8_t*)o->key;
+
	union {
+
		struct {
+
			unsigned char c1, c2, c3, c4;
+
		} c;
+
		uint32_t pp;
+
	} u;
+
	XXH64_state_t st;
+

+
	fp = len - leftover;
+
	XXH64_reset (&st, ucl_hash_seed ());
+

+
	for (i = 0; i != fp; i += 4) {
+
		u.c.c1 = s[i], u.c.c2 = s[i + 1], u.c.c3 = s[i + 2], u.c.c4 = s[i + 3];
+
		u.c.c1 = lc_map[u.c.c1];
+
		u.c.c2 = lc_map[u.c.c2];
+
		u.c.c3 = lc_map[u.c.c3];
+
		u.c.c4 = lc_map[u.c.c4];
+
		XXH64_update (&st, &u.pp, sizeof (u));
+
	}

-
	while (remain > 0) {
-
		*c++ = tolower (*p++);
+
	u.pp = 0;
+
	switch (leftover) {
+
	case 3:
+
		u.c.c3 = lc_map[(unsigned char)s[i++]];
+
	case 2:
+
		u.c.c2 = lc_map[(unsigned char)s[i++]];
+
	case 1:
+
		u.c.c1 = lc_map[(unsigned char)s[i]];
+
		XXH64_update (&st, &u.pp, leftover);
+
		break;
+
	}

-
		if (c - &hash_buf[0] == sizeof (hash_buf)) {
-
			XXH32_update (xxh, hash_buf, sizeof (hash_buf));
-
			c = &hash_buf[0];
-
		}
-
		remain --;
+
	return XXH64_digest (&st);
+
}
+
#else
+
static inline uint32_t
+
ucl_hash_caseless_func (const ucl_object_t *o)
+
{
+
	unsigned len = o->keylen;
+
	unsigned leftover = o->keylen % 4;
+
	unsigned fp, i;
+
	const uint8_t* s = (const uint8_t*)o->key;
+
	union {
+
		struct {
+
			unsigned char c1, c2, c3, c4;
+
		} c;
+
		uint32_t pp;
+
	} u;
+
	XXH32_state_t st;
+

+
	fp = len - leftover;
+
	XXH32_reset (&st, ucl_hash_seed ());
+

+
	for (i = 0; i != fp; i += 4) {
+
		u.c.c1 = s[i], u.c.c2 = s[i + 1], u.c.c3 = s[i + 2], u.c.c4 = s[i + 3];
+
		u.c.c1 = lc_map[u.c.c1];
+
		u.c.c2 = lc_map[u.c.c2];
+
		u.c.c3 = lc_map[u.c.c3];
+
		u.c.c4 = lc_map[u.c.c4];
+
		XXH32_update (&st, &u.pp, sizeof (u));
	}

-
	if (c - &hash_buf[0] != 0) {
-
		XXH32_update (xxh, hash_buf, c - &hash_buf[0]);
+
	u.pp = 0;
+
	switch (leftover) {
+
	case 3:
+
		u.c.c3 = lc_map[(unsigned char)s[i++]];
+
	case 2:
+
		u.c.c2 = lc_map[(unsigned char)s[i++]];
+
	case 1:
+
		u.c.c1 = lc_map[(unsigned char)s[i]];
+
		XXH32_update (&st, &u.pp, leftover);
+
		break;
	}

-
	return XXH32_digest (xxh);
+
	return XXH32_digest (&st);
}
+
#endif

static inline int
ucl_hash_caseless_equal (const ucl_object_t *k1, const ucl_object_t *k2)
@@ -254,6 +382,11 @@ ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter)

	if (it == NULL) {
		it = UCL_ALLOC (sizeof (*it));
+

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

		it->cur = &hashlin->ar.a[0];
		it->end = it->cur + hashlin->ar.n;
	}
@@ -336,7 +469,7 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
		k = kh_get (ucl_hash_caseless_node, h, obj);
		if (k != kh_end (h)) {
			elt = &kh_value (h, k);
-
			kv_A (hashlin->ar, elt->ar_idx) = NULL;
+
			kv_del (const ucl_object_t *, hashlin->ar, elt->ar_idx);
			kh_del (ucl_hash_caseless_node, h, k);
		}
	}
@@ -346,7 +479,7 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
		k = kh_get (ucl_hash_node, h, obj);
		if (k != kh_end (h)) {
			elt = &kh_value (h, k);
-
			kv_A (hashlin->ar, elt->ar_idx) = NULL;
+
			kv_del (const ucl_object_t *, hashlin->ar, elt->ar_idx);
			kh_del (ucl_hash_node, h, k);
		}
	}
modified external/libucl/src/ucl_internal.h
@@ -145,8 +145,12 @@ enum ucl_character_type {

struct ucl_macro {
	char *name;
-
	ucl_macro_handler handler;
+
	union {
+
		ucl_macro_handler handler;
+
		ucl_context_macro_handler context_handler;
+
	} h;
	void* ud;
+
	bool is_context;
	UT_hash_handle hh;
};

@@ -191,8 +195,12 @@ struct ucl_parser {
	enum ucl_parser_state prev_state;
	unsigned int recursion;
	int flags;
+
	unsigned default_priority;
+
	int err_code;
	ucl_object_t *top_obj;
	ucl_object_t *cur_obj;
+
	ucl_object_t *trash_objs;
+
	ucl_object_t *includepaths;
	char *cur_file;
	struct ucl_macro *macroes;
	struct ucl_stack *stack;
@@ -220,13 +228,21 @@ size_t ucl_unescape_json_string (char *str, size_t len);
 * Handle include macro
 * @param data include data
 * @param len length of data
+
 * @param args UCL object representing arguments to the macro
 * @param ud user data
-
 * @param err error ptr
 * @return
 */
bool ucl_include_handler (const unsigned char *data, size_t len,
		const ucl_object_t *args, void* ud);

+
/**
+
 * Handle tryinclude macro
+
 * @param data include data
+
 * @param len length of data
+
 * @param args UCL object representing arguments to the macro
+
 * @param ud user data
+
 * @return
+
 */
bool ucl_try_include_handler (const unsigned char *data, size_t len,
		const ucl_object_t *args, void* ud);

@@ -234,17 +250,52 @@ bool ucl_try_include_handler (const unsigned char *data, size_t len,
 * Handle includes macro
 * @param data include data
 * @param len length of data
+
 * @param args UCL object representing arguments to the macro
 * @param ud user data
-
 * @param err error ptr
 * @return
 */
bool ucl_includes_handler (const unsigned char *data, size_t len,
		const ucl_object_t *args, void* ud);

+
/**
+
 * Handle priority macro
+
 * @param data include data
+
 * @param len length of data
+
 * @param args UCL object representing arguments to the macro
+
 * @param ud user data
+
 * @return
+
 */
+
bool ucl_priority_handler (const unsigned char *data, size_t len,
+
		const ucl_object_t *args, void* ud);
+

+
/**
+
 * Handle load macro
+
 * @param data include data
+
 * @param len length of data
+
 * @param args UCL object representing arguments to the macro
+
 * @param ud user data
+
 * @return
+
 */
+
bool ucl_load_handler (const unsigned char *data, size_t len,
+
		const ucl_object_t *args, void* ud);
+
/**
+
 * Handle inherit macro
+
 * @param data include data
+
 * @param len length of data
+
 * @param args UCL object representing arguments to the macro
+
 * @param ctx the current context object
+
 * @param ud user data
+
 * @return
+
 */
+
bool ucl_inherit_handler (const unsigned char *data, size_t len,
+
		const ucl_object_t *args, const ucl_object_t *ctx, void* ud);
+

size_t ucl_strlcpy (char *dst, const char *src, size_t siz);
size_t ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz);
size_t ucl_strlcpy_tolower (char *dst, const char *src, size_t siz);

+
char *ucl_strnstr (const char *s, const char *find, int len);
+
char *ucl_strncasestr (const char *s, const char *find, int len);

#ifdef __GNUC__
static inline void
@@ -311,7 +362,7 @@ ucl_maybe_parse_boolean (ucl_object_t *obj, const unsigned char *start, size_t l
		}
	}

-
	if (ret) {
+
	if (ret && obj != NULL) {
		obj->type = UCL_BOOLEAN;
		obj->value.iv = val;
	}
@@ -396,4 +447,64 @@ unsigned char * ucl_object_emit_single_json (const ucl_object_t *obj);
 */
bool ucl_maybe_long_string (const ucl_object_t *obj);

+
/**
+
 * Print integer to the msgpack output
+
 * @param ctx
+
 * @param val
+
 */
+
void ucl_emitter_print_int_msgpack (struct ucl_emitter_context *ctx,
+
		int64_t val);
+
/**
+
 * Print integer to the msgpack output
+
 * @param ctx
+
 * @param val
+
 */
+
void ucl_emitter_print_double_msgpack (struct ucl_emitter_context *ctx,
+
		double val);
+
/**
+
 * Print double to the msgpack output
+
 * @param ctx
+
 * @param val
+
 */
+
void ucl_emitter_print_bool_msgpack (struct ucl_emitter_context *ctx,
+
		bool val);
+
/**
+
 * Print string to the msgpack output
+
 * @param ctx
+
 * @param s
+
 * @param len
+
 */
+
void ucl_emitter_print_string_msgpack (struct ucl_emitter_context *ctx,
+
		const char *s, size_t len);
+

+
/**
+
 * Print array preamble for msgpack
+
 * @param ctx
+
 * @param len
+
 */
+
void ucl_emitter_print_array_msgpack (struct ucl_emitter_context *ctx,
+
		size_t len);
+

+
/**
+
 * Print object preamble for msgpack
+
 * @param ctx
+
 * @param len
+
 */
+
void ucl_emitter_print_object_msgpack (struct ucl_emitter_context *ctx,
+
		size_t len);
+
/**
+
 * Print NULL to the msgpack output
+
 * @param ctx
+
 */
+
void ucl_emitter_print_null_msgpack (struct ucl_emitter_context *ctx);
+
/**
+
 * Print object's key if needed to the msgpakc output
+
 * @param print_key
+
 * @param ctx
+
 * @param obj
+
 */
+
void ucl_emitter_print_key_msgpack (bool print_key,
+
		struct ucl_emitter_context *ctx,
+
		const ucl_object_t *obj);
+

#endif /* UCL_INTERNAL_H_ */
added external/libucl/src/ucl_msgpack.c
@@ -0,0 +1,319 @@
+
/*
+
 * Copyright (c) 2015, Vsevolod Stakhov
+
 * All rights reserved.
+
 *
+
 * Redistribution and use in source and binary forms, with or without
+
 * modification, are permitted provided that the following conditions are met:
+
 *	 * Redistributions of source code must retain the above copyright
+
 *	   notice, this list of conditions and the following disclaimer.
+
 *	 * Redistributions in binary form must reproduce the above copyright
+
 *	   notice, this list of conditions and the following disclaimer in the
+
 *	   documentation and/or other materials provided with the distribution.
+
 *
+
 * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
+
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+
 * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
+
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 */
+

+

+
#ifdef HAVE_CONFIG_H
+
#include "config.h"
+
#endif
+

+
#include "ucl.h"
+
#include "ucl_internal.h"
+

+
#ifdef HAVE_ENDIAN_H
+
#include <endian.h>
+
#elif defined(HAVE_SYS_ENDIAN_H)
+
#include <sys/endian.h>
+
#elif defined(HAVE_MACHINE_ENDIAN_H)
+
#include <machine/endian.h>
+
#endif
+

+
#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
+
	#if __BYTE_ORDER == __LITTLE_ENDIAN
+
		#define __LITTLE_ENDIAN__
+
	#elif __BYTE_ORDER == __BIG_ENDIAN
+
		#define __BIG_ENDIAN__
+
	#elif _WIN32
+
		#define __LITTLE_ENDIAN__
+
	#endif
+
#endif
+

+
#define SWAP_LE_BE16(val)	((uint16_t) ( 		\
+
		(uint16_t) ((uint16_t) (val) >> 8) |	\
+
		(uint16_t) ((uint16_t) (val) << 8)))
+

+
#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 4 && defined (__GNUC_MINOR__) && __GNUC_MINOR__ >= 3)
+
#	define SWAP_LE_BE32(val) ((uint32_t)__builtin_bswap32 ((uint32_t)(val)))
+
#	define SWAP_LE_BE64(val) ((uint64_t)__builtin_bswap64 ((uint64_t)(val)))
+
#else
+
	#define SWAP_LE_BE32(val)	((uint32_t)( \
+
		(((uint32_t)(val) & (uint32_t)0x000000ffU) << 24) | \
+
		(((uint32_t)(val) & (uint32_t)0x0000ff00U) <<  8) | \
+
		(((uint32_t)(val) & (uint32_t)0x00ff0000U) >>  8) | \
+
		(((uint32_t)(val) & (uint32_t)0xff000000U) >> 24)))
+

+
	#define SWAP_LE_BE64(val)	((uint64_t)( 			\
+
		  (((uint64_t)(val) &							\
+
		(uint64_t)(0x00000000000000ffULL)) << 56) |		\
+
		  (((uint64_t)(val) &							\
+
		(uint64_t)(0x000000000000ff00ULL)) << 40) |		\
+
		  (((uint64_t)(val) &							\
+
		(uint64_t)(0x0000000000ff0000ULL)) << 24) |		\
+
		  (((uint64_t)(val) &							\
+
		(uint64_t) (0x00000000ff000000ULL)) <<  8) |	\
+
		  (((uint64_t)(val) &							\
+
		(uint64_t)(0x000000ff00000000ULL)) >>  8) |		\
+
		  (((uint64_t)(val) &							\
+
		(uint64_t)(0x0000ff0000000000ULL)) >> 24) |		\
+
		  (((uint64_t)(val) &							\
+
		(uint64_t)(0x00ff000000000000ULL)) >> 40) |		\
+
		  (((uint64_t)(val) &							\
+
		(uint64_t)(0xff00000000000000ULL)) >> 56)))
+
#endif
+

+
#ifdef __LITTLE_ENDIAN__
+
#define TO_BE16 SWAP_LE_BE16
+
#define TO_BE32 SWAP_LE_BE32
+
#define TO_BE64 SWAP_LE_BE64
+
#else
+
#define TO_BE16(val) (uint16_t)(val)
+
#define TO_BE32(val) (uint32_t)(val)
+
#define TO_BE64(val) (uint64_t)(val)
+
#endif
+

+
void
+
ucl_emitter_print_int_msgpack (struct ucl_emitter_context *ctx, int64_t val)
+
{
+
	const struct ucl_emitter_functions *func = ctx->func;
+
	unsigned char buf[sizeof(uint64_t) + 1];
+
	const unsigned char mask_positive = 0x7f, mask_negative = 0xe0,
+
		uint8_ch = 0xcc, uint16_ch = 0xcd, uint32_ch = 0xce, uint64_ch = 0xcf,
+
		int8_ch = 0xd0, int16_ch = 0xd1, int32_ch = 0xd2, int64_ch = 0xd3;
+
	unsigned len;
+

+
	if (val >= 0) {
+
		if (val <= 0x7f) {
+
			/* Fixed num 7 bits */
+
			len = 1;
+
			buf[0] = mask_positive & val;
+
		}
+
		else if (val <= 0xff) {
+
			len = 2;
+
			buf[0] = uint8_ch;
+
			buf[1] = val & 0xff;
+
		}
+
		else if (val <= 0xffff) {
+
			uint16_t v = TO_BE16 (val);
+

+
			len = 3;
+
			buf[0] = uint16_ch;
+
			memcpy (&buf[1], &v, sizeof (v));
+
		}
+
		else if (val <= 0xffffffff) {
+
			uint32_t v = TO_BE32 (val);
+

+
			len = 5;
+
			buf[0] = uint32_ch;
+
			memcpy (&buf[1], &v, sizeof (v));
+
		}
+
		else {
+
			uint64_t v = TO_BE64 (val);
+

+
			len = 9;
+
			buf[0] = uint64_ch;
+
			memcpy (&buf[1], &v, sizeof (v));
+
		}
+
	}
+
	else {
+
		uint64_t uval;
+
		/* Bithack abs */
+
		uval = ((val ^ (val >> 63)) - (val >> 63));
+

+
		if (val >= -(1 << 5)) {
+
			len = 1;
+
			buf[0] = mask_negative | (uval & 0xff);
+
		}
+
		else if (uval <= 0xff) {
+
			len = 2;
+
			buf[0] = int8_ch;
+
			buf[1] = (unsigned char)val;
+
		}
+
		else if (uval <= 0xffff) {
+
			uint16_t v = TO_BE16 (val);
+

+
			len = 3;
+
			buf[0] = int16_ch;
+
			memcpy (&buf[1], &v, sizeof (v));
+
		}
+
		else if (uval <= 0xffffffff) {
+
			uint32_t v = TO_BE32 (val);
+

+
			len = 5;
+
			buf[0] = int32_ch;
+
			memcpy (&buf[1], &v, sizeof (v));
+
		}
+
		else {
+
			uint64_t v = TO_BE64 (val);
+

+
			len = 9;
+
			buf[0] = int64_ch;
+
			memcpy (&buf[1], &v, sizeof (v));
+
		}
+
	}
+

+
	func->ucl_emitter_append_len (buf, len, func->ud);
+
}
+

+
void
+
ucl_emitter_print_double_msgpack (struct ucl_emitter_context *ctx, double val)
+
{
+
	const struct ucl_emitter_functions *func = ctx->func;
+
	union {
+
		double d;
+
		uint64_t i;
+
	} u;
+
	const unsigned char dbl_ch = 0xcb;
+
	unsigned char buf[sizeof(double) + 1];
+

+
	/* Convert to big endian */
+
	u.d = val;
+
	u.i = TO_BE64 (u.i);
+

+
	buf[0] = dbl_ch;
+
	memcpy (&buf[1], &u.d, sizeof (double));
+
	func->ucl_emitter_append_len (buf, sizeof (buf), func->ud);
+
}
+

+
void
+
ucl_emitter_print_bool_msgpack (struct ucl_emitter_context *ctx, bool val)
+
{
+
	const struct ucl_emitter_functions *func = ctx->func;
+
	const unsigned char true_ch = 0xc3, false_ch = 0xc2;
+

+
	func->ucl_emitter_append_character (val ? true_ch : false_ch, 1, func->ud);
+
}
+

+
void
+
ucl_emitter_print_string_msgpack (struct ucl_emitter_context *ctx,
+
		const char *s, size_t len)
+
{
+
	const struct ucl_emitter_functions *func = ctx->func;
+
	const unsigned char fix_mask = 0xA0, l8_ch = 0xd9, l16_ch = 0xda, l32_ch = 0xdb;
+
	unsigned char buf[5];
+
	unsigned blen;
+

+
	if (len <= 0x1F) {
+
		blen = 1;
+
		buf[0] = (len | fix_mask) & 0xff;
+
	}
+
	else if (len <= 0xff) {
+
		blen = 2;
+
		buf[0] = l8_ch;
+
		buf[1] = len & 0xff;
+
	}
+
	else if (len <= 0xffff) {
+
		uint16_t bl = TO_BE16 (len);
+

+
		blen = 3;
+
		buf[0] = l16_ch;
+
		memcpy (&buf[1], &bl, sizeof (bl));
+
	}
+
	else {
+
		uint32_t bl = TO_BE32 (len);
+

+
		blen = 5;
+
		buf[0] = l32_ch;
+
		memcpy (&buf[1], &bl, sizeof (bl));
+
	}
+

+
	func->ucl_emitter_append_len (buf, blen, func->ud);
+
	func->ucl_emitter_append_len (s, len, func->ud);
+
}
+

+
void
+
ucl_emitter_print_null_msgpack (struct ucl_emitter_context *ctx)
+
{
+
	const struct ucl_emitter_functions *func = ctx->func;
+
	const unsigned char nil = 0xc0;
+

+
	func->ucl_emitter_append_character (nil, 1, func->ud);
+
}
+

+
void
+
ucl_emitter_print_key_msgpack (bool print_key, struct ucl_emitter_context *ctx,
+
		const ucl_object_t *obj)
+
{
+
	if (print_key) {
+
		ucl_emitter_print_string_msgpack (ctx, obj->key, obj->keylen);
+
	}
+
}
+

+
void
+
ucl_emitter_print_array_msgpack (struct ucl_emitter_context *ctx, size_t len)
+
{
+
	const struct ucl_emitter_functions *func = ctx->func;
+
	const unsigned char fix_mask = 0x90, l16_ch = 0xdc, l32_ch = 0xdd;
+
	unsigned char buf[5];
+
	unsigned blen;
+

+
	if (len <= 0xF) {
+
		blen = 1;
+
		buf[0] = (len | fix_mask) & 0xff;
+
	}
+
	else if (len <= 0xffff) {
+
		uint16_t bl = TO_BE16 (len);
+

+
		blen = 3;
+
		buf[0] = l16_ch;
+
		memcpy (&buf[1], &bl, sizeof (bl));
+
	}
+
	else {
+
		uint32_t bl = TO_BE32 (len);
+

+
		blen = 5;
+
		buf[0] = l32_ch;
+
		memcpy (&buf[1], &bl, sizeof (bl));
+
	}
+

+
	func->ucl_emitter_append_len (buf, blen, func->ud);
+
}
+

+
void
+
ucl_emitter_print_object_msgpack (struct ucl_emitter_context *ctx, size_t len)
+
{
+
	const struct ucl_emitter_functions *func = ctx->func;
+
	const unsigned char fix_mask = 0x80, l16_ch = 0xde, l32_ch = 0xdf;
+
	unsigned char buf[5];
+
	unsigned blen;
+

+
	if (len <= 0xF) {
+
		blen = 1;
+
		buf[0] = (len | fix_mask) & 0xff;
+
	}
+
	else if (len <= 0xffff) {
+
		uint16_t bl = TO_BE16 (len);
+

+
		blen = 3;
+
		buf[0] = l16_ch;
+
		memcpy (&buf[1], &bl, sizeof (bl));
+
	}
+
	else {
+
		uint32_t bl = TO_BE32 (len);
+

+
		blen = 5;
+
		buf[0] = l32_ch;
+
		memcpy (&buf[1], &bl, sizeof (bl));
+
	}
+

+
	func->ucl_emitter_append_len (buf, blen, func->ud);
+
}
modified external/libucl/src/ucl_parser.c
@@ -67,6 +67,7 @@ ucl_set_err (struct ucl_parser *parser, int code, const char *str, UT_string **e
	else {
		filename = "<unknown>";
	}
+

	if (chunk->pos < chunk->end) {
		if (isgraph (*chunk->pos)) {
			fmt_string = "error while parsing %s: "
@@ -84,6 +85,8 @@ ucl_set_err (struct ucl_parser *parser, int code, const char *str, UT_string **e
		ucl_create_err (err, "error while parsing %s: at the end of chunk: %s",
			filename, str);
	}
+

+
	parser->err_code = code;
}

/**
@@ -513,7 +516,7 @@ ucl_copy_or_store_ptr (struct ucl_parser *parser,
		/* Copy string */
		*dst = UCL_ALLOC (in_len + 1);
		if (*dst == NULL) {
-
			ucl_set_err (parser, 0, "cannot allocate memory for a string",
+
			ucl_set_err (parser, UCL_EINTERNAL, "cannot allocate memory for a string",
					&parser->err);
			return false;
		}
@@ -585,7 +588,7 @@ 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, 0, "cannot allocate memory for an object",
+
		ucl_set_err (parser, UCL_EINTERNAL, "cannot allocate memory for an object",
				&parser->err);
		ucl_object_unref (obj);
		return NULL;
@@ -834,19 +837,21 @@ ucl_maybe_parse_number (ucl_object_t *obj,
	*pos = c;
	return EINVAL;

-
	set_obj:
-
	if (allow_double && (need_double || is_time)) {
-
		if (!is_time) {
-
			obj->type = UCL_FLOAT;
+
set_obj:
+
	if (obj != NULL) {
+
		if (allow_double && (need_double || is_time)) {
+
			if (!is_time) {
+
				obj->type = UCL_FLOAT;
+
			}
+
			else {
+
				obj->type = UCL_TIME;
+
			}
+
			obj->value.dv = is_neg ? (-dv) : dv;
		}
		else {
-
			obj->type = UCL_TIME;
+
			obj->type = UCL_INT;
+
			obj->value.iv = is_neg ? (-lv) : lv;
		}
-
		obj->value.dv = is_neg ? (-dv) : dv;
-
	}
-
	else {
-
		obj->type = UCL_INT;
-
		obj->value.iv = is_neg ? (-lv) : lv;
	}
	*pos = p;
	return 0;
@@ -856,6 +861,7 @@ ucl_maybe_parse_number (ucl_object_t *obj,
 * Parse possible number
 * @param parser
 * @param chunk
+
 * @param obj
 * @return true if a number has been parsed
 */
static bool
@@ -875,7 +881,8 @@ ucl_lex_number (struct ucl_parser *parser,
		return true;
	}
	else if (ret == ERANGE) {
-
		ucl_set_err (parser, ERANGE, "numeric value out of range", &parser->err);
+
		ucl_set_err (parser, UCL_ESYNTAX, "numeric value out of range",
+
				&parser->err);
	}

	return false;
@@ -885,6 +892,9 @@ ucl_lex_number (struct ucl_parser *parser,
 * Parse quoted string with possible escapes
 * @param parser
 * @param chunk
+
 * @param need_unescape
+
 * @param ucl_escape
+
 * @param var_expand
 * @return true if a string has been parsed
 */
static bool
@@ -971,6 +981,7 @@ ucl_parser_append_elt (struct ucl_parser *parser, ucl_hash_t *cont,
		/* Implicit array */
		top->flags |= UCL_OBJECT_MULTIVALUE;
		DL_APPEND (top, elt);
+
		parser->stack->obj->len ++;
	}
	else {
		if ((top->flags & UCL_OBJECT_MULTIVALUE) != 0) {
@@ -979,14 +990,13 @@ ucl_parser_append_elt (struct ucl_parser *parser, ucl_hash_t *cont,
		}
		else {
			/* Convert to an array */
-
			ucl_hash_delete (cont, top);
			nobj = ucl_object_typed_new (UCL_ARRAY);
			nobj->key = top->key;
			nobj->keylen = top->keylen;
			nobj->flags |= UCL_OBJECT_MULTIVALUE;
			ucl_array_append (nobj, top);
			ucl_array_append (nobj, elt);
-
			ucl_hash_insert (cont, nobj, nobj->key, nobj->keylen);
+
			ucl_hash_replace (cont, top, nobj);
		}
	}
}
@@ -995,10 +1005,13 @@ ucl_parser_append_elt (struct ucl_parser *parser, ucl_hash_t *cont,
 * Parse a key in an object
 * @param parser
 * @param chunk
+
 * @param next_key
+
 * @param end_of_object
 * @return true if a key has been parsed
 */
static bool
-
ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_key, bool *end_of_object)
+
ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk,
+
		bool *next_key, bool *end_of_object)
{
	const unsigned char *p, *c = NULL, *end, *t;
	const char *key = NULL;
@@ -1016,6 +1029,7 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
		ucl_chunk_skipc (chunk, p);
		parser->prev_state = parser->state;
		parser->state = UCL_STATE_MACRO_NAME;
+
		*end_of_object = false;
		return true;
	}
	while (p < chunk->end) {
@@ -1212,12 +1226,22 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
		 */
		unsigned priold = ucl_object_get_priority (tobj),
				prinew = ucl_object_get_priority (nobj);
+

+
		/* Special case for inherited objects */
+
		if (tobj->flags & UCL_OBJECT_INHERITED) {
+
			prinew = priold + 1;
+
		}
+

		if (priold == prinew) {
			ucl_parser_append_elt (parser, container, tobj, nobj);
		}
		else if (priold > prinew) {
-
			ucl_object_unref (nobj);
-
			return true;
+
			/*
+
			 * We add this new object to a list of trash objects just to ensure
+
			 * that it won't come to any real object
+
			 * XXX: rather inefficient approach
+
			 */
+
			DL_APPEND (parser->trash_objs, nobj);
		}
		else {
			ucl_hash_replace (container, tobj, nobj);
@@ -1228,8 +1252,8 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
	if (ucl_escape) {
		nobj->flags |= UCL_OBJECT_NEED_KEY_ESCAPE;
	}
-
	parser->stack->obj->value.ov = container;

+
	parser->stack->obj->value.ov = container;
	parser->cur_obj = nobj;

	return true;
@@ -1239,6 +1263,8 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
 * Parse a cl string
 * @param parser
 * @param chunk
+
 * @param var_expand
+
 * @param need_unescape
 * @return true if a key has been parsed
 */
static bool
@@ -1308,6 +1334,8 @@ ucl_parse_string_value (struct ucl_parser *parser,
 * @param chunk
 * @param term
 * @param term_len
+
 * @param beg
+
 * @param var_expand
 * @return size of multiline string or 0 in case of error
 */
static int
@@ -1416,20 +1444,27 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
		c = p;
		switch (*p) {
		case '"':
-
			obj = ucl_get_value_object (parser);
			ucl_chunk_skipc (chunk, p);
-
			if (!ucl_lex_json_string (parser, chunk, &need_unescape, &ucl_escape, &var_expand)) {
+

+
			if (!ucl_lex_json_string (parser, chunk, &need_unescape, &ucl_escape,
+
					&var_expand)) {
				return false;
			}
+

+
			obj = ucl_get_value_object (parser);
			str_len = chunk->pos - c - 2;
			obj->type = UCL_STRING;
-
			if ((str_len = ucl_copy_or_store_ptr (parser, c + 1, &obj->trash_stack[UCL_TRASH_VALUE],
-
					&obj->value.sv, str_len, need_unescape, false, var_expand)) == -1) {
+
			if ((str_len = ucl_copy_or_store_ptr (parser, c + 1,
+
					&obj->trash_stack[UCL_TRASH_VALUE],
+
					&obj->value.sv, str_len, need_unescape, false,
+
					var_expand)) == -1) {
				return false;
			}
			obj->len = str_len;
+

			parser->state = UCL_STATE_AFTER_VALUE;
			p = chunk->pos;
+

			return true;
			break;
		case '{':
@@ -1441,6 +1476,7 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
			}

			ucl_chunk_skipc (chunk, p);
+

			return true;
			break;
		case '[':
@@ -1452,6 +1488,7 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
			}

			ucl_chunk_skipc (chunk, p);
+

			return true;
			break;
		case ']':
@@ -1487,13 +1524,19 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
									"unterminated multiline value", &parser->err);
							return false;
						}
+

						obj->type = UCL_STRING;
-
						if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE],
-
							&obj->value.sv, str_len - 1, false, false, var_expand)) == -1) {
+
						obj->flags |= UCL_OBJECT_MULTILINE;
+
						if ((str_len = ucl_copy_or_store_ptr (parser, c,
+
								&obj->trash_stack[UCL_TRASH_VALUE],
+
								&obj->value.sv, str_len - 1, false,
+
								false, var_expand)) == -1) {
							return false;
						}
						obj->len = str_len;
+

						parser->state = UCL_STATE_AFTER_VALUE;
+

						return true;
					}
				}
@@ -1504,6 +1547,7 @@ parse_string:
			if (obj == NULL) {
				obj = ucl_get_value_object (parser);
			}
+

			/* Parse atom */
			if (ucl_test_character (*p, UCL_CHARACTER_VALUE_DIGIT_START)) {
				if (!ucl_lex_number (parser, chunk, obj)) {
@@ -1518,7 +1562,8 @@ parse_string:
				/* Fallback to normal string */
			}

-
			if (!ucl_parse_string_value (parser, chunk, &var_expand, &need_unescape)) {
+
			if (!ucl_parse_string_value (parser, chunk, &var_expand,
+
					&need_unescape)) {
				return false;
			}
			/* Cut trailing spaces */
@@ -1529,7 +1574,7 @@ parse_string:
			}
			str_len = chunk->pos - c - stripped_spaces;
			if (str_len <= 0) {
-
				ucl_set_err (parser, 0, "string value must not be empty",
+
				ucl_set_err (parser, UCL_ESYNTAX, "string value must not be empty",
						&parser->err);
				return false;
			}
@@ -1539,7 +1584,8 @@ parse_string:
			}
			else if (!ucl_maybe_parse_boolean (obj, c, str_len)) {
				obj->type = UCL_STRING;
-
				if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE],
+
				if ((str_len = ucl_copy_or_store_ptr (parser, c,
+
						&obj->trash_stack[UCL_TRASH_VALUE],
						&obj->value.sv, str_len, need_unescape,
						false, var_expand)) == -1) {
					return false;
@@ -1651,6 +1697,9 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
 * Handle macro data
 * @param parser
 * @param chunk
+
 * @param marco
+
 * @param macro_start
+
 * @param macro_len
 * @return
 */
static bool
@@ -1789,6 +1838,7 @@ ucl_parse_macro_arguments (struct ucl_parser *parser,
			if (chunk->remain == 0) {
				goto restore_chunk;
			}
+
			args_len ++;
			ucl_chunk_skipc (chunk, p);
			break;
		case 99:
@@ -1841,8 +1891,6 @@ restore_chunk:
/**
 * Handle the main states of rcl parser
 * @param parser parser structure
-
 * @param data the pointer to the beginning of a chunk
-
 * @param len the length of a chunk
 * @return true if chunk has been parsed and false in case of error
 */
static bool
@@ -1966,6 +2014,7 @@ ucl_state_machine (struct ucl_parser *parser)
				parser->state = UCL_STATE_ERROR;
				return false;
			}
+

			if (parser->stack != NULL) {
				if (parser->stack->obj->type == UCL_OBJECT) {
					parser->state = UCL_STATE_KEY;
@@ -2023,14 +2072,36 @@ ucl_state_machine (struct ucl_parser *parser)
					macro_start, macro_len);
			parser->state = parser->prev_state;
			if (macro_escaped == NULL) {
-
				ret = macro->handler (macro_start, macro_len, macro_args,
-
						macro->ud);
+
				if (macro->is_context) {
+
					ret = macro->h.context_handler (macro_start, macro_len,
+
							macro_args,
+
							parser->top_obj,
+
							macro->ud);
+
				}
+
				else {
+
					ret = macro->h.handler (macro_start, macro_len, macro_args,
+
							macro->ud);
+
				}
			}
			else {
-
				ret = macro->handler (macro_escaped, macro_len, macro_args,
+
				if (macro->is_context) {
+
					ret = macro->h.context_handler (macro_escaped, macro_len,
+
							macro_args,
+
							parser->top_obj,
+
							macro->ud);
+
				}
+
				else {
+
					ret = macro->h.handler (macro_escaped, macro_len, macro_args,
						macro->ud);
+
				}
+

				UCL_FREE (macro_len + 1, macro_escaped);
			}
+

+
			/*
+
			 * Chunk can be modified within macro handler
+
			 */
+
			chunk = parser->chunks;
			p = chunk->pos;
			if (macro_args) {
				ucl_object_unref (macro_args);
@@ -2060,13 +2131,18 @@ ucl_parser_new (int flags)
	if (new == NULL) {
		return NULL;
	}
+

	memset (new, 0, sizeof (struct ucl_parser));

	ucl_parser_register_macro (new, "include", ucl_include_handler, new);
	ucl_parser_register_macro (new, "try_include", ucl_try_include_handler, new);
	ucl_parser_register_macro (new, "includes", ucl_includes_handler, new);
+
	ucl_parser_register_macro (new, "priority", ucl_priority_handler, new);
+
	ucl_parser_register_macro (new, "load", ucl_load_handler, new);
+
	ucl_parser_register_context_macro (new, "inherit", ucl_inherit_handler, new);

	new->flags = flags;
+
	new->includepaths = NULL;

	/* Initial assumption about filevars */
	ucl_parser_set_filevars (new, NULL, false);
@@ -2074,6 +2150,17 @@ ucl_parser_new (int flags)
	return new;
}

+
bool
+
ucl_parser_set_default_priority (struct ucl_parser *parser, unsigned prio)
+
{
+
	if (parser == NULL) {
+
		return false;
+
	}
+

+
	parser->default_priority = prio;
+

+
	return true;
+
}

void
ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
@@ -2084,14 +2171,39 @@ ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
	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->h.handler = handler;
+
	new->name = strdup (macro);
+
	new->ud = ud;
+
	HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new);
+
}
+

+
void
+
ucl_parser_register_context_macro (struct ucl_parser *parser, const char *macro,
+
		ucl_context_macro_handler handler, void* ud)
+
{
+
	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->h.context_handler = handler;
	new->name = strdup (macro);
	new->ud = ud;
+
	new->is_context = true;
	HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new);
}

@@ -2163,6 +2275,10 @@ ucl_parser_add_chunk_priority (struct ucl_parser *parser, const unsigned char *d
{
	struct ucl_chunk *chunk;

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

	if (data == NULL) {
		ucl_create_err (&parser->err, "invalid chunk added");
		return false;
@@ -2203,12 +2319,17 @@ bool
ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data,
		size_t len)
{
-
	return ucl_parser_add_chunk_priority (parser, data, len, 0);
+
	if (parser == NULL) {
+
		return false;
+
	}
+

+
	return ucl_parser_add_chunk_priority (parser, data, len,
+
			parser->default_priority);
}

bool
-
ucl_parser_add_string (struct ucl_parser *parser, const char *data,
-
		size_t len)
+
ucl_parser_add_string_priority (struct ucl_parser *parser, const char *data,
+
		size_t len, unsigned priority)
{
	if (data == NULL) {
		ucl_create_err (&parser->err, "invalid string added");
@@ -2218,5 +2339,40 @@ ucl_parser_add_string (struct ucl_parser *parser, const char *data,
		len = strlen (data);
	}

-
	return ucl_parser_add_chunk (parser, (const unsigned char *)data, len);
+
	return ucl_parser_add_chunk_priority (parser,
+
			(const unsigned char *)data, len, priority);
+
}
+

+
bool
+
ucl_parser_add_string (struct ucl_parser *parser, const char *data,
+
		size_t len)
+
{
+
	if (parser == NULL) {
+
		return false;
+
	}
+

+
	return ucl_parser_add_string_priority (parser,
+
			(const unsigned char *)data, len, parser->default_priority);
+
}
+

+
bool
+
ucl_set_include_path (struct ucl_parser *parser, ucl_object_t *paths)
+
{
+
	if (parser == NULL || paths == NULL) {
+
		return false;
+
	}
+

+
	if (parser->includepaths == NULL) {
+
		parser->includepaths = ucl_object_copy (paths);
+
	}
+
	else {
+
		ucl_object_unref (parser->includepaths);
+
		parser->includepaths = ucl_object_copy (paths);
+
	}
+

+
	if (parser->includepaths == NULL) {
+
		return false;
+
	}
+

+
	return true;
}
modified external/libucl/src/ucl_util.c
@@ -1,4 +1,5 @@
/* Copyright (c) 2013, Vsevolod Stakhov
+
 * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
@@ -25,6 +26,7 @@
#include "ucl_internal.h"
#include "ucl_chartable.h"
#include "kvec.h"
+
#include <stdarg.h>

#ifndef _WIN32
#include <glob.h>
@@ -230,11 +232,13 @@ ucl_object_free_internal (ucl_object_t *obj, bool allow_rec, ucl_object_dtor dto
				kv_destroy (*vec);
				UCL_FREE (sizeof (*vec), vec);
			}
+
			obj->value.av = NULL;
		}
		else if (obj->type == UCL_OBJECT) {
			if (obj->value.ov != NULL) {
				ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)dtor);
			}
+
			obj->value.ov = NULL;
		}
		tmp = obj->next;
		dtor (obj);
@@ -266,6 +270,17 @@ ucl_unescape_json_string (char *str, size_t len)
	while (len) {
		if (*h == '\\') {
			h ++;
+

+
			if (len == 1) {
+
				/*
+
				 * If \ is last, then do not try to go further
+
				 * Issue: #74
+
				 */
+
				len --;
+
				*t++ = '\\';
+
				continue;
+
			}
+

			switch (*h) {
			case 'n':
				*t++ = '\n';
@@ -350,7 +365,10 @@ ucl_unescape_json_string (char *str, size_t len)
		else {
			*t++ = *h++;
		}
-
		len --;
+

+
		if (len > 0) {
+
			len --;
+
		}
	}
	*t = '\0';

@@ -409,7 +427,7 @@ ucl_copy_value_trash (const ucl_object_t *obj)
	return obj->trash_stack[UCL_TRASH_VALUE];
}

-
UCL_EXTERN ucl_object_t*
+
ucl_object_t*
ucl_parser_get_object (struct ucl_parser *parser)
{
	if (parser->state != UCL_STATE_ERROR && parser->top_obj != NULL) {
@@ -419,7 +437,7 @@ ucl_parser_get_object (struct ucl_parser *parser)
	return NULL;
}

-
UCL_EXTERN void
+
void
ucl_parser_free (struct ucl_parser *parser)
{
	struct ucl_stack *stack, *stmp;
@@ -427,6 +445,7 @@ ucl_parser_free (struct ucl_parser *parser)
	struct ucl_chunk *chunk, *ctmp;
	struct ucl_pubkey *key, *ktmp;
	struct ucl_variable *var, *vtmp;
+
	ucl_object_t *tr, *trtmp;

	if (parser == NULL) {
		return;
@@ -436,6 +455,10 @@ ucl_parser_free (struct ucl_parser *parser)
		ucl_object_unref (parser->top_obj);
	}

+
	if (parser->includepaths != NULL) {
+
		ucl_object_unref (parser->includepaths);
+
	}
+

	LL_FOREACH_SAFE (parser->stack, stack, stmp) {
		free (stack);
	}
@@ -455,6 +478,9 @@ ucl_parser_free (struct ucl_parser *parser)
		free (var->var);
		UCL_FREE (sizeof (struct ucl_variable), var);
	}
+
	LL_FOREACH_SAFE (parser->trash_objs, tr, trtmp) {
+
		ucl_object_free_internal (tr, false, ucl_object_dtor_free);
+
	}

	if (parser->err != NULL) {
		utstring_free (parser->err);
@@ -467,29 +493,61 @@ ucl_parser_free (struct ucl_parser *parser)
	UCL_FREE (sizeof (struct ucl_parser), parser);
}

-
UCL_EXTERN const char *
+
const char *
ucl_parser_get_error(struct ucl_parser *parser)
{
	if (parser == NULL) {
		return NULL;
	}

-
	if (parser->err == NULL)
+
	if (parser->err == NULL) {
		return NULL;
+
	}
+

+
	return utstring_body (parser->err);
+
}
+

+
int
+
ucl_parser_get_error_code(struct ucl_parser *parser)
+
{
+
	if (parser == NULL) {
+
		return 0;
+
	}

-
	return utstring_body(parser->err);
+
	return parser->err_code;
}

-
UCL_EXTERN void
+
unsigned
+
ucl_parser_get_column(struct ucl_parser *parser)
+
{
+
	if (parser == NULL || parser->chunks == NULL) {
+
		return 0;
+
	}
+

+
	return parser->chunks->column;
+
}
+

+
unsigned
+
ucl_parser_get_linenum(struct ucl_parser *parser)
+
{
+
	if (parser == NULL || parser->chunks == NULL) {
+
		return 0;
+
	}
+

+
	return parser->chunks->line;
+
}
+

+
void
ucl_parser_clear_error(struct ucl_parser *parser)
{
	if (parser != NULL && parser->err != NULL) {
		utstring_free(parser->err);
		parser->err = NULL;
+
		parser->err_code = 0;
	}
}

-
UCL_EXTERN bool
+
bool
ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)
{
#ifndef HAVE_OPENSSL
@@ -749,7 +807,7 @@ ucl_sig_check (const unsigned char *data, size_t datalen,
static bool
ucl_include_url (const unsigned char *data, size_t len,
		struct ucl_parser *parser, bool check_signature, bool must_exist,
-
		unsigned priority)
+
		bool use_prefix, const char *prefix, const char *target, unsigned priority)
{

	bool res;
@@ -822,20 +880,27 @@ ucl_include_url (const unsigned char *data, size_t len,
static bool
ucl_include_file_single (const unsigned char *data, size_t len,
		struct ucl_parser *parser, bool check_signature, bool must_exist,
-
		unsigned priority)
+
		bool use_prefix, const char *prefix, const char *target,
+
		bool soft_fail, unsigned priority)
{
	bool res;
	struct ucl_chunk *chunk;
	unsigned char *buf = NULL;
-
	char *old_curfile;
-
	size_t buflen;
+
	char *old_curfile, *ext;
+
	size_t buflen = 0;
	char filebuf[PATH_MAX], realbuf[PATH_MAX];
	int prev_state;
	struct ucl_variable *cur_var, *tmp_var, *old_curdir = NULL,
			*old_filename = NULL;
+
	ucl_object_t *nest_obj = NULL, *old_obj = NULL, *new_obj = NULL;
+
	ucl_hash_t *container = NULL;
+
	struct ucl_stack *st = NULL;

	snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
	if (ucl_realpath (filebuf, realbuf) == NULL) {
+
		if (soft_fail) {
+
			return false;
+
		}
		if (!must_exist) {
			return true;
		}
@@ -847,12 +912,18 @@ ucl_include_file_single (const unsigned char *data, size_t len,

	if (parser->cur_file && strcmp (realbuf, parser->cur_file) == 0) {
		/* We are likely including the file itself */
+
		if (soft_fail) {
+
			return false;
+
		}
		ucl_create_err (&parser->err, "trying to include the file %s from itself",
				realbuf);
		return false;
	}

	if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err, must_exist)) {
+
		if (soft_fail) {
+
			return false;
+
		}
		return (!must_exist || false);
	}

@@ -900,6 +971,111 @@ ucl_include_file_single (const unsigned char *data, size_t len,
	prev_state = parser->state;
	parser->state = UCL_STATE_INIT;

+
	if (use_prefix && prefix == NULL) {
+
		/* Auto generate a key name based on the included filename */
+
		prefix = basename (realbuf);
+
		ext = strrchr(prefix, '.');
+
		if (ext != NULL && (strcmp (ext, ".conf") == 0 || strcmp (ext, ".ucl") == 0)) {
+
			/* Strip off .conf or .ucl */
+
			*ext = '\0';
+
		}
+
	}
+
	if (prefix != NULL) {
+
		/* This is a prefixed include */
+
		container = parser->stack->obj->value.ov;
+

+
		old_obj = __DECONST (ucl_object_t *, ucl_hash_search (container, prefix, strlen (prefix)));
+

+
		if (strcasecmp (target, "array") == 0 && old_obj == NULL) {
+
			/* Create an array with key: prefix */
+
			old_obj = ucl_object_new_full (UCL_ARRAY, priority);
+
			old_obj->key = prefix;
+
			old_obj->keylen = strlen (prefix);
+
			ucl_copy_key_trash(old_obj);
+
			old_obj->prev = old_obj;
+
			old_obj->next = NULL;
+

+
			container = ucl_hash_insert_object (container, old_obj,
+
					parser->flags & UCL_PARSER_KEY_LOWERCASE);
+
			parser->stack->obj->len ++;
+

+
			nest_obj = ucl_object_new_full (UCL_OBJECT, priority);
+
			nest_obj->prev = nest_obj;
+
			nest_obj->next = NULL;
+

+
			ucl_array_append (old_obj, nest_obj);
+
		}
+
		else if (old_obj == NULL) {
+
			/* Create an object with key: prefix */
+
			nest_obj = ucl_object_new_full (UCL_OBJECT, priority);
+
			nest_obj->key = prefix;
+
			nest_obj->keylen = strlen (prefix);
+
			ucl_copy_key_trash(nest_obj);
+
			nest_obj->prev = nest_obj;
+
			nest_obj->next = NULL;
+

+
			container = ucl_hash_insert_object (container, nest_obj,
+
					parser->flags & UCL_PARSER_KEY_LOWERCASE);
+
			parser->stack->obj->len ++;
+
		}
+
		else if (strcasecmp (target, "array") == 0 || ucl_object_type(old_obj) == UCL_ARRAY) {
+
			if (ucl_object_type(old_obj) == UCL_ARRAY) {
+
				/* Append to the existing array */
+
				nest_obj = ucl_object_new_full (UCL_OBJECT, priority);
+
				nest_obj->prev = nest_obj;
+
				nest_obj->next = NULL;
+

+
				ucl_array_append (old_obj, nest_obj);
+
			}
+
			else {
+
				/* Convert the object to an array */
+
				new_obj = ucl_object_typed_new (UCL_ARRAY);
+
				new_obj->key = old_obj->key;
+
				new_obj->keylen = old_obj->keylen;
+
				new_obj->flags |= UCL_OBJECT_MULTIVALUE;
+
				new_obj->prev = new_obj;
+
				new_obj->next = NULL;
+

+
				nest_obj = ucl_object_new_full (UCL_OBJECT, priority);
+
				nest_obj->prev = nest_obj;
+
				nest_obj->next = NULL;
+

+
				ucl_array_append (new_obj, old_obj);
+
				ucl_array_append (new_obj, nest_obj);
+
				ucl_hash_replace (container, old_obj, new_obj);
+
			}
+
		}
+
		else {
+
			if (ucl_object_type (old_obj) == UCL_OBJECT) {
+
				/* Append to existing Object*/
+
				nest_obj = old_obj;
+
			}
+
			else {
+
				/* The key is not an object */
+
				ucl_create_err (&parser->err,
+
						"Conflicting type for key: %s",
+
						prefix);
+
				return false;
+
			}
+
		}
+

+
		 /* Put all of the content of the include inside that object */
+
		parser->stack->obj->value.ov = container;
+

+
		if (nest_obj != NULL) {
+
			st = UCL_ALLOC (sizeof (struct ucl_stack));
+
			if (st == NULL) {
+
				ucl_create_err (&parser->err, "cannot allocate memory for an object");
+
				ucl_object_unref (nest_obj);
+
				return NULL;
+
			}
+
			st->obj = nest_obj;
+
			st->level = parser->stack->level;
+
			LL_PREPEND (parser->stack, st);
+
			parser->cur_obj = nest_obj;
+
		}
+
	}
+

	res = ucl_parser_add_chunk_priority (parser, buf, buflen, priority);
	if (!res && !must_exist) {
		/* Free error */
@@ -908,6 +1084,12 @@ ucl_include_file_single (const unsigned char *data, size_t len,
		parser->state = UCL_STATE_AFTER_VALUE;
	}

+
	/* Stop nesting the include, take 1 level off the stack */
+
	if (prefix != NULL && nest_obj != NULL) {
+
		parser->stack = st->next;
+
		UCL_FREE (sizeof (struct ucl_stack), st);
+
	}
+

	/* Remove chunk from the stack */
	chunk = parser->chunks;
	if (chunk != NULL) {
@@ -917,6 +1099,10 @@ ucl_include_file_single (const unsigned char *data, size_t len,
	}

	/* Restore old file vars */
+
	if (parser->cur_file) {
+
		free (parser->cur_file);
+
	}
+

	parser->cur_file = old_curfile;
	DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) {
		if (strcmp (cur_var->var, "CURDIR") == 0 && old_curdir) {
@@ -938,9 +1124,6 @@ ucl_include_file_single (const unsigned char *data, size_t len,
	if (old_curdir) {
		DL_APPEND (parser->variables, old_curdir);
	}
-
	if (old_curfile) {
-
		free (old_curfile);
-
	}

	parser->state = prev_state;

@@ -962,7 +1145,8 @@ ucl_include_file_single (const unsigned char *data, size_t len,
static bool
ucl_include_file (const unsigned char *data, size_t len,
		struct ucl_parser *parser, bool check_signature, bool must_exist,
-
		bool allow_glob, unsigned priority)
+
		bool allow_glob, bool use_prefix, const char *prefix,
+
		const char *target, bool soft_fail, unsigned priority)
{
	const unsigned char *p = data, *end = data + len;
	bool need_glob = false;
@@ -973,7 +1157,7 @@ ucl_include_file (const unsigned char *data, size_t len,
#ifndef _WIN32
	if (!allow_glob) {
		return ucl_include_file_single (data, len, parser, check_signature,
-
			must_exist, priority);
+
			must_exist, use_prefix, prefix, target, soft_fail, priority);
	}
	else {
		/* Check for special symbols in a filename */
@@ -987,14 +1171,18 @@ ucl_include_file (const unsigned char *data, size_t len,
		if (need_glob) {
			glob_t globbuf;
			memset (&globbuf, 0, sizeof (globbuf));
-
			ucl_strlcpy (glob_pattern, (const char *)data, sizeof (glob_pattern));
+
			ucl_strlcpy (glob_pattern, (const char *)data,
+
				(len + 1 < sizeof (glob_pattern) ? len + 1 : sizeof (glob_pattern)));
			if (glob (glob_pattern, 0, NULL, &globbuf) != 0) {
				return (!must_exist || false);
			}
			for (i = 0; i < globbuf.gl_pathc; i ++) {
				if (!ucl_include_file_single ((unsigned char *)globbuf.gl_pathv[i],
						strlen (globbuf.gl_pathv[i]), parser, check_signature,
-
						must_exist, priority)) {
+
						must_exist, use_prefix, prefix, target, soft_fail, priority)) {
+
					if (soft_fail) {
+
						continue;
+
					}
					globfree (&globbuf);
					return false;
				}
@@ -1010,14 +1198,14 @@ ucl_include_file (const unsigned char *data, size_t len,
		}
		else {
			return ucl_include_file_single (data, len, parser, check_signature,
-
				must_exist, priority);
+
				must_exist, use_prefix, prefix, target, soft_fail, priority);
		}
	}
#else
	/* Win32 compilers do not support globbing. Therefore, for Win32,
	   treat allow_glob/need_glob as a NOOP and just return */
	return ucl_include_file_single (data, len, parser, check_signature,
-
		must_exist, priority);
+
		must_exist, use_prefix, prefix, target, soft_fail, priority);
#endif
	
	return true;
@@ -1039,52 +1227,107 @@ ucl_include_common (const unsigned char *data, size_t len,
		bool default_try,
		bool default_sign)
{
-
	bool try_load, allow_glob, allow_url, need_sign;
+
	bool try_load, allow_glob, allow_url, need_sign, use_prefix, search;
+
	const char *prefix, *target;
	unsigned priority;
	const ucl_object_t *param;
-
	ucl_object_iter_t it = NULL;
+
	ucl_object_iter_t it = NULL, ip = NULL;
+
	char ipath[PATH_MAX];

	/* Default values */
	try_load = default_try;
	allow_glob = false;
	allow_url = true;
	need_sign = default_sign;
+
	use_prefix = false;
+
	prefix = NULL;
+
	target = "object";
	priority = 0;
+
	search = false;

	/* Process arguments */
	if (args != NULL && args->type == UCL_OBJECT) {
		while ((param = ucl_iterate_object (args, &it, true)) != NULL) {
			if (param->type == UCL_BOOLEAN) {
-
				if (strcmp (param->key, "try") == 0) {
+
				if (strncmp (param->key, "try", param->keylen) == 0) {
					try_load = ucl_object_toboolean (param);
				}
-
				else if (strcmp (param->key, "sign") == 0) {
+
				else if (strncmp (param->key, "sign", param->keylen) == 0) {
					need_sign = ucl_object_toboolean (param);
				}
-
				else if (strcmp (param->key, "glob") == 0) {
-
					allow_glob =  ucl_object_toboolean (param);
+
				else if (strncmp (param->key, "glob", param->keylen) == 0) {
+
					allow_glob = ucl_object_toboolean (param);
				}
-
				else if (strcmp (param->key, "url") == 0) {
-
					allow_url =  ucl_object_toboolean (param);
+
				else if (strncmp (param->key, "url", param->keylen) == 0) {
+
					allow_url = ucl_object_toboolean (param);
+
				}
+
				else if (strncmp (param->key, "prefix", param->keylen) == 0) {
+
					use_prefix = ucl_object_toboolean (param);
+
				}
+
			}
+
			else if (param->type == UCL_STRING) {
+
				if (strncmp (param->key, "key", param->keylen) == 0) {
+
					prefix = ucl_object_tostring (param);
+
				}
+
				else if (strncmp (param->key, "target", param->keylen) == 0) {
+
					target = ucl_object_tostring (param);
+
				}
+
			}
+
			else if (param->type == UCL_ARRAY) {
+
				if (strncmp (param->key, "path", param->keylen) == 0) {
+
					ucl_set_include_path (parser, __DECONST(ucl_object_t *, param));
				}
			}
			else if (param->type == UCL_INT) {
-
				if (strcmp (param->key, "priority") == 0) {
+
				if (strncmp (param->key, "priority", param->keylen) == 0) {
					priority = ucl_object_toint (param);
				}
			}
		}
	}

-
	if (*data == '/' || *data == '.') {
-
		/* Try to load a file */
-
		return ucl_include_file (data, len, parser, need_sign, !try_load,
-
				allow_glob, priority);
+
	if (parser->includepaths == NULL) {
+
		if (allow_url && ucl_strnstr (data, "://", len) != NULL) {
+
			/* Globbing is not used for URL's */
+
			return ucl_include_url (data, len, parser, need_sign,
+
					!try_load, use_prefix, prefix, target, priority);
+
		}
+
		else if (data != NULL) {
+
			/* Try to load a file */
+
			return ucl_include_file (data, len, parser, need_sign, !try_load,
+
					allow_glob, use_prefix, prefix, target, false, priority);
+
		}
	}
-
	else if (allow_url) {
-
		/* Globbing is not used for URL's */
-
		return ucl_include_url (data, len, parser, need_sign, !try_load,
-
				priority);
+
	else {
+
		if (allow_url && ucl_strnstr (data, "://", len) != NULL) {
+
			/* Globbing is not used for URL's */
+
			return ucl_include_url (data, len, parser, need_sign,
+
					!try_load, use_prefix, prefix, target, priority);
+
		}
+

+
		ip = ucl_object_iterate_new (parser->includepaths);
+
		while ((param = ucl_object_iterate_safe (ip, true)) != NULL) {
+
			if (ucl_object_type(param) == UCL_STRING) {
+
				snprintf (ipath, sizeof (ipath), "%s/%.*s", ucl_object_tostring(param),
+
						(int)len, data);
+
				if ((search = ucl_include_file (ipath, strlen (ipath), parser, need_sign,
+
						!try_load, allow_glob, use_prefix, prefix, target, true, priority))) {
+
					if (!allow_glob) {
+
						break;
+
					}
+
				}
+
			}
+
		}
+
		ucl_object_iterate_free (ip);
+
		if (search == true) {
+
			return true;
+
		}
+
		else {
+
			ucl_create_err (&parser->err,
+
					"cannot find file: %.*s in search path",
+
					(int)len, data);
+
			return false;
+
		}
	}

	return false;
@@ -1094,11 +1337,11 @@ ucl_include_common (const unsigned char *data, size_t len,
 * Handle include macro
 * @param data include data
 * @param len length of data
+
 * @param args UCL object representing arguments to the macro
 * @param ud user data
-
 * @param err error ptr
 * @return
 */
-
UCL_EXTERN bool
+
bool
ucl_include_handler (const unsigned char *data, size_t len,
		const ucl_object_t *args, void* ud)
{
@@ -1111,11 +1354,11 @@ ucl_include_handler (const unsigned char *data, size_t len,
 * Handle includes macro
 * @param data include data
 * @param len length of data
+
 * @param args UCL object representing arguments to the macro
 * @param ud user data
-
 * @param err error ptr
 * @return
 */
-
UCL_EXTERN bool
+
bool
ucl_includes_handler (const unsigned char *data, size_t len,
		const ucl_object_t *args, void* ud)
{
@@ -1124,8 +1367,15 @@ ucl_includes_handler (const unsigned char *data, size_t len,
	return ucl_include_common (data, len, args, parser, false, true);
}

-

-
UCL_EXTERN bool
+
/**
+
 * Handle tryinclude macro
+
 * @param data include data
+
 * @param len length of data
+
 * @param args UCL object representing arguments to the macro
+
 * @param ud user data
+
 * @return
+
 */
+
bool
ucl_try_include_handler (const unsigned char *data, size_t len,
		const ucl_object_t *args, void* ud)
{
@@ -1134,7 +1384,251 @@ ucl_try_include_handler (const unsigned char *data, size_t len,
	return ucl_include_common (data, len, args, parser, true, false);
}

-
UCL_EXTERN bool
+
/**
+
 * Handle priority macro
+
 * @param data include data
+
 * @param len length of data
+
 * @param args UCL object representing arguments to the macro
+
 * @param ud user data
+
 * @return
+
 */
+
bool
+
ucl_priority_handler (const unsigned char *data, size_t len,
+
		const ucl_object_t *args, void* ud)
+
{
+
	struct ucl_parser *parser = ud;
+
	unsigned priority = 255;
+
	const ucl_object_t *param;
+
	bool found = false;
+
	char *value = NULL, *leftover = NULL;
+
	ucl_object_iter_t it = NULL;
+

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

+
	/* Process arguments */
+
	if (args != NULL && args->type == UCL_OBJECT) {
+
		while ((param = ucl_iterate_object (args, &it, true)) != NULL) {
+
			if (param->type == UCL_INT) {
+
				if (strncmp (param->key, "priority", param->keylen) == 0) {
+
					priority = ucl_object_toint (param);
+
					found = true;
+
				}
+
			}
+
		}
+
	}
+

+
	if (len > 0) {
+
		value = malloc(len + 1);
+
		ucl_strlcpy(value, (const char *)data, len + 1);
+
		priority = strtol(value, &leftover, 10);
+
		if (*leftover != '\0') {
+
			ucl_create_err (&parser->err, "Invalid priority value in macro: %s",
+
				value);
+
			free(value);
+
			return false;
+
		}
+
		free(value);
+
		found = true;
+
	}
+

+
	if (found == true) {
+
		parser->chunks->priority = priority;
+
		return true;
+
	}
+

+
	ucl_create_err (&parser->err, "Unable to parse priority macro");
+
	return false;
+
}
+

+
/**
+
 * Handle load macro
+
 * @param data include data
+
 * @param len length of data
+
 * @param args UCL object representing arguments to the macro
+
 * @param ud user data
+
 * @return
+
 */
+
bool
+
ucl_load_handler (const unsigned char *data, size_t len,
+
		const ucl_object_t *args, void* ud)
+
{
+
	struct ucl_parser *parser = ud;
+
	const ucl_object_t *param;
+
	ucl_object_t *obj, *old_obj;
+
	ucl_object_iter_t it = NULL;
+
	bool try_load, multiline, test;
+
	const char *target, *prefix;
+
	char *load_file, *tmp;
+
	unsigned char *buf;
+
	size_t buflen;
+
	unsigned priority;
+
	int64_t iv;
+
	ucl_hash_t *container = NULL;
+
	enum ucl_string_flags flags;
+

+
	/* Default values */
+
	try_load = false;
+
	multiline = false;
+
	test = false;
+
	target = "string";
+
	prefix = NULL;
+
	load_file = NULL;
+
	buf = NULL;
+
	buflen = 0;
+
	priority = 0;
+
	obj = NULL;
+
	old_obj = NULL;
+
	flags = 0;
+

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

+
	/* Process arguments */
+
	if (args != NULL && args->type == UCL_OBJECT) {
+
		while ((param = ucl_iterate_object (args, &it, true)) != NULL) {
+
			if (param->type == UCL_BOOLEAN) {
+
				if (strncmp (param->key, "try", param->keylen) == 0) {
+
					try_load = ucl_object_toboolean (param);
+
				}
+
				else if (strncmp (param->key, "multiline", param->keylen) == 0) {
+
					multiline = ucl_object_toboolean (param);
+
				}
+
				else if (strncmp (param->key, "escape", param->keylen) == 0) {
+
					test = ucl_object_toboolean (param);
+
					if (test) {
+
						flags |= UCL_STRING_ESCAPE;
+
					}
+
				}
+
				else if (strncmp (param->key, "trim", param->keylen) == 0) {
+
					test = ucl_object_toboolean (param);
+
					if (test) {
+
						flags |= UCL_STRING_TRIM;
+
					}
+
				}
+
			}
+
			else if (param->type == UCL_STRING) {
+
				if (strncmp (param->key, "key", param->keylen) == 0) {
+
					prefix = ucl_object_tostring (param);
+
				}
+
				else if (strncmp (param->key, "target", param->keylen) == 0) {
+
					target = ucl_object_tostring (param);
+
				}
+
			}
+
			else if (param->type == UCL_INT) {
+
				if (strncmp (param->key, "priority", param->keylen) == 0) {
+
					priority = ucl_object_toint (param);
+
				}
+
			}
+
		}
+
	}
+

+
	if (prefix == NULL || strlen(prefix) == 0) {
+
		ucl_create_err (&parser->err, "No Key specified in load macro");
+
		return false;
+
	}
+

+
	if (len > 0) {
+
		asprintf (&load_file, "%.*s", (int)len, data);
+
		if (!ucl_fetch_file (load_file, &buf, &buflen, &parser->err, !try_load)) {
+
			return (try_load || false);
+
		}
+

+
		container = parser->stack->obj->value.ov;
+
		old_obj = __DECONST (ucl_object_t *, ucl_hash_search (container, prefix, strlen (prefix)));
+
		if (old_obj != NULL) {
+
			ucl_create_err (&parser->err, "Key %s already exists", prefix);
+
			return false;
+
		}
+

+
		if (strcasecmp (target, "string") == 0) {
+
			obj = ucl_object_fromstring_common (buf, buflen, flags);
+
			ucl_copy_value_trash (obj);
+
			if (multiline) {
+
				obj->flags |= UCL_OBJECT_MULTILINE;
+
			}
+
		}
+
		else if (strcasecmp (target, "int") == 0) {
+
			asprintf(&tmp, "%.*s", (int)buflen, buf);
+
			iv = strtoll(tmp, NULL, 10);
+
			obj = ucl_object_fromint(iv);
+
		}
+

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

+
		if (obj != NULL) {
+
			obj->key = prefix;
+
			obj->keylen = strlen (prefix);
+
			ucl_copy_key_trash(obj);
+
			obj->prev = obj;
+
			obj->next = NULL;
+
			ucl_object_set_priority (obj, priority);
+
			container = ucl_hash_insert_object (container, obj,
+
					parser->flags & UCL_PARSER_KEY_LOWERCASE);
+
			parser->stack->obj->value.ov = container;
+
		}
+
		return true;
+
	}
+

+
	ucl_create_err (&parser->err, "Unable to parse load macro");
+
	return false;
+
}
+

+
bool
+
ucl_inherit_handler (const unsigned char *data, size_t len,
+
		const ucl_object_t *args, const ucl_object_t *ctx, void* ud)
+
{
+
	const ucl_object_t *parent, *cur;
+
	ucl_object_t *target, *copy;
+
	ucl_object_iter_t it = NULL;
+
	bool replace = false;
+
	struct ucl_parser *parser = ud;
+

+
	parent = ucl_object_find_keyl (ctx, data, len);
+

+
	/* Some sanity checks */
+
	if (parent == NULL || ucl_object_type (parent) != UCL_OBJECT) {
+
		ucl_create_err (&parser->err, "Unable to find inherited object %*.s",
+
				(int)len, data);
+
		return false;
+
	}
+

+
	if (parser->stack == NULL || parser->stack->obj == NULL ||
+
			ucl_object_type (parser->stack->obj) != UCL_OBJECT) {
+
		ucl_create_err (&parser->err, "Invalid inherit context");
+
		return false;
+
	}
+

+
	target = parser->stack->obj;
+

+
	if (args && (cur = ucl_object_find_key (args, "replace")) != NULL) {
+
		replace = ucl_object_toboolean (cur);
+
	}
+

+
	while ((cur = ucl_iterate_object (parent, &it, true))) {
+
		/* We do not replace existing keys */
+
		if (!replace && ucl_object_find_keyl (target, cur->key, cur->keylen)) {
+
			continue;
+
		}
+

+
		copy = ucl_object_copy (cur);
+

+
		if (!replace) {
+
			copy->flags |= UCL_OBJECT_INHERITED;
+
		}
+

+
		ucl_object_insert_key (target, copy, copy->key,
+
				copy->keylen, false);
+
	}
+

+
	return true;
+
}
+

+
bool
ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
{
	char realbuf[PATH_MAX], *curdir;
@@ -1164,8 +1658,9 @@ ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool n
	return true;
}

-
UCL_EXTERN bool
-
ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
+
bool
+
ucl_parser_add_file_priority (struct ucl_parser *parser, const char *filename,
+
		unsigned priority)
{
	unsigned char *buf;
	size_t len;
@@ -1188,7 +1683,7 @@ ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
	}
	parser->cur_file = strdup (realbuf);
	ucl_parser_set_filevars (parser, realbuf, false);
-
	ret = ucl_parser_add_chunk (parser, buf, len);
+
	ret = ucl_parser_add_chunk_priority (parser, buf, len, priority);

	if (len > 0) {
		ucl_munmap (buf, len);
@@ -1197,8 +1692,20 @@ ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
	return ret;
}

-
UCL_EXTERN bool
-
ucl_parser_add_fd (struct ucl_parser *parser, int fd)
+
bool
+
ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
+
{
+
	if (parser == NULL) {
+
		return false;
+
	}
+

+
	return ucl_parser_add_file_priority(parser, filename,
+
			parser->default_priority);
+
}
+

+
bool
+
ucl_parser_add_fd_priority (struct ucl_parser *parser, int fd,
+
		unsigned priority)
{
	unsigned char *buf;
	size_t len;
@@ -1221,7 +1728,7 @@ ucl_parser_add_fd (struct ucl_parser *parser, int fd)
	}
	parser->cur_file = NULL;
	len = st.st_size;
-
	ret = ucl_parser_add_chunk (parser, buf, len);
+
	ret = ucl_parser_add_chunk_priority (parser, buf, len, priority);

	if (len > 0) {
		ucl_munmap (buf, len);
@@ -1230,6 +1737,16 @@ ucl_parser_add_fd (struct ucl_parser *parser, int fd)
	return ret;
}

+
bool
+
ucl_parser_add_fd (struct ucl_parser *parser, int fd)
+
{
+
	if (parser == NULL) {
+
		return false;
+
	}
+

+
	return ucl_parser_add_fd_priority(parser, fd, parser->default_priority);
+
}
+

size_t
ucl_strlcpy (char *dst, const char *src, size_t siz)
{
@@ -1285,6 +1802,51 @@ ucl_strlcpy_tolower (char *dst, const char *src, size_t siz)
	return (s - src);    /* count does not include NUL */
}

+
/*
+
 * Find the first occurrence of find in s
+
 */
+
char *
+
ucl_strnstr (const char *s, const char *find, int len)
+
{
+
	char c, sc;
+
	int mlen;
+

+
	if ((c = *find++) != 0) {
+
		mlen = strlen (find);
+
		do {
+
			do {
+
				if ((sc = *s++) == 0 || len-- == 0)
+
					return (NULL);
+
			} while (sc != c);
+
		} while (strncmp (s, find, mlen) != 0);
+
		s--;
+
	}
+
	return ((char *)s);
+
}
+

+
/*
+
 * Find the first occurrence of find in s, ignore case.
+
 */
+
char *
+
ucl_strncasestr (const char *s, const char *find, int len)
+
{
+
	char c, sc;
+
	int mlen;
+

+
	if ((c = *find++) != 0) {
+
		c = tolower (c);
+
		mlen = strlen (find);
+
		do {
+
			do {
+
				if ((sc = *s++) == 0 || len-- == 0)
+
					return (NULL);
+
			} while (tolower (sc) != c);
+
		} while (strncasecmp (s, find, mlen) != 0);
+
		s--;
+
	}
+
	return ((char *)s);
+
}
+

ucl_object_t *
ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags)
{
@@ -1539,7 +2101,7 @@ ucl_object_delete_keyl (ucl_object_t *top, const char *key, size_t keylen)
bool
ucl_object_delete_key (ucl_object_t *top, const char *key)
{
-
	return ucl_object_delete_keyl (top, key, strlen(key));
+
	return ucl_object_delete_keyl (top, key, strlen (key));
}

ucl_object_t*
@@ -1564,7 +2126,7 @@ ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen)
ucl_object_t*
ucl_object_pop_key (ucl_object_t *top, const char *key)
{
-
	return ucl_object_pop_keyl (top, key, strlen(key));
+
	return ucl_object_pop_keyl (top, key, strlen (key));
}

bool
@@ -1642,10 +2204,45 @@ ucl_object_find_keyl (const ucl_object_t *obj, const char *key, size_t klen)
const ucl_object_t *
ucl_object_find_key (const ucl_object_t *obj, const char *key)
{
-
	if (key == NULL)
+
	if (key == NULL) {
+
		return NULL;
+
	}
+

+
	return ucl_object_find_keyl (obj, key, strlen (key));
+
}
+

+
const ucl_object_t*
+
ucl_object_find_any_key (const ucl_object_t *obj,
+
		const char *key, ...)
+
{
+
	va_list ap;
+
	const ucl_object_t *ret = NULL;
+
	const char *nk = NULL;
+

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

+
	ret = ucl_object_find_keyl (obj, key, strlen (key));
+

+
	if (ret == NULL) {
+
		va_start (ap, key);

-
	return ucl_object_find_keyl (obj, key, strlen(key));
+
		while (ret == NULL) {
+
			nk = va_arg (ap, const char *);
+

+
			if (nk == NULL) {
+
				break;
+
			}
+
			else {
+
				ret = ucl_object_find_keyl (obj, nk, strlen (nk));
+
			}
+
		}
+

+
		va_end (ap);
+
	}
+

+
	return ret;
}

const ucl_object_t*
@@ -1792,6 +2389,12 @@ ucl_object_iterate_free (ucl_object_iter_t it)

const ucl_object_t *
ucl_lookup_path (const ucl_object_t *top, const char *path_in) {
+
	return ucl_lookup_path_char (top, path_in, '.');
+
}
+

+

+
const ucl_object_t *
+
ucl_lookup_path_char (const ucl_object_t *top, const char *path_in, const char sep) {
	const ucl_object_t *o = NULL, *found;
	const char *p, *c;
	char *err_str;
@@ -1805,20 +2408,20 @@ ucl_lookup_path (const ucl_object_t *top, const char *path_in) {
	p = path_in;

	/* Skip leading dots */
-
	while (*p == '.') {
+
	while (*p == sep) {
		p ++;
	}

	c = p;
	while (*p != '\0') {
		p ++;
-
		if (*p == '.' || *p == '\0') {
+
		if (*p == sep || *p == '\0') {
			if (p > c) {
				switch (top->type) {
				case UCL_ARRAY:
					/* Key should be an int */
					index = strtoul (c, &err_str, 10);
-
					if (err_str != NULL && (*err_str != '.' && *err_str != '\0')) {
+
					if (err_str != NULL && (*err_str != sep && *err_str != '\0')) {
						return NULL;
					}
					o = ucl_array_find_index (top, index);
@@ -1913,6 +2516,10 @@ ucl_object_new_userdata (ucl_userdata_dtor dtor, ucl_userdata_emitter emitter)
ucl_type_t
ucl_object_type (const ucl_object_t *obj)
{
+
	if (obj == NULL) {
+
		return UCL_NULL;
+
	}
+

	return obj->type;
}

@@ -1981,6 +2588,11 @@ ucl_array_append (ucl_object_t *top, ucl_object_t *elt)

	if (vec == NULL) {
		vec = UCL_ALLOC (sizeof (*vec));
+

+
		if (vec == NULL) {
+
			return false;
+
		}
+

		kv_init (*vec);
		top->value.av = (void *)vec;
	}
@@ -2021,14 +2633,23 @@ bool
ucl_array_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
{
	unsigned i;
+
	ucl_object_t *cp = NULL;
	ucl_object_t **obj;
-
	UCL_ARRAY_GET (v1, top);
-
	UCL_ARRAY_GET (v2, elt);

	if (elt == NULL || top == NULL || top->type != UCL_ARRAY || elt->type != UCL_ARRAY) {
		return false;
	}

+
	if (copy) {
+
		cp = ucl_object_copy (elt);
+
	}
+
	else {
+
		cp = ucl_object_ref (elt);
+
	}
+

+
	UCL_ARRAY_GET (v1, top);
+
	UCL_ARRAY_GET (v2, cp);
+

	kv_concat (ucl_object_t *, *v1, *v2);

	for (i = v2->n; i < v1->n; i ++) {
@@ -2036,14 +2657,7 @@ ucl_array_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
		if (*obj == NULL) {
			continue;
		}
-

		top->len ++;
-
		if (copy) {
-
			*obj = ucl_object_copy (*obj);
-
		}
-
		else {
-
			ucl_object_ref (*obj);
-
		}
	}

	return true;
@@ -2056,6 +2670,10 @@ ucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
	ucl_object_t *ret = NULL;
	unsigned i;

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

	for (i = 0; i < vec->n; i ++) {
		if (kv_A (*vec, i) == elt) {
			kv_del (ucl_object_t *, *vec, i);
@@ -2073,7 +2691,8 @@ ucl_array_head (const ucl_object_t *top)
{
	UCL_ARRAY_GET (vec, top);

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

@@ -2136,6 +2755,25 @@ ucl_array_find_index (const ucl_object_t *top, unsigned int index)
	return NULL;
}

+
unsigned int
+
ucl_array_index_of (ucl_object_t *top, ucl_object_t *elt)
+
{
+
	UCL_ARRAY_GET (vec, top);
+
	unsigned i;
+

+
	if (vec == NULL) {
+
		return (unsigned int)(-1);
+
	}
+

+
	for (i = 0; i < vec->n; i ++) {
+
		if (kv_A (*vec, i) == elt) {
+
			return i;
+
		}
+
	}
+

+
	return (unsigned int)(-1);
+
}
+

ucl_object_t *
ucl_array_replace_index (ucl_object_t *top, ucl_object_t *elt,
	unsigned int index)
@@ -2563,6 +3201,9 @@ ucl_object_set_priority (ucl_object_t *obj,
{
	if (obj != NULL) {
		priority &= (0x1 << PRIOBITS) - 1;
-
		obj->flags |= priority << ((sizeof (obj->flags) * NBBY) - PRIOBITS);
+
		priority <<= ((sizeof (obj->flags) * NBBY) - PRIOBITS);
+
		priority |= obj->flags & ((1 << ((sizeof (obj->flags) * NBBY) -
+
				PRIOBITS)) - 1);
+
		obj->flags = priority;
	}
}
modified external/libucl/src/xxhash.c
@@ -1,475 +1,941 @@
-
/*
-
xxHash - Fast Hash algorithm
-
Copyright (C) 2012-2013, Yann Collet.
-
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-

-
Redistribution and use in source and binary forms, with or without
-
modification, are permitted provided that the following conditions are
-
met:
-

-
* Redistributions of source code must retain the above copyright
-
notice, this list of conditions and the following disclaimer.
-
* Redistributions in binary form must reproduce the above
-
copyright notice, this list of conditions and the following disclaimer
-
in the documentation and/or other materials provided with the
-
distribution.
-

-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-

-
You can contact the author at :
-
- xxHash source repository : http://code.google.com/p/xxhash/
-
*/
-

-

-
//**************************************
-
// Tuning parameters
-
//**************************************
-
// Unaligned memory access is automatically enabled for "common" CPU, such as x86.
-
// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected.
-
// If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance.
-
// You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32).
-
#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
-
#  define XXH_USE_UNALIGNED_ACCESS 1
-
#endif
-

-
// XXH_ACCEPT_NULL_INPUT_POINTER :
-
// If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
-
// When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
-
// This option has a very small performance cost (only measurable on small inputs).
-
// By default, this option is disabled. To enable it, uncomment below define :
-
//#define XXH_ACCEPT_NULL_INPUT_POINTER 1
-

-
// XXH_FORCE_NATIVE_FORMAT :
-
// By default, xxHash library provides endian-independant Hash values, based on little-endian convention.
-
// Results are therefore identical for little-endian and big-endian CPU.
-
// This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
-
// Should endian-independance be of no importance for your application, you may set the #define below to 1.
-
// It will improve speed for Big-endian CPU.
-
// This option has no impact on Little_Endian CPU.
-
#define XXH_FORCE_NATIVE_FORMAT 0
-

-

-
//**************************************
-
// Compiler Specific Options
-
//**************************************
-
// Disable some Visual warning messages
-
#ifdef _MSC_VER  // Visual Studio
-
#  pragma warning(disable : 4127)      // disable: C4127: conditional expression is constant
-
#endif
-

-
#ifdef _MSC_VER    // Visual Studio
-
#  define forceinline static __forceinline
-
#else 
-
#  ifdef __GNUC__
-
#    define forceinline static inline __attribute__((always_inline))
-
#  else
-
#    define forceinline static inline
-
#  endif
-
#endif
-

-

-
//**************************************
-
// Includes & Memory related functions
-
//**************************************
-
#include "xxhash.h"
-
// Modify the local functions below should you wish to use some other memory related routines
-
// for malloc(), free()
-
#include <stdlib.h>
-
forceinline void* XXH_malloc(size_t s) { return malloc(s); }
-
forceinline void  XXH_free  (void* p)  { free(p); }
-
// for memcpy()
-
#include <string.h>
-
forceinline void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
-

-

-
//**************************************
-
// Basic Types
-
//**************************************
-
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   // C99
-
# include <stdint.h>
-
  typedef uint8_t  BYTE;
-
  typedef uint16_t U16;
-
  typedef uint32_t U32;
-
  typedef  int32_t S32;
-
  typedef uint64_t U64;
-
#else
-
  typedef unsigned char      BYTE;
-
  typedef unsigned short     U16;
-
  typedef unsigned int       U32;
-
  typedef   signed int       S32;
-
  typedef unsigned long long U64;
-
#endif
-

-
#if defined(__GNUC__)  && !defined(XXH_USE_UNALIGNED_ACCESS)
-
#  define _PACKED __attribute__ ((packed))
-
#else
-
#  define _PACKED
-
#endif
-

-
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
-
#  ifdef __IBMC__
-
#    pragma pack(1)
-
#  else
-
#    pragma pack(push, 1)
-
#  endif
-
#endif
-

-
typedef struct _U32_S { U32 v; } _PACKED U32_S;
-

-
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
-
#  pragma pack(pop)
-
#endif
-

-
#define A32(x) (((U32_S *)(x))->v)
-

-

-
//***************************************
-
// Compiler-specific Functions and Macros
-
//***************************************
-
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-

-
// Note : although _rotl exists for minGW (GCC under windows), performance seems poor
-
#if defined(_MSC_VER)
-
#  define XXH_rotl32(x,r) _rotl(x,r)
-
#else
-
#  define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
-
#endif
-

-
#if defined(_MSC_VER)     // Visual Studio
-
#  define XXH_swap32 _byteswap_ulong
-
#elif GCC_VERSION >= 403
-
#  define XXH_swap32 __builtin_bswap32
-
#else
-
static inline U32 XXH_swap32 (U32 x) {
-
    return  ((x << 24) & 0xff000000 ) |
-
        ((x <<  8) & 0x00ff0000 ) |
-
        ((x >>  8) & 0x0000ff00 ) |
-
        ((x >> 24) & 0x000000ff );}
-
#endif
-

-

-
//**************************************
-
// Constants
-
//**************************************
-
#define PRIME32_1   2654435761U
-
#define PRIME32_2   2246822519U
-
#define PRIME32_3   3266489917U
-
#define PRIME32_4    668265263U
-
#define PRIME32_5    374761393U
-

-

-
//**************************************
-
// Architecture Macros
-
//**************************************
-
typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
-
#ifndef XXH_CPU_LITTLE_ENDIAN   // It is possible to define XXH_CPU_LITTLE_ENDIAN externally, for example using a compiler switch
-
    static const int one = 1;
-
#   define XXH_CPU_LITTLE_ENDIAN   (*(char*)(&one))
-
#endif
-

-

-
//**************************************
-
// Macros
-
//**************************************
-
#define XXH_STATIC_ASSERT(c)   { enum { XXH_static_assert = 1/(!!(c)) }; }    // use only *after* variable declarations
-

-

-
//****************************
-
// Memory reads
-
//****************************
-
typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
-

-
forceinline U32 XXH_readLE32_align(const U32* ptr, XXH_endianess endian, XXH_alignment align)
-
{ 
-
    if (align==XXH_unaligned)
-
        return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr)); 
-
    else
-
        return endian==XXH_littleEndian ? *ptr : XXH_swap32(*ptr); 
-
}
-

-
forceinline U32 XXH_readLE32(const U32* ptr, XXH_endianess endian) { return XXH_readLE32_align(ptr, endian, XXH_unaligned); }
-

-

-
//****************************
-
// Simple Hash Functions
-
//****************************
-
forceinline U32 XXH32_endian_align(const void* input, int len, U32 seed, XXH_endianess endian, XXH_alignment align)
-
{
-
    const BYTE* p = (const BYTE*)input;
-
    const BYTE* const bEnd = p + len;
-
    U32 h32;
-

-
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
-
    if (p==NULL) { len=0; p=(const BYTE*)(size_t)16; }
-
#endif
-

-
    if (len>=16)
-
    {
-
        const BYTE* const limit = bEnd - 16;
-
        U32 v1 = seed + PRIME32_1 + PRIME32_2;
-
        U32 v2 = seed + PRIME32_2;
-
        U32 v3 = seed + 0;
-
        U32 v4 = seed - PRIME32_1;
-

-
        do
-
        {
-
            v1 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
-
            v2 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
-
            v3 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
-
            v4 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
-
        } while (p<=limit);
-

-
        h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
-
    }
-
    else
-
    {
-
        h32  = seed + PRIME32_5;
-
    }
-

-
    h32 += (U32) len;
-

-
    while (p<=bEnd-4)
-
    {
-
        h32 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_3;
-
        h32  = XXH_rotl32(h32, 17) * PRIME32_4 ;
-
        p+=4;
-
    }
-

-
    while (p<bEnd)
-
    {
-
        h32 += (*p) * PRIME32_5;
-
        h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
-
        p++;
-
    }
-

-
    h32 ^= h32 >> 15;
-
    h32 *= PRIME32_2;
-
    h32 ^= h32 >> 13;
-
    h32 *= PRIME32_3;
-
    h32 ^= h32 >> 16;
-

-
    return h32;
-
}
-

-

-
U32 XXH32(const void* input, int len, U32 seed)
-
{
-
#if 0
-
    // Simple version, good for code maintenance, but unfortunately slow for small inputs
-
    void* state = XXH32_init(seed);
-
    XXH32_update(state, input, len);
-
    return XXH32_digest(state);
-
#else
-
    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
-

-
#  if !defined(XXH_USE_UNALIGNED_ACCESS)
-
    if (!(((size_t)input) & 3))   // Input is aligned, let's leverage the speed advantage
-
    {
-
        if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
-
            return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
-
        else
-
            return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
-
    }
-
#  endif
-

-
    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
-
        return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
-
    else
-
        return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
-
#endif
-
}
-

-

-
//****************************
-
// Advanced Hash Functions
-
//****************************
-

-
struct XXH_state32_t
-
{
-
    U64 total_len;
-
    U32 seed;
-
    U32 v1;
-
    U32 v2;
-
    U32 v3;
-
    U32 v4;
-
    int memsize;
-
    char memory[16];
-
};
-

-

-
int XXH32_sizeofState(void)
-
{
-
    XXH_STATIC_ASSERT(XXH32_SIZEOFSTATE >= sizeof(struct XXH_state32_t));   // A compilation error here means XXH32_SIZEOFSTATE is not large enough
-
    return sizeof(struct XXH_state32_t); 
-
}
-

-

-
XXH_errorcode XXH32_resetState(void* state_in, U32 seed)
-
{ 
-
    struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
-
    state->seed = seed;
-
    state->v1 = seed + PRIME32_1 + PRIME32_2;
-
    state->v2 = seed + PRIME32_2;
-
    state->v3 = seed + 0;
-
    state->v4 = seed - PRIME32_1;
-
    state->total_len = 0;
-
    state->memsize = 0;
-
    return XXH_OK;
-
}
-

-

-
void* XXH32_init (U32 seed)
-
{
-
    void* state = XXH_malloc (sizeof(struct XXH_state32_t));
-
    XXH32_resetState(state, seed);
-
    return state;
-
}
-

-

-
forceinline XXH_errorcode XXH32_update_endian (void* state_in, const void* input, int len, XXH_endianess endian)
-
{
-
    struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
-
    const BYTE* p = (const BYTE*)input;
-
    const BYTE* const bEnd = p + len;
-

-
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
-
    if (input==NULL) return XXH_ERROR;
-
#endif
-

-
    state->total_len += len;
-

-
    if (state->memsize + len < 16)   // fill in tmp buffer
-
    {
-
        XXH_memcpy(state->memory + state->memsize, input, len);
-
        state->memsize +=  len;
-
        return XXH_OK;
-
    }
-

-
    if (state->memsize)   // some data left from previous update
-
    {
-
        XXH_memcpy(state->memory + state->memsize, input, 16-state->memsize);
-
        {
-
            const U32* p32 = (const U32*)state->memory;
-
            state->v1 += XXH_readLE32(p32, endian) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++;
-
            state->v2 += XXH_readLE32(p32, endian) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++; 
-
            state->v3 += XXH_readLE32(p32, endian) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++;
-
            state->v4 += XXH_readLE32(p32, endian) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++;
-
        }
-
        p += 16-state->memsize;
-
        state->memsize = 0;
-
    }
-

-
    if (p <= bEnd-16)
-
    {
-
        const BYTE* const limit = bEnd - 16;
-
        U32 v1 = state->v1;
-
        U32 v2 = state->v2;
-
        U32 v3 = state->v3;
-
        U32 v4 = state->v4;
-

-
        do
-
        {
-
            v1 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
-
            v2 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
-
            v3 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
-
            v4 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
-
        } while (p<=limit);
-

-
        state->v1 = v1;
-
        state->v2 = v2;
-
        state->v3 = v3;
-
        state->v4 = v4;
-
    }
-

-
    if (p < bEnd)
-
    {
-
        XXH_memcpy(state->memory, p, bEnd-p);
-
        state->memsize = (int)(bEnd-p);
-
    }
-

-
    return XXH_OK;
-
}
-

-
XXH_errorcode XXH32_update (void* state_in, const void* input, int len)
-
{
-
    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
-
    
-
    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
-
        return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
-
    else
-
        return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
-
}
-

-

-

-
forceinline U32 XXH32_intermediateDigest_endian (void* state_in, XXH_endianess endian)
-
{
-
    struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
-
    const BYTE * p = (const BYTE*)state->memory;
-
    BYTE* bEnd = (BYTE*)state->memory + state->memsize;
-
    U32 h32;
-

-
    if (state->total_len >= 16)
-
    {
-
        h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
-
    }
-
    else
-
    {
-
        h32  = state->seed + PRIME32_5;
-
    }
-

-
    h32 += (U32) state->total_len;
-

-
    while (p<=bEnd-4)
-
    {
-
        h32 += XXH_readLE32((const U32*)p, endian) * PRIME32_3;
-
        h32  = XXH_rotl32(h32, 17) * PRIME32_4;
-
        p+=4;
-
    }
-

-
    while (p<bEnd)
-
    {
-
        h32 += (*p) * PRIME32_5;
-
        h32 = XXH_rotl32(h32, 11) * PRIME32_1;
-
        p++;
-
    }
-

-
    h32 ^= h32 >> 15;
-
    h32 *= PRIME32_2;
-
    h32 ^= h32 >> 13;
-
    h32 *= PRIME32_3;
-
    h32 ^= h32 >> 16;
-

-
    return h32;
-
}
-

-

-
U32 XXH32_intermediateDigest (void* state_in)
-
{
-
    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
-
    
-
    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
-
        return XXH32_intermediateDigest_endian(state_in, XXH_littleEndian);
-
    else
-
        return XXH32_intermediateDigest_endian(state_in, XXH_bigEndian);
-
}
-

-

-
U32 XXH32_digest (void* state_in)
-
{
-
    U32 h32 = XXH32_intermediateDigest(state_in);
-

-
    XXH_free(state_in);
-

-
    return h32;
-
}
+
/*
+
xxHash - Fast Hash algorithm
+
Copyright (C) 2012-2014, Yann Collet.
+
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+

+
Redistribution and use in source and binary forms, with or without
+
modification, are permitted provided that the following conditions are
+
met:
+

+
* Redistributions of source code must retain the above copyright
+
notice, this list of conditions and the following disclaimer.
+
* Redistributions in binary form must reproduce the above
+
copyright notice, this list of conditions and the following disclaimer
+
in the documentation and/or other materials provided with the
+
distribution.
+

+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+

+
You can contact the author at :
+
- xxHash source repository : http://code.google.com/p/xxhash/
+
- public discussion board : https://groups.google.com/forum/#!forum/lz4c
+
*/
+

+

+
//**************************************
+
// Tuning parameters
+
//**************************************
+
// Unaligned memory access is automatically enabled for "common" CPU, such as x86.
+
// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected.
+
// If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance.
+
// You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32).
+
#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
+
#  define XXH_USE_UNALIGNED_ACCESS 1
+
#endif
+

+
// XXH_ACCEPT_NULL_INPUT_POINTER :
+
// If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
+
// When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
+
// This option has a very small performance cost (only measurable on small inputs).
+
// By default, this option is disabled. To enable it, uncomment below define :
+
// #define XXH_ACCEPT_NULL_INPUT_POINTER 1
+

+
// XXH_FORCE_NATIVE_FORMAT :
+
// By default, xxHash library provides endian-independant Hash values, based on little-endian convention.
+
// Results are therefore identical for little-endian and big-endian CPU.
+
// This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
+
// Should endian-independance be of no importance for your application, you may set the #define below to 1.
+
// It will improve speed for Big-endian CPU.
+
// This option has no impact on Little_Endian CPU.
+
#define XXH_FORCE_NATIVE_FORMAT 0
+

+
//**************************************
+
// Compiler Specific Options
+
//**************************************
+
// Disable some Visual warning messages
+
#ifdef _MSC_VER  // Visual Studio
+
#  pragma warning(disable : 4127)      // disable: C4127: conditional expression is constant
+
#endif
+

+
#ifdef _MSC_VER    // Visual Studio
+
#  define FORCE_INLINE static __forceinline
+
#else
+
#  ifdef __GNUC__
+
#    define FORCE_INLINE static inline __attribute__((always_inline))
+
#  else
+
#    define FORCE_INLINE static inline
+
#  endif
+
#endif
+

+
//**************************************
+
// Includes & Memory related functions
+
//**************************************
+
#include "xxhash.h"
+
// Modify the local functions below should you wish to use some other memory routines
+
// for malloc(), free()
+
#include <stdlib.h>
+
static void* XXH_malloc(size_t s) { return malloc(s); }
+
static void  XXH_free  (void* p)  { free(p); }
+
// for memcpy()
+
#include <string.h>
+
static void* XXH_memcpy(void* dest, const void* src, size_t size)
+
{
+
    return memcpy(dest,src,size);
+
}
+

+

+
//**************************************
+
// Basic Types
+
//**************************************
+
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   // C99
+
# include <stdint.h>
+
typedef uint8_t  BYTE;
+
typedef uint16_t U16;
+
typedef uint32_t U32;
+
typedef  int32_t S32;
+
typedef uint64_t U64;
+
#else
+
typedef unsigned char      BYTE;
+
typedef unsigned short     U16;
+
typedef unsigned int       U32;
+
typedef   signed int       S32;
+
typedef uint64_t U64;
+
#endif
+

+
#if defined(__GNUC__)  && !defined(XXH_USE_UNALIGNED_ACCESS)
+
#  define _PACKED __attribute__ ((packed))
+
#else
+
#  define _PACKED
+
#endif
+

+
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
+
#  ifdef __IBMC__
+
#    pragma pack(1)
+
#  else
+
#    pragma pack(push, 1)
+
#  endif
+
#endif
+

+
typedef struct _U32_S
+
{
+
    U32 v;
+
} _PACKED U32_S;
+
typedef struct _U64_S
+
{
+
    U64 v;
+
} _PACKED U64_S;
+

+
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
+
#  pragma pack(pop)
+
#endif
+

+
#define A32(x) (((U32_S *)(x))->v)
+
#define A64(x) (((U64_S *)(x))->v)
+

+

+
//***************************************
+
// Compiler-specific Functions and Macros
+
//***************************************
+
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+

+
// Note : although _rotl exists for minGW (GCC under windows), performance seems poor
+
#if defined(_MSC_VER)
+
#  define XXH_rotl32(x,r) _rotl(x,r)
+
#  define XXH_rotl64(x,r) _rotl64(x,r)
+
#else
+
#  define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
+
#  define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
+
#endif
+

+
#if defined(_MSC_VER)     // Visual Studio
+
#  define XXH_swap32 _byteswap_ulong
+
#  define XXH_swap64 _byteswap_uint64
+
#elif GCC_VERSION >= 403 || defined(__clang__)
+
#  define XXH_swap32 __builtin_bswap32
+
#  define XXH_swap64 __builtin_bswap64
+
#else
+
static inline U32 XXH_swap32 (U32 x)
+
{
+
    return  ((x << 24) & 0xff000000 ) |
+
            ((x <<  8) & 0x00ff0000 ) |
+
            ((x >>  8) & 0x0000ff00 ) |
+
            ((x >> 24) & 0x000000ff );
+
}
+
static inline U64 XXH_swap64 (U64 x)
+
{
+
    return  ((x << 56) & 0xff00000000000000ULL) |
+
            ((x << 40) & 0x00ff000000000000ULL) |
+
            ((x << 24) & 0x0000ff0000000000ULL) |
+
            ((x << 8)  & 0x000000ff00000000ULL) |
+
            ((x >> 8)  & 0x00000000ff000000ULL) |
+
            ((x >> 24) & 0x0000000000ff0000ULL) |
+
            ((x >> 40) & 0x000000000000ff00ULL) |
+
            ((x >> 56) & 0x00000000000000ffULL);
+
}
+
#endif
+

+

+
//**************************************
+
// Constants
+
//**************************************
+
#define PRIME32_1   2654435761U
+
#define PRIME32_2   2246822519U
+
#define PRIME32_3   3266489917U
+
#define PRIME32_4    668265263U
+
#define PRIME32_5    374761393U
+

+
#define PRIME64_1 11400714785074694791ULL
+
#define PRIME64_2 14029467366897019727ULL
+
#define PRIME64_3  1609587929392839161ULL
+
#define PRIME64_4  9650029242287828579ULL
+
#define PRIME64_5  2870177450012600261ULL
+

+
//**************************************
+
// Architecture Macros
+
//**************************************
+
typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
+
#ifndef XXH_CPU_LITTLE_ENDIAN   // It is possible to define XXH_CPU_LITTLE_ENDIAN externally, for example using a compiler switch
+
static const int one = 1;
+
#   define XXH_CPU_LITTLE_ENDIAN   (*(char*)(&one))
+
#endif
+

+

+
//**************************************
+
// Macros
+
//**************************************
+
#define XXH_STATIC_ASSERT(c)   { enum { XXH_static_assert = 1/(!!(c)) }; }    // use only *after* variable declarations
+

+

+
//****************************
+
// Memory reads
+
//****************************
+
typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
+

+
FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
+
{
+
    if (align==XXH_unaligned)
+
        return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr));
+
    else
+
        return endian==XXH_littleEndian ? *(U32*)ptr : XXH_swap32(*(U32*)ptr);
+
}
+

+
FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
+
{
+
    return XXH_readLE32_align(ptr, endian, XXH_unaligned);
+
}
+

+
FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
+
{
+
    if (align==XXH_unaligned)
+
        return endian==XXH_littleEndian ? A64(ptr) : XXH_swap64(A64(ptr));
+
    else
+
        return endian==XXH_littleEndian ? *(U64*)ptr : XXH_swap64(*(U64*)ptr);
+
}
+

+
FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
+
{
+
    return XXH_readLE64_align(ptr, endian, XXH_unaligned);
+
}
+

+

+
//****************************
+
// Simple Hash Functions
+
//****************************
+
FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
+
{
+
    const BYTE* p = (const BYTE*)input;
+
    const BYTE* bEnd = p + len;
+
    U32 h32;
+
#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
+

+
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
+
    if (p==NULL)
+
    {
+
        len=0;
+
        bEnd=p=(const BYTE*)(size_t)16;
+
    }
+
#endif
+

+
    if (len>=16)
+
    {
+
        const BYTE* const limit = bEnd - 16;
+
        U32 v1 = seed + PRIME32_1 + PRIME32_2;
+
        U32 v2 = seed + PRIME32_2;
+
        U32 v3 = seed + 0;
+
        U32 v4 = seed - PRIME32_1;
+

+
        do
+
        {
+
            v1 += XXH_get32bits(p) * PRIME32_2;
+
            v1 = XXH_rotl32(v1, 13);
+
            v1 *= PRIME32_1;
+
            p+=4;
+
            v2 += XXH_get32bits(p) * PRIME32_2;
+
            v2 = XXH_rotl32(v2, 13);
+
            v2 *= PRIME32_1;
+
            p+=4;
+
            v3 += XXH_get32bits(p) * PRIME32_2;
+
            v3 = XXH_rotl32(v3, 13);
+
            v3 *= PRIME32_1;
+
            p+=4;
+
            v4 += XXH_get32bits(p) * PRIME32_2;
+
            v4 = XXH_rotl32(v4, 13);
+
            v4 *= PRIME32_1;
+
            p+=4;
+
        }
+
        while (p<=limit);
+

+
        h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
+
    }
+
    else
+
    {
+
        h32  = seed + PRIME32_5;
+
    }
+

+
    h32 += (U32) len;
+

+
    while (p+4<=bEnd)
+
    {
+
        h32 += XXH_get32bits(p) * PRIME32_3;
+
        h32  = XXH_rotl32(h32, 17) * PRIME32_4 ;
+
        p+=4;
+
    }
+

+
    while (p<bEnd)
+
    {
+
        h32 += (*p) * PRIME32_5;
+
        h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
+
        p++;
+
    }
+

+
    h32 ^= h32 >> 15;
+
    h32 *= PRIME32_2;
+
    h32 ^= h32 >> 13;
+
    h32 *= PRIME32_3;
+
    h32 ^= h32 >> 16;
+

+
    return h32;
+
}
+

+

+
unsigned int XXH32 (const void* input, size_t len, unsigned seed)
+
{
+
#if 0
+
    // Simple version, good for code maintenance, but unfortunately slow for small inputs
+
    XXH32_state_t state;
+
    XXH32_reset(&state, seed);
+
    XXH32_update(&state, input, len);
+
    return XXH32_digest(&state);
+
#else
+
    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
+

+
#  if !defined(XXH_USE_UNALIGNED_ACCESS)
+
    if ((((size_t)input) & 3) == 0)   // Input is aligned, let's leverage the speed advantage
+
    {
+
        if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+
            return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
+
        else
+
            return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
+
    }
+
#  endif
+

+
    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+
        return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
+
    else
+
        return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
+
#endif
+
}
+

+
FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
+
{
+
    const BYTE* p = (const BYTE*)input;
+
    const BYTE* bEnd = p + len;
+
    U64 h64;
+
#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
+

+
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
+
    if (p==NULL)
+
    {
+
        len=0;
+
        bEnd=p=(const BYTE*)(size_t)32;
+
    }
+
#endif
+

+
    if (len>=32)
+
    {
+
        const BYTE* const limit = bEnd - 32;
+
        U64 v1 = seed + PRIME64_1 + PRIME64_2;
+
        U64 v2 = seed + PRIME64_2;
+
        U64 v3 = seed + 0;
+
        U64 v4 = seed - PRIME64_1;
+

+
        do
+
        {
+
            v1 += XXH_get64bits(p) * PRIME64_2;
+
            p+=8;
+
            v1 = XXH_rotl64(v1, 31);
+
            v1 *= PRIME64_1;
+
            v2 += XXH_get64bits(p) * PRIME64_2;
+
            p+=8;
+
            v2 = XXH_rotl64(v2, 31);
+
            v2 *= PRIME64_1;
+
            v3 += XXH_get64bits(p) * PRIME64_2;
+
            p+=8;
+
            v3 = XXH_rotl64(v3, 31);
+
            v3 *= PRIME64_1;
+
            v4 += XXH_get64bits(p) * PRIME64_2;
+
            p+=8;
+
            v4 = XXH_rotl64(v4, 31);
+
            v4 *= PRIME64_1;
+
        }
+
        while (p<=limit);
+

+
        h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
+

+
        v1 *= PRIME64_2;
+
        v1 = XXH_rotl64(v1, 31);
+
        v1 *= PRIME64_1;
+
        h64 ^= v1;
+
        h64 = h64 * PRIME64_1 + PRIME64_4;
+

+
        v2 *= PRIME64_2;
+
        v2 = XXH_rotl64(v2, 31);
+
        v2 *= PRIME64_1;
+
        h64 ^= v2;
+
        h64 = h64 * PRIME64_1 + PRIME64_4;
+

+
        v3 *= PRIME64_2;
+
        v3 = XXH_rotl64(v3, 31);
+
        v3 *= PRIME64_1;
+
        h64 ^= v3;
+
        h64 = h64 * PRIME64_1 + PRIME64_4;
+

+
        v4 *= PRIME64_2;
+
        v4 = XXH_rotl64(v4, 31);
+
        v4 *= PRIME64_1;
+
        h64 ^= v4;
+
        h64 = h64 * PRIME64_1 + PRIME64_4;
+
    }
+
    else
+
    {
+
        h64  = seed + PRIME64_5;
+
    }
+

+
    h64 += (U64) len;
+

+
    while (p+8<=bEnd)
+
    {
+
        U64 k1 = XXH_get64bits(p);
+
        k1 *= PRIME64_2;
+
        k1 = XXH_rotl64(k1,31);
+
        k1 *= PRIME64_1;
+
        h64 ^= k1;
+
        h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
+
        p+=8;
+
    }
+

+
    if (p+4<=bEnd)
+
    {
+
        h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
+
        h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
+
        p+=4;
+
    }
+

+
    while (p<bEnd)
+
    {
+
        h64 ^= (*p) * PRIME64_5;
+
        h64 = XXH_rotl64(h64, 11) * PRIME64_1;
+
        p++;
+
    }
+

+
    h64 ^= h64 >> 33;
+
    h64 *= PRIME64_2;
+
    h64 ^= h64 >> 29;
+
    h64 *= PRIME64_3;
+
    h64 ^= h64 >> 32;
+

+
    return h64;
+
}
+

+

+
uint64_t XXH64 (const void* input, size_t len, uint64_t seed)
+
{
+
#if 0
+
    // Simple version, good for code maintenance, but unfortunately slow for small inputs
+
    XXH64_state_t state;
+
    XXH64_reset(&state, seed);
+
    XXH64_update(&state, input, len);
+
    return XXH64_digest(&state);
+
#else
+
    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
+

+
#  if !defined(XXH_USE_UNALIGNED_ACCESS)
+
    if ((((size_t)input) & 7)==0)   // Input is aligned, let's leverage the speed advantage
+
    {
+
        if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+
            return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
+
        else
+
            return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
+
    }
+
#  endif
+

+
    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+
        return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
+
    else
+
        return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
+
#endif
+
}
+

+
/****************************************************
+
 *  Advanced Hash Functions
+
****************************************************/
+

+
/*** Allocation ***/
+
typedef struct
+
{
+
    U64 total_len;
+
    U32 seed;
+
    U32 v1;
+
    U32 v2;
+
    U32 v3;
+
    U32 v4;
+
    U32 mem32[4];   /* defined as U32 for alignment */
+
    U32 memsize;
+
} XXH_istate32_t;
+

+
typedef struct
+
{
+
    U64 total_len;
+
    U64 seed;
+
    U64 v1;
+
    U64 v2;
+
    U64 v3;
+
    U64 v4;
+
    U64 mem64[4];   /* defined as U64 for alignment */
+
    U32 memsize;
+
} XXH_istate64_t;
+

+

+
XXH32_state_t* XXH32_createState(void)
+
{
+
    XXH_STATIC_ASSERT(sizeof(XXH32_state_t) >= sizeof(XXH_istate32_t));   // A compilation error here means XXH32_state_t is not large enough
+
    return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
+
}
+

+
void* XXH32_init (unsigned seed)
+
{
+
	XXH32_state_t *st = XXH32_createState();
+
	XXH32_reset(st, seed);
+

+
	return st;
+
}
+

+
XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
+
{
+
    XXH_free(statePtr);
+
    return XXH_OK;
+
};
+

+
XXH64_state_t* XXH64_createState(void)
+
{
+
    XXH_STATIC_ASSERT(sizeof(XXH64_state_t) >= sizeof(XXH_istate64_t));   // A compilation error here means XXH64_state_t is not large enough
+
    return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
+
}
+
XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
+
{
+
    XXH_free(statePtr);
+
    return XXH_OK;
+
};
+

+

+
/*** Hash feed ***/
+

+
XXH_errorcode XXH32_reset(XXH32_state_t* state_in, U32 seed)
+
{
+
    XXH_istate32_t* state = (XXH_istate32_t*) state_in;
+
    state->seed = seed;
+
    state->v1 = seed + PRIME32_1 + PRIME32_2;
+
    state->v2 = seed + PRIME32_2;
+
    state->v3 = seed + 0;
+
    state->v4 = seed - PRIME32_1;
+
    state->total_len = 0;
+
    state->memsize = 0;
+
    return XXH_OK;
+
}
+

+
XXH_errorcode XXH64_reset(XXH64_state_t* state_in, uint64_t seed)
+
{
+
    XXH_istate64_t* state = (XXH_istate64_t*) state_in;
+
    state->seed = seed;
+
    state->v1 = seed + PRIME64_1 + PRIME64_2;
+
    state->v2 = seed + PRIME64_2;
+
    state->v3 = seed + 0;
+
    state->v4 = seed - PRIME64_1;
+
    state->total_len = 0;
+
    state->memsize = 0;
+
    return XXH_OK;
+
}
+

+

+
FORCE_INLINE XXH_errorcode XXH32_update_endian (XXH32_state_t* state_in, const void* input, size_t len, XXH_endianess endian)
+
{
+
    XXH_istate32_t* state = (XXH_istate32_t *) state_in;
+
    const BYTE* p = (const BYTE*)input;
+
    const BYTE* const bEnd = p + len;
+

+
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
+
    if (input==NULL) return XXH_ERROR;
+
#endif
+

+
    state->total_len += len;
+

+
    if (state->memsize + len < 16)   // fill in tmp buffer
+
    {
+
        XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
+
        state->memsize += (U32)len;
+
        return XXH_OK;
+
    }
+

+
    if (state->memsize)   // some data left from previous update
+
    {
+
        XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);
+
        {
+
            const U32* p32 = state->mem32;
+
            state->v1 += XXH_readLE32(p32, endian) * PRIME32_2;
+
            state->v1 = XXH_rotl32(state->v1, 13);
+
            state->v1 *= PRIME32_1;
+
            p32++;
+
            state->v2 += XXH_readLE32(p32, endian) * PRIME32_2;
+
            state->v2 = XXH_rotl32(state->v2, 13);
+
            state->v2 *= PRIME32_1;
+
            p32++;
+
            state->v3 += XXH_readLE32(p32, endian) * PRIME32_2;
+
            state->v3 = XXH_rotl32(state->v3, 13);
+
            state->v3 *= PRIME32_1;
+
            p32++;
+
            state->v4 += XXH_readLE32(p32, endian) * PRIME32_2;
+
            state->v4 = XXH_rotl32(state->v4, 13);
+
            state->v4 *= PRIME32_1;
+
            p32++;
+
        }
+
        p += 16-state->memsize;
+
        state->memsize = 0;
+
    }
+

+
    if (p <= bEnd-16)
+
    {
+
        const BYTE* const limit = bEnd - 16;
+
        U32 v1 = state->v1;
+
        U32 v2 = state->v2;
+
        U32 v3 = state->v3;
+
        U32 v4 = state->v4;
+

+
        do
+
        {
+
            v1 += XXH_readLE32(p, endian) * PRIME32_2;
+
            v1 = XXH_rotl32(v1, 13);
+
            v1 *= PRIME32_1;
+
            p+=4;
+
            v2 += XXH_readLE32(p, endian) * PRIME32_2;
+
            v2 = XXH_rotl32(v2, 13);
+
            v2 *= PRIME32_1;
+
            p+=4;
+
            v3 += XXH_readLE32(p, endian) * PRIME32_2;
+
            v3 = XXH_rotl32(v3, 13);
+
            v3 *= PRIME32_1;
+
            p+=4;
+
            v4 += XXH_readLE32(p, endian) * PRIME32_2;
+
            v4 = XXH_rotl32(v4, 13);
+
            v4 *= PRIME32_1;
+
            p+=4;
+
        }
+
        while (p<=limit);
+

+
        state->v1 = v1;
+
        state->v2 = v2;
+
        state->v3 = v3;
+
        state->v4 = v4;
+
    }
+

+
    if (p < bEnd)
+
    {
+
        XXH_memcpy(state->mem32, p, bEnd-p);
+
        state->memsize = (int)(bEnd-p);
+
    }
+

+
    return XXH_OK;
+
}
+

+
XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len)
+
{
+
    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
+

+
    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+
        return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
+
    else
+
        return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
+
}
+

+

+

+
FORCE_INLINE U32 XXH32_digest_endian (const XXH32_state_t* state_in, XXH_endianess endian)
+
{
+
    XXH_istate32_t* state = (XXH_istate32_t*) state_in;
+
    const BYTE * p = (const BYTE*)state->mem32;
+
    BYTE* bEnd = (BYTE*)(state->mem32) + state->memsize;
+
    U32 h32;
+

+
    if (state->total_len >= 16)
+
    {
+
        h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
+
    }
+
    else
+
    {
+
        h32  = state->seed + PRIME32_5;
+
    }
+

+
    h32 += (U32) state->total_len;
+

+
    while (p+4<=bEnd)
+
    {
+
        h32 += XXH_readLE32(p, endian) * PRIME32_3;
+
        h32  = XXH_rotl32(h32, 17) * PRIME32_4;
+
        p+=4;
+
    }
+

+
    while (p<bEnd)
+
    {
+
        h32 += (*p) * PRIME32_5;
+
        h32 = XXH_rotl32(h32, 11) * PRIME32_1;
+
        p++;
+
    }
+

+
    h32 ^= h32 >> 15;
+
    h32 *= PRIME32_2;
+
    h32 ^= h32 >> 13;
+
    h32 *= PRIME32_3;
+
    h32 ^= h32 >> 16;
+
#if 0
+
    XXH32_freeState((XXH32_state_t *)state_in);
+
#endif
+
    return h32;
+
}
+

+

+
U32 XXH32_digest (const XXH32_state_t* state_in)
+
{
+
    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
+

+
    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+
        return XXH32_digest_endian(state_in, XXH_littleEndian);
+
    else
+
        return XXH32_digest_endian(state_in, XXH_bigEndian);
+
}
+

+

+
FORCE_INLINE XXH_errorcode XXH64_update_endian (XXH64_state_t* state_in, const void* input, size_t len, XXH_endianess endian)
+
{
+
    XXH_istate64_t * state = (XXH_istate64_t *) state_in;
+
    const BYTE* p = (const BYTE*)input;
+
    const BYTE* const bEnd = p + len;
+

+
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
+
    if (input==NULL) return XXH_ERROR;
+
#endif
+

+
    state->total_len += len;
+

+
    if (state->memsize + len < 32)   // fill in tmp buffer
+
    {
+
        XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
+
        state->memsize += (U32)len;
+
        return XXH_OK;
+
    }
+

+
    if (state->memsize)   // some data left from previous update
+
    {
+
        XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);
+
        {
+
            const U64* p64 = state->mem64;
+
            state->v1 += XXH_readLE64(p64, endian) * PRIME64_2;
+
            state->v1 = XXH_rotl64(state->v1, 31);
+
            state->v1 *= PRIME64_1;
+
            p64++;
+
            state->v2 += XXH_readLE64(p64, endian) * PRIME64_2;
+
            state->v2 = XXH_rotl64(state->v2, 31);
+
            state->v2 *= PRIME64_1;
+
            p64++;
+
            state->v3 += XXH_readLE64(p64, endian) * PRIME64_2;
+
            state->v3 = XXH_rotl64(state->v3, 31);
+
            state->v3 *= PRIME64_1;
+
            p64++;
+
            state->v4 += XXH_readLE64(p64, endian) * PRIME64_2;
+
            state->v4 = XXH_rotl64(state->v4, 31);
+
            state->v4 *= PRIME64_1;
+
            p64++;
+
        }
+
        p += 32-state->memsize;
+
        state->memsize = 0;
+
    }
+

+
    if (p+32 <= bEnd)
+
    {
+
        const BYTE* const limit = bEnd - 32;
+
        U64 v1 = state->v1;
+
        U64 v2 = state->v2;
+
        U64 v3 = state->v3;
+
        U64 v4 = state->v4;
+

+
        do
+
        {
+
            v1 += XXH_readLE64(p, endian) * PRIME64_2;
+
            v1 = XXH_rotl64(v1, 31);
+
            v1 *= PRIME64_1;
+
            p+=8;
+
            v2 += XXH_readLE64(p, endian) * PRIME64_2;
+
            v2 = XXH_rotl64(v2, 31);
+
            v2 *= PRIME64_1;
+
            p+=8;
+
            v3 += XXH_readLE64(p, endian) * PRIME64_2;
+
            v3 = XXH_rotl64(v3, 31);
+
            v3 *= PRIME64_1;
+
            p+=8;
+
            v4 += XXH_readLE64(p, endian) * PRIME64_2;
+
            v4 = XXH_rotl64(v4, 31);
+
            v4 *= PRIME64_1;
+
            p+=8;
+
        }
+
        while (p<=limit);
+

+
        state->v1 = v1;
+
        state->v2 = v2;
+
        state->v3 = v3;
+
        state->v4 = v4;
+
    }
+

+
    if (p < bEnd)
+
    {
+
        XXH_memcpy(state->mem64, p, bEnd-p);
+
        state->memsize = (int)(bEnd-p);
+
    }
+

+
    return XXH_OK;
+
}
+

+
XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len)
+
{
+
    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
+

+
    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+
        return XXH64_update_endian(state_in, input, len, XXH_littleEndian);
+
    else
+
        return XXH64_update_endian(state_in, input, len, XXH_bigEndian);
+
}
+

+

+

+
FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state_in, XXH_endianess endian)
+
{
+
    XXH_istate64_t * state = (XXH_istate64_t *) state_in;
+
    const BYTE * p = (const BYTE*)state->mem64;
+
    BYTE* bEnd = (BYTE*)state->mem64 + state->memsize;
+
    U64 h64;
+

+
    if (state->total_len >= 32)
+
    {
+
        U64 v1 = state->v1;
+
        U64 v2 = state->v2;
+
        U64 v3 = state->v3;
+
        U64 v4 = state->v4;
+

+
        h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
+

+
        v1 *= PRIME64_2;
+
        v1 = XXH_rotl64(v1, 31);
+
        v1 *= PRIME64_1;
+
        h64 ^= v1;
+
        h64 = h64*PRIME64_1 + PRIME64_4;
+

+
        v2 *= PRIME64_2;
+
        v2 = XXH_rotl64(v2, 31);
+
        v2 *= PRIME64_1;
+
        h64 ^= v2;
+
        h64 = h64*PRIME64_1 + PRIME64_4;
+

+
        v3 *= PRIME64_2;
+
        v3 = XXH_rotl64(v3, 31);
+
        v3 *= PRIME64_1;
+
        h64 ^= v3;
+
        h64 = h64*PRIME64_1 + PRIME64_4;
+

+
        v4 *= PRIME64_2;
+
        v4 = XXH_rotl64(v4, 31);
+
        v4 *= PRIME64_1;
+
        h64 ^= v4;
+
        h64 = h64*PRIME64_1 + PRIME64_4;
+
    }
+
    else
+
    {
+
        h64  = state->seed + PRIME64_5;
+
    }
+

+
    h64 += (U64) state->total_len;
+

+
    while (p+8<=bEnd)
+
    {
+
        U64 k1 = XXH_readLE64(p, endian);
+
        k1 *= PRIME64_2;
+
        k1 = XXH_rotl64(k1,31);
+
        k1 *= PRIME64_1;
+
        h64 ^= k1;
+
        h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
+
        p+=8;
+
    }
+

+
    if (p+4<=bEnd)
+
    {
+
        h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;
+
        h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
+
        p+=4;
+
    }
+

+
    while (p<bEnd)
+
    {
+
        h64 ^= (*p) * PRIME64_5;
+
        h64 = XXH_rotl64(h64, 11) * PRIME64_1;
+
        p++;
+
    }
+

+
    h64 ^= h64 >> 33;
+
    h64 *= PRIME64_2;
+
    h64 ^= h64 >> 29;
+
    h64 *= PRIME64_3;
+
    h64 ^= h64 >> 32;
+
#if 0
+
    XXH64_freeState((XXH64_state_t *)state_in);
+
#endif
+
    return h64;
+
}
+

+

+
uint64_t XXH64_digest (const XXH64_state_t* state_in)
+
{
+
    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
+

+
    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+
        return XXH64_digest_endian(state_in, XXH_littleEndian);
+
    else
+
        return XXH64_digest_endian(state_in, XXH_bigEndian);
+
}
+

+

modified external/libucl/src/xxhash.h
@@ -1,164 +1,165 @@
-
/*
-
   xxHash - Fast Hash algorithm
-
   Header File
-
   Copyright (C) 2012-2013, Yann Collet.
-
   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-

-
   Redistribution and use in source and binary forms, with or without
-
   modification, are permitted provided that the following conditions are
-
   met:
-
  
-
       * Redistributions of source code must retain the above copyright
-
   notice, this list of conditions and the following disclaimer.
-
       * Redistributions in binary form must reproduce the above
-
   copyright notice, this list of conditions and the following disclaimer
-
   in the documentation and/or other materials provided with the
-
   distribution.
-
  
-
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-
   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-
   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-
   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-
   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-
   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-
   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-
   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-
   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-

-
   You can contact the author at :
-
   - xxHash source repository : http://code.google.com/p/xxhash/
-
*/
-

-
/* Notice extracted from xxHash homepage :
-

-
xxHash is an extremely fast Hash algorithm, running at RAM speed limits.
-
It also successfully passes all tests from the SMHasher suite.
-

-
Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz)
-

-
Name            Speed       Q.Score   Author
-
xxHash          5.4 GB/s     10
-
CrapWow         3.2 GB/s      2       Andrew
-
MumurHash 3a    2.7 GB/s     10       Austin Appleby
-
SpookyHash      2.0 GB/s     10       Bob Jenkins
-
SBox            1.4 GB/s      9       Bret Mulvey
-
Lookup3         1.2 GB/s      9       Bob Jenkins
-
SuperFastHash   1.2 GB/s      1       Paul Hsieh
-
CityHash64      1.05 GB/s    10       Pike & Alakuijala
-
FNV             0.55 GB/s     5       Fowler, Noll, Vo
-
CRC32           0.43 GB/s     9
-
MD5-32          0.33 GB/s    10       Ronald L. Rivest
-
SHA1-32         0.28 GB/s    10
-

-
Q.Score is a measure of quality of the hash function. 
-
It depends on successfully passing SMHasher test set. 
-
10 is a perfect score.
-
*/
-

-
#pragma once
-

-
#if defined (__cplusplus)
-
extern "C" {
-
#endif
-

-

-
//****************************
-
// Type
-
//****************************
-
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
-

-

-

-
//****************************
-
// Simple Hash Functions
-
//****************************
-

-
unsigned int XXH32 (const void* input, int len, unsigned int seed);
-

-
/*
-
XXH32() :
-
    Calculate the 32-bits hash of sequence of length "len" stored at memory address "input".
-
    The memory between input & input+len must be valid (allocated and read-accessible).
-
    "seed" can be used to alter the result predictably.
-
    This function successfully passes all SMHasher tests.
-
    Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s
-
    Note that "len" is type "int", which means it is limited to 2^31-1.
-
    If your data is larger, use the advanced functions below.
-
*/
-

-

-

-
//****************************
-
// Advanced Hash Functions
-
//****************************
-

-
void*         XXH32_init   (unsigned int seed);
-
XXH_errorcode XXH32_update (void* state, const void* input, int len);
-
unsigned int  XXH32_digest (void* state);
-

-
/*
-
These functions calculate the xxhash of an input provided in several small packets,
-
as opposed to an input provided as a single block.
-

-
It must be started with :
-
void* XXH32_init()
-
The function returns a pointer which holds the state of calculation.
-

-
This pointer must be provided as "void* state" parameter for XXH32_update().
-
XXH32_update() can be called as many times as necessary.
-
The user must provide a valid (allocated) input.
-
The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
-
Note that "len" is type "int", which means it is limited to 2^31-1. 
-
If your data is larger, it is recommended to chunk your data into blocks 
-
of size for example 2^30 (1GB) to avoid any "int" overflow issue.
-

-
Finally, you can end the calculation anytime, by using XXH32_digest().
-
This function returns the final 32-bits hash.
-
You must provide the same "void* state" parameter created by XXH32_init().
-
Memory will be freed by XXH32_digest().
-
*/
-

-

-
int           XXH32_sizeofState(void);
-
XXH_errorcode XXH32_resetState(void* state, unsigned int seed);
-

-
#define       XXH32_SIZEOFSTATE 48
-
typedef struct { long long ll[(XXH32_SIZEOFSTATE+(sizeof(long long)-1))/sizeof(long long)]; } XXH32_stateSpace_t;
-
/*
-
These functions allow user application to make its own allocation for state.
-

-
XXH32_sizeofState() is used to know how much space must be allocated for the xxHash 32-bits state.
-
Note that the state must be aligned to access 'long long' fields. Memory must be allocated and referenced by a pointer.
-
This pointer must then be provided as 'state' into XXH32_resetState(), which initializes the state.
-

-
For static allocation purposes (such as allocation on stack, or freestanding systems without malloc()),
-
use the structure XXH32_stateSpace_t, which will ensure that memory space is large enough and correctly aligned to access 'long long' fields.
-
*/
-

-

-
unsigned int XXH32_intermediateDigest (void* state);
-
/*
-
This function does the same as XXH32_digest(), generating a 32-bit hash,
-
but preserve memory context.
-
This way, it becomes possible to generate intermediate hashes, and then continue feeding data with XXH32_update().
-
To free memory context, use XXH32_digest(), or free().
-
*/
-

-

-

-
//****************************
-
// Deprecated function names
-
//****************************
-
// The following translations are provided to ease code transition
-
// You are encouraged to no longer this function names
-
#define XXH32_feed   XXH32_update
-
#define XXH32_result XXH32_digest
-
#define XXH32_getIntermediateResult XXH32_intermediateDigest
-

-

-

-
#if defined (__cplusplus)
-
}
-
#endif
+
/*
+
   xxHash - Extremely Fast Hash algorithm
+
   Header File
+
   Copyright (C) 2012-2014, Yann Collet.
+
   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+

+
   Redistribution and use in source and binary forms, with or without
+
   modification, are permitted provided that the following conditions are
+
   met:
+

+
       * Redistributions of source code must retain the above copyright
+
   notice, this list of conditions and the following disclaimer.
+
       * Redistributions in binary form must reproduce the above
+
   copyright notice, this list of conditions and the following disclaimer
+
   in the documentation and/or other materials provided with the
+
   distribution.
+

+
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+
   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+
   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+
   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+
   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+
   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+
   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+
   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+
   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+

+
   You can contact the author at :
+
   - xxHash source repository : http://code.google.com/p/xxhash/
+
*/
+

+
/* Notice extracted from xxHash homepage :
+

+
xxHash is an extremely fast Hash algorithm, running at RAM speed limits.
+
It also successfully passes all tests from the SMHasher suite.
+

+
Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz)
+

+
Name            Speed       Q.Score   Author
+
xxHash          5.4 GB/s     10
+
CrapWow         3.2 GB/s      2       Andrew
+
MumurHash 3a    2.7 GB/s     10       Austin Appleby
+
SpookyHash      2.0 GB/s     10       Bob Jenkins
+
SBox            1.4 GB/s      9       Bret Mulvey
+
Lookup3         1.2 GB/s      9       Bob Jenkins
+
SuperFastHash   1.2 GB/s      1       Paul Hsieh
+
CityHash64      1.05 GB/s    10       Pike & Alakuijala
+
FNV             0.55 GB/s     5       Fowler, Noll, Vo
+
CRC32           0.43 GB/s     9
+
MD5-32          0.33 GB/s    10       Ronald L. Rivest
+
SHA1-32         0.28 GB/s    10
+

+
Q.Score is a measure of quality of the hash function.
+
It depends on successfully passing SMHasher test set.
+
10 is a perfect score.
+
*/
+
#ifndef LIBUCL_XXHASH_H
+
#define LIBUCL_XXHASH_H
+

+
#if defined (__cplusplus)
+
extern "C" {
+
#endif
+

+

+
/*****************************
+
   Includes
+
*****************************/
+
#include <stddef.h>   /* size_t */
+
#include <stdint.h>
+

+

+
/*****************************
+
   Type
+
*****************************/
+
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
+

+

+

+
/*****************************
+
   Simple Hash Functions
+
*****************************/
+

+
unsigned int       XXH32 (const void* input, size_t length, unsigned seed);
+
uint64_t XXH64 (const void* input, size_t length, uint64_t seed);
+

+
/*
+
XXH32() :
+
    Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input".
+
    The memory between input & input+length must be valid (allocated and read-accessible).
+
    "seed" can be used to alter the result predictably.
+
    This function successfully passes all SMHasher tests.
+
    Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s
+
XXH64() :
+
    Calculate the 64-bits hash of sequence of length "len" stored at memory address "input".
+
*/
+

+

+

+
/*****************************
+
   Advanced Hash Functions
+
*****************************/
+
typedef struct { int64_t ll[ 6]; } XXH32_state_t;
+
typedef struct { int64_t ll[11]; } XXH64_state_t;
+

+
/*
+
These structures allow static allocation of XXH states.
+
States must then be initialized using XXHnn_reset() before first use.
+

+
If you prefer dynamic allocation, please refer to functions below.
+
*/
+

+
/*
+
 * !!!
+
 * Rspamd specific: we use the legacy method to free state when digest is obtained
+
 * !!!
+
 */
+
void * XXH32_init (unsigned seed);
+
XXH32_state_t* XXH32_createState(void);
+
XXH_errorcode  XXH32_freeState(XXH32_state_t* statePtr);
+

+
XXH64_state_t* XXH64_createState(void);
+
XXH_errorcode  XXH64_freeState(XXH64_state_t* statePtr);
+

+
/*
+
These functions create and release memory for XXH state.
+
States must then be initialized using XXHnn_reset() before first use.
+
*/
+

+

+
XXH_errorcode XXH32_reset  (XXH32_state_t* statePtr, unsigned seed);
+
XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
+
unsigned int  XXH32_digest (const XXH32_state_t* statePtr);
+

+
XXH_errorcode      XXH64_reset  (XXH64_state_t* statePtr, uint64_t seed);
+
XXH_errorcode      XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
+
uint64_t XXH64_digest (const XXH64_state_t* statePtr);
+

+
/*
+
These functions calculate the xxHash of an input provided in multiple smaller packets,
+
as opposed to an input provided as a single block.
+

+
XXH state space must first be allocated, using either static or dynamic method provided above.
+

+
Start a new hash by initializing state with a seed, using XXHnn_reset().
+

+
Then, feed the hash state by calling XXHnn_update() as many times as necessary.
+
Obviously, input must be valid, meaning allocated and read accessible.
+
The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
+

+
Finally, you can produce a hash anytime, by using XXHnn_digest().
+
This function returns the final nn-bits hash.
+
You can nonetheless continue feeding the hash state with more input,
+
and therefore get some new hashes, by calling again XXHnn_digest().
+

+
When you are done, don't forget to free XXH state space, using typically XXHnn_freeState().
+
*/
+

+

+
#if defined (__cplusplus)
+
}
+
#endif
+

+
#endif
modified external/libucl/tests/basic/13.in
@@ -1,7 +1,7 @@
key = value_orig;

# test glob
-
.include(glob=true) "${CURDIR}/include_dir/test*.conf"
+
.include(glob=true,something="test") "${CURDIR}/include_dir/test*.conf"

.include(priority=1) "${CURDIR}/include_dir/pri1.conf"
.include(priority=2) "${CURDIR}/include_dir/pri2.conf"
modified external/libucl/tests/test_basic.c
@@ -27,13 +27,14 @@
int
main (int argc, char **argv)
{
-
	char inbuf[8192], *test_in = NULL;
+
	char *inbuf;
	struct ucl_parser *parser = NULL, *parser2 = NULL;
	ucl_object_t *obj;
+
	ssize_t bufsize, r;
	FILE *in, *out;
	unsigned char *emitted = NULL;
	const char *fname_in = NULL, *fname_out = NULL;
-
	int ret = 0, inlen, opt, json = 0, compact = 0, yaml = 0;
+
	int ret = 0, opt, json = 0, compact = 0, yaml = 0;

	while ((opt = getopt(argc, argv, "jcy")) != -1) {
		switch (opt) {
@@ -82,16 +83,28 @@ main (int argc, char **argv)
		ucl_parser_set_filevars (parser, fname_in, true);
	}

-
	while (!feof (in)) {
-
		memset (inbuf, 0, sizeof (inbuf));
-
		if (fread (inbuf, 1, sizeof (inbuf) - 1, in) == 0) {
-
			break;
+
	inbuf = malloc (BUFSIZ);
+
	bufsize = BUFSIZ;
+
	r = 0;
+

+
	while (!feof (in) && !ferror (in)) {
+
		if (r == bufsize) {
+
			inbuf = realloc (inbuf, bufsize * 2);
+
			bufsize *= 2;
+
			if (inbuf == NULL) {
+
				perror ("realloc");
+
				exit (EXIT_FAILURE);
+
			}
		}
-
		inlen = strlen (inbuf);
-
		test_in = malloc (inlen);
-
		memcpy (test_in, inbuf, inlen);
-
		ucl_parser_add_chunk (parser, (const unsigned char *)test_in, inlen);
+
		r += fread (inbuf + r, 1, bufsize - r, in);
+
	}
+

+
	if (ferror (in)) {
+
		fprintf (stderr, "Failed to read the input file.\n");
+
		exit (EXIT_FAILURE);
	}
+

+
	ucl_parser_add_chunk (parser, (const unsigned char *)inbuf, r);
	fclose (in);

	if (fname_out != NULL) {
@@ -103,12 +116,15 @@ main (int argc, char **argv)
	else {
		out = stdout;
	}
+

	if (ucl_parser_get_error (parser) != NULL) {
		fprintf (out, "Error occurred: %s\n", ucl_parser_get_error(parser));
		ret = 1;
		goto end;
	}
+

	obj = ucl_parser_get_object (parser);
+

	if (json) {
		if (compact) {
			emitted = ucl_object_emit (obj, UCL_EMIT_JSON_COMPACT);
@@ -123,6 +139,7 @@ main (int argc, char **argv)
	else {
		emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG);
	}
+

	ucl_parser_free (parser);
	ucl_object_unref (obj);
	parser2 = ucl_parser_new (UCL_PARSER_KEY_LOWERCASE);
@@ -134,9 +151,11 @@ main (int argc, char **argv)
		ret = 1;
		goto end;
	}
+

	if (emitted != NULL) {
		free (emitted);
	}
+

	obj = ucl_parser_get_object (parser2);
	if (json) {
		if (compact) {
@@ -163,8 +182,8 @@ end:
	if (parser2 != NULL) {
		ucl_parser_free (parser2);
	}
-
	if (test_in != NULL) {
-
		free (test_in);
+
	if (inbuf != NULL) {
+
		free (inbuf);
	}

	fclose (out);
modified external/libucl/utils/Makefile.am
@@ -11,8 +11,12 @@ ucl_objdump_SOURCES = objdump.c
ucl_objdump_LDADD = $(common_utils_ldadd)
ucl_objdump_CFLAGS = $(common_utils_cflags)

+
ucl_tool_SOURCES = ucl-tool.c
+
ucl_tool_LDADD = $(common_utils_ldadd)
+
ucl_tool_CFLAGS = $(common_utils_cflags)
+

if UTILS
-
UTL = ucl_chargen ucl_objdump
+
UTL = ucl_chargen ucl_objdump ucl_tool
else
UTL =
endif
modified external/libucl/utils/objdump.c
@@ -46,7 +46,7 @@ ucl_obj_dump (const ucl_object_t *obj, unsigned int shift)
		if (obj->key != NULL) {
			printf ("%skey: \"%s\"\n", pre, ucl_object_key (obj));
		}
-
		printf ("%sref: %hd\n", pre, obj->ref);
+
		printf ("%sref: %u\n", pre, obj->ref);
		printf ("%slen: %u\n", pre, obj->len);
		printf ("%sprev: %p\n", pre, obj->prev);
		printf ("%snext: %p\n", pre, obj->next);
@@ -61,7 +61,10 @@ ucl_obj_dump (const ucl_object_t *obj, unsigned int shift)
		else if (obj->type == UCL_ARRAY) {
			printf ("%stype: UCL_ARRAY\n", pre);
			printf ("%svalue: %p\n", pre, obj->value.av);
-
			ucl_obj_dump (obj->value.av, shift + 2);
+
			it_obj = NULL;
+
			while ((cur = ucl_iterate_object (obj, &it_obj, true))) {
+
				ucl_obj_dump (cur, shift + 2);
+
			}
		}
		else if (obj->type == UCL_INT) {
			printf ("%stype: UCL_INT\n", pre);
@@ -96,9 +99,10 @@ int
main(int argc, char **argv)
{
	const char *fn = NULL;
-
	char inbuf[8192];
+
	unsigned char *inbuf;
	struct ucl_parser *parser;
	int k, ret = 0, r = 0;
+
	ssize_t bufsize;
	ucl_object_t *obj = NULL;
	const ucl_object_t *par;
	FILE *in;
@@ -118,9 +122,27 @@ main(int argc, char **argv)
	}

	parser = ucl_parser_new (0);
-
	while (!feof (in) && r < (int)sizeof (inbuf)) {
-
		r += fread (inbuf + r, 1, sizeof (inbuf) - r, in);
+
	inbuf = malloc (BUFSIZ);
+
	bufsize = BUFSIZ;
+
	r = 0;
+

+
	while (!feof (in) && !ferror (in)) {
+
		if (r == bufsize) {
+
			inbuf = realloc (inbuf, bufsize * 2);
+
			bufsize *= 2;
+
			if (inbuf == NULL) {
+
				perror ("realloc");
+
				exit (EXIT_FAILURE);
+
			}
+
		}
+
		r += fread (inbuf + r, 1, bufsize - r, in);
	}
+

+
	if (ferror (in)) {
+
		fprintf (stderr, "Failed to read the input file.\n");
+
		exit (EXIT_FAILURE);
+
	}
+

	ucl_parser_add_chunk (parser, inbuf, r);
	fclose (in);
	if (ucl_parser_get_error(parser)) {