--- libelwix/src/json.c 2025/08/21 15:40:07 1.11.2.1 +++ libelwix/src/json.c 2025/08/25 13:00:37 1.13 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: json.c,v 1.11.2.1 2025/08/21 15:40:07 misho Exp $ +* $Id: json.c,v 1.13 2025/08/25 13:00:37 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,9 +728,108 @@ 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_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 { * * @jstr = JSON string @@ -1331,16 +1430,24 @@ 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, s = 0, pos = 0; + register int o = 0, a = 0, q = 0, pos = 0; - while (isspace(jstr[pos]) || jstr[pos] != '{') { + if (!jstr) + return -1; + + if (started) + *started = 0; + + while (jstr[pos] && jstr[pos] != '{' && jstr[pos] != '[') { pos++; - s++; + if (started) + (*started)++; } do { @@ -1357,10 +1464,71 @@ 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; +} + +/* + * 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; }