fix[mpp_cfg_io]: Add more mpp_cfg_io function

1. Move MppCfgStrFmt to rk_mpp_cfg.h
2. Add mpp_cfg_find and mpp_cfg_set_cond
3. Fix memory leak in mpp_cfg_test
4. Add log->cfg function
5. Add cfg->json function
6. Add to / from log / json check to mpp_cfg_test

Signed-off-by: xiaoxu.chen <xiaoxu.chen@rock-chips.com>
Signed-off-by: Herman Chen <herman.chen@rock-chips.com>
Change-Id: I02e80cd21da664019bf0b767b073c14dbbfe0776
This commit is contained in:
Herman Chen
2025-06-20 17:50:42 +08:00
parent 4f102251f3
commit 981a15d9c6
4 changed files with 817 additions and 88 deletions

View File

@@ -9,6 +9,13 @@
#include "rk_type.h"
#include "mpp_err.h"
typedef enum MppCfgStrFmt_e {
MPP_CFG_STR_FMT_LOG,
MPP_CFG_STR_FMT_JSON,
MPP_CFG_STR_FMT_TOML,
MPP_CFG_STR_FMT_BUTT,
} MppCfgStrFmt;
typedef void* MppSysCfg;
#ifdef __cplusplus

View File

@@ -6,6 +6,8 @@
#ifndef __MPP_CFG_IO__
#define __MPP_CFG_IO__
#include "rk_mpp_cfg.h"
#include "mpp_internal.h"
typedef enum MppCfgType_e {
@@ -32,13 +34,6 @@ typedef enum MppCfgType_e {
MPP_CFG_TYPE_BUTT,
} MppCfgType;
typedef enum MppCfgStrFmt_e {
MPP_CFG_STR_FMT_LOG,
MPP_CFG_STR_FMT_JSON,
MPP_CFG_STR_FMT_TOML,
MPP_CFG_STR_FMT_BUTT,
} MppCfgStrFmt;
typedef union MppCfgVal_u {
rk_bool b1;
rk_s32 s32;
@@ -52,6 +47,7 @@ typedef union MppCfgVal_u {
} MppCfgVal;
typedef void* MppCfgObj;
typedef rk_s32 (*MppCfgObjCond)(MppCfgObj obj);
#ifdef __cplusplus
extern "C" {
@@ -66,9 +62,15 @@ rk_s32 mpp_cfg_put_all(MppCfgObj obj);
rk_s32 mpp_cfg_add(MppCfgObj root, MppCfgObj leaf);
/* object tree release */
rk_s32 mpp_cfg_del(MppCfgObj obj);
/* find by name string */
rk_s32 mpp_cfg_find(MppCfgObj *obj, MppCfgObj root, char *name, rk_s32 type);
/* attach MppCfgInfo for access location */
rk_s32 mpp_cfg_set_info(MppCfgObj obj, MppCfgInfo *info);
/* attach KmppEntry for access location */
rk_s32 mpp_cfg_set_entry(MppCfgObj obj, KmppEntry *entry);
/* add cfg obj condition for input / output option */
rk_s32 mpp_cfg_set_cond(MppCfgObj obj, MppCfgObjCond cond);
void mpp_cfg_dump(MppCfgObj obj, const char *func);
#define mpp_cfg_dump_f(obj) mpp_cfg_dump(obj, __FUNCTION__)
@@ -93,6 +95,8 @@ rk_s32 mpp_cfg_to_struct(MppCfgObj obj, MppCfgObj type, void *st);
*/
rk_s32 mpp_cfg_from_struct(MppCfgObj *obj, MppCfgObj type, void *st);
rk_s32 mpp_cfg_print_string(char *buf);
#ifdef __cplusplus
}
#endif

View File

@@ -44,6 +44,14 @@
#define cfg_io_dbg_show(fmt, ...) cfg_io_dbg_f(CFG_IO_DBG_SHOW, fmt, ## __VA_ARGS__)
#define cfg_io_dbg_info(fmt, ...) cfg_io_dbg(CFG_IO_DBG_INFO, fmt, ## __VA_ARGS__)
typedef enum MppCfgParserType_e {
MPP_CFG_PARSER_TYPE_KEY = 0,
MPP_CFG_PARSER_TYPE_VALUE,
MPP_CFG_PARSER_TYPE_TABLE,
MPP_CFG_PARSER_TYPE_ARRAY,
MPP_CFG_PARSER_TYPE_BUTT,
} MppCfgParserType;
typedef struct MppCfgIoImpl_t MppCfgIoImpl;
typedef void (*MppCfgIoFunc)(MppCfgIoImpl *obj, void *data);
@@ -52,7 +60,10 @@ struct MppCfgIoImpl_t {
struct list_head list;
/* list for children */
struct list_head child;
/* parent of current object */
MppCfgIoImpl *parent;
/* valid condition callback for the current object */
MppCfgObjCond cond;
MppCfgType type;
MppCfgVal val;
@@ -468,6 +479,53 @@ rk_s32 mpp_cfg_del(MppCfgObj obj)
return rk_ok;
}
rk_s32 mpp_cfg_find(MppCfgObj *obj, MppCfgObj root, char *name, rk_s32 type)
{
MppCfgIoImpl *impl = (MppCfgIoImpl *)root;
rk_s32 str_start = 0;
rk_s32 str_len = 0;
rk_s32 i;
char delimiter;
if (!obj || !root || !name) {
mpp_loge_f("invalid param obj %p root %p name %s\n", obj, root, name);
return rk_nok;
}
delimiter = (type == MPP_CFG_STR_FMT_TOML) ? '.' : ':';
str_len = strlen(name);
for (i = 0; i <= str_len; i++) {
if (name[i] == delimiter || name[i] == '\0') {
MppCfgIoImpl *pos, *n;
char bak = name[i];
rk_s32 found = 0;
name[i] = '\0';
mpp_logi("try match %s\n", name + str_start);
list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) {
if (pos->name && !strcmp(pos->name, name + str_start)) {
impl = pos;
found = 1;
break;
}
}
name[i] = bak;
if (!found) {
*obj = NULL;
return rk_nok;
}
str_start = i + 1;
}
}
*obj = impl;
return rk_ok;
}
rk_s32 mpp_cfg_set_info(MppCfgObj obj, MppCfgInfo *info)
{
MppCfgIoImpl *impl = (MppCfgIoImpl *)obj;
@@ -506,6 +564,15 @@ rk_s32 mpp_cfg_set_info(MppCfgObj obj, MppCfgInfo *info)
return rk_nok;
}
rk_s32 mpp_cfg_set_cond(MppCfgObj obj, MppCfgObjCond cond)
{
MppCfgIoImpl *impl = (MppCfgIoImpl *)obj;
if (impl)
impl->cond = cond;
return rk_ok;
}
typedef struct MppCfgFullNameCtx_t {
MppTrie trie;
char *buf;
@@ -566,6 +633,7 @@ MppTrie mpp_cfg_to_trie(MppCfgObj obj)
return p;
}
/* read byte functions */
/* check valid len, get offset position */
#define test_byte_f(str, len) test_byte(str, len, __FUNCTION__)
/* check valid pos, get offset + pos position */
@@ -574,8 +642,11 @@ MppTrie mpp_cfg_to_trie(MppCfgObj obj)
#define skip_byte_f(str, len) skip_byte(str, len, __FUNCTION__)
#define skip_ws_f(str) skip_ws(str, __FUNCTION__)
#define write_byte_f(str, buf, size) write_byte(str, buf, size, __FUNCTION__)
/* write byte functions */
#define write_byte_f(str, buf, size) write_byte(str, (void *)buf, size, __FUNCTION__)
#define write_indent_f(str) write_indent(str, __FUNCTION__)
/* revert comma for json */
#define revert_comma_f(str) revert_comma(str, __FUNCTION__)
static char *test_byte(MppCfgStrBuf *str, rk_s32 len, const char *caller)
{
@@ -681,6 +752,7 @@ static rk_s32 write_byte(MppCfgStrBuf *str, void *buf, rk_s32 *size, const char
memcpy(str->buf + str->offset, buf, len);
str->offset += len;
str->buf[str->offset] = '\0';
size[0] = 0;
return rk_ok;
@@ -706,6 +778,26 @@ static rk_s32 write_indent(MppCfgStrBuf *str, const char *caller)
return rk_ok;
}
static rk_s32 revert_comma(MppCfgStrBuf *str, const char *caller)
{
cfg_io_dbg_byte("str %p-[%p:%d] revert_comma %d at %s\n",
str, str->buf, str->buf_size, str->depth, caller);
if (str->offset <= 1) {
cfg_io_dbg_byte("str %p offset %d skip revert_comma at %s\n",
str, str->offset, caller);
return rk_ok;
}
if (str->buf[str->offset - 2] == ',') {
str->buf[str->offset - 2] = str->buf[str->offset - 1];
str->buf[str->offset - 1] = str->buf[str->offset];
str->offset--;
}
return rk_ok;
}
static rk_s32 mpp_cfg_to_log(MppCfgIoImpl *impl, MppCfgStrBuf *str)
{
MppCfgIoImpl *pos, *n;
@@ -750,7 +842,7 @@ static rk_s32 mpp_cfg_to_log(MppCfgIoImpl *impl, MppCfgStrBuf *str)
} break;
case MPP_CFG_TYPE_STRING :
case MPP_CFG_TYPE_RAW : {
len += snprintf(buf + len, total - len, "“%s”\n", (char *)impl->val.str);
len += snprintf(buf + len, total - len, "\"%s\"\n", (char *)impl->val.str);
} break;
default : {
mpp_loge("invalid type %d\n", impl->type);
@@ -799,9 +891,99 @@ static rk_s32 mpp_cfg_to_log(MppCfgIoImpl *impl, MppCfgStrBuf *str)
static rk_s32 mpp_cfg_to_json(MppCfgIoImpl *impl, MppCfgStrBuf *str)
{
(void)impl;
(void)str;
return 0;
MppCfgIoImpl *pos, *n;
char buf[256];
rk_s32 len = 0;
rk_s32 total = sizeof(buf) - 1;
rk_s32 ret = rk_ok;
write_indent_f(str);
/* leaf node write once and finish */
if (impl->type < MPP_CFG_TYPE_OBJECT) {
cfg_io_dbg_to("depth %d leaf write name %s type %d\n", str->depth, impl->name, impl->type);
if (impl->name)
len += snprintf(buf + len, total - len, "\"%s\" : ", impl->name);
switch (impl->type) {
case MPP_CFG_TYPE_NULL : {
len += snprintf(buf + len, total - len, "null,\n");
} break;
case MPP_CFG_TYPE_BOOL : {
len += snprintf(buf + len, total - len, "%s,\n", impl->val.b1 ? "true" : "false");
} break;
case MPP_CFG_TYPE_S32 : {
len += snprintf(buf + len, total - len, "%d,\n", impl->val.s32);
} break;
case MPP_CFG_TYPE_U32 : {
len += snprintf(buf + len, total - len, "%u,\n", impl->val.u32);
} break;
case MPP_CFG_TYPE_S64 : {
len += snprintf(buf + len, total - len, "%lld,\n", impl->val.s64);
} break;
case MPP_CFG_TYPE_U64 : {
len += snprintf(buf + len, total - len, "%llu,\n", impl->val.u64);
} break;
case MPP_CFG_TYPE_F32 : {
len += snprintf(buf + len, total - len, "%f,\n", impl->val.f32);
} break;
case MPP_CFG_TYPE_F64 : {
len += snprintf(buf + len, total - len, "%lf,\n", impl->val.f64);
} break;
case MPP_CFG_TYPE_STRING :
case MPP_CFG_TYPE_RAW : {
len += snprintf(buf + len, total - len, "\"%s\",\n", (char *)impl->val.str);
} break;
default : {
mpp_loge("invalid type %d\n", impl->type);
} break;
}
return write_byte_f(str, buf, &len);
}
cfg_io_dbg_to("depth %d branch write name %s type %d\n", str->depth, impl->name, impl->type);
if (impl->name)
len += snprintf(buf + len, total - len, "\"%s\" : ", impl->name);
if (list_empty(&impl->child)) {
len += snprintf(buf + len, total - len, "%s,\n",
impl->type == MPP_CFG_TYPE_OBJECT ? "{}" : "[]");
return write_byte_f(str, buf, &len);
}
len += snprintf(buf + len, total - len, "%c\n",
impl->type == MPP_CFG_TYPE_OBJECT ? '{' : '[');
ret = write_byte_f(str, buf, &len);
if (ret)
return ret;
str->depth++;
list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) {
cfg_io_dbg_to("depth %d child write name %s type %d\n", str->depth, pos->name, pos->type);
ret = mpp_cfg_to_json(pos, str);
if (ret)
break;
}
revert_comma_f(str);
str->depth--;
write_indent_f(str);
if (str->depth)
len += snprintf(buf + len, total - len, "%c,\n",
impl->type == MPP_CFG_TYPE_OBJECT ? '}' : ']');
else
len += snprintf(buf + len, total - len, "%c\n",
impl->type == MPP_CFG_TYPE_OBJECT ? '}' : ']');
return write_byte_f(str, buf, &len);
}
static rk_s32 mpp_cfg_to_toml(MppCfgIoImpl *impl, MppCfgStrBuf *str)
@@ -811,42 +993,41 @@ static rk_s32 mpp_cfg_to_toml(MppCfgIoImpl *impl, MppCfgStrBuf *str)
return 0;
}
static rk_s32 mpp_cfg_from_log(MppCfgObj obj, MppCfgStrBuf *str)
{
(void)obj;
(void)str;
return 0;
}
static rk_s32 parse_json_string(MppCfgStrBuf *str, char **name, rk_s32 *len)
static rk_s32 parse_log_string(MppCfgStrBuf *str, char **name, rk_s32 *len, rk_u32 type)
{
char *buf = NULL;
char *start = NULL;
rk_s32 name_len = 0;
char terminator = type ? '\"' : ' ';
*name = NULL;
*len = 0;
/* skip whitespace and find first double quotes */
buf = skip_ws_f(str);
if (!buf || buf[0] != '\"')
if (!buf)
return -101;
buf = skip_byte_f(str, 1);
if (!buf)
return -102;
if (type) {
if (buf[0] != '\"')
return -101;
buf = skip_byte_f(str, 1);
if (!buf)
return -102;
}
start = buf;
/* find the last double quotes */
while ((buf = show_byte_f(str, name_len)) && buf[0] != '\"') {
/* find the terminator */
while ((buf = show_byte_f(str, name_len)) && buf[0] != terminator) {
name_len++;
}
if (!buf || buf[0] != '\"')
if (!buf || buf[0] != terminator)
return -103;
/* find complete string skip the string and double quotes */
/* find complete string skip the string and terminator */
buf = skip_byte_f(str, name_len + 1);
if (!buf)
return -104;
@@ -927,7 +1108,438 @@ done:
return rk_ok;
}
static rk_s32 parse_log_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str);
static rk_s32 parse_log_array(MppCfgIoImpl *obj, MppCfgStrBuf *str)
{
MppCfgIoImpl *parent = obj;
char *buf = NULL;
rk_s32 old = str->offset;
rk_s32 ret = rk_nok;
if (str->depth >= MAX_CFG_DEPTH) {
mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH);
return rk_nok;
}
str->depth++;
cfg_io_dbg_from("depth %d offset %d array parse start\n", str->depth, str->offset);
buf = test_byte_f(str, 0);
if (!buf || buf[0] != '[') {
ret = -2;
goto failed;
}
buf = skip_byte_f(str, 1);
if (!buf) {
ret = -3;
goto failed;
}
/* skip whitespace and check the end of buffer */
buf = skip_ws_f(str);
if (!buf) {
ret = -4;
goto failed;
}
/* check empty object */
if (buf[0] == ']') {
skip_byte_f(str, 1);
cfg_io_dbg_from("depth %d found empty array\n", str->depth);
str->depth--;
return rk_ok;
}
do {
/* find colon for separater */
buf = skip_ws_f(str);
if (!buf) {
ret = -5;
goto failed;
}
/* parse value */
ret = parse_log_value(parent, NULL, str);
if (ret) {
ret = -6;
goto failed;
}
buf = skip_ws_f(str);
if (!buf) {
ret = -7;
goto failed;
}
if (buf[0] == ']')
break;
} while (1);
if (!buf || buf[0] != ']') {
ret = -9;
goto failed;
}
skip_byte_f(str, 1);
cfg_io_dbg_from("depth %d offset %d -> %d array parse success\n",
str->depth, old, str->offset);
str->depth--;
ret = rk_ok;
failed:
if (ret)
cfg_io_dbg_from("depth %d offset %d -> %d array parse failed ret %d\n",
str->depth, old, str->offset, ret);
return ret;
}
static rk_s32 parse_log_object(MppCfgIoImpl *obj, MppCfgStrBuf *str);
static rk_s32 parse_log_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str)
{
MppCfgObj obj = NULL;
char *buf = NULL;
cfg_io_dbg_from("depth %d offset %d: parse value\n", str->depth, str->offset);
buf = test_byte_f(str, 4);
if (buf && !strncmp(buf, "null", 4)) {
mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_NULL, NULL);
mpp_cfg_add(parent, obj);
cfg_io_dbg_from("depth %d offset %d: get value null\n", str->depth, str->offset);
skip_byte_f(str, 4);
return rk_ok;
}
if (buf && !strncmp(buf, "true", 4)) {
MppCfgVal val;
val.b1 = 1;
mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_BOOL, &val);
mpp_cfg_add(parent, obj);
cfg_io_dbg_from("depth %d offset %d: get value true\n", str->depth, str->offset);
skip_byte_f(str, 4);
return rk_ok;
}
buf = test_byte_f(str, 5);
if (buf && !strncmp(buf, "false", 5)) {
MppCfgVal val;
val.b1 = 0;
mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_BOOL, &val);
mpp_cfg_add(parent, obj);
cfg_io_dbg_from("depth %d offset %d: get value false\n", str->depth, str->offset);
skip_byte_f(str, 5);
return rk_ok;
}
buf = test_byte_f(str, 0);
if (buf && buf[0] == '\"') {
MppCfgVal val;
char *string = NULL;
rk_s32 len = 0;
cfg_io_dbg_from("depth %d offset %d: get value string start\n", str->depth, str->offset);
parse_log_string(str, &string, &len, MPP_CFG_PARSER_TYPE_VALUE);
if (!string)
return rk_nok;
val.str = dup_str(string, len);
mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_STRING, &val);
mpp_cfg_add(parent, obj);
MPP_FREE(val.str);
cfg_io_dbg_from("depth %d offset %d: get value string success\n", str->depth, str->offset);
return rk_ok;
}
if (buf && (buf[0] == '-' || (buf[0] >= '0' && buf[0] <= '9'))) {
MppCfgType type;
MppCfgVal val;
rk_s32 ret;
cfg_io_dbg_from("depth %d offset %d: get value number start\n",
str->depth, str->offset);
ret = parse_json_number(str, &type, &val);
if (ret)
return ret;
mpp_cfg_get_object(&obj, name, type, &val);
mpp_cfg_add(parent, obj);
cfg_io_dbg_from("depth %d offset %d: get value number success\n",
str->depth, str->offset);
return ret;
}
if (buf && buf[0] == '{') {
rk_s32 ret;
cfg_io_dbg_from("depth %d offset %d: get value object start\n",
str->depth, str->offset);
mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_OBJECT, NULL);
mpp_cfg_add(parent, obj);
ret = parse_log_object(obj, str);
cfg_io_dbg_from("depth %d offset %d: get value object ret %d\n",
str->depth, str->offset, ret);
return ret;
}
if (buf && buf[0] == '[') {
rk_s32 ret;
cfg_io_dbg_from("depth %d offset %d: get value array start\n",
str->depth, str->offset);
mpp_cfg_get_array(&obj, name, 0);
mpp_cfg_add(parent, obj);
ret = parse_log_array(obj, str);
cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n",
str->depth, str->offset, ret);
return ret;
}
return rk_nok;
}
static rk_s32 parse_log_object(MppCfgIoImpl *obj, MppCfgStrBuf *str)
{
MppCfgIoImpl *parent = obj;
char *buf = NULL;
rk_s32 old = str->offset;
rk_s32 ret = rk_nok;
if (str->depth >= MAX_CFG_DEPTH) {
mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH);
return rk_nok;
}
str->depth++;
cfg_io_dbg_from("depth %d offset %d object parse start\n", str->depth, str->offset);
buf = test_byte_f(str, 0);
if (!buf || buf[0] != '{') {
ret = -2;
goto failed;
}
buf = skip_byte_f(str, 1);
if (!buf) {
ret = -3;
goto failed;
}
/* skip whitespace and check the end of buffer */
buf = skip_ws_f(str);
if (!buf) {
ret = -4;
goto failed;
}
/* check empty object */
if (buf[0] == '}') {
skip_byte_f(str, 1);
cfg_io_dbg_from("depth %d found empty object\n", str->depth);
str->depth--;
return rk_ok;
}
do {
rk_s32 name_len = 0;
char *name = NULL;
char *tmp = NULL;
/* support array without name */
if (buf[0] == '[') {
MppCfgObj object = NULL;
cfg_io_dbg_from("depth %d offset %d: get value array start\n",
str->depth, str->offset);
mpp_cfg_get_array(&object, NULL, 0);
mpp_cfg_add(parent, object);
ret = parse_log_array(object, str);
cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n",
str->depth, str->offset, ret);
if (ret) {
mpp_cfg_put_all_child(object);
goto failed;
}
goto __next;
}
ret = parse_log_string(str, &name, &name_len, MPP_CFG_PARSER_TYPE_KEY);
if (ret) {
goto failed;
}
tmp = dup_str(name, name_len);
cfg_io_dbg_from("depth %d offset %d found object key %s len %d\n",
str->depth, str->offset, tmp, name_len);
MPP_FREE(tmp);
/* find colon for separater */
buf = skip_ws_f(str);
if (!buf || buf[0] != ':') {
ret = -5;
goto failed;
}
/* skip colon */
buf = skip_byte_f(str, 1);
if (!buf) {
ret = -6;
goto failed;
}
buf = skip_ws_f(str);
if (!buf) {
ret = -7;
goto failed;
}
tmp = dup_str(name, name_len);
if (!tmp) {
mpp_loge_f("failed to dup name\n");
ret = -8;
goto failed;
}
/* parse value */
ret = parse_log_value(parent, tmp, str);
MPP_FREE(tmp);
if (ret) {
ret = -9;
goto failed;
}
__next:
buf = skip_ws_f(str);
if (!buf) {
ret = -10;
goto failed;
}
if (buf[0] == '}')
break;
cfg_io_dbg_from("depth %d offset %d: get next object\n", str->depth, str->offset);
} while (1);
skip_byte_f(str, 1);
cfg_io_dbg_from("depth %d offset %d -> %d object parse success\n",
str->depth, old, str->offset);
str->depth--;
ret = rk_ok;
failed:
if (ret)
cfg_io_dbg_from("depth %d offset %d -> %d object parse failed ret %d\n",
str->depth, old, str->offset, ret);
return ret;
}
static rk_s32 mpp_cfg_from_log(MppCfgObj *obj, MppCfgStrBuf *str)
{
MppCfgObj object = NULL;
char *buf = NULL;
rk_s32 ret = rk_ok;
/* skip white space and check the end of buffer */
buf = skip_ws_f(str);
if (!buf)
return rk_nok;
if (buf[0] == '{') {
ret = mpp_cfg_get_object(&object, NULL, MPP_CFG_TYPE_OBJECT, NULL);
if (ret || !object) {
mpp_loge_f("failed to create top object\n");
return rk_nok;
}
ret = parse_log_object(object, str);
} else if (buf[0] == '[') {
ret = mpp_cfg_get_array(&object, NULL, 0);
if (ret || !object) {
mpp_loge_f("failed to create top object\n");
return rk_nok;
}
ret = parse_log_array(object, str);
} else {
mpp_loge_f("invalid top element '%c' on offset %d\n", buf[0], str->offset);
}
*obj = object;
return ret;
}
static rk_s32 parse_json_string(MppCfgStrBuf *str, char **name, rk_s32 *len)
{
char *buf = NULL;
char *start = NULL;
rk_s32 name_len = 0;
*name = NULL;
*len = 0;
/* skip whitespace and find first double quotes */
buf = skip_ws_f(str);
if (!buf || buf[0] != '\"')
return -101;
buf = skip_byte_f(str, 1);
if (!buf)
return -102;
start = buf;
/* find the last double quotes */
while ((buf = show_byte_f(str, name_len)) && buf[0] != '\"') {
name_len++;
}
if (!buf || buf[0] != '\"')
return -103;
/* find complete string skip the string and double quotes */
buf = skip_byte_f(str, name_len + 1);
if (!buf)
return -104;
*name = start;
*len = name_len;
return rk_ok;
}
static rk_s32 parse_json_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str);
static rk_s32 parse_json_array(MppCfgIoImpl *obj, MppCfgStrBuf *str);
static rk_s32 parse_json_object(MppCfgIoImpl *obj, MppCfgStrBuf *str)
{
@@ -975,6 +1587,29 @@ static rk_s32 parse_json_object(MppCfgIoImpl *obj, MppCfgStrBuf *str)
do {
rk_s32 name_len = 0;
char *name = NULL;
char *tmp = NULL;
if (buf[0] == '[') {
MppCfgObj object = NULL;
cfg_io_dbg_from("depth %d offset %d: get value array start\n",
str->depth, str->offset);
mpp_cfg_get_array(&object, NULL, 0);
mpp_cfg_add(parent, object);
ret = parse_json_array(object, str);
cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n",
str->depth, str->offset, ret);
if (ret) {
mpp_cfg_put_all_child(object);
goto failed;
}
goto __next;
}
ret = parse_json_string(str, &name, &name_len);
if (ret) {
@@ -1001,21 +1636,21 @@ static rk_s32 parse_json_object(MppCfgIoImpl *obj, MppCfgStrBuf *str)
goto failed;
}
name = dup_str(name, name_len);
if (!name) {
tmp = dup_str(name, name_len);
if (!tmp) {
mpp_loge_f("failed to dup name\n");
ret = -8;
goto failed;
}
/* parse value */
ret = parse_json_value(parent, name, str);
MPP_FREE(name);
ret = parse_json_value(parent, tmp, str);
MPP_FREE(tmp);
if (ret) {
ret = -9;
goto failed;
}
__next:
buf = skip_ws_f(str);
if (!buf) {
ret = -10;
@@ -1222,6 +1857,7 @@ static rk_s32 parse_json_value(MppCfgIoImpl *parent, const char *name, MppCfgStr
val.str = dup_str(string, len);
mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_STRING, &val);
mpp_cfg_add(parent, obj);
MPP_FREE(val.str);
cfg_io_dbg_from("depth %d offset %d: get value string success\n", str->depth, str->offset);
return rk_ok;
@@ -1334,37 +1970,25 @@ void mpp_cfg_dump(MppCfgObj obj, const char *func)
{
MppCfgIoImpl *impl = (MppCfgIoImpl *)obj;
MppCfgStrBuf str;
rk_s32 ret;
if (!obj) {
mpp_loge_f("invalid param obj %p at %s\n", obj, func);
return;
}
mpp_logi_f("obj %s - %p at %s\n", impl->name, impl, func);
mpp_logi_f("obj %s - %p at %s\n", impl->name ? impl->name : "n/a", impl, func);
str.buf_size = 4096;
str.buf = mpp_malloc_size(void, str.buf_size);
str.offset = 0;
str.depth = 0;
if (mpp_cfg_to_log(impl, &str))
ret = mpp_cfg_to_log(impl, &str);
if (ret)
mpp_loge_f("failed to get log buffer\n");
/* it may be a very long string, split by \n to different line and print */
if (str.offset >= 256) {
RK_S32 start = 0;
RK_S32 pos = 0;
for (pos = 0; pos < str.offset; pos++) {
if (str.buf[pos] == '\n') {
str.buf[pos] = '\0';
mpp_logi("%s\n", &str.buf[start]);
start = pos + 1;
}
}
} else {
mpp_logi("%s", str.buf);
}
else
mpp_cfg_print_string(str.buf);
MPP_FREE(str.buf);
}
@@ -1629,3 +2253,22 @@ rk_s32 mpp_cfg_from_struct(MppCfgObj *obj, MppCfgObj type, void *st)
return *obj ? rk_ok : rk_nok;
}
rk_s32 mpp_cfg_print_string(char *buf)
{
rk_s32 start = 0;
rk_s32 pos = 0;
rk_s32 len = strlen(buf);
/* it may be a very long string, split by \n to different line and print */
for (pos = 0; pos < len; pos++) {
if (buf[pos] == '\n') {
buf[pos] = '\0';
mpp_logi("%s\n", &buf[start]);
buf[pos] = '\n';
start = pos + 1;
}
}
return rk_ok;
}

View File

@@ -9,11 +9,62 @@
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <string.h>
#include "mpp_log.h"
#include "mpp_mem.h"
#include "mpp_debug.h"
#include "mpp_cfg_io.h"
static const char *str_fmt[] = {
"log",
"json",
"toml",
"invalid"
};
static rk_s32 test_to_from(MppCfgObj obj, MppCfgStrFmt fmt)
{
MppCfgObj out = NULL;
char *std = NULL;
char *str = NULL;
rk_s32 ret = rk_nok;
ret = mpp_cfg_to_string(obj, fmt, &std);
if (ret) {
mpp_loge("mpp_cfg obj to %s string failed\n", str_fmt[fmt]);
goto DONE;
}
ret = mpp_cfg_from_string(&out, fmt, std);
if (ret) {
mpp_loge("mpp_cfg out from %s string failed\n", str_fmt[fmt]);
goto DONE;
}
ret = mpp_cfg_to_string(out, fmt, &str);
if (ret) {
mpp_loge("mpp_cfg out to %s string failed\n", str_fmt[fmt]);
goto DONE;
}
if (strcmp(std, str)) {
mpp_loge("mpp_cfg mismatch on from / to %s string\n", str_fmt[fmt]);
mpp_logi("string std:\n");
mpp_cfg_print_string(std);
mpp_logi("string out:\n");
mpp_cfg_print_string(out);
ret = rk_nok;
}
DONE:
MPP_FREE(std);
MPP_FREE(str);
mpp_cfg_put_all(out);
return ret;
}
int main(int argc, char *argv[])
{
MppCfgObj root = NULL;
@@ -24,7 +75,7 @@ int main(int argc, char *argv[])
rk_s32 ret = rk_nok;
rk_s32 i;
mpp_log("start\n");
mpp_logi("start\n");
if (argc > 1) {
char *path = argv[1];
@@ -34,45 +85,49 @@ int main(int argc, char *argv[])
fd = open(path, O_RDWR);
if (fd < 0) {
mpp_err("open %s failed\n", path);
mpp_loge("open %s failed\n", path);
goto FILE_DONE;
}
mpp_log("open file %s\n", path);
mpp_logi("open file %s\n", path);
size = lseek(fd, 0, SEEK_END);
if (size < 0) {
mpp_err("lseek failed\n");
mpp_loge("lseek failed\n");
goto FILE_DONE;
}
lseek(fd, 0, SEEK_SET);
mpp_log("get file size %d\n", size);
mpp_logi("get file size %d\n", size);
buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
buf = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if (!buf) {
mpp_err("mmap fd %d size %d failed\n", fd, size);
mpp_loge("mmap fd %d size %d failed\n", fd, size);
goto FILE_DONE;
}
mpp_log("mmap size %d to %p content:\n", size, buf);
mpp_log("%s", buf);
mpp_logi("mmap size %d to %p content:\n", size, buf);
mpp_logi("%s", buf);
ret = mpp_cfg_from_string(&root, MPP_CFG_STR_FMT_JSON, buf);
if (ret) {
mpp_err("mpp_cfg_from_string failed\n");
mpp_loge("mpp_cfg_from_string failed\n");
goto FILE_DONE;
}
mpp_log("get cfg object %p from file\n", root);
mpp_logi("get cfg object %p from file\n", root);
mpp_cfg_dump_f(root);
mpp_cfg_put_all(root);
root = NULL;
ret = rk_ok;
ret = test_to_from(root, MPP_CFG_STR_FMT_LOG);
mpp_logi("test to / from log string %s\n", ret ? "failed" : "success");
if (ret)
goto FILE_DONE;
mpp_log("put cfg object\n");
ret = test_to_from(root, MPP_CFG_STR_FMT_JSON);
mpp_logi("test to / from json string %s\n", ret ? "failed" : "success");
if (ret)
goto FILE_DONE;
FILE_DONE:
if (buf) {
@@ -84,112 +139,132 @@ int main(int argc, char *argv[])
fd = -1;
}
mpp_cfg_put_all(root);
root = NULL;
if (ret)
return ret;
}
ret = mpp_cfg_get_object(&root, NULL, MPP_CFG_TYPE_OBJECT, NULL);
if (ret) {
mpp_err("mpp_cfg_get_object failed\n");
mpp_loge("mpp_cfg_get_object failed\n");
goto DONE;
}
mpp_log("get root object\n");
mpp_logi("get root object\n");
ret = mpp_cfg_get_array(&array, NULL, array_size);
if (ret) {
mpp_err("mpp_cfg_get_array failed\n");
mpp_loge("mpp_cfg_get_array failed\n");
goto DONE;
}
mpp_log("get array\n");
mpp_logi("get array\n");
for (i = 0; i < array_size; i++) {
obj = NULL;
val.s32 = i;
ret = mpp_cfg_get_object(&obj, NULL, MPP_CFG_TYPE_S32, &val);
if (ret) {
mpp_err("mpp_cfg_get_object array element failed\n");
mpp_loge("mpp_cfg_get_object array element failed\n");
goto DONE;
}
ret = mpp_cfg_add(array, obj);
if (ret) {
mpp_err("mpp_cfg_add array element failed\n");
mpp_loge("mpp_cfg_add array element failed\n");
goto DONE;
}
}
ret = mpp_cfg_add(root, array);
if (ret) {
mpp_err("mpp_cfg_add failed\n");
mpp_loge("mpp_cfg_add failed\n");
goto DONE;
}
mpp_log("add array to root\n");
mpp_logi("add array to root\n");
obj = NULL;
val.s32 = 1920;
ret = mpp_cfg_get_object(&obj, "width", MPP_CFG_TYPE_S32, &val);
if (ret) {
mpp_err("mpp_cfg_get s32 failed\n");
mpp_loge("mpp_cfg_get s32 failed\n");
goto DONE;
}
ret = mpp_cfg_add(root, obj);
if (ret) {
mpp_err("mpp_cfg_add s32 failed\n");
mpp_loge("mpp_cfg_add s32 failed\n");
goto DONE;
}
mpp_log("add s32 to root\n");
mpp_logi("add s32 to root\n");
obj = NULL;
val.u32 = 1080;
ret = mpp_cfg_get_object(&obj, "height", MPP_CFG_TYPE_U32, &val);
if (ret) {
mpp_err("mpp_cfg_get u32 failed\n");
mpp_loge("mpp_cfg_get u32 failed\n");
goto DONE;
}
ret = mpp_cfg_add(root, obj);
if (ret) {
mpp_err("mpp_cfg_add u32 failed\n");
mpp_loge("mpp_cfg_add u32 failed\n");
goto DONE;
}
mpp_log("set u32 to root\n");
mpp_logi("set u32 to root\n");
obj = NULL;
val.str = "hello world";
ret = mpp_cfg_get_object(&obj, "test", MPP_CFG_TYPE_STRING, &val);
if (ret) {
mpp_err("mpp_cfg_get string failed\n");
mpp_loge("mpp_cfg_get string failed\n");
goto DONE;
}
ret = mpp_cfg_add(root, obj);
if (ret) {
mpp_err("mpp_cfg_add string failed\n");
mpp_loge("mpp_cfg_add string failed\n");
goto DONE;
}
mpp_log("set string to root\n");
mpp_logi("set string to root\n");
mpp_cfg_dump_f(root);
ret = test_to_from(root, MPP_CFG_STR_FMT_LOG);
mpp_logi("test to / from log string %s\n", ret ? "failed" : "success");
if (ret)
goto DONE;
ret = test_to_from(root, MPP_CFG_STR_FMT_JSON);
mpp_logi("test to / from json string %s\n", ret ? "failed" : "success");
if (ret)
goto DONE;
ret = mpp_cfg_del(array);
if (ret) {
mpp_err("mpp_cfg_del failed\n");
mpp_loge("mpp_cfg_del failed\n");
goto DONE;
}
mpp_log("del array from root\n");
mpp_logi("del array from root\n");
DONE:
mpp_cfg_put_all(root);
if (root) {
mpp_cfg_put_all(root);
root = NULL;
}
if (array) {
mpp_cfg_put_all(array);
array = NULL;
}
mpp_log("done %s\n", ret ? "failed" : "success");
mpp_logi("done %s\n", ret ? "failed" : "success");
return ret;
}