9ceb218f80
Co-authored-by: Cursor <cursoragent@cursor.com>
843 lines
24 KiB
C
843 lines
24 KiB
C
/*
|
|
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
|
*/
|
|
#include "infra_config.h"
|
|
|
|
#ifdef INFRA_JSON_PARSER
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "infra_types.h"
|
|
#include "infra_json_parser.h"
|
|
#include "wrappers.h"
|
|
|
|
#ifdef INFRA_LOG
|
|
#include "infra_log.h"
|
|
#define jparser_debug(...) log_debug("jparser", __VA_ARGS__)
|
|
#else
|
|
#define jparser_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
|
|
#endif
|
|
|
|
#ifdef INFRA_MEM_STATS
|
|
#include "infra_mem_stats.h"
|
|
#define jparser_malloc(size) LITE_malloc(size, MEM_MAGIC, "jparser")
|
|
#define jparser_free(ptr) LITE_free(ptr)
|
|
#else
|
|
#define jparser_malloc(size) HAL_Malloc(size)
|
|
#define jparser_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
|
|
#endif
|
|
|
|
char *json_get_object(int type, char *str, char *str_end)
|
|
{
|
|
char *pos = NULL;
|
|
char ch = (type == JOBJECT) ? '{' : '[';
|
|
|
|
if (!str || !str_end) {
|
|
return NULL;
|
|
}
|
|
|
|
while (str != NULL && *str != 0 && str < str_end) {
|
|
if (*str == ' ') {
|
|
str++;
|
|
continue;
|
|
}
|
|
pos = (*str == ch) ? str : NULL;
|
|
break;
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
char *json_get_next_object(int type, char *str, char *str_end, char **key, int *key_len,
|
|
char **val, int *val_len, int *val_type)
|
|
{
|
|
char JsonMark[JTYPEMAX][2] = { { '\"', '\"' }, { '{', '}' }, { '[', ']' }, { '0', ' ' } };
|
|
int iMarkDepth = 0, iValueType = JNONE, iNameLen = 0, iValueLen = 0, iStringDepth = 0;
|
|
char *p_cName = 0, *p_cValue = 0, *p_cPos = str;
|
|
|
|
if (type == JOBJECT) {
|
|
/* Get Key */
|
|
p_cPos = strchr(p_cPos, '\"');
|
|
if (!p_cPos) {
|
|
goto do_exit;
|
|
}
|
|
p_cName = ++p_cPos;
|
|
p_cPos = strchr(p_cPos, '\"');
|
|
if (!p_cPos) {
|
|
goto do_exit;
|
|
}
|
|
iNameLen = p_cPos - p_cName;
|
|
|
|
/* Get Value */
|
|
p_cPos = strchr(p_cPos, ':');
|
|
}
|
|
while (p_cPos && *p_cPos && p_cPos < str_end) {
|
|
if (*p_cPos == '\"') {
|
|
iValueType = JSTRING;
|
|
p_cValue = ++p_cPos;
|
|
break;
|
|
} else if (*p_cPos == '{') {
|
|
iValueType = JOBJECT;
|
|
p_cValue = p_cPos++;
|
|
break;
|
|
} else if (*p_cPos == '[') {
|
|
iValueType = JARRAY;
|
|
p_cValue = p_cPos++;
|
|
break;
|
|
} else if ((*p_cPos == '-') || (*p_cPos >= '0' && *p_cPos <= '9')) {
|
|
iValueType = JNUMBER;
|
|
p_cValue = p_cPos++;
|
|
break;
|
|
} else if (*p_cPos == 't' || *p_cPos == 'T' || *p_cPos == 'f' || *p_cPos == 'F') {
|
|
iValueType = JBOOLEAN;
|
|
p_cValue = p_cPos;
|
|
break;
|
|
}
|
|
p_cPos++;
|
|
}
|
|
|
|
while (p_cPos && *p_cPos && p_cPos < str_end && iValueType > JNONE) {
|
|
if (iValueType == JBOOLEAN) {
|
|
int len = strlen(p_cValue);
|
|
|
|
if ((*p_cValue == 't' || *p_cValue == 'T') && len >= 4
|
|
&& (!strncmp(p_cValue, "true", 4)
|
|
|| !strncmp(p_cValue, "TRUE", 4))) {
|
|
iValueLen = 4;
|
|
p_cPos = p_cValue + iValueLen;
|
|
break;
|
|
} else if ((*p_cValue == 'f' || *p_cValue == 'F') && len >= 5
|
|
&& (!strncmp(p_cValue, "false", 5)
|
|
|| !strncmp(p_cValue, "FALSE", 5))) {
|
|
iValueLen = 5;
|
|
p_cPos = p_cValue + iValueLen;
|
|
break;
|
|
}
|
|
} else if (iValueType == JNUMBER) {
|
|
if ((*p_cPos < '0' || *p_cPos > '9') && (*p_cPos != '.') && (*p_cPos != '+') \
|
|
&& (*p_cPos != '-') && ((*p_cPos != 'e')) && (*p_cPos != 'E')) {
|
|
iValueLen = p_cPos - p_cValue;
|
|
break;
|
|
}
|
|
} else if (iValueType == JSTRING) {
|
|
if (*p_cPos == '\"') {
|
|
iValueLen = p_cPos - p_cValue;
|
|
break;
|
|
}
|
|
} else if (*p_cPos == JsonMark[iValueType][1]) {
|
|
if (iStringDepth == 0) {
|
|
if (iMarkDepth == 0) {
|
|
iValueLen = p_cPos - p_cValue + 1;
|
|
p_cPos++;
|
|
break;
|
|
} else {
|
|
iMarkDepth--;
|
|
}
|
|
}
|
|
} else if (*p_cPos == JsonMark[iValueType][0]) {
|
|
if (iStringDepth == 0) {
|
|
iMarkDepth++;
|
|
}
|
|
} else if (*p_cPos == '\"') {
|
|
if (iStringDepth) {
|
|
iStringDepth = 0;
|
|
} else {
|
|
iStringDepth = 1;
|
|
}
|
|
}
|
|
p_cPos++;
|
|
}
|
|
|
|
if (type == JOBJECT) {
|
|
if ((p_cName + iNameLen) > str_end) {
|
|
goto do_exit;
|
|
}
|
|
*key = p_cName;
|
|
*key_len = iNameLen;
|
|
}
|
|
if ((p_cValue + iValueLen) > str_end) {
|
|
goto do_exit;
|
|
}
|
|
|
|
*val = p_cValue;
|
|
*val_len = iValueLen;
|
|
*val_type = iValueType;
|
|
if (iValueType == JSTRING) {
|
|
return p_cValue + iValueLen + 1;
|
|
} else {
|
|
return p_cValue + iValueLen;
|
|
}
|
|
|
|
do_exit:
|
|
*val = NULL;
|
|
*val_len = 0;
|
|
*key = NULL;
|
|
*key_len = 0;
|
|
return NULL;
|
|
}
|
|
|
|
int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, void *p_CBData)
|
|
{
|
|
char *pos = 0, *key = 0, *val = 0;
|
|
int klen = 0, vlen = 0, vtype = 0;
|
|
int ret = JSON_RESULT_ERR;
|
|
|
|
if (p_cJsonStr == NULL || iStrLen == 0 || pfnCB == NULL) {
|
|
return ret;
|
|
}
|
|
|
|
json_object_for_each_kv(p_cJsonStr, iStrLen, pos, key, klen, val, vlen, vtype) {
|
|
if (key && klen && val && vlen) {
|
|
ret = JSON_RESULT_OK;
|
|
if (JSON_PARSE_FINISH == pfnCB(key, klen, val, vlen, vtype, p_CBData)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int json_get_value_by_name_cb(char *p_cName, int iNameLen, char *p_cValue, int iValueLen, int iValueType,
|
|
void *p_CBData)
|
|
{
|
|
JSON_NV *p_stNameValue = (JSON_NV *)p_CBData;
|
|
|
|
#ifdef JSON_DEBUG
|
|
int i;
|
|
|
|
if (p_cName) {
|
|
jparser_debug("Name:");
|
|
for (i = 0; i < iNameLen; i++) {
|
|
jparser_debug("%c", *(p_cName + i));
|
|
}
|
|
}
|
|
|
|
if (p_cValue) {
|
|
jparser_debug("Value:");
|
|
for (i = 0; i < iValueLen; i++) {
|
|
jparser_debug("%c", *(p_cValue + i));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if ((iNameLen == p_stNameValue->nLen) && !strncmp(p_cName, p_stNameValue->pN, p_stNameValue->nLen)) {
|
|
p_stNameValue->pV = p_cValue;
|
|
p_stNameValue->vLen = iValueLen;
|
|
p_stNameValue->vType = iValueType;
|
|
return JSON_PARSE_FINISH;
|
|
} else {
|
|
return JSON_PARSE_OK;
|
|
}
|
|
}
|
|
|
|
char *json_get_value_by_name(char *p_cJsonStr, int iStrLen, char *p_cName, int *p_iValueLen, int *p_iValueType)
|
|
{
|
|
JSON_NV stNV;
|
|
|
|
memset(&stNV, 0, sizeof(stNV));
|
|
stNV.pN = p_cName;
|
|
stNV.nLen = strlen(p_cName);
|
|
if (JSON_RESULT_OK == json_parse_name_value(p_cJsonStr, iStrLen, json_get_value_by_name_cb, (void *)&stNV)) {
|
|
if (p_iValueLen) {
|
|
*p_iValueLen = stNV.vLen;
|
|
}
|
|
if (p_iValueType) {
|
|
*p_iValueType = stNV.vType;
|
|
}
|
|
}
|
|
return stNV.pV;
|
|
}
|
|
|
|
char *json_get_value_by_name_len(char *p_cJsonStr, int iStrLen, char *p_cName, int p_cNameLen, int *p_iValueLen,
|
|
int *p_iValueType)
|
|
{
|
|
JSON_NV stNV;
|
|
|
|
memset(&stNV, 0, sizeof(stNV));
|
|
stNV.pN = p_cName;
|
|
stNV.nLen = p_cNameLen;
|
|
if (JSON_RESULT_OK == json_parse_name_value(p_cJsonStr, iStrLen, json_get_value_by_name_cb, (void *)&stNV)) {
|
|
if (p_iValueLen) {
|
|
*p_iValueLen = stNV.vLen;
|
|
}
|
|
if (p_iValueType) {
|
|
*p_iValueType = stNV.vType;
|
|
}
|
|
}
|
|
return stNV.pV;
|
|
}
|
|
|
|
char *LITE_json_value_of(char *key, char *src, ...)
|
|
{
|
|
char *value = NULL;
|
|
char *ret = NULL;
|
|
char *delim = NULL;
|
|
char *key_iter;
|
|
char *key_next;
|
|
char *src_iter;
|
|
|
|
int key_len;
|
|
int value_len = -1;
|
|
int src_iter_len;
|
|
|
|
if (NULL == key || NULL == src) {
|
|
return NULL;
|
|
}
|
|
|
|
#if WITH_MEM_STATS_PER_MODULE
|
|
{
|
|
char *module_name = NULL;
|
|
int magic = 0;
|
|
va_list ap;
|
|
va_start(ap, src);
|
|
magic = va_arg(ap, int);
|
|
if (MEM_MAGIC == magic) {
|
|
module_name = va_arg(ap, char *);
|
|
}
|
|
va_end(ap);
|
|
}
|
|
#endif
|
|
|
|
src_iter = src;
|
|
src_iter_len = strlen(src_iter);
|
|
key_iter = key;
|
|
|
|
do {
|
|
if ((delim = strchr(key_iter, '.')) != NULL) {
|
|
key_len = delim - key_iter;
|
|
key_next = key_iter;
|
|
|
|
value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0);
|
|
if (value == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
src_iter = value;
|
|
src_iter_len = value_len;
|
|
key_iter = delim + 1;
|
|
}
|
|
} while (delim);
|
|
|
|
key_len = strlen(key_iter);
|
|
key_next = key_iter;
|
|
value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0);
|
|
if (NULL == value) {
|
|
return NULL;
|
|
}
|
|
|
|
ret = jparser_malloc((value_len + 1) * sizeof(char));
|
|
|
|
if (NULL == ret) {
|
|
return NULL;
|
|
}
|
|
|
|
HAL_Snprintf(ret, value_len + 1, "%s", value);
|
|
return ret;
|
|
}
|
|
|
|
#if WITH_JSON_KEYS_OF
|
|
static list_head_t *_LITE_json_keys_of(char *src, int src_len, char *prefix, ...)
|
|
{
|
|
static LIST_HEAD(keylist);
|
|
char *module_name = NULL;
|
|
char *iter_pre = NULL;
|
|
char *pos = 0, *key = 0, *val = 0;
|
|
int klen = 0, vlen = 0, vtype = 0;
|
|
int magic = 0;
|
|
unsigned int mlen = 0;
|
|
|
|
#if WITH_MEM_STATS_PER_MODULE
|
|
va_list ap;
|
|
va_start(ap, prefix);
|
|
magic = va_arg(ap, int);
|
|
if (MEM_MAGIC == magic) {
|
|
module_name = va_arg(ap, char *);
|
|
}
|
|
va_end(ap);
|
|
#endif
|
|
|
|
if (!strcmp("", prefix)) {
|
|
INIT_LIST_HEAD(&keylist);
|
|
}
|
|
|
|
json_object_for_each_kv(src, src_len, pos, key, klen, val, vlen, vtype) {
|
|
if (key && klen && val && vlen) {
|
|
|
|
json_key_t *entry = NULL;
|
|
|
|
entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
|
|
if (NULL == entry) {
|
|
utils_err("jparser_malloc failed!");
|
|
return NULL;
|
|
}
|
|
memset(entry, 0, sizeof(json_key_t));
|
|
|
|
mlen = strlen(prefix) + klen + 1;
|
|
if (module_name) {
|
|
entry->key = LITE_format_nstring(mlen, "%s%.*s", magic, module_name, prefix, klen, key);
|
|
} else {
|
|
entry->key = LITE_format_nstring(mlen, "%s%.*s", prefix, klen, key);
|
|
}
|
|
if (NULL == entry->key) {
|
|
jparser_free(entry);
|
|
return NULL;
|
|
}
|
|
|
|
list_add_tail(&entry->list, &keylist);
|
|
|
|
if (JOBJECT == vtype) {
|
|
mlen = strlen(prefix) + klen + 2;
|
|
if (module_name) {
|
|
iter_pre = LITE_format_nstring(mlen, "%s%.*s.", magic, module_name, prefix, klen, key);
|
|
} else {
|
|
iter_pre = LITE_format_nstring(mlen, "%s%.*s.", prefix, klen, key);
|
|
}
|
|
if (NULL == iter_pre) {
|
|
return NULL;
|
|
}
|
|
|
|
_LITE_json_keys_of(val, vlen, iter_pre, magic, module_name);
|
|
jparser_free(iter_pre);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!strcmp("", prefix)) {
|
|
json_key_t *entry = NULL;
|
|
|
|
entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
|
|
if (NULL == entry) {
|
|
utils_err("jparser_malloc failed!");
|
|
return NULL;
|
|
}
|
|
memset(entry, 0, sizeof(json_key_t));
|
|
list_add_tail(&entry->list, &keylist);
|
|
|
|
return &keylist;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
list_head_t *LITE_json_keys_of(char *src, char *prefix, ...)
|
|
{
|
|
char *module_name = NULL;
|
|
int magic = 0;
|
|
|
|
if (!src || !prefix) {
|
|
return NULL;
|
|
}
|
|
|
|
#if WITH_MEM_STATS_PER_MODULE
|
|
|
|
va_list ap;
|
|
va_start(ap, prefix);
|
|
magic = va_arg(ap, int);
|
|
if (MEM_MAGIC == magic) {
|
|
module_name = va_arg(ap, char *);
|
|
}
|
|
va_end(ap);
|
|
#endif
|
|
|
|
return _LITE_json_keys_of(src, strlen(src), prefix, magic, module_name);
|
|
|
|
}
|
|
|
|
#if WITH_JSON_TOKEN_EXT
|
|
static list_head_t *_LITE_json_keys_of_ext(int type, char *src, int src_len, char *prefix, ...)
|
|
{
|
|
static LIST_HEAD(keylist);
|
|
char *module_name = NULL;
|
|
char *iter_pre = NULL;
|
|
char *pos = 0, *key = 0, *val = 0;
|
|
int klen = 0, vlen = 0, vtype = 0;
|
|
int magic = 0;
|
|
unsigned int count = 1;
|
|
unsigned int mlen = 0;
|
|
|
|
if (src == NULL || prefix == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
#if WITH_MEM_STATS_PER_MODULE
|
|
va_list ap;
|
|
va_start(ap, prefix);
|
|
magic = va_arg(ap, int);
|
|
if (MEM_MAGIC == magic) {
|
|
module_name = va_arg(ap, char *);
|
|
}
|
|
va_end(ap);
|
|
#endif
|
|
|
|
if (!strcmp("", prefix)) {
|
|
INIT_LIST_HEAD(&keylist);
|
|
}
|
|
|
|
if (JOBJECT == type) {
|
|
json_object_for_each_kv(src, src_len, pos, key, klen, val, vlen, vtype) {
|
|
if (key && klen && val && vlen) {
|
|
|
|
json_key_t *entry = NULL;
|
|
|
|
entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
|
|
|
|
if (NULL == entry) {
|
|
utils_err("jparser_malloc failed!");
|
|
return NULL;
|
|
}
|
|
memset(entry, 0, sizeof(json_key_t));
|
|
|
|
mlen = strlen(prefix) + klen + 1;
|
|
if (module_name) {
|
|
entry->key = LITE_format_nstring(mlen, "%s%.*s", magic, module_name, prefix, klen, key);
|
|
} else {
|
|
entry->key = LITE_format_nstring(mlen, "%s%.*s", prefix, klen, key);
|
|
}
|
|
|
|
if (NULL == entry->key) {
|
|
jparser_free(entry);
|
|
return NULL;
|
|
}
|
|
|
|
list_add_tail(&entry->list, &keylist);
|
|
|
|
if (JOBJECT == vtype) {
|
|
mlen = strlen(prefix) + klen + 2;
|
|
if (module_name) {
|
|
iter_pre = LITE_format_nstring(mlen, "%s%.*s.", magic, module_name, prefix, klen, key);
|
|
} else {
|
|
iter_pre = LITE_format_nstring(mlen, "%s%.*s.", prefix, klen, key);
|
|
}
|
|
if (NULL == iter_pre) {
|
|
return NULL;
|
|
}
|
|
|
|
_LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name);
|
|
jparser_free(iter_pre);
|
|
} else if (JARRAY == vtype) {
|
|
mlen = strlen(prefix) + klen + 1;
|
|
if (module_name) {
|
|
iter_pre = LITE_format_nstring(mlen, "%s%.*s", magic, module_name, prefix, klen, key);
|
|
} else {
|
|
iter_pre = LITE_format_nstring(mlen, "%s%.*s", prefix, klen, key);
|
|
}
|
|
if (NULL == iter_pre) {
|
|
return NULL;
|
|
}
|
|
|
|
_LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name);
|
|
jparser_free(iter_pre);
|
|
}
|
|
}
|
|
}
|
|
} else if (JARRAY == type) {
|
|
json_array_for_each_entry(src, src_len, pos, val, vlen, vtype) {
|
|
if (val && vlen) {
|
|
|
|
json_key_t *entry = NULL;
|
|
unsigned int tmp = 0;
|
|
unsigned int arridxlen = 0;
|
|
entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
|
|
if (NULL == entry) {
|
|
utils_err("jparser_malloc failed!");
|
|
return NULL;
|
|
}
|
|
memset(entry, 0, sizeof(json_key_t));
|
|
|
|
tmp = count;
|
|
do {
|
|
tmp /= 10;
|
|
++arridxlen;
|
|
} while (tmp);
|
|
mlen = strlen("%s[%d]") + strlen(prefix) + arridxlen;
|
|
if (module_name) {
|
|
entry->key = LITE_format_nstring(mlen, "%s[%d]", magic, module_name, prefix, count);
|
|
} else {
|
|
entry->key = LITE_format_nstring(mlen, "%s[%d]", prefix, count);
|
|
}
|
|
if (NULL == entry->key) {
|
|
jparser_free(entry);
|
|
return NULL;
|
|
}
|
|
|
|
list_add_tail(&entry->list, &keylist);
|
|
|
|
if (JOBJECT == vtype) {
|
|
mlen = strlen("%s[%d].") + strlen(prefix) + arridxlen;
|
|
if (module_name) {
|
|
iter_pre = LITE_format_nstring(mlen, "%s[%d].", magic, module_name, prefix, count);
|
|
} else {
|
|
iter_pre = LITE_format_nstring(mlen, "%s[%d].", prefix, count);
|
|
}
|
|
if (NULL == iter_pre) {
|
|
return NULL;
|
|
}
|
|
|
|
_LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name);
|
|
jparser_free(iter_pre);
|
|
} else if (JARRAY == vtype) {
|
|
mlen = strlen("%s[%d]") + strlen(prefix) + arridxlen;
|
|
if (module_name) {
|
|
iter_pre = LITE_format_nstring(mlen, "%s[%d]", magic, module_name, prefix, count);
|
|
} else {
|
|
iter_pre = LITE_format_nstring(mlen, "%s[%d]", prefix, count);
|
|
}
|
|
if (NULL == iter_pre) {
|
|
return NULL;
|
|
}
|
|
|
|
_LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name);
|
|
jparser_free(iter_pre);
|
|
}
|
|
++count;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!strcmp("", prefix)) {
|
|
json_key_t *entry = NULL;
|
|
|
|
entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
|
|
if (NULL == entry) {
|
|
utils_err("jparser_malloc failed!");
|
|
return NULL;
|
|
}
|
|
memset(entry, 0, sizeof(json_key_t));
|
|
list_add_tail(&entry->list, &keylist);
|
|
|
|
return &keylist;
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
int contain_arr(const char *src, int src_len, const char **arr_pre)
|
|
{
|
|
int i = 0;
|
|
int ret = -1;
|
|
int deep = 0;
|
|
const char *pre = NULL;
|
|
|
|
if (NULL == src || NULL == arr_pre || src_len <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
*arr_pre = NULL;
|
|
for (i = 0; i < src_len; ++i) {
|
|
switch (src[i]) {
|
|
case '[': {
|
|
if (deep != 0) {
|
|
return ret;
|
|
}
|
|
++deep;
|
|
if (!pre) {
|
|
pre = &src[i];
|
|
}
|
|
}
|
|
break;
|
|
case ']': {
|
|
if (deep != 1) {
|
|
return ret;
|
|
}
|
|
--deep;
|
|
if ('[' == src[i - 1]) {
|
|
return ret;
|
|
}
|
|
}
|
|
break;
|
|
default: {
|
|
if ((pre != NULL) && (0 == deep)) {
|
|
return ret;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if ((NULL != pre) && (pre < src + src_len) && (pre >= src)) {
|
|
*arr_pre = pre;
|
|
ret = 0;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static char *_json_value_by_arrname(char *src, int src_len, const char *key, int key_len, int *val_len)
|
|
{
|
|
char *pos = src;
|
|
char *entry = NULL;
|
|
const char *p = NULL;
|
|
const char *arr_pre = key;
|
|
const char *arr_suf = NULL;
|
|
int vtype;
|
|
int loop;
|
|
int loop_tmp = 0;
|
|
do {
|
|
loop = 0;
|
|
|
|
arr_pre = strchr(arr_pre, '[');
|
|
if (arr_pre && (arr_pre < key + key_len)) {
|
|
arr_suf = strchr(arr_pre, ']');
|
|
}
|
|
if (arr_pre && arr_suf && (arr_suf < key + key_len)) {
|
|
loop_tmp = 0;
|
|
for (p = arr_pre + 1; p < arr_suf; ++p) {
|
|
if (*p > '9' || *p < '0') {
|
|
return NULL;
|
|
}
|
|
loop_tmp *= 10;
|
|
loop_tmp += *p - '0';
|
|
|
|
}
|
|
|
|
pos = json_get_object(JARRAY, pos, src + src_len);
|
|
if (pos != 0 && *pos != 0) {
|
|
if (*pos == '[' && *(pos + 1) == ']') {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
json_array_for_each_entry(src, src_len, pos, entry, *val_len, vtype) {
|
|
if (entry && *val_len) {
|
|
if (++loop >= loop_tmp) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (loop != loop_tmp) {
|
|
return NULL;
|
|
}
|
|
src = entry;
|
|
arr_pre = arr_suf + 1;
|
|
}
|
|
} while (arr_pre && arr_suf && (arr_pre < key + key_len));
|
|
return entry;
|
|
}
|
|
|
|
void LITE_json_keys_release(list_head_t *keylist)
|
|
{
|
|
json_key_t *pos, *tmp;
|
|
|
|
if (NULL == keylist) {
|
|
return;
|
|
}
|
|
|
|
list_for_each_entry_safe(pos, tmp, keylist, list, json_key_t) {
|
|
if (pos->key) {
|
|
jparser_free(pos->key);
|
|
}
|
|
list_del(&pos->list);
|
|
jparser_free(pos);
|
|
}
|
|
}
|
|
|
|
list_head_t *LITE_json_keys_of_ext(char *src, char *prefix, ...)
|
|
{
|
|
char *module_name = NULL;
|
|
int magic = 0;
|
|
|
|
#if WITH_MEM_STATS_PER_MODULE
|
|
|
|
va_list ap;
|
|
va_start(ap, prefix);
|
|
magic = va_arg(ap, int);
|
|
if (MEM_MAGIC == magic) {
|
|
module_name = va_arg(ap, char *);
|
|
}
|
|
va_end(ap);
|
|
#endif
|
|
|
|
if (!src || !prefix) {
|
|
return NULL;
|
|
}
|
|
|
|
return _LITE_json_keys_of_ext(JOBJECT, src, strlen(src), prefix, magic, module_name);
|
|
}
|
|
|
|
static char *_LITE_json_value_of_ext(char *key, char *src, int src_len, int *val_len)
|
|
{
|
|
char *value = NULL;
|
|
char *delim = NULL;
|
|
char *key_iter;
|
|
char *key_next;
|
|
char *src_iter;
|
|
const char *arr_pre = NULL;
|
|
|
|
int value_len;
|
|
int key_len;
|
|
int obj_key_len = 0;
|
|
int key_type;
|
|
int src_iter_len;
|
|
|
|
src_iter = src;
|
|
src_iter_len = src_len;
|
|
key_iter = key;
|
|
value_len = src_iter_len;
|
|
do {
|
|
if ((delim = strchr(key_iter, '.')) != NULL) {
|
|
key_len = delim - key_iter;
|
|
key_type = JOBJECT;
|
|
key_next = key_iter;
|
|
if (0 == contain_arr(key_next, key_len, &arr_pre)) {
|
|
key_type = JARRAY;
|
|
obj_key_len = arr_pre - key_iter;
|
|
if (obj_key_len) {
|
|
value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, obj_key_len, &value_len, 0);
|
|
} else {
|
|
value = src_iter;
|
|
}
|
|
} else {
|
|
value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0);
|
|
}
|
|
|
|
if (NULL == value) {
|
|
return NULL;
|
|
}
|
|
|
|
if (key_type == JARRAY) {
|
|
if (NULL == (value = _json_value_by_arrname(value, value_len, arr_pre, key_len - obj_key_len, &value_len))) {
|
|
return NULL;
|
|
}
|
|
}
|
|
src_iter = value;
|
|
src_iter_len = value_len;
|
|
key_iter = delim + 1;
|
|
|
|
}
|
|
} while (delim);
|
|
|
|
key_len = strlen(key_iter);
|
|
key_next = key_iter;
|
|
key_type = JOBJECT;
|
|
if (0 == contain_arr(key_next, key_len, &arr_pre)) {
|
|
key_type = JARRAY;
|
|
obj_key_len = arr_pre - key_iter;
|
|
if (obj_key_len) {
|
|
value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, obj_key_len, &value_len, 0);
|
|
} else {
|
|
value = src_iter;
|
|
}
|
|
} else {
|
|
value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0);
|
|
}
|
|
|
|
if (NULL == value) {
|
|
return NULL;
|
|
}
|
|
if (key_type == JARRAY) {
|
|
if (NULL == (value = _json_value_by_arrname(value, value_len, arr_pre, key_len - obj_key_len, &value_len))) {
|
|
return NULL;
|
|
}
|
|
}
|
|
*val_len = value_len;
|
|
return value;
|
|
}
|
|
|
|
#endif /* #if WITH_JSON_TOKEN_EXT */
|
|
#endif /* #if WITH_JSON_KEYS_OF */
|
|
#endif
|
|
|