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
*/
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
#include "kvec.h"
#include <time.h>
+#include <limits.h>
struct ucl_hash_elt {
const ucl_object_t *obj;
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)
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)
{
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)
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;
}
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);
}
}
}
if (new == NULL) {
return NULL;
}
+
memset (new, 0, sizeof (struct ucl_parser));
ucl_parser_register_macro (new, "include", ucl_include_handler, new);
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,
{
struct ucl_chunk *chunk;
+ if (parser == NULL) {
+ return false;
+ }
+
if (data == NULL) {
ucl_create_err (&parser->err, "invalid chunk added");
return false;
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
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';
else {
*t++ = *h++;
}
- len --;
+
+ if (len > 0) {
+ len --;
+ }
}
*t = '\0';
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) {
if (parser->err == NULL)
return NULL;
- return utstring_body(parser->err);
+ return utstring_body (parser->err);
}
UCL_EXTERN void
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)