From 253aee289e1a6b6c3cefd11b3f719655226dc34d Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sun, 17 May 2015 16:10:29 +0100 Subject: [PATCH] Backport fixes from libucl. --- contrib/libucl/ucl.h | 18 ++++++++++++ contrib/libucl/ucl_hash.c | 53 +++++++++++++++++++++++++++++++++++ contrib/libucl/ucl_internal.h | 1 + contrib/libucl/ucl_parser.c | 26 +++++++++++++++-- contrib/libucl/ucl_util.c | 35 +++++++++++++++++++++-- 5 files changed, 127 insertions(+), 6 deletions(-) diff --git a/contrib/libucl/ucl.h b/contrib/libucl/ucl.h index 7262c8e11..0fbd5b822 100644 --- a/contrib/libucl/ucl.h +++ b/contrib/libucl/ucl.h @@ -497,6 +497,15 @@ UCL_EXTERN ucl_object_t* ucl_array_pop_first (ucl_object_t *top); 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 @@ -791,6 +800,15 @@ 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 diff --git a/contrib/libucl/ucl_hash.c b/contrib/libucl/ucl_hash.c index ddddf1dd0..4730b82b8 100644 --- a/contrib/libucl/ucl_hash.c +++ b/contrib/libucl/ucl_hash.c @@ -27,6 +27,7 @@ #include "kvec.h" #include +#include struct ucl_hash_elt { const ucl_object_t *obj; @@ -87,11 +88,19 @@ static const unsigned char lc_map[256] = { 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; +#if (defined(WORD_BIT) && WORD_BIT == 64) || (defined(__WORDSIZE) && __WORDSIZE == 64) 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, ucl_hash_seed ()); +} +#endif static inline int ucl_hash_equal (const ucl_object_t *k1, const ucl_object_t *k2) @@ -106,6 +115,7 @@ 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) +#if (defined(WORD_BIT) && WORD_BIT == 64) || (defined(__WORDSIZE) && __WORDSIZE == 64) static inline uint32_t ucl_hash_caseless_func (const ucl_object_t *o) { @@ -147,6 +157,49 @@ ucl_hash_caseless_func (const ucl_object_t *o) 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)); + } + + 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 (&st); +} +#endif static inline int ucl_hash_caseless_equal (const ucl_object_t *k1, const ucl_object_t *k2) diff --git a/contrib/libucl/ucl_internal.h b/contrib/libucl/ucl_internal.h index 0bb225148..836fcad80 100644 --- a/contrib/libucl/ucl_internal.h +++ b/contrib/libucl/ucl_internal.h @@ -191,6 +191,7 @@ struct ucl_parser { enum ucl_parser_state prev_state; unsigned int recursion; int flags; + unsigned default_priority; ucl_object_t *top_obj; ucl_object_t *cur_obj; ucl_object_t *trash_objs; diff --git a/contrib/libucl/ucl_parser.c b/contrib/libucl/ucl_parser.c index 4b5005be6..804744972 100644 --- a/contrib/libucl/ucl_parser.c +++ b/contrib/libucl/ucl_parser.c @@ -981,14 +981,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); } } } @@ -2091,6 +2090,7 @@ 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); @@ -2105,6 +2105,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, @@ -2194,6 +2205,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; @@ -2234,7 +2249,12 @@ 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 diff --git a/contrib/libucl/ucl_util.c b/contrib/libucl/ucl_util.c index d976b0d71..c8ea06c26 100644 --- a/contrib/libucl/ucl_util.c +++ b/contrib/libucl/ucl_util.c @@ -268,6 +268,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'; @@ -352,7 +363,10 @@ ucl_unescape_json_string (char *str, size_t len) else { *t++ = *h++; } - len --; + + if (len > 0) { + len --; + } } *t = '\0'; @@ -459,7 +473,7 @@ ucl_parser_free (struct ucl_parser *parser) UCL_FREE (sizeof (struct ucl_variable), var); } LL_FOREACH_SAFE (parser->trash_objs, tr, trtmp) { - ucl_object_unref (tr); + ucl_object_free_internal (tr, false, ucl_object_dtor_free); } if (parser->err != NULL) { @@ -483,7 +497,7 @@ ucl_parser_get_error(struct ucl_parser *parser) if (parser->err == NULL) return NULL; - return utstring_body(parser->err); + return utstring_body (parser->err); } UCL_EXTERN void @@ -2153,6 +2167,21 @@ 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; + + 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) -- 2.39.5