--- libelwix/src/json.c 2018/06/08 13:08:37 1.6.6.1 +++ libelwix/src/json.c 2024/12/04 17:47:28 1.11 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: json.c,v 1.6.6.1 2018/06/08 13:08:37 misho Exp $ +* $Id: json.c,v 1.11 2024/12/04 17:47:28 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -12,7 +12,7 @@ terms: All of the documentation and software included in the ELWIX and AITNET Releases is copyrighted by ELWIX - Sofia/Bulgaria -Copyright 2004 - 2018 +Copyright 2004 - 2024 by Michael Pounov . All rights reserved. Redistribution and use in source and binary forms, with or without @@ -224,7 +224,7 @@ json_parse_value(json_t * __restrict json, const char case '}': goto found; } - if (jstr[json->h_pos] < 32 || jstr[json->h_pos] > 127) { + if (jstr[json->h_pos] < 32 || (u_char) jstr[json->h_pos] > 127) { json->h_pos = pos; elwix_SetErr(J_ERR_INVAL, "%s", jerrstr[J_ERR_INVAL]); return -1; @@ -427,7 +427,10 @@ json_token2val(const char *jstr, jtok_t * __restrict t return NULL; AIT_SET_STRSIZ(v, json_toklen(tok)); - strncpy(AIT_GET_STR(v), json_tokstr(jstr, tok), AIT_LEN(v) - 1); + if (AIT_GET_STR(v)) + strncpy(AIT_GET_STR(v), json_tokstr(jstr, tok), AIT_LEN(v) - 1); + else + ait_freeVar(&v); return v; } @@ -442,19 +445,25 @@ json_token2val(const char *jstr, jtok_t * __restrict t char * json_token2str(const char *jstr, jtok_t * __restrict tok) { - char *str = NULL; + char *s, *s2, *wrk, *str = NULL; size_t len; if (!jstr || !tok) return NULL; + len = json_toklen(tok); str = e_malloc(len + 1); if (!str) return NULL; else { - strncpy(str, json_tokstr(jstr, tok), len); - str[len] = 0; + memset(str, 0, len + 1); + + wrk = e_strdup(json_tokstr(jstr, tok)); + wrk[len] = 0; + for (s = wrk, s2 = str; *s; s++) + *s2++ = (*s != '\\') ? *s : *++s; + e_free(wrk); } return str; @@ -561,7 +570,7 @@ json_findbykey(const char *jstr, const char *key, jtyp klen = strlen(key); for (i = 1; i < toksnum; i++) { - if (toks[i].tok_type == J_STRING && + 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 (type != J_UNDEF) { @@ -580,6 +589,49 @@ 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 * * @pos = Offset from begin of JSON string @@ -593,7 +645,7 @@ json_findbypos(u_long pos, jtok_t * __restrict toks, i jtok_t *tok = NULL; register int i; - if (toks) + if (!toks) return NULL; for (i = 1; i < toksnum; i++) @@ -636,13 +688,21 @@ json_token2array(const char *jstr, jtok_t * __restrict if (tok->tok_type == J_STRING || tok->tok_type == J_VALUE) { v = ait_getVars(&arr, 0); 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) { for (i = 0, j = 1; i < tok->tok_size; i++) { t = &tok[i + j]; v = ait_getVars(&arr, i); 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 */ while (i < tok->tok_size - 1 && tok->tok_idx != tok[i + j + 1].tok_parent) @@ -653,7 +713,11 @@ json_token2array(const char *jstr, jtok_t * __restrict t = &tok[i + 1]; v = ait_getVars(&arr, i); 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 { elwix_SetErr(J_ERR_PARAM, "%s", jerrstr[J_ERR_PARAM]); @@ -1135,7 +1199,7 @@ json_dump_yaml(FILE *f, const char *jstr, jtok_t *toks { register int i, j, k; - if (!toksnum) + if (!toksnum || !toks) return 0; if (toks->tok_type == J_VALUE) { @@ -1225,4 +1289,40 @@ json_dump(FILE *f, const char *jstr, jtok_t *toks, int } 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; }