Radish alpha
H
HardenedBSD Package Manager
Radicle
Git (anonymous pull)
Log in to clone via SSH
Update libucl to latest version
Baptiste Daroussin committed 10 years ago
commit 69206ba10d0c7731680be601ef7c1bc139583737
parent 7236e35663a49eeabf81770a4a2686d545928a49
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)) {