--- libelwix/src/json.c 2025/08/21 15:41:26 1.11.2.2 +++ libelwix/src/json.c 2025/08/25 10:05:52 1.12.2.1 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: json.c,v 1.11.2.2 2025/08/21 15:41:26 misho Exp $ +* $Id: json.c,v 1.12.2.1 2025/08/25 10:05:52 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -658,7 +658,7 @@ 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 * @tok = Token for convert @@ -666,7 +666,7 @@ json_findbypos(u_long pos, jtok_t * __restrict toks, i * after use should be ait_freeVars() */ array_t * -json_token2array(const char *jstr, jtok_t * __restrict tok) +json_token2vars(const char *jstr, jtok_t * __restrict tok) { array_t *arr = NULL; register int i, j; @@ -728,8 +728,90 @@ json_token2array(const char *jstr, jtok_t * __restrict 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_add_begin_object() - Adds begin of object { * @@ -1331,15 +1413,22 @@ json_objscope(const char *key, const char *jstr, jtok_ * 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) +json_validate(const char *jstr, int *started) { - register int o = 0, a = 0, pos = 0; + register int o = 0, a = 0, q = 0, pos = 0; - while (isspace(jstr[pos]) || jstr[pos] != '{') + if (started) + *started = 0; + + while (jstr[pos] && jstr[pos] != '{' && jstr[pos] != '[') { pos++; + if (started) + (*started)++; + } do { switch (jstr[pos++]) { @@ -1355,10 +1444,18 @@ json_validate(const char *jstr) case ']': a--; break; + case '"': + q = ~q; + break; + case '\\': + pos++; + break; case 0: /* string ends without valid JSON */ + if (started) + *started = 0; return 0; } - } while (a || o); + } while (q || a || o); return pos; }