srcs/toolbox/json.c

00001 /* 
00002  * Copyright (c) 2005-2012 by KoanLogic s.r.l. - All rights reserved.  
00003  */
00004 
00005 #include <stdlib.h>
00006 #include <string.h>
00007 #include <ctype.h>
00008 #include <math.h>
00009 
00010 #include <toolbox/json.h>
00011 #include <toolbox/carpal.h>
00012 #include <toolbox/misc.h>
00013 #include <toolbox/memory.h>
00014 #include <toolbox/lexer.h>
00015 
00016 /* Internal representation of any JSON value. */
00017 struct u_json_s
00018 {
00019     u_json_type_t type;
00020 
00021     char fqn[U_JSON_FQN_SZ];    /* Fully qualified name of this (sub)object. */
00022     char key[U_TOKEN_SZ];       /* Local name, if applicable (i.e. !anon) */
00023     char val[U_TOKEN_SZ];       /* If applicable, i.e. (!OBJECT && !ARRAY) */
00024 
00025     /* Parent container. */
00026     struct u_json_s *parent;            
00027 
00028     /* Nodes at the same level as this one (if any). */
00029     TAILQ_ENTRY(u_json_s) siblings;
00030 
00031     /* Children nodes' list when i.e. (ARRAY || OBJECT). */
00032     TAILQ_HEAD(u_json_chld_s, u_json_s) children;
00033 
00034     unsigned int depth;         /* Depth of this node in the decoded tree. */
00035 
00036     /* Cacheing machinery. */
00037     unsigned int icur, count;   /* Aux stuff used when indexing arrays. */
00038     u_hmap_t *map;              /* Alias reference to the global cache. */
00039 };
00040 
00041 /* Pointer to the name part of .fqn */
00042 #define U_JSON_OBJ_NAME(jo) \
00043         ((jo->parent != NULL) ? jo->fqn + strlen(p->fqn) : jo->fqn)
00044 
00045 #define U_JSON_OBJ_IS_CONTAINER(jo) \
00046         ((jo->type == U_JSON_TYPE_OBJECT) || (jo->type == U_JSON_TYPE_ARRAY))
00047 
00048 #define U_JSON_OBJ_IS_BOOL(jo) \
00049         ((jo->type == U_JSON_TYPE_TRUE) || (jo->type == U_JSON_TYPE_FALSE))
00050 
00051 /* Lexer methods */
00052 static int u_json_match_value (u_lexer_t *jl, u_json_t *jo);
00053 static int u_json_match_number_first (u_lexer_t *jl);
00054 static int u_json_match_number (u_lexer_t *jl, u_json_t *jo);
00055 static int u_json_match_int (u_lexer_t *jl);
00056 static int u_json_match_frac_first (char c);
00057 static int u_json_match_frac (u_lexer_t *jl);
00058 static int u_json_match_exp_first (char c);
00059 static int u_json_match_exp (u_lexer_t *jl);
00060 static int u_json_match_true_first (u_lexer_t *jl);
00061 static int u_json_match_false_first (u_lexer_t *jl);
00062 static int u_json_match_true (u_lexer_t *jl, u_json_t *jo);
00063 static int u_json_match_false (u_lexer_t *jl, u_json_t *jo);
00064 static int u_json_match_null_first (u_lexer_t *jl);
00065 static int u_json_match_null (u_lexer_t *jl, u_json_t *jo);
00066 static int u_json_match_string (u_lexer_t *jl, u_json_t *jo);
00067 static int u_json_match_string_first (u_lexer_t *jl);
00068 static int u_json_match_escaped_unicode (u_lexer_t *jl);
00069 static int u_json_match_object (u_lexer_t *jl, u_json_t *jo);
00070 static int u_json_match_object_first (u_lexer_t *jl);
00071 static int u_json_match_array (u_lexer_t *jl, u_json_t *jo);
00072 static int u_json_match_array_first (u_lexer_t *jl);
00073 static int u_json_match_pair (u_lexer_t *jl, u_json_t *jo);
00074 static int u_json_match_pair_first (u_lexer_t *jl);
00075 
00076 /* Lexer misc stuff. */
00077 static int u_json_match_seq (u_lexer_t *jl, u_json_t *jo, int type, 
00078         char first, const char *rem, size_t rem_sz);
00079 static const char *u_json_type_str (int type);
00080 
00081 /* Objects misc stuff. */
00082 static void u_json_do_print (u_json_t *jo, size_t l, void *opaque);
00083 static void u_json_do_free (u_json_t *jo, size_t l, void *opaque);
00084 static void u_json_do_index (u_json_t *jo, size_t l, void *map);
00085 
00086 /* Encode/Decode/Validate. */
00087 static int u_json_do_encode (u_json_t *jo, u_string_t *s);
00088 static int u_json_do_parse (const char *json, u_json_t **pjo, 
00089         char status[U_LEXER_ERR_SZ]);
00090 
00091 /* Needed by hmap_easy* because we are storing pointer data not owned by the
00092  * hmap. */
00093 static void nopf (void *dummy) { u_unused_args(dummy); return; }
00094 
00095 static int u_json_new_container (u_json_type_t type, const char *key, 
00096         u_json_t **pjo);
00097 static int u_json_new_atom (u_json_type_t type, const char *key, 
00098         const char *val, char check, u_json_t **pjo);
00099 
00100 static int u_json_set_depth (u_json_t *jo, unsigned int depth);
00101 
00301 int u_json_new (u_json_t **pjo)
00302 {
00303     u_json_t *jo = NULL;
00304 
00305     dbg_return_if (pjo == NULL, ~0);
00306 
00307     warn_err_sif ((jo = u_zalloc(sizeof *jo)) == NULL);
00308     TAILQ_INIT(&jo->children);
00309     jo->type = U_JSON_TYPE_UNKNOWN;
00310     jo->key[0] = jo->val[0] = jo->fqn[0] = '\0';
00311     jo->parent = NULL;
00312     jo->map = NULL;
00313     jo->count = 0;
00314     jo->depth = 0;
00315 
00316     *pjo = jo;
00317 
00318     return 0;
00319 err:
00320     if (jo)
00321         u_free(jo);
00322     return ~0;
00323 }
00324 
00336 int u_json_set_type (u_json_t *jo, u_json_type_t type)
00337 {
00338     dbg_return_if (jo == NULL, ~0);
00339     dbg_return_ifm (jo->map, ~0, "Cannot set type of a cached object");
00340 
00341     switch (type)
00342     {
00343         case U_JSON_TYPE_STRING:
00344         case U_JSON_TYPE_NUMBER:
00345         case U_JSON_TYPE_ARRAY:
00346         case U_JSON_TYPE_OBJECT:
00347         case U_JSON_TYPE_TRUE:
00348         case U_JSON_TYPE_FALSE:
00349         case U_JSON_TYPE_NULL:
00350         case U_JSON_TYPE_UNKNOWN:
00351             jo->type = type;
00352             break;
00353         default:
00354            u_err("unhandled type %d", type);
00355            return ~0;
00356     }
00357 
00358     return 0;
00359 }
00360 
00364 int u_json_set_val (u_json_t *jo, const char *val)
00365 {
00366     return u_json_set_val_ex(jo, val, 0);
00367 }
00368 
00369 /*
00370  *  \brief  Set the value of a JSON object
00371  *
00372  *  Set the value of the JSON object \p jo to the string value pointed by
00373  *  \p val.  This operation is meaningful only in case the underlying object
00374  *  is a number or a string, in which case the syntax of the supplied value
00375  *  can be checked by passing non-0 value to the \p check parameter.
00376  *
00377  *  \param  jo      Pointer to a ::u_json_t object
00378  *  \param  val     Pointer to the (non-NULL) value string
00379  *  \param  check   Set to non-0 if you need to syntax check \p val
00380  *
00381  *  \retval ~0  on failure
00382  *  \retval  0  on success
00383  */
00384 int u_json_set_val_ex (u_json_t *jo, const char *val, char check)
00385 {
00386     u_lexer_t *vl = NULL;
00387 
00388     dbg_return_if (jo == NULL, ~0);
00389     dbg_return_if (val == NULL, ~0);
00390     /* Note that cached objects allow for value overwrite. */
00391 
00392     if (check)
00393     {
00394         /* XXX The following declaration assumes C99 or C89+support of variable 
00395          *     length automatic arrays -- as in GCC since at least version 
00396          *     2.95.3. */
00397         char qval[strlen(val) + 3]; 
00398 
00399         /* If we are supposed to set a string value, we need to quote it. */
00400         (void) u_snprintf(qval, sizeof qval, 
00401                 (jo->type == U_JSON_TYPE_STRING) ? "\"%s\"" : "%s", val);
00402 
00403         dbg_err_if (u_lexer_new(qval, &vl));
00404     }
00405 
00406     /* If requested, pass 'val' through its validator. */
00407     switch (jo->type)
00408     {
00409         case U_JSON_TYPE_STRING:
00410             dbg_err_if (check && u_json_match_string(vl, NULL));
00411             break;
00412         case U_JSON_TYPE_NUMBER:
00413             dbg_err_if (check && u_json_match_number(vl, NULL));
00414             break;
00415         default:
00416             /* Non-critical error, just emit some debug info. */
00417             goto end;
00418     }
00419 
00420     dbg_return_if (u_strlcpy(jo->val, val, sizeof jo->val), ~0);
00421 
00422     /* Fall through. */       
00423 end:
00424     u_lexer_free(vl);
00425     return 0;
00426 err:
00427     u_lexer_free(vl);
00428     return ~0;
00429 }
00443 int u_json_set_key (u_json_t *jo, const char *key)
00444 {
00445     dbg_return_if (jo == NULL, ~0);
00446     dbg_return_ifm (jo->map, ~0, "Cannot set key of a cached object");
00447 
00448     dbg_return_if (u_strlcpy(jo->key, key ? key : "", sizeof jo->key), ~0);
00449 
00450     return 0;
00451 }
00452 
00455 int u_json_new_array (const char *key, u_json_t **pjo)
00456 {
00457     return u_json_new_container(U_JSON_TYPE_ARRAY, key, pjo);
00458 }
00459 
00462 int u_json_new_object (const char *key, u_json_t **pjo)
00463 {
00464     return u_json_new_container(U_JSON_TYPE_OBJECT, key, pjo);
00465 }
00466 
00478 int u_json_add (u_json_t *head, u_json_t *jo)
00479 {
00480     dbg_return_if (head == NULL, ~0);
00481     dbg_return_if (!U_JSON_OBJ_IS_CONTAINER(head), ~0);
00482     dbg_return_ifm (head->map, ~0, "Cannot add new child to a cached object");
00483     dbg_return_if (jo == NULL, ~0);
00484 
00485 #ifdef U_JSON_OBJ_DEBUG
00486     u_con("chld (%p): %s {%s} added at depth %u", 
00487             jo, u_json_type_str(jo->type), jo->key, jo->depth);
00488     u_con("prnt (%p): %s {%s} at depth %u\n", 
00489             head, u_json_type_str(head->type), head->key, head->depth);
00490 #endif  /* U_JSON_OBJ_DEBUG */
00491 
00492     TAILQ_INSERT_TAIL(&head->children, jo, siblings);
00493     jo->parent = head;
00494 
00495     /* Adjust children counter for array-type parents. */
00496     if (head->type == U_JSON_TYPE_ARRAY)
00497         head->count += 1;
00498 
00499     return 0;
00500 }
00501 
00516 int u_json_decode (const char *json, u_json_t **pjo)
00517 {
00518     return u_json_do_parse(json, pjo, NULL);
00519 }
00520 
00534 int u_json_validate (const char *json, char status[U_LEXER_ERR_SZ])
00535 {
00536     /* Just try to validate the input string (do not build the tree). */
00537     return u_json_do_parse(json, NULL, status);
00538 }
00539 
00549 void u_json_free (u_json_t *jo)
00550 {
00551     size_t dummy = 0;
00552 
00553     if (jo == NULL)
00554         return;
00555 
00556     /* If there is an associated hmap free it. */
00557     if (jo->map)
00558     {
00559         u_hmap_easy_free(jo->map);
00560         jo->map = NULL;
00561     }
00562  
00563     /* Walk the tree in post order and free each node while we traverse. */
00564     u_json_walk(jo, U_JSON_WALK_POSTORDER, dummy, u_json_do_free, NULL);
00565 
00566     return;
00567 }
00568 
00581 int u_json_encode (u_json_t *jo, char **ps)
00582 {
00583     u_string_t *s = NULL;
00584 
00585     dbg_return_if (jo == NULL, ~0);
00586     dbg_return_if (ps == NULL, ~0);
00587 
00588     dbg_err_if (u_string_create(NULL, 0, &s));
00589     dbg_err_if (u_json_do_encode(jo, s));
00590     *ps = u_string_detach_cstr(s);
00591 
00592     return 0;
00593 err:
00594     if (s)
00595         u_string_free(s);
00596     return ~0;
00597 }
00598 
00613 void u_json_walk (u_json_t *jo, int strategy, size_t l, 
00614         void (*cb)(u_json_t *, size_t, void *), void *cb_args)
00615 {
00616     dbg_return_if (strategy != U_JSON_WALK_PREORDER && 
00617             strategy != U_JSON_WALK_POSTORDER, );
00618 
00619     if (jo == NULL)
00620         return;
00621 
00622     if (strategy == U_JSON_WALK_PREORDER && cb)
00623         cb(jo, l, cb_args);
00624 
00625     /* When recurring into the children branch, increment depth by one. */
00626     u_json_walk(TAILQ_FIRST(&jo->children), strategy, l + 1, cb, cb_args);
00627 
00628     /* Siblings are at the same depth as the current node. */
00629     u_json_walk(TAILQ_NEXT(jo, siblings), strategy, l, cb, cb_args);
00630 
00631     if (strategy == U_JSON_WALK_POSTORDER && cb)
00632         cb(jo, l, cb_args);
00633 
00634     return;
00635 }
00636 
00646 void u_json_print (u_json_t *jo)
00647 {
00648     dbg_return_if (jo == NULL, );
00649 
00650     /* Tree root is at '0' depth. */
00651     u_json_walk(jo, U_JSON_WALK_PREORDER, 0, u_json_do_print, NULL);
00652 
00653     return;
00654 }
00655 
00670 int u_json_index (u_json_t *jo)
00671 {
00672     size_t u;   /* Unused. */
00673     u_hmap_opts_t *opts = NULL;
00674     u_hmap_t *hmap = NULL;
00675 
00676     dbg_return_if (jo == NULL, ~0);
00677     nop_return_if (jo->map, 0);     /* If already cached, return ok. */
00678     dbg_return_if (jo->parent, ~0); /* Cache can be created on top-objs only. */
00679 
00680     /* Create the associative array. */
00681     dbg_err_if (u_hmap_opts_new(&opts));
00682     dbg_err_if (u_hmap_opts_set_val_type(opts, U_HMAP_OPTS_DATATYPE_POINTER));
00683     dbg_err_if (u_hmap_opts_set_val_freefunc(opts, nopf));
00684     dbg_err_if (u_hmap_easy_new(opts, &hmap));
00685     opts = NULL;
00686 
00687     /* Initialize array elems' indexing. */
00688     jo->icur = 0;
00689 
00690     /* Walk the tree in pre-order and cache each node while we traverse. */
00691     u_json_walk(jo, U_JSON_WALK_PREORDER, u, u_json_do_index, hmap);
00692 
00693     /* Attach the associative array to the top level object. */
00694     jo->map = hmap, hmap = NULL;
00695 
00696     return 0;
00697 err:
00698     if (opts)
00699         u_hmap_opts_free(opts);
00700     if (hmap)
00701         u_hmap_easy_free(hmap);
00702     return ~0;
00703 }
00704 
00716 int u_json_unindex (u_json_t *jo)
00717 {
00718     dbg_return_if (jo == NULL, ~0);
00719     nop_return_if (jo->map == NULL, 0);
00720 
00721     u_hmap_easy_free(jo->map);
00722     jo->map = NULL;
00723 
00724     return 0;
00725 }
00726 
00739 u_json_t *u_json_cache_get (u_json_t *jo, const char *name)
00740 {
00741     u_json_t *res, *p;
00742     char fqn[U_JSON_FQN_SZ];
00743 
00744     dbg_return_if (jo == NULL, NULL);
00745     dbg_return_if (jo->map == NULL, NULL);
00746     dbg_return_if (name == NULL, NULL);
00747 
00748     if ((p = jo->parent) == NULL)
00749     {
00750         /* If 'jo' is top level, 'name' must be fully qualified. */ 
00751         return (u_json_t *) u_hmap_easy_get(jo->map, name);
00752     }
00753 
00754     /* Else ('jo' != top): first try 'name' as it were fully qualified. */
00755     if ((res = (u_json_t *) u_hmap_easy_get(jo->map, name)))
00756         return res;
00757 
00758     /* If 'name' is relative, we need to prefix it with the parent name 
00759      * space. */
00760     dbg_if (u_snprintf(fqn, sizeof fqn, "%s%s", jo->fqn, name));
00761 
00762     return (u_json_t *) u_hmap_easy_get(jo->map, fqn);
00763 }
00764 
00781 int u_json_cache_set_tv (u_json_t *jo, const char *name, 
00782         u_json_type_t type, const char *val)
00783 {
00784     u_json_t *res;
00785 
00786     dbg_return_if (U_JSON_OBJ_IS_CONTAINER(jo), ~0);
00787     dbg_return_if (type == U_JSON_TYPE_OBJECT || type == U_JSON_TYPE_ARRAY, ~0);
00788     /* 'jo' and 'name' will be checked by u_json_cache_get(); 
00789      * 'val' consistency is checked after type has been set. */
00790 
00791     /* Retrieve the node. */
00792     dbg_err_if ((res = u_json_cache_get(jo, name)) == NULL);
00793 
00794     /* First set type (in case !unknown) so that we know how to check the
00795      * subsequent value setting. */
00796     if (type != U_JSON_TYPE_UNKNOWN)
00797         res->type = type;
00798 
00799     /* Set value.  The caller must have supplied some non-NULL 'val' in case 
00800      * the final underlying type is a string or a number. */
00801     if (res->type == U_JSON_TYPE_STRING || res->type == U_JSON_TYPE_NUMBER)
00802         dbg_err_if (val == NULL || u_strlcpy(res->val, val, sizeof res->val));
00803 
00804     return 0;
00805 err:
00806     return ~0;
00807 }
00808 
00810 unsigned int u_json_array_count (u_json_t *jo)
00811 {
00812     dbg_return_if (jo == NULL, 0);
00813     dbg_return_if (jo->type != U_JSON_TYPE_ARRAY, 0);
00814 
00815     return jo->count;
00816 }
00817 
00819 u_json_t *u_json_array_get_nth (u_json_t *jo, unsigned int n)
00820 {
00821     u_json_t *elem;
00822 
00823     dbg_return_if (jo == NULL, NULL);
00824     dbg_return_if (jo->type != U_JSON_TYPE_ARRAY, NULL);
00825     dbg_return_if (n >= jo->count, NULL);
00826 
00827     /* Use cache if available. */
00828     if (jo->map)
00829     {
00830         char elem_fqn[U_JSON_FQN_SZ] = { '\0' };
00831         dbg_if (u_snprintf(elem_fqn, sizeof elem_fqn, "%s[%u]", jo->fqn, n));
00832         return u_json_cache_get(jo, elem_fqn);
00833     }
00834     
00835     /* Too bad if we don't have cache in place: we have to go through the 
00836      * list which is quadratic even with the following silly optimisation.
00837      * So it's ok for a couple of lookups, but if done systematically it's
00838      * an overkill.  Freeze instead ! */
00839     if (n > (jo->count / 2))
00840     {
00841         unsigned int r = jo->count - (n + 1);
00842 
00843         TAILQ_FOREACH_REVERSE (elem, &jo->children, u_json_chld_s, siblings)
00844         {
00845             if (r == 0)
00846                 return elem;
00847             r -= 1;
00848         } 
00849     }
00850     else
00851     {
00852         TAILQ_FOREACH (elem, &jo->children, siblings)
00853         {
00854             if (n == 0)
00855                 return elem;
00856             n -= 1;
00857         } 
00858     }
00859 
00860     /* Unreachable. */
00861     return NULL;
00862 }
00863 
00865 const char *u_json_get_val (u_json_t *jo)
00866 {
00867     dbg_return_if (jo == NULL, NULL);
00868 
00869     switch (jo->type)
00870     {
00871         case U_JSON_TYPE_STRING:
00872         case U_JSON_TYPE_NUMBER:
00873             return jo->val;
00874         case U_JSON_TYPE_TRUE:
00875             return "true";
00876         case U_JSON_TYPE_FALSE:
00877             return "false";
00878         case U_JSON_TYPE_NULL:
00879             return "null";
00880         case U_JSON_TYPE_OBJECT:
00881         case U_JSON_TYPE_ARRAY:
00882         case U_JSON_TYPE_UNKNOWN:
00883         default:
00884             return NULL;
00885     }
00886 }
00887 
00889 int u_json_get_int (u_json_t *jo, long *pl)
00890 {
00891     dbg_return_if (jo == NULL, ~0);
00892     dbg_return_if (jo->type != U_JSON_TYPE_NUMBER, ~0);
00893     dbg_return_if (pl == NULL, ~0);
00894 
00895     dbg_err_if (u_atol(jo->val, pl));
00896 
00897     return 0;
00898 err:
00899     return ~0;
00900 }
00901 
00904 int u_json_get_real (u_json_t *jo, double *pd)
00905 {
00906     dbg_return_if (jo == NULL, ~0);
00907     dbg_return_if (jo->type != U_JSON_TYPE_NUMBER, ~0);
00908     dbg_return_if (pd == NULL, ~0);
00909 
00910     dbg_err_if (u_atof(jo->val, pd));
00911 
00912     return 0;
00913 err:
00914     return ~0;
00915 }
00916 
00918 int u_json_get_bool (u_json_t *jo, char *pb)
00919 {
00920     dbg_return_if (jo == NULL, ~0);
00921     dbg_return_if (pb == NULL, ~0);
00922 
00923     switch (jo->type)
00924     {
00925         case U_JSON_TYPE_TRUE:
00926             *pb = 1;
00927             break;
00928         case U_JSON_TYPE_FALSE:
00929             *pb = 0;
00930             break;
00931         default:
00932             return ~0;
00933     }
00934 
00935     return 0;
00936 }
00937 
00940 const char *u_json_cache_get_val (u_json_t *jo, const char *name)
00941 {
00942     u_json_t *res = u_json_cache_get(jo, name);
00943 
00944     return u_json_get_val(res);
00945 }
00946 
00949 int u_json_cache_get_int (u_json_t *jo, const char *name, long *pval)
00950 {
00951     u_json_t *res;
00952 
00953     dbg_return_if ((res = u_json_cache_get(jo, name)) == NULL, ~0);
00954 
00955     return u_json_get_int(res, pval);
00956 }
00957 
00960 int u_json_cache_get_real (u_json_t *jo, const char *name, double *pval)
00961 {
00962     u_json_t *res;
00963 
00964     dbg_return_if ((res = u_json_cache_get(jo, name)) == NULL, ~0);
00965 
00966     return u_json_get_real(res, pval);
00967 }
00968 
00971 int u_json_cache_get_bool (u_json_t *jo, const char *name, char *pval)
00972 {
00973     u_json_t *res;
00974 
00975     dbg_return_if ((res = u_json_cache_get(jo, name)) == NULL, ~0);
00976 
00977     return u_json_get_bool(res, pval);
00978 }
00979 
00991 int u_json_remove (u_json_t *jo)
00992 {
00993     u_json_t *p;
00994 
00995     dbg_return_if (jo == NULL, ~0);
00996     dbg_return_ifm (jo->map, ~0, "Cannot remove (from) a cached object");
00997 
00998     if ((p = jo->parent))
00999     {            
01000         /* Fix counters when parent is an array. */
01001         if (p->type == U_JSON_TYPE_ARRAY)
01002             p->count -= 1;
01003 
01004         /* Evict from the parent container. */
01005         TAILQ_REMOVE(&p->children, jo, siblings);
01006     }
01007 
01008     /* Give back the resources allocated to the node (and its children). */
01009     u_json_free(jo);
01010 
01011     return 0;
01012 }
01013 
01015 int u_json_new_string (const char *key, const char *val, u_json_t **pjo)
01016 {
01017     return u_json_new_atom(U_JSON_TYPE_STRING, key, val, 1, pjo);
01018 }
01019 
01021 int u_json_new_number (const char *key, const char *val, u_json_t **pjo)
01022 {
01023     return u_json_new_atom(U_JSON_TYPE_NUMBER, key, val, 1, pjo);
01024 }
01025 
01027 int u_json_new_real (const char *key, double val, u_json_t **pjo)
01028 {
01029     char sval[U_TOKEN_SZ], check = 0;
01030 
01031 #ifdef HAVE_ISFINITE
01032     /* Use isfinite() to avoid infinity's and NaN's which would break the
01033      * JSON syntax. */
01034     dbg_return_if (!isfinite(val), ~0);
01035 #else
01036     /* If isfinite() is not available (i.e. !C99), force check in 
01037      * u_json_new_atom(). */
01038     check = 1;
01039 #endif  /* HAVE_ISFINITE */
01040 
01041     /* "%g" does exponential (i.e. [+-]d.d...dE[+-]dd) or fixed-point (i.e.
01042      * [+-]d...d.d...d) notation depending on 'val'.  Both should be compatible
01043      * with JSON number spec. */ 
01044     dbg_return_if (u_snprintf(sval, sizeof sval, "%g", val), ~0);
01045 
01046     return u_json_new_atom(U_JSON_TYPE_NUMBER, key, sval, check, pjo);
01047 }
01048 
01050 int u_json_new_int (const char *key, long val, u_json_t **pjo)
01051 {
01052     char sval[U_TOKEN_SZ];
01053 
01054     dbg_return_if (u_snprintf(sval, sizeof sval, "%ld", val), ~0);
01055 
01056     /* Assume 'sval' correctly formatted (no need to validate). */
01057     return u_json_new_atom(U_JSON_TYPE_NUMBER, key, sval, 0, pjo);
01058 }
01059 
01061 int u_json_new_null (const char *key, u_json_t **pjo)
01062 {
01063     /* No need to validate. */
01064     return u_json_new_atom(U_JSON_TYPE_NULL, key, NULL, 0, pjo);
01065 }
01066 
01068 int u_json_new_bool (const char *key, char val, u_json_t **pjo)
01069 {
01070     /* No need to validate. */
01071     return u_json_new_atom(val ? U_JSON_TYPE_TRUE : U_JSON_TYPE_FALSE, 
01072             key, NULL, 0, pjo);
01073 }
01074 
01077 u_json_t *u_json_child_first (u_json_t *jo)
01078 {
01079     dbg_return_if (jo == NULL, NULL);
01080     dbg_return_if (!U_JSON_OBJ_IS_CONTAINER(jo), NULL);
01081 
01082     return TAILQ_FIRST(&jo->children);
01083 }
01084 
01087 u_json_t *u_json_child_last (u_json_t *jo)
01088 {
01089     dbg_return_if (jo == NULL, NULL);
01090     dbg_return_if (!U_JSON_OBJ_IS_CONTAINER(jo), NULL);
01091 
01092     return TAILQ_LAST(&jo->children, u_json_chld_s);
01093 }
01094 
01096 int u_json_it (u_json_t *jo, u_json_it_t *it)
01097 {
01098     dbg_return_if (it == NULL, ~0);
01099 
01100     it->cur = jo;
01101 
01102     return 0;
01103 }
01104 
01107 u_json_t *u_json_it_next (u_json_it_t *it)
01108 {
01109     u_json_t *jo;
01110 
01111     dbg_return_if (it == NULL, NULL);
01112 
01113     if ((jo = it->cur) != NULL)
01114         it->cur = TAILQ_NEXT(jo, siblings);
01115 
01116     return jo;
01117 }
01118 
01121 u_json_t *u_json_it_prev (u_json_it_t *it)
01122 {
01123     u_json_t *jo;
01124 
01125     dbg_return_if (it == NULL, NULL);
01126 
01127     if ((jo = it->cur) != NULL)
01128         it->cur = TAILQ_PREV(jo, u_json_chld_s, siblings);
01129 
01130     return jo;
01131 }
01132 
01137 static int u_json_do_encode (u_json_t *jo, u_string_t *s)
01138 {
01139     if (jo == NULL)
01140         return 0;
01141 
01142     /* Optional key. */
01143     if (strlen(jo->key))
01144         dbg_err_if (u_string_aprintf(s, "\"%s\": ", jo->key));
01145 
01146     /* Value. */
01147     switch (jo->type)
01148     {
01149         case U_JSON_TYPE_STRING:
01150             dbg_err_if (u_string_aprintf(s, "\"%s\"", jo->val));
01151             break;
01152         case U_JSON_TYPE_NUMBER:
01153             dbg_err_if (u_string_aprintf(s, "%s", jo->val));
01154             break;
01155         case U_JSON_TYPE_OBJECT:
01156             dbg_err_if (u_string_aprintf(s, "{ "));
01157             break;
01158         case U_JSON_TYPE_ARRAY:
01159             dbg_err_if (u_string_aprintf(s, "[ "));
01160             break;
01161         case U_JSON_TYPE_TRUE:
01162             dbg_err_if (u_string_aprintf(s, "true"));
01163             break;
01164         case U_JSON_TYPE_FALSE:
01165             dbg_err_if (u_string_aprintf(s, "false"));
01166             break;
01167         case U_JSON_TYPE_NULL:
01168             dbg_err_if (u_string_aprintf(s, "null"));
01169             break;
01170         default:
01171             dbg_err("!");
01172     }
01173 
01174     /* Explore depth. */
01175     dbg_err_if (u_json_do_encode(TAILQ_FIRST(&jo->children), s));
01176 
01177     /* Close matching paren. */
01178     switch (jo->type)
01179     {
01180         case U_JSON_TYPE_ARRAY:
01181             dbg_err_if (u_string_aprintf(s, " ]"));
01182             break;
01183         case U_JSON_TYPE_OBJECT:
01184             dbg_err_if (u_string_aprintf(s, " }"));
01185             break;
01186         default:
01187             break;
01188     }
01189 
01190     /* When needed, add comma to separate siblings. */
01191     if (TAILQ_NEXT(jo, siblings))
01192         dbg_err_if (u_string_aprintf(s, ", "));
01193 
01194     /* Explore horizontally. */
01195     dbg_err_if (u_json_do_encode(TAILQ_NEXT(jo, siblings), s));
01196 
01197     return 0;
01198 err:
01199     return ~0;
01200 }
01201 
01202 static int u_json_match_value (u_lexer_t *jl, u_json_t *jo)
01203 {
01204     /* 'jo' can be NULL in case of a validating-only parser. */
01205     dbg_return_if (jl == NULL, ~0);
01206 
01207     if (u_json_match_string_first(jl))
01208         dbg_err_if (u_json_match_string(jl, jo));
01209     else if (u_json_match_number_first(jl))
01210         dbg_err_if (u_json_match_number(jl, jo));
01211     else if (u_json_match_object_first(jl))
01212         dbg_err_if (u_json_match_object(jl, jo));
01213     else if (u_json_match_array_first(jl))
01214         dbg_err_if (u_json_match_array(jl, jo));
01215     else if (u_json_match_true_first(jl))
01216         dbg_err_if (u_json_match_true(jl, jo));
01217     else if (u_json_match_false_first(jl))
01218         dbg_err_if (u_json_match_false(jl, jo));
01219     else if (u_json_match_null_first(jl))
01220         dbg_err_if (u_json_match_null(jl, jo));
01221     else
01222         U_LEXER_ERR(jl, "value not found at \'%s\'", u_lexer_lookahead(jl));
01223 
01224     return 0;
01225 err:
01226     return ~0;
01227 }
01228 
01229 static int u_json_match_array_first (u_lexer_t *jl)
01230 {
01231     return (u_lexer_peek(jl) == '[');
01232 }
01233 
01234 static int u_json_match_object_first (u_lexer_t *jl)
01235 {
01236     return (u_lexer_peek(jl) == '{');
01237 }
01238 
01239 static int u_json_match_number_first (u_lexer_t *jl)
01240 {
01241     char r, c = u_lexer_peek(jl);
01242 
01243     if ((r = (c == '-' || isdigit(c))))
01244         u_lexer_record_lmatch(jl);
01245 
01246     return r;
01247 }
01248 
01249 static int u_json_match_pair_first (u_lexer_t *jl)
01250 {
01251     return u_json_match_string_first(jl);
01252 }
01253 
01254 static int u_json_match_false_first (u_lexer_t *jl)
01255 {
01256     return (u_lexer_peek(jl) == 'f');
01257 }
01258 
01259 static int u_json_match_true_first (u_lexer_t *jl)
01260 {
01261     return (u_lexer_peek(jl) == 't');
01262 }
01263 
01264 static int u_json_match_null_first (u_lexer_t *jl)
01265 {
01266     return (u_lexer_peek(jl) == 'n');
01267 }
01268 
01269 static int u_json_match_string_first (u_lexer_t *jl)
01270 {
01271     char r, c = u_lexer_peek(jl);
01272 
01273     if ((r = (c == '"')))
01274         u_lexer_record_lmatch(jl);
01275 
01276     return r;
01277 }
01278 
01279 /* number ::= INT[FRAC][EXP] */
01280 static int u_json_match_number (u_lexer_t *jl, u_json_t *jo)
01281 {
01282     char match[U_TOKEN_SZ];
01283 
01284     /* INT is mandatory */
01285     dbg_err_if (u_json_match_int(jl));
01286 
01287     /* c IN first(FRAC) */
01288     if (u_json_match_frac_first(u_lexer_peek(jl)))
01289         dbg_err_if (u_json_match_frac(jl));
01290 
01291     /* c IN first(EXP) */
01292     if (u_json_match_exp_first(u_lexer_peek(jl)))
01293         dbg_err_if (u_json_match_exp(jl));
01294 
01295     /* Register right side of the matched number. */
01296     u_lexer_record_rmatch(jl);
01297 
01298     /* Take care of the fact that the match includes the first non-number char
01299      * (see u_json_match_{int,exp,frac} for details). */
01300     (void) u_lexer_get_match(jl, match);
01301     match[strlen(match) - 1] = '\0';
01302 
01303     /* Push the matched number into the supplied json object. */
01304     if (jo)
01305     {
01306         dbg_err_if (u_json_set_type(jo, U_JSON_TYPE_NUMBER));
01307         dbg_err_if (u_json_set_val(jo, match));
01308     }
01309 
01310 #ifdef U_JSON_LEX_DEBUG
01311     u_con("matched number: %s", u_lexer_get_match(jl, match));
01312 #endif  /* U_JSON_LEX_DEBUG */
01313 
01314     return 0;
01315 err:
01316     return ~0;
01317 }
01318 
01319 static int u_json_match_int (u_lexer_t *jl)
01320 {
01321     char c = u_lexer_peek(jl);
01322 
01323     /* optional minus sign */
01324     if (c == '-')
01325         U_LEXER_NEXT(jl, &c);
01326 
01327     /* on '0' as the first char, we're done */
01328     if (c == '0')
01329     {
01330         U_LEXER_NEXT(jl, &c);
01331         goto end;
01332     }
01333 
01334     /* [1-9][0-9]+ */
01335     if (c >= 48 && c <= 57)
01336         do { U_LEXER_NEXT(jl, &c); } while (isdigit(c));
01337     else 
01338         U_LEXER_ERR(jl, "bad int syntax at %s", u_lexer_lookahead(jl));
01339 
01340     /* fall through */
01341 end:
01342     return 0;
01343 err:
01344     return ~0;
01345 }
01346 
01347 static int u_json_match_exp_first (char c)
01348 {
01349     return (c == 'e' || c == 'E');
01350 }
01351 
01352 static int u_json_match_frac_first (char c)
01353 {
01354     return (c == '.');
01355 }
01356 
01357 static int u_json_match_frac (u_lexer_t *jl)
01358 {
01359     char c = u_lexer_peek(jl);
01360 
01361     /* Mandatory dot. */
01362     if (c != '.')
01363         U_LEXER_ERR(jl, "bad frac syntax at %s", u_lexer_lookahead(jl));
01364 
01365     U_LEXER_NEXT(jl, &c);
01366 
01367     /* [0-9] */
01368     if (!isdigit(c))
01369         U_LEXER_ERR(jl, "bad frac syntax at %s", u_lexer_lookahead(jl));
01370 
01371     /* [0-9]* */
01372     while (isdigit(c))
01373         U_LEXER_NEXT(jl, &c);
01374 
01375     return 0;
01376 err:
01377     return ~0;
01378 }
01379 
01380 static int u_json_match_exp (u_lexer_t *jl)
01381 {
01382     char c = u_lexer_peek(jl);
01383 
01384     /* [eE] */
01385     if (c != 'e' && c != 'E')
01386         U_LEXER_ERR(jl, "bad exp syntax at %s", u_lexer_lookahead(jl));
01387 
01388     U_LEXER_NEXT(jl, &c);
01389 
01390     /* Optional plus/minus sign. */
01391     if (c == '+' || c == '-')
01392         U_LEXER_NEXT(jl, &c);
01393 
01394     /* [0-9] */
01395     if (!isdigit(c))
01396         U_LEXER_ERR(jl, "bad exp syntax at %s", u_lexer_lookahead(jl));
01397 
01398     /* [0-9]* */
01399     while (isdigit(c))
01400         U_LEXER_NEXT(jl, &c);
01401 
01402     return 0;
01403 err:
01404     return ~0;
01405 }
01406 
01407 static int u_json_match_seq (u_lexer_t *jl, u_json_t *jo, int type, 
01408         char first, const char *rem, size_t rem_sz)
01409 {
01410     char c;
01411     size_t i = 0;
01412 
01413     if ((c = u_lexer_peek(jl)) != first)
01414     {
01415         U_LEXER_ERR(jl, "expect \'%c\', got %c at %s", 
01416                 first, c, u_lexer_lookahead(jl));
01417     }
01418 
01419     for (i = 0; i < rem_sz; i++)
01420     {
01421         U_LEXER_SKIP(jl, &c);
01422         if (c != *(rem + i))
01423         {
01424             U_LEXER_ERR(jl, "expect \'%c\', got %c at %s", 
01425                     *(rem + i), c, u_lexer_lookahead(jl));
01426         }
01427     }
01428 
01429     /* Consume last checked char. */
01430     U_LEXER_SKIP(jl, NULL);
01431 
01432     if (jo)
01433         dbg_err_if (u_json_set_type(jo, type));
01434 
01435 #ifdef U_JSON_LEX_DEBUG
01436     u_con("matched \'%s\' sequence", u_json_type_str(type));
01437 #endif  /* U_JSON_LEX_DEBUG */
01438     return 0;
01439 err:
01440     return ~0;
01441 }
01442 
01443 static int u_json_match_null (u_lexer_t *jl, u_json_t *jo)
01444 {
01445     return u_json_match_seq(jl, jo, U_JSON_TYPE_NULL, 
01446             'n', "ull", strlen("ull"));
01447 }
01448 
01449 static int u_json_match_true (u_lexer_t *jl, u_json_t *jo)
01450 {
01451     return u_json_match_seq(jl, jo, U_JSON_TYPE_TRUE, 
01452             't', "rue", strlen("rue"));
01453 }
01454 
01455 static int u_json_match_false (u_lexer_t *jl, u_json_t *jo)
01456 {
01457     return u_json_match_seq(jl, jo, U_JSON_TYPE_FALSE, 
01458             'f', "alse", strlen("alse"));
01459 }
01460 
01461 static int u_json_match_array (u_lexer_t *jl, u_json_t *jo)
01462 {
01463     char c;
01464     u_json_t *elem = NULL;
01465 
01466 #ifdef U_JSON_LEX_DEBUG
01467     u_con("ARRAY");
01468 #endif  /* U_JSON_LEX_DEBUG */
01469 
01470     if ((c = u_lexer_peek(jl)) != '[')
01471     {
01472         U_LEXER_ERR(jl, "expect \'[\', got %c at %s", 
01473                 c, u_lexer_lookahead(jl));
01474     }
01475 
01476     /* Parent object is an array. */
01477     if (jo)
01478         dbg_err_if (u_json_set_type(jo, U_JSON_TYPE_ARRAY));
01479 
01480     do {
01481         /* As long as we want to accept empty arrays in this same scan loop, 
01482          * we could let trailing ',' pass unseen when a value has been already
01483          * consumed.  So, at each iteration, last non-whitespace char is saved 
01484          * to 'd' and checked when testing the empty array condition so that
01485          * we can emit a warn if needed.  
01486          * NOTE this is done equivalently in u_json_match_object(). */
01487         char d = u_lexer_peek(jl);
01488 
01489         U_LEXER_SKIP(jl, &c);
01490         
01491         if (c == ']')   /* break on empty array */
01492         {
01493             if (d == ',')
01494                 u_warn("Trailing \',\' at the end of array !");
01495             break;
01496         }
01497 
01498         if (jo)
01499         {
01500             /* Create a new object to store next array element. */
01501             dbg_err_if (u_json_new(&elem));
01502             dbg_err_if (u_json_set_type(elem, U_JSON_TYPE_UNKNOWN));
01503             dbg_err_if (u_json_set_depth(elem, jo->depth + 1));
01504         }
01505 
01506         /* Fetch new value. */
01507         dbg_err_if (u_json_match_value(jl, elem));
01508 
01509         if (jo)
01510         {
01511             /* Push the fetched element to its parent array. */
01512             dbg_err_if (u_json_add(jo, elem)); 
01513             elem = NULL;
01514         }
01515 
01516         /* Consume any trailing white spaces. */
01517         if (isspace((int) u_lexer_peek(jl)))
01518             U_LEXER_SKIP(jl, NULL);
01519 
01520     } while (u_lexer_peek(jl) == ',');
01521 
01522     if ((c = u_lexer_peek(jl)) != ']')
01523     {
01524         U_LEXER_ERR(jl, "expect \']\', got %c at %s", 
01525                 c, u_lexer_lookahead(jl));
01526     }
01527 
01528     /* Ignore EOT, shall be catched later. */
01529     (void) u_lexer_skip(jl, NULL);
01530 
01531     return 0;
01532 err:
01533     u_json_free(elem);
01534     return ~0;
01535 }
01536 
01537 static int u_json_match_object (u_lexer_t *jl, u_json_t *jo)
01538 {
01539     char c;
01540 
01541 #ifdef U_JSON_LEX_DEBUG
01542     u_con("OBJECT");
01543 #endif  /* U_JSON_LEX_DEBUG */
01544 
01545     if ((c = u_lexer_peek(jl)) != '{')
01546     {
01547         U_LEXER_ERR(jl, "expect \'{\', got %c at %s", 
01548                 c, u_lexer_lookahead(jl));
01549     }
01550 
01551     if (jo)
01552         dbg_err_if (u_json_set_type(jo, U_JSON_TYPE_OBJECT));
01553 
01554     do {
01555         char d = u_lexer_peek(jl);
01556 
01557         U_LEXER_SKIP(jl, &c);
01558 
01559         /* Break on empty object. */
01560         if (c == '}')
01561         {
01562             if (d == ',')
01563                 u_warn("Trailing \',\' at the end of object !");
01564             break;
01565         }
01566 
01567         /* Process assignement. */
01568         dbg_err_if (!u_json_match_pair_first(jl) || u_json_match_pair(jl, jo));
01569 
01570         /* Consume trailing white spaces, if any. */
01571         if (isspace((int) u_lexer_peek(jl)))
01572             U_LEXER_SKIP(jl, NULL);
01573 
01574     } while (u_lexer_peek(jl) == ',');
01575 
01576     if ((c = u_lexer_peek(jl)) != '}')
01577     {
01578         U_LEXER_ERR(jl, "expect \'}\', got %c at %s", 
01579                 c, u_lexer_lookahead(jl));
01580     }
01581 
01582     /* Ignore EOT, shall be catched later. */
01583     (void) u_lexer_skip(jl, NULL);
01584 
01585     return 0;
01586 err:
01587     return ~0;
01588 }
01589 
01590 static int u_json_match_pair (u_lexer_t *jl, u_json_t *jo)
01591 {
01592     size_t mlen;
01593     char c, match[U_TOKEN_SZ];
01594     u_json_t *pair = NULL;
01595 
01596     dbg_return_if (jl == NULL, ~0);
01597 
01598 #ifdef U_JSON_LEX_DEBUG
01599     u_con("PAIR");
01600 #endif  /* U_JSON_LEX_DEBUG */
01601 
01602     /* Here we use the matched string as the 'key' for the associated value, 
01603      * hence there is no associated json object. */
01604     dbg_err_if (u_json_match_string(jl, NULL));
01605 
01606     /* Initialize new json object to store the key/value pair. */
01607     if (jo)
01608     {
01609         dbg_err_if (u_json_new(&pair));
01610         dbg_err_if (u_json_set_depth(pair, jo->depth + 1));
01611     }
01612 
01613     (void) u_lexer_get_match(jl, match);
01614 
01615     /* Trim trailing '"'. */
01616     if ((mlen = strlen(match)) >= 1)
01617         match[mlen - 1] = '\0';
01618 
01619     if (jo)
01620         dbg_err_if (u_json_set_key(pair, match));
01621 
01622     /* Consume trailing white spaces, if any. */
01623     if (isspace((int) u_lexer_peek(jl)))
01624         U_LEXER_SKIP(jl, NULL);
01625 
01626     /* Consume ':' */
01627     if ((c = u_lexer_peek(jl)) != ':')
01628     {
01629         U_LEXER_ERR(jl, "expect \':\', got %c at %s", 
01630                 c, u_lexer_lookahead(jl));
01631     }
01632 
01633     U_LEXER_SKIP(jl, &c);
01634 
01635     /* Assign value. */
01636     dbg_err_if (u_json_match_value(jl, pair));
01637 
01638     /* Push the new value to the parent json object. */
01639     if (jo)
01640     {
01641         dbg_err_if (u_json_add(jo, pair));
01642         pair = NULL;
01643     }
01644 
01645     return 0;
01646 err:
01647     u_json_free(pair);
01648     return ~0;
01649 }
01650 
01651 static int u_json_match_string (u_lexer_t *jl, u_json_t *jo)
01652 {
01653     size_t mlen;
01654     char c, match[U_TOKEN_SZ];
01655 
01656     /* In case string is matched as an lval (i.e. the key side of a 'pair'),
01657      * there is no json object. */
01658     dbg_return_if (jl == NULL, ~0);
01659 
01660 #ifdef U_JSON_LEX_DEBUG
01661     u_con("STRING");
01662 #endif  /* U_JSON_LEX_DEBUG */
01663 
01664     if ((c = u_lexer_peek(jl)) != '"')
01665         U_LEXER_ERR(jl, "expect \", got %c at %s", c, u_lexer_lookahead(jl));
01666 
01667     U_LEXER_NEXT(jl, &c);
01668 
01669     /* Re-record the left side match pointer (trim leading '"'). */
01670     u_lexer_record_lmatch(jl);
01671 
01672     while (c != '"')
01673     {
01674         if (c == '\\')
01675         {
01676             U_LEXER_NEXT(jl, &c);
01677             switch (c)
01678             {
01679                 case 'u':
01680                     dbg_err_if (u_json_match_escaped_unicode(jl));
01681                     break;
01682                 case '"': case '\\': case '/': case 'b':
01683                 case 'f': case 'n':  case 'r': case 't':
01684                     U_LEXER_NEXT(jl, &c);
01685                     break;
01686                 default:
01687                     U_LEXER_ERR(jl, "invalid char %c in escape", c);
01688             }
01689         }
01690         else if (iscntrl((int) c))
01691             U_LEXER_ERR(jl, "control character in string", c); 
01692         else    
01693             U_LEXER_NEXT(jl, &c);
01694     }
01695 
01696     /* Record right match pointer.
01697      * This is a greedy match, which includes the trailing '"', and must
01698      * be taken into account when pulling out the string. */
01699     u_lexer_record_rmatch(jl);
01700 
01701     /* Consume last '"'. */
01702     U_LEXER_NEXT(jl, &c);
01703 
01704 #ifdef U_JSON_LEX_DEBUG
01705     u_con("matched string: \'%s\'", u_lexer_get_match(jl, match));
01706 #endif  /* U_JSON_LEX_DEBUG */
01707 
01708     /* In case the string is matched as an rval, the caller shall
01709      * supply the json object that has to be set. */
01710     if (jo)
01711     {
01712         dbg_err_if (u_json_set_type(jo, U_JSON_TYPE_STRING));
01713 
01714         /* Remove trailing '"' from match. */
01715         (void) u_lexer_get_match(jl, match);
01716 
01717         /* Trim trailing '"'. */
01718         if ((mlen = strlen(match)) >= 1)
01719             match[mlen - 1] = '\0';
01720 
01721         dbg_err_if (u_json_set_val(jo, match));
01722     }
01723 
01724     return 0;
01725 err:
01726     return ~0;
01727 }
01728 
01729 static int u_json_match_escaped_unicode (u_lexer_t *jl)
01730 {
01731     char i, c;
01732 
01733     for (i = 0; i < 4; i++)
01734     {
01735         U_LEXER_NEXT(jl, &c);
01736 
01737         if (!isxdigit((int) c))
01738             U_LEXER_ERR(jl, "non hex digit %c in escaped unicode", c); 
01739     }
01740 
01741     return 0;
01742 err:
01743     return ~0;
01744 }
01745 
01746 static const char *u_json_type_str (int type)
01747 {
01748     switch (type)
01749     {
01750         case U_JSON_TYPE_STRING:  return "string";
01751         case U_JSON_TYPE_NUMBER:  return "number";
01752         case U_JSON_TYPE_ARRAY:   return "array";
01753         case U_JSON_TYPE_OBJECT:  return "object";
01754         case U_JSON_TYPE_TRUE:    return "true";
01755         case U_JSON_TYPE_FALSE:   return "false";
01756         case U_JSON_TYPE_NULL:    return "null";
01757         case U_JSON_TYPE_UNKNOWN: default: break;
01758     }
01759 
01760     return "unknown";
01761 }
01762 
01763 static void u_json_do_free (u_json_t *jo, size_t l, void *opaque)
01764 {
01765     u_unused_args(l, opaque);
01766 
01767     if (jo)
01768         u_free(jo);
01769 
01770     return;
01771 }
01772 
01773 static void u_json_do_print (u_json_t *jo, size_t l, void *opaque)
01774 {
01775     u_unused_args(opaque);
01776 
01777     dbg_return_if (jo == NULL, );
01778 
01779     switch (jo->type)
01780     {
01781         case U_JSON_TYPE_ARRAY:
01782         case U_JSON_TYPE_OBJECT:
01783             /* No value. */
01784             u_con("%*c %s %s", l, ' ', u_json_type_str(jo->type), jo->key);
01785             break;
01786         default:
01787             u_con("%*c %s %s : \'%s\'", l, ' ', 
01788                     u_json_type_str(jo->type), jo->key, jo->val);
01789             break;
01790     }
01791 
01792     return;
01793 }
01794 
01795 static void u_json_do_index (u_json_t *jo, size_t l, void *map)
01796 {
01797     u_json_t *p;
01798     u_hmap_t *hmap = (u_hmap_t *) map;
01799 
01800     u_unused_args(l);
01801 
01802     if ((p = jo->parent) == NULL)
01803     {
01804         /* Root node is named '.', its name and fully qualified name match. */
01805         (void) u_strlcpy(jo->fqn, ".", sizeof jo->fqn);
01806     }
01807     else if (p->type == U_JSON_TYPE_OBJECT)
01808     {
01809         /* Nodes in object containers are named after their key. */
01810         dbg_if (u_snprintf(jo->fqn, sizeof jo->fqn, "%s.%s", p->fqn, jo->key));
01811     }
01812     else if (p->type == U_JSON_TYPE_ARRAY)
01813     {
01814         /* Nodes in array containers are named after their ordinal position. */
01815         dbg_if (u_snprintf(jo->fqn, sizeof jo->fqn, "%s[%u]", p->fqn, p->icur));
01816 
01817         /* Increment the counting index in the parent array. */
01818         p->icur += 1;
01819 
01820         /* In case we have an array inside another array, initialize the 
01821          * counter for later recursive invocation. */
01822         if (jo->type == U_JSON_TYPE_ARRAY)
01823             jo->icur = 0;
01824     }
01825     else
01826         u_warn("Expecting an object, an array, or a top-level node.");
01827 
01828     /* Insert node into the hmap. */
01829     dbg_if (u_hmap_easy_put(hmap, jo->fqn, (const void *) jo));
01830 
01831     /* Stick the map pointer inside each visited node, so that it can
01832      * be readily referenced on retrieval. */
01833     jo->map = map;
01834 
01835 #ifdef U_JSON_IDX_DEBUG
01836     u_con("%p => %s (%s) = %s", jo, jo->fqn, U_JSON_OBJ_NAME(jo), jo->val);
01837 #endif
01838 
01839     return;
01840 }
01841 
01842 static int u_json_new_container (u_json_type_t type, const char *key, 
01843         u_json_t **pjo)
01844 {
01845     u_json_t *jo = NULL;
01846 
01847     dbg_return_if (pjo == NULL, ~0);
01848 
01849     dbg_err_if (u_json_new(&jo));
01850 
01851     dbg_err_if (u_json_set_type(jo, type));
01852     dbg_err_if (u_json_set_key(jo, key ? key : ""));
01853 
01854     *pjo = jo;
01855 
01856     return 0;
01857 err:
01858     if (jo)
01859         u_json_free(jo);
01860     return ~0;
01861 }
01862 
01863 static int u_json_new_atom (u_json_type_t type, const char *key, 
01864         const char *val, char check, u_json_t **pjo)
01865 {
01866     u_json_t *jo = NULL;
01867 
01868     dbg_return_if (pjo == NULL, ~0);
01869 
01870     dbg_err_if (u_json_new(&jo));
01871 
01872     dbg_err_if (u_json_set_type(jo, type));
01873     dbg_err_if (u_json_set_key(jo, key));
01874 
01875     /* Values are meaningful only in case of string and number objects,
01876      * "null", "true" and "false" are completely defined by the type. */
01877     switch (type)
01878     {
01879         case U_JSON_TYPE_NUMBER:  
01880         case U_JSON_TYPE_STRING:  
01881             dbg_err_if (u_json_set_val_ex(jo, val, check));
01882         default: break;
01883     }
01884 
01885     *pjo = jo;
01886 
01887     return 0;
01888 err:
01889     if (jo)
01890         u_json_free(jo);
01891     return ~0;
01892 }
01893 
01894 static int u_json_do_parse (const char *json, u_json_t **pjo, 
01895         char status[U_LEXER_ERR_SZ])
01896 {
01897     u_json_t *jo = NULL;
01898     u_lexer_t *jl = NULL;
01899 
01900     /* When 'pjo' is NULL, assume this is a validating-only parser. */
01901     dbg_return_if (json == NULL, ~0);
01902 
01903     /* Create a disposable lexer context associated to the supplied
01904      * 'json' string. */
01905     dbg_err_if (u_lexer_new(json, &jl));
01906 
01907     /* Create top level json object. */
01908     dbg_err_if (pjo && u_json_new(&jo));
01909 
01910     /* Consume any trailing white space before starting actual parsing. */
01911     if (u_lexer_eat_ws(jl) == -1)
01912         U_LEXER_ERR(jl, "Empty JSON text !");
01913 
01914     /* Launch the lexer expecting the input JSON text as a serialized object 
01915      * or array. */ 
01916     if (u_json_match_object_first(jl))
01917         dbg_err_if (u_json_match_object(jl, jo));
01918     else if (u_json_match_array_first(jl))
01919         dbg_err_if (u_json_match_array(jl, jo));
01920     else
01921         U_LEXER_ERR(jl, "Expect \'{\' or \'[\', got \'%c\'.", u_lexer_peek(jl));
01922 
01923     /* Just warn in case the JSON string has not been completely consumed. */
01924     if (!u_lexer_eot(jl))
01925     {
01926         u_warn("Unparsed trailing text \'%s\' at position %u", 
01927                 u_lexer_lookahead(jl), u_lexer_pos(jl));
01928     }
01929 
01930     /* Dispose the lexer context. */
01931     u_lexer_free(jl);
01932 
01933     /* Copy out the broken down tree. */
01934     if (pjo)
01935         *pjo = jo;
01936 
01937     return 0;
01938 err:
01939     /* Copy out the lexer error string (if requested). */
01940     if (status)
01941         (void) u_strlcpy(status, u_lexer_geterr(jl), U_LEXER_ERR_SZ);
01942 
01943     u_lexer_free(jl);
01944     u_json_free(jo);
01945 
01946     return ~0;
01947 }
01948 
01949 static int u_json_set_depth (u_json_t *jo, unsigned int depth)
01950 {
01951     /* Don't let'em smash our stack. */
01952     warn_err_ifm ((jo->depth = depth) >= U_JSON_MAX_DEPTH,
01953         "Maximum allowed nesting is %u.", U_JSON_MAX_DEPTH);
01954 
01955     return 0;
01956 err:
01957     return ~0;
01958 }

←Products
© 2005-2012 - KoanLogic S.r.l. - All rights reserved