Diff for /libelwix/src/json.c between versions 1.9.34.2 and 1.13

version 1.9.34.2, 2024/10/26 14:56:14 version 1.13, 2025/08/25 13:00:37
Line 12  terms: Line 12  terms:
 All of the documentation and software included in the ELWIX and AITNET  All of the documentation and software included in the ELWIX and AITNET
 Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>  Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   
Copyright 2004 - 2024Copyright 2004 - 2025
         by Michael Pounov <misho@elwix.org>.  All rights reserved.          by Michael Pounov <misho@elwix.org>.  All rights reserved.
   
 Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
Line 589  json_findbykey(const char *jstr, const char *key, jtyp Line 589  json_findbykey(const char *jstr, const char *key, jtyp
 }  }
   
 /*  /*
    * json_findbykeyatscope() - Find token data by key at particular scope
    *
    * @scope = Search at object scope, =0 main object scope
    * @jstr = JSON string
    * @key = Search key
    * @type = Search key for particular token type, if is J_UNDEF this mean any type
    * @toks = Parsed tokens
    * @toksnum = Number of parsed tokens
    * return: =NULL error or !=NULL data token found
    */
   jtok_t *
   json_findbykeyatscope(long scope, const char *jstr, const char *key, jtype_t type, jtok_t * __restrict toks, int toksnum)
   {
           jtok_t *tok = NULL;
           register int i;
           int klen;
   
           if (!jstr || !key || !toks)
                   return NULL;
           else
                   klen = strlen(key);
   
           for (i = 1; i < toksnum; i++) {
                   if (toks[i].tok_type == J_STRING && toks[i].tok_size == 1 && 
                                   toks[i].tok_parent == scope && 
                                   klen == toks[i].tok_end - toks[i].tok_start && 
                                   !strncmp(jstr + toks[i].tok_start, key, klen)) {
                           if (type != J_UNDEF) {
                                   if (toks[i + 1].tok_type == type) {
                                           tok = toks + i + 1;
                                           break;
                                   }
                           } else {
                                   tok = toks + i + 1;
                                   break;
                           }
                   }
           }
   
           return tok;
   }
   
   /*
  * json_findbypos() - Find token by position on JSON string   * json_findbypos() - Find token by position on JSON string
  *   *
  * @pos = Offset from begin of JSON string   * @pos = Offset from begin of JSON string
Line 602  json_findbypos(u_long pos, jtok_t * __restrict toks, i Line 645  json_findbypos(u_long pos, jtok_t * __restrict toks, i
         jtok_t *tok = NULL;          jtok_t *tok = NULL;
         register int i;          register int i;
   
        if (toks)        if (!toks)
                 return NULL;                  return NULL;
   
         for (i = 1; i < toksnum; i++)          for (i = 1; i < toksnum; i++)
Line 615  json_findbypos(u_long pos, jtok_t * __restrict toks, i Line 658  json_findbypos(u_long pos, jtok_t * __restrict toks, i
 }  }
   
 /*  /*
 * json_token2array() - Convert token to string array * json_token2vars() - Convert token to string variable array
  *   *
  * @jstr = JSON string   * @jstr = JSON string
  * @tok = Token for convert   * @tok = Token for convert
Line 623  json_findbypos(u_long pos, jtok_t * __restrict toks, i Line 666  json_findbypos(u_long pos, jtok_t * __restrict toks, i
  *              after use should be ait_freeVars()   *              after use should be ait_freeVars()
  */   */
 array_t *  array_t *
json_token2array(const char *jstr, jtok_t * __restrict tok)json_token2vars(const char *jstr, jtok_t * __restrict tok)
 {  {
         array_t *arr = NULL;          array_t *arr = NULL;
         register int i, j;          register int i, j;
Line 645  json_token2array(const char *jstr, jtok_t * __restrict Line 688  json_token2array(const char *jstr, jtok_t * __restrict
         if (tok->tok_type == J_STRING || tok->tok_type == J_VALUE) {          if (tok->tok_type == J_STRING || tok->tok_type == J_VALUE) {
                 v = ait_getVars(&arr, 0);                  v = ait_getVars(&arr, 0);
                 AIT_SET_STRSIZ(v, json_toklen(tok) + 1);                  AIT_SET_STRSIZ(v, json_toklen(tok) + 1);
                json_tokstrcpy(AIT_GET_STR(v), jstr, tok);                if (AIT_GET_STR(v)) {
                         json_tokstrcpy(AIT_GET_STR(v), jstr, tok);
                 } else {
                         ait_freeVar(&v);
                 }
         } else if (tok->tok_type == J_ARRAY) {          } else if (tok->tok_type == J_ARRAY) {
                 for (i = 0, j = 1; i < tok->tok_size; i++) {                  for (i = 0, j = 1; i < tok->tok_size; i++) {
                         t = &tok[i + j];                          t = &tok[i + j];
                         v = ait_getVars(&arr, i);                          v = ait_getVars(&arr, i);
                         AIT_SET_STRSIZ(v, json_toklen(t) + 1);                          AIT_SET_STRSIZ(v, json_toklen(t) + 1);
                        json_tokstrcpy(AIT_GET_STR(v), jstr, t);                        if (AIT_GET_STR(v)) {
                                 json_tokstrcpy(AIT_GET_STR(v), jstr, t);
                         } else {
                                 ait_freeVar(&v);
                         }
   
                         /* if there we have array from objects should parse all object tokens */                          /* if there we have array from objects should parse all object tokens */
                         while (i < tok->tok_size - 1 && tok->tok_idx != tok[i + j + 1].tok_parent)                          while (i < tok->tok_size - 1 && tok->tok_idx != tok[i + j + 1].tok_parent)
Line 662  json_token2array(const char *jstr, jtok_t * __restrict Line 713  json_token2array(const char *jstr, jtok_t * __restrict
                         t = &tok[i + 1];                          t = &tok[i + 1];
                         v = ait_getVars(&arr, i);                          v = ait_getVars(&arr, i);
                         AIT_SET_STRSIZ(v, json_toklen(t) + 1);                          AIT_SET_STRSIZ(v, json_toklen(t) + 1);
                        json_tokstrcpy(AIT_GET_STR(v), jstr, t);                        if (AIT_GET_STR(v)) {
                                 json_tokstrcpy(AIT_GET_STR(v), jstr, t);
                         } else {
                                 ait_freeVar(&v);
                         }
                 }                  }
         } else {          } else {
                 elwix_SetErr(J_ERR_PARAM, "%s", jerrstr[J_ERR_PARAM]);                  elwix_SetErr(J_ERR_PARAM, "%s", jerrstr[J_ERR_PARAM]);
Line 673  json_token2array(const char *jstr, jtok_t * __restrict Line 728  json_token2array(const char *jstr, jtok_t * __restrict
         return arr;          return arr;
 }  }
   
   /*
    * json_token2array() - Convert token to string array
    *
    * @jstr = JSON string
    * @tok = Token for convert
    * return: =NULL error or !=NULL allocated array with strings,
    *              after use should be ait_freearray()
    */
   array_t *
   json_token2array(const char *jstr, jtok_t * __restrict tok)
   {
           array_t *arr = NULL;
           register int i, j;
           int siz;
           char *str;
           jtok_t *t;
   
           if (!jstr || !tok)
                   return NULL;
   
           siz = tok->tok_size;
           if (!siz && json_toktype(tok) != J_ARRAY && json_toktype(tok) != J_OBJECT)
                   siz++;
   
           arr = array_Init(siz);
           if (!arr)
                   return NULL;
   
           if (tok->tok_type == J_STRING || tok->tok_type == J_VALUE) {
                   str = e_malloc(json_toklen(tok) + 1);
                   if (!str) {
                           array_Destroy(&arr);
                           return NULL;
                   } else
                           json_tokstrcpy(str, jstr, tok);
                   if (array_Push(arr, str, 0) == -1) {
                           e_free(str);
                           array_Destroy(&arr);
                           return NULL;
                   }
           } else if (tok->tok_type == J_ARRAY) {
                   for (i = 0, j = 1; i < tok->tok_size; i++) {
                           t = &tok[i + j];
                           str = e_malloc(json_toklen(t) + 1);
                           if (!str) {
                                   json_freearray(&arr);
                                   return NULL;
                           } else
                                   json_tokstrcpy(str, jstr, t);
                           if (array_Push(arr, str, 0) == -1) {
                                   e_free(str);
                                   json_freearray(&arr);
                                   return NULL;
                           }
   
                           /* if there we have array from objects should parse all object tokens */
                           while (i < tok->tok_size - 1 && tok->tok_idx != tok[i + j + 1].tok_parent)
                                   j++;
                   }
           } else if (tok->tok_type == J_OBJECT) {
                   for (i = 0; tok->tok_idx <= tok[i + 1].tok_parent; i++) {
                           t = &tok[i + 1];
                           str = e_malloc(json_toklen(t) + 1);
                           if (!str) {
                                   json_freearray(&arr);
                                   return NULL;
                           } else
                                   json_tokstrcpy(str, jstr, t);
                           if (array_Push(arr, str, 0) == -1) {
                                   e_free(str);
                                   json_freearray(&arr);
                                   return NULL;
                           }
                   }
           } else {
                   elwix_SetErr(J_ERR_PARAM, "%s", jerrstr[J_ERR_PARAM]);
                   array_Destroy(&arr);
                   return NULL;
           }
   
           return arr;
   }
   
 /*  /*
    * json_freearray() - Free & destroy allocated array from json_token2array function
    *
    * @parr = Array
    * return -1 error or 0 ok
    */
   int
   json_freearray(array_t **parr)
   {
           if (!parr)
                   return -1;
   
           array_Free(*parr);
           array_Destroy(parr);
           return 0;
   }
   
   
   /*
  * json_add_begin_object() - Adds begin of object {   * json_add_begin_object() - Adds begin of object {
  *   *
  * @jstr = JSON string   * @jstr = JSON string
Line 1144  json_dump_yaml(FILE *f, const char *jstr, jtok_t *toks Line 1298  json_dump_yaml(FILE *f, const char *jstr, jtok_t *toks
 {  {
         register int i, j, k;          register int i, j, k;
   
        if (!toksnum)        if (!toksnum || !toks)
                 return 0;                  return 0;
   
         if (toks->tok_type == J_VALUE) {          if (toks->tok_type == J_VALUE) {
Line 1234  json_dump(FILE *f, const char *jstr, jtok_t *toks, int Line 1388  json_dump(FILE *f, const char *jstr, jtok_t *toks, int
         }          }
   
         return 0;          return 0;
   }
   
   /*
    * json_objscope() - Find object scope of key
    *
    * @key = Key of object, if it is =NULL, then return 0 (default scope)
    * @jstr = JSON string
    * @toks = JSON tokens
    * @toksnum = Number of tokens
    * return: -1 on error or >=0 scope of object
    */
   long
   json_objscope(const char *key, const char *jstr, jtok_t * __restrict toks, int toksnum)
   {
           long scope = 0;
           register int i;
           int klen;
   
           if (!key)
                   return 0;       /* default scope */
   
           if (!jstr || !toks)
                   return -1;
           else
                   klen = strlen(key);
   
           for (i = 1; i < toksnum; i++)
                   if (toks[i].tok_type == J_STRING && toks[i].tok_size == 1 && 
                                   klen == toks[i].tok_end - toks[i].tok_start && 
                                   !strncmp(jstr + toks[i].tok_start, key, klen))
                           if (toks[i + 1].tok_type == J_OBJECT) {
                                   scope = toks[i + 1].tok_idx;
                                   break;
                           }
   
           return scope;
   }
   
   /*
    * json_validate() - Validate JSON
    *
    * @jstr = JSON string
    * @started = if started != NULL then here will return start position of found JSON
    * return: -1 error or >=0 where valid JSON ends
    */
   int
   json_validate(const char *jstr, int *started)
   {
           register int o = 0, a = 0, q = 0, pos = 0;
   
           if (!jstr)
                   return -1;
   
           if (started)
                   *started = 0;
   
           while (jstr[pos] && jstr[pos] != '{' && jstr[pos] != '[') {
                   pos++;
                   if (started)
                           (*started)++;
           }
   
           do {
                   switch (jstr[pos++]) {
                           case '{':
                                   o++;
                                   break;
                           case '}':
                                   o--;
                                   break;
                           case '[':
                                   a++;
                                   break;
                           case ']':
                                   a--;
                                   break;
                           case '"':
                                   q = ~q;
                                   break;
                           case '\\':
                                   pos++;
                                   break;
                           case 0: /* string ends without valid JSON */
                                   if (started)
                                           *started = 0;
                                   return 0;
                   }
           } while (q || a || o);
   
           return pos;
   }
   
   /*
    * json_marshaling() - Prepare JSON to one continues line
    *
    * @jstr = JSON string
    * @space = if it is 0 then spaces will be removed
    * return NULL error or !=NULL ready JSON for proceeding
    */
   char *
   json_marshaling(char * __restrict jstr, int space)
   {
           int started, ended, len;
           char *str, *pos, *js;
           register int q = 0;
   
           if (!jstr)
                   return NULL;
           else
                   js = jstr;
   
           ended = json_validate(jstr, &started);
           if (!ended)
                   return NULL;
           len = ended - started + 1;
           str = e_malloc(len);
           if (!str)
                   return NULL;
           else {
                   memset(str, 0, len);
                   pos = str;
           }
   
           js += started;
           while (*js && js < jstr + ended && --len) {
                   if (*js < 0x20) {
                           js++;
                           continue;
                   }
                   if (space && !q && *js == 0x20) {
                           js++;
                           continue;
                   }
                   if (*js == '"')
                           q = ~q;
                   *pos++ = *js++;
           }
           *pos = 0;
   
           len = strlen(jstr) + 1;
           strlcpy(jstr, str, len);
           e_free(str);
           return jstr;
 }  }

Removed from v.1.9.34.2  
changed lines
  Added in v.1.13


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>