Author: bapt
Date: Sat May 24 23:46:41 2014
New Revision: 266636
URL: http://svnweb.freebsd.org/changeset/base/266636

Log:
  merge libucl 20140514
  
  this version brings xpath-like interface for ucl objects

Modified:
  head/contrib/libucl/configure.ac
  head/contrib/libucl/include/ucl.h
  head/contrib/libucl/src/ucl_internal.h
  head/contrib/libucl/src/ucl_parser.c
  head/contrib/libucl/src/ucl_util.c
  head/contrib/libucl/tests/test_generate.c
Directory Properties:
  head/contrib/libucl/   (props changed)

Modified: head/contrib/libucl/configure.ac
==============================================================================
--- head/contrib/libucl/configure.ac    Sat May 24 23:42:44 2014        
(r266635)
+++ head/contrib/libucl/configure.ac    Sat May 24 23:46:41 2014        
(r266636)
@@ -1,7 +1,7 @@
 m4_define([maj_ver], [0])
 m4_define([med_ver], [4])
-m4_define([min_ver], [0])
-m4_define([so_version], [maj_ver:med_ver])
+m4_define([min_ver], [1])
+m4_define([so_version], [1:0:0])
 m4_define([ucl_version], [maj_ver.med_ver.min_ver])
 
 AC_INIT([libucl],[ucl_version],[https://github.com/vstakhov/libucl],[libucl])

Modified: head/contrib/libucl/include/ucl.h
==============================================================================
--- head/contrib/libucl/include/ucl.h   Sat May 24 23:42:44 2014        
(r266635)
+++ head/contrib/libucl/include/ucl.h   Sat May 24 23:46:41 2014        
(r266636)
@@ -236,7 +236,13 @@ UCL_EXTERN ucl_object_t* ucl_object_new 
  * @param type type of a new object
  * @return new object
  */
-UCL_EXTERN ucl_object_t* ucl_object_typed_new (unsigned int type) 
UCL_WARN_UNUSED_RESULT;
+UCL_EXTERN ucl_object_t* ucl_object_typed_new (ucl_type_t type) 
UCL_WARN_UNUSED_RESULT;
+
+/**
+ * Return the type of an object
+ * @return the object type
+ */
+UCL_EXTERN ucl_type_t ucl_object_type (const ucl_object_t *obj);
 
 /**
  * Convert any string to an ucl object making the specified transformations
@@ -413,6 +419,15 @@ UCL_EXTERN const ucl_object_t* ucl_array
 UCL_EXTERN ucl_object_t* ucl_array_pop_last (ucl_object_t *top);
 
 /**
+ * Return object identified by an index of the array `top`
+ * @param obj object to get a key from (must be of type UCL_ARRAY)
+ * @param index index to return
+ * @return object at the specified index or NULL if index is not found
+ */
+UCL_EXTERN const ucl_object_t* ucl_array_find_index (const ucl_object_t *top,
+               unsigned int index);
+
+/**
  * Removes the first element from the array `top`. Caller must unref the 
returned object when it is not
  * needed.
  * @param top array ucl object
@@ -534,6 +549,15 @@ UCL_EXTERN const ucl_object_t* ucl_objec
                const char *key, size_t klen);
 
 /**
+ * Return object identified by dot notation string
+ * @param obj object to search in
+ * @param path dot.notation.path to the path to lookup. May use numeric .index 
on arrays
+ * @return object matched the specified path or NULL if path is not found
+ */
+UCL_EXTERN const ucl_object_t *ucl_lookup_path (const ucl_object_t *obj,
+               const char *path);
+
+/**
  * Returns a key of an object as a NULL terminated string
  * @param obj CL object
  * @return key or NULL if there is no key
@@ -643,6 +667,19 @@ UCL_EXTERN void ucl_parser_register_macr
                ucl_macro_handler handler, void* ud);
 
 /**
+ * Handler to detect unregistered variables
+ * @param data variable data
+ * @param len length of variable
+ * @param replace (out) replace value for variable
+ * @param replace_len (out) replace length for variable
+ * @param need_free (out) UCL will free `dest` after usage
+ * @param ud opaque userdata
+ * @return true if variable
+ */
+typedef bool (*ucl_variable_handler) (const unsigned char *data, size_t len,
+               unsigned char **replace, size_t *replace_len, bool *need_free, 
void* ud);
+
+/**
  * Register new parser variable
  * @param parser parser object
  * @param var variable name
@@ -652,6 +689,15 @@ UCL_EXTERN void ucl_parser_register_vari
                const char *value);
 
 /**
+ * Set handler for unknown variables
+ * @param parser parser structure
+ * @param handler desired handler
+ * @param ud opaque data for the handler
+ */
+UCL_EXTERN void ucl_parser_set_variables_handler (struct ucl_parser *parser,
+               ucl_variable_handler handler, void *ud);
+
+/**
  * Load new chunk to a parser
  * @param parser parser structure
  * @param data the pointer to the beginning of a chunk

Modified: head/contrib/libucl/src/ucl_internal.h
==============================================================================
--- head/contrib/libucl/src/ucl_internal.h      Sat May 24 23:42:44 2014        
(r266635)
+++ head/contrib/libucl/src/ucl_internal.h      Sat May 24 23:46:41 2014        
(r266636)
@@ -197,6 +197,8 @@ struct ucl_parser {
        struct ucl_chunk *chunks;
        struct ucl_pubkey *keys;
        struct ucl_variable *variables;
+       ucl_variable_handler var_handler;
+       void *var_data;
        UT_string *err;
 };
 

Modified: head/contrib/libucl/src/ucl_parser.c
==============================================================================
--- head/contrib/libucl/src/ucl_parser.c        Sat May 24 23:42:44 2014        
(r266635)
+++ head/contrib/libucl/src/ucl_parser.c        Sat May 24 23:46:41 2014        
(r266636)
@@ -236,6 +236,9 @@ ucl_check_variable_safe (struct ucl_pars
                size_t *out_len, bool strict, bool *found)
 {
        struct ucl_variable *var;
+       unsigned char *dst;
+       size_t dstlen;
+       bool need_free = false;
 
        LL_FOREACH (parser->variables, var) {
                if (strict) {
@@ -258,6 +261,19 @@ ucl_check_variable_safe (struct ucl_pars
                }
        }
 
+       /* XXX: can only handle ${VAR} */
+       if (!(*found) && parser->var_handler != NULL && strict) {
+               /* Call generic handler */
+               if (parser->var_handler (ptr, remain, &dst, &dstlen, &need_free,
+                               parser->var_data)) {
+                       *found = true;
+                       if (need_free) {
+                               free (dst);
+                       }
+                       return (ptr + remain);
+               }
+       }
+
        return ptr;
 }
 
@@ -271,7 +287,8 @@ ucl_check_variable_safe (struct ucl_pars
  * @return
  */
 static const char *
-ucl_check_variable (struct ucl_parser *parser, const char *ptr, size_t remain, 
size_t *out_len, bool *vars_found)
+ucl_check_variable (struct ucl_parser *parser, const char *ptr,
+               size_t remain, size_t *out_len, bool *vars_found)
 {
        const char *p, *end, *ret = ptr;
        bool found = false;
@@ -282,7 +299,8 @@ ucl_check_variable (struct ucl_parser *p
                end = ptr + remain;
                while (p < end) {
                        if (*p == '}') {
-                               ret = ucl_check_variable_safe (parser, ptr + 1, 
p - ptr - 1, out_len, true, &found);
+                               ret = ucl_check_variable_safe (parser, ptr + 1, 
p - ptr - 1,
+                                               out_len, true, &found);
                                if (found) {
                                        /* {} must be excluded actually */
                                        ret ++;
@@ -328,10 +346,13 @@ static const char *
 ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr,
                size_t remain, unsigned char **dest)
 {
-       unsigned char *d = *dest;
+       unsigned char *d = *dest, *dst;
        const char *p = ptr + 1, *ret;
        struct ucl_variable *var;
+       size_t dstlen;
+       bool need_free = false;
        bool found = false;
+       bool strict = false;
 
        ret = ptr + 1;
        remain --;
@@ -343,6 +364,7 @@ ucl_expand_single_variable (struct ucl_p
        }
        else if (*p == '{') {
                p ++;
+               strict = true;
                ret += 2;
                remain -= 2;
        }
@@ -359,9 +381,22 @@ ucl_expand_single_variable (struct ucl_p
                }
        }
        if (!found) {
-               memcpy (d, ptr, 2);
-               d += 2;
-               ret --;
+               if (strict && parser->var_handler != NULL) {
+                       if (parser->var_handler (ptr, remain, &dst, &dstlen, 
&need_free,
+                                                       parser->var_data)) {
+                               memcpy (d, dst, dstlen);
+                               ret += dstlen;
+                               d += remain;
+                               found = true;
+                       }
+               }
+
+               /* Leave variable as is */
+               if (!found) {
+                       memcpy (d, ptr, 2);
+                       d += 2;
+                       ret --;
+               }
        }
 
        *dest = d;
@@ -1873,6 +1908,14 @@ ucl_parser_register_variable (struct ucl
        }
 }
 
+void
+ucl_parser_set_variables_handler (struct ucl_parser *parser,
+               ucl_variable_handler handler, void *ud)
+{
+       parser->var_handler = handler;
+       parser->var_data = ud;
+}
+
 bool
 ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data,
                size_t len)

Modified: head/contrib/libucl/src/ucl_util.c
==============================================================================
--- head/contrib/libucl/src/ucl_util.c  Sat May 24 23:42:44 2014        
(r266635)
+++ head/contrib/libucl/src/ucl_util.c  Sat May 24 23:46:41 2014        
(r266636)
@@ -1330,20 +1330,10 @@ ucl_object_find_keyl (const ucl_object_t
 const ucl_object_t *
 ucl_object_find_key (const ucl_object_t *obj, const char *key)
 {
-       size_t klen;
-       const ucl_object_t *ret;
-       ucl_object_t srch;
-
-       if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
+       if (key == NULL)
                return NULL;
-       }
 
-       klen = strlen (key);
-       srch.key = key;
-       srch.keylen = klen;
-       ret = ucl_hash_search_obj (obj->value.ov, &srch);
-
-       return ret;
+       return ucl_object_find_keyl (obj, key, strlen(key));
 }
 
 const ucl_object_t*
@@ -1396,6 +1386,58 @@ ucl_iterate_object (const ucl_object_t *
        return NULL;
 }
 
+const ucl_object_t *
+ucl_lookup_path (const ucl_object_t *top, const char *path_in) {
+       const ucl_object_t *o = NULL, *found;
+       const char *p, *c;
+       char *err_str;
+       unsigned index;
+
+       if (path_in == NULL || top == NULL) {
+               return NULL;
+       }
+
+       found = NULL;
+       p = path_in;
+
+       /* Skip leading dots */
+       while (*p == '.') {
+               p ++;
+       }
+
+       c = p;
+       while (*p != '\0') {
+               p ++;
+               if (*p == '.' || *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')) {
+                                               return NULL;
+                                       }
+                                       o = ucl_array_find_index (top, index);
+                                       break;
+                               default:
+                                       o = ucl_object_find_keyl (top, c, p - 
c);
+                                       break;
+                               }
+                               if (o == NULL) {
+                                       return NULL;
+                               }
+                               top = o;
+                       }
+                       if (*p != '\0') {
+                               c = p + 1;
+                       }
+               }
+       }
+       found = o;
+
+       return found;
+}
+
 
 ucl_object_t *
 ucl_object_new (void)
@@ -1411,7 +1453,7 @@ ucl_object_new (void)
 }
 
 ucl_object_t *
-ucl_object_typed_new (unsigned int type)
+ucl_object_typed_new (ucl_type_t type)
 {
        ucl_object_t *new;
        new = malloc (sizeof (ucl_object_t));
@@ -1423,6 +1465,12 @@ ucl_object_typed_new (unsigned int type)
        return new;
 }
 
+ucl_type_t
+ucl_object_type (const ucl_object_t *obj)
+{
+       return obj->type;
+}
+
 ucl_object_t*
 ucl_object_fromstring (const char *str)
 {
@@ -1591,6 +1639,27 @@ ucl_array_pop_first (ucl_object_t *top)
        return ucl_array_delete (top, __DECONST(ucl_object_t *, ucl_array_head 
(top)));
 }
 
+const ucl_object_t *
+ucl_array_find_index (const ucl_object_t *top, unsigned int index)
+{
+       ucl_object_iter_t it = NULL;
+       const ucl_object_t *ret;
+
+       if (top == NULL || top->type != UCL_ARRAY || top->len == 0 ||
+           (index + 1) > top->len) {
+               return NULL;
+       }
+
+       while ((ret = ucl_iterate_object (top, &it, true)) != NULL) {
+               if (index == 0) {
+                       return ret;
+               }
+               --index;
+       }
+
+       return NULL;
+}
+
 ucl_object_t *
 ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
 {

Modified: head/contrib/libucl/tests/test_generate.c
==============================================================================
--- head/contrib/libucl/tests/test_generate.c   Sat May 24 23:42:44 2014        
(r266635)
+++ head/contrib/libucl/tests/test_generate.c   Sat May 24 23:46:41 2014        
(r266636)
@@ -30,6 +30,7 @@ int
 main (int argc, char **argv)
 {
        ucl_object_t *obj, *cur, *ar, *ref;
+       const ucl_object_t *found;
        FILE *out;
        unsigned char *emitted;
        const char *fname_out = NULL;
@@ -114,6 +115,23 @@ main (int argc, char **argv)
        cur = ucl_object_frombool (true);
        ucl_object_insert_key (obj, cur, "k=3", 0, false);
 
+       /* Try to find using path */
+       /* Should exist */
+       found = ucl_lookup_path (obj, "key4.1");
+       assert (found != NULL && ucl_object_toint (found) == 10);
+       /* . should be ignored */
+       found = ucl_lookup_path (obj, ".key4.1");
+       assert (found != NULL && ucl_object_toint (found) == 10);
+       /* moar dots... */
+       found = ucl_lookup_path (obj, ".key4........1...");
+       assert (found != NULL && ucl_object_toint (found) == 10);
+       /* No such index */
+       found = ucl_lookup_path (obj, ".key4.3");
+       assert (found == NULL);
+       /* No such key */
+       found = ucl_lookup_path (obj, "key9..key1");
+       assert (found == NULL);
+
        emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG);
 
        fprintf (out, "%s\n", emitted);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to