--- libelwix/src/json.c	2024/10/26 14:56:14	1.9.34.2
+++ libelwix/src/json.c	2024/12/04 17:47:28	1.11
@@ -3,7 +3,7 @@
 *  by Michael Pounov <misho@elwix.org>
 *
 * $Author: misho $
-* $Id: json.c,v 1.9.34.2 2024/10/26 14:56:14 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
@@ -589,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
@@ -602,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++)
@@ -645,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)
@@ -662,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]);
@@ -1144,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) {
@@ -1234,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;
 }