Skip to content

Commit

Permalink
improve conf ubjson
Browse files Browse the repository at this point in the history
  • Loading branch information
xianjimli committed Feb 17, 2025
1 parent f63c2ef commit 8ed7d4a
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 15 deletions.
1 change: 1 addition & 0 deletions docs/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* 完善样式(感谢兆坤提供补丁)
* 修复拼写错误(感谢兆坤提供补丁)
* edit_ex 增加奇数项和偶数项的样式设置(感谢兆坤提供补丁)
* 完善 conf_ubjson (感谢林福提供补丁)

2025/02/14
* endian类增加了小端的支持和修改了注释(增加测试用例)(感谢智明提供补丁)
Expand Down
27 changes: 27 additions & 0 deletions src/conf_io/conf_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,14 @@ ret_t conf_node_set_value(conf_node_t* node, const value_t* v) {
}
}
TKMEM_FREE(node->value.wstr);
} else if (node->value_type == CONF_NODE_VALUE_BINARY) {
if (v->type == VALUE_TYPE_BINARY) {
if (node->value.binary_data.data == v->value.binary_data.data &&
node->value.binary_data.size == v->value.binary_data.size) {
return RET_OK;
}
}
TKMEM_FREE(node->value.binary_data.data);
}

switch (v->type) {
Expand Down Expand Up @@ -598,6 +606,21 @@ ret_t conf_node_set_value(conf_node_t* node, const value_t* v) {
}
break;
}
case VALUE_TYPE_BINARY: {
binary_data_t* bdata = value_binary_data(v);
node->value_type = CONF_NODE_VALUE_BINARY;
if (bdata == NULL) {
node->value.binary_data.data = NULL;
node->value.binary_data.size = 0;
} else {
node->value.binary_data.data = tk_memdup(bdata->data, bdata->size);
return_value_if_fail(node->value.binary_data.data != NULL, RET_OOM);
node->value.binary_data.size = bdata->size;
}

node->node_type = CONF_NODE_ARRAY_UINT8;
return RET_OK;
}
default: {
return RET_NOT_IMPL;
}
Expand Down Expand Up @@ -671,6 +694,10 @@ ret_t conf_node_get_value(conf_node_t* node, value_t* v) {
value_set_str(v, node->value.small_str);
break;
}
case CONF_NODE_VALUE_BINARY: {
value_set_binary_data(v, node->value.binary_data.data, node->value.binary_data.size);
break;
}
default: {
return RET_NOT_IMPL;
}
Expand Down
11 changes: 11 additions & 0 deletions src/conf_io/conf_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,11 @@ typedef enum _conf_node_type_t {
* 数组节点。
*/
CONF_NODE_ARRAY,
/**
* @const CONF_NODE_ARRAY_UINT8
* uint8_t 类型的数组节点。
*/
CONF_NODE_ARRAY_UINT8,
/**
* @const CONF_NODE_SIMPLE
* 简单节点。
Expand Down Expand Up @@ -591,6 +596,11 @@ typedef enum _conf_node_value_t {
* 短字符(len<=7)串类型。
*/
CONF_NODE_VALUE_SMALL_STR,
/**
* @const CONF_NODE_VALUE_BINARY
* 二进制数据类型。
*/
CONF_NODE_VALUE_BINARY,
/**
* @const CONF_NODE_VALUE_NODE
* 节点类型。
Expand Down Expand Up @@ -650,6 +660,7 @@ struct _conf_node_t {
wchar_t* wstr;
char small_str[8];
conf_node_t* first_child;
binary_data_t binary_data;
} value;
};

Expand Down
37 changes: 34 additions & 3 deletions src/conf_io/conf_ubjson.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* File: ubjson.c
* Author: AWTK Develop Team
* Brief: ubjson
* Brief: ubjson
*
* Copyright (c) 2020 - 2025 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
Expand Down Expand Up @@ -64,12 +64,23 @@ static ret_t conf_ubjson_save_node_value_simple(conf_node_t* node, ubjson_writer
}
}

static ret_t conf_ubjson_save_node_value_array_uint8(conf_node_t* node, ubjson_writer_t* writer) {
value_t v;
return_value_if_fail(conf_node_get_value(node, &v) == RET_OK, RET_BAD_PARAMS);
return_value_if_fail(v.type == VALUE_TYPE_BINARY, RET_BAD_PARAMS);

return ubjson_writer_write_array_uint8(writer, v.value.binary_data.data,
v.value.binary_data.size);
}

static ret_t conf_ubjson_save_node_value(conf_node_t* node, ubjson_writer_t* writer) {
return_value_if_fail(node != NULL, RET_BAD_PARAMS);
if (node->node_type == CONF_NODE_OBJECT) {
return conf_ubjson_save_node_value_object(node, writer);
} else if (node->node_type == CONF_NODE_ARRAY) {
return conf_ubjson_save_node_value_array(node, writer);
} else if (node->node_type == CONF_NODE_ARRAY_UINT8) {
return conf_ubjson_save_node_value_array_uint8(node, writer);
} else {
return conf_ubjson_save_node_value_simple(node, writer);
}
Expand Down Expand Up @@ -119,6 +130,8 @@ static ret_t conf_ubjson_save_node_children(conf_node_t* node, ubjson_writer_t*
return conf_ubjson_save_node_children_object(node, writer);
} else if (node->node_type == CONF_NODE_ARRAY) {
return conf_ubjson_save_node_children_array(node, writer);
} else if (node->node_type == CONF_NODE_ARRAY_UINT8) {
return conf_ubjson_save_node_value_array_uint8(node, writer);
} else {
assert(!"invalid type");
return RET_FAIL;
Expand All @@ -134,6 +147,7 @@ ret_t conf_doc_save_ubjson(conf_doc_t* doc, ubjson_writer_t* writer) {
typedef struct _parse_ctx_t {
conf_doc_t* doc;
conf_node_t* node;
uint32_t optimized_type;
} parse_ctx_t;

static ret_t ubjson_conf_on_key_value(void* ctx, const char* key, value_t* v) {
Expand All @@ -160,6 +174,10 @@ static ret_t ubjson_conf_on_key_value(void* ctx, const char* key, value_t* v) {
return_value_if_fail(node != NULL, RET_OOM);
parser->doc->root = node;
parser->node = node;
} else if (v->type == VALUE_TYPE_TOKEN && value_token(v) == UBJSON_MARKER_UINT8) {
node = current;
} else if (current->node_type == CONF_NODE_ARRAY_UINT8) {
node = current;
} else {
node = conf_doc_create_node(parser->doc, key);
return_value_if_fail(node != NULL, RET_OOM);
Expand All @@ -175,13 +193,26 @@ static ret_t ubjson_conf_on_key_value(void* ctx, const char* key, value_t* v) {
} else if (token == UBJSON_MARKER_ARRAY_BEGIN) {
node->node_type = CONF_NODE_ARRAY;
parser->node = node;

} else if (token == UBJSON_MARKER_UINT8) {
parser->optimized_type = token;
node->node_type = CONF_NODE_ARRAY_UINT8;
} else {
assert(!"not supported");
ret = RET_NOT_IMPL;
}
} else {
node->node_type = CONF_NODE_SIMPLE;
ret = conf_node_set_value(node, v);
if (node->node_type == CONF_NODE_ARRAY_UINT8) {
if (current->parent != NULL) {
parser->node = current->parent;
}

ret = conf_node_set_value(node, v);

} else {
node->node_type = CONF_NODE_SIMPLE;
ret = conf_node_set_value(node, v);
}
}

return ret;
Expand Down
94 changes: 82 additions & 12 deletions src/ubjson/ubjson_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,20 +371,77 @@ tk_object_t* ubjson_to_object(void* data, uint32_t size) {
return parser.root;
}

typedef struct {
int32_t level;
uint32_t optimized_type;
} dump_ctx_t;

static ret_t ubjson_on_optimized_array_dump(dump_ctx_t* ctx, const char* key, value_t* v) {
uint32_t type = ctx->optimized_type;
ctx->optimized_type = 0;

if (type == UBJSON_MARKER_UINT8 || type == UBJSON_MARKER_INT8) {
uint8_t* p = v->value.binary_data.data;
for (uint32_t i = 0; i < v->value.binary_data.size - 1; i++) {
log_debug("0x%02x, ", p[i]);
}
log_debug("0x%02x", p[v->value.binary_data.size - 1]);
} else if (type == UBJSON_MARKER_INT16) {
int16_t* p = v->value.binary_data.data;
uint32_t count = v->value.binary_data.size / sizeof(int16_t);
for (uint32_t i = 0; i < count - 1; i++) {
log_debug("0x%04x, ", p[i]);
}
log_debug("0x%04x", p[count - 1]);
} else if (type == UBJSON_MARKER_INT32) {
int32_t* p = v->value.binary_data.data;
uint32_t count = v->value.binary_data.size / sizeof(int32_t);
for (uint32_t i = 0; i < count - 1; i++) {
log_debug("0x%08x, ", p[i]);
}
log_debug("0x%08x", p[count - 1]);
} else if (type == UBJSON_MARKER_INT64) {
int64_t* p = v->value.binary_data.data;
uint32_t count = v->value.binary_data.size / sizeof(int64_t);
for (uint32_t i = 0; i < count - 1; i++) {
log_debug("0x%016"PRIx64", ", p[i]);
}
log_debug("0x%016"PRIx64, p[count - 1]);
} else if (type == UBJSON_MARKER_FLOAT32) {
float* p = v->value.binary_data.data;
uint32_t count = v->value.binary_data.size / sizeof(float);
for (uint32_t i = 0; i < count - 1; i++) {
log_debug("%f, ", p[i]);
}
log_debug("%f", p[count - 1]);
} else if (type == UBJSON_MARKER_FLOAT64) {
double* p = v->value.binary_data.data;
uint32_t count = v->value.binary_data.size / sizeof(double);
for (uint32_t i = 0; i < count - 1; i++) {
log_debug("%f, ", p[i]);
}
log_debug("%f", p[count - 1]);
} else {
return_value_if_fail(!"invalid format", RET_NOT_IMPL);
}

return RET_OK;
}

static ret_t ubjson_on_key_value_dump(void* ctx, const char* key, value_t* v) {
int32_t i = 0;
ret_t ret = RET_OK;
int32_t* level = (int32_t*)ctx;
dump_ctx_t* dump_ctx = (dump_ctx_t*)ctx;

if (v->type == VALUE_TYPE_TOKEN) {
uint32_t token = value_token(v);

if (token == UBJSON_MARKER_OBJECT_END) {
*level = *level - 1;
dump_ctx->level = dump_ctx->level - 1;
}
}

for (i = 0; i < *level; i++) {
for (i = 0; i < dump_ctx->level; i++) {
log_debug(" ");
}

Expand All @@ -397,13 +454,18 @@ static ret_t ubjson_on_key_value_dump(void* ctx, const char* key, value_t* v) {

if (token == UBJSON_MARKER_OBJECT_BEGIN) {
log_debug("{\n");
*level = *level + 1;
dump_ctx->level = dump_ctx->level + 1;
} else if (token == UBJSON_MARKER_OBJECT_END) {
log_debug("},\n");
} else if (token == UBJSON_MARKER_ARRAY_BEGIN) {
log_debug("[");
} else if (token == UBJSON_MARKER_ARRAY_END) {
log_debug("],\n");
} else if (token == UBJSON_MARKER_UINT8 || token == UBJSON_MARKER_INT8 ||
token == UBJSON_MARKER_INT16 || token == UBJSON_MARKER_INT32 ||
token == UBJSON_MARKER_INT64 || token == UBJSON_MARKER_FLOAT32 ||
token == UBJSON_MARKER_FLOAT64) {
dump_ctx->optimized_type = token;
} else {
assert(!"not supported");
ret = RET_NOT_IMPL;
Expand All @@ -420,13 +482,21 @@ static ret_t ubjson_on_key_value_dump(void* ctx, const char* key, value_t* v) {
} else if (v->type == VALUE_TYPE_POINTER) {
log_debug("\"%p\"", value_pointer(v));
} else if (v->type == VALUE_TYPE_BINARY) {
uint32_t i = 0;
binary_data_t* data = value_binary_data(v);
log_debug("{");
for (i = 0; i < data->size - 1; i++) {
log_debug("0x%02x, ", ((uint8_t*)data->data)[i]);
if (dump_ctx->optimized_type != 0) {
ubjson_on_optimized_array_dump(dump_ctx, key, v);
log_debug("],\n");
return ret;
} else {
uint32_t i = 0;
binary_data_t* data = value_binary_data(v);

log_debug("{");
for (i = 0; i < data->size - 1; i++) {
log_debug("0x%02x, ", ((uint8_t*)data->data)[i]);
}
log_debug("0x%02x}", ((uint8_t*)data->data)[i]);
}
log_debug("0x%02x}", ((uint8_t*)data->data)[i]);

} else {
log_debug("%d", value_int(v));
}
Expand All @@ -453,7 +523,7 @@ ret_t ubjson_parse(void* data, uint32_t size, ubjson_on_key_value_t on_key_value
}

ret_t ubjson_dump(void* data, uint32_t size) {
int32_t level = 0;
dump_ctx_t ctx = {0};

return ubjson_parse(data, size, ubjson_on_key_value_dump, &level);
return ubjson_parse(data, size, ubjson_on_key_value_dump, &ctx);
}
34 changes: 34 additions & 0 deletions tests/conf_node_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,40 @@ TEST(ConfNode, set_get_wstr) {
wbuffer_deinit(&wb);
}

TEST(ConfNode, binary) {
value_t v;
conf_doc_t* doc = conf_doc_create(100);

ASSERT_EQ(conf_doc_set(doc, "names.[0]", value_set_binary_data(&v, (void*)"jim", 3)), RET_OK);
ASSERT_EQ(conf_doc_set(doc, "names.[1]", value_set_binary_data(&v, (void*)"tom", 3)), RET_OK);

ASSERT_EQ(conf_doc_get(doc, "names.[0]", &v), RET_OK);
ASSERT_EQ(v.type, VALUE_TYPE_BINARY);

ASSERT_EQ(conf_doc_get(doc, "names.[1]", &v), RET_OK);
ASSERT_EQ(v.type, VALUE_TYPE_BINARY);
ASSERT_EQ(memcmp(v.value.binary_data.data, "tom", v.value.binary_data.size), 0);
ASSERT_EQ(memcmp(v.value.binary_data.data, "tom", v.value.binary_data.size), 0);

conf_node_t* node;
node = conf_doc_find_node(doc, doc->root, "names.[0]", FALSE);
ASSERT_TRUE(node != NULL);
ASSERT_EQ(node->node_type, CONF_NODE_ARRAY_UINT8);
ASSERT_EQ(node->value_type, CONF_NODE_VALUE_BINARY);

node = conf_doc_find_node(doc, doc->root, "names.[1]", FALSE);
ASSERT_TRUE(node != NULL);
ASSERT_EQ(node->node_type, CONF_NODE_ARRAY_UINT8);
ASSERT_EQ(node->value_type, CONF_NODE_VALUE_BINARY);

ASSERT_EQ(conf_doc_set(doc, "names.[0]", value_set_int32(&v, 1)), RET_OK);
conf_doc_get(doc, "names.[0]", &v);
ASSERT_EQ(v.type, VALUE_TYPE_INT32);
ASSERT_EQ(value_int(&v), 1);

conf_doc_destroy(doc);
}

static tk_object_t* conf_node_test_object_create(void) {
tk_object_t* ret = object_default_create();
tk_object_set_prop_str(ret, "name", "test1");
Expand Down
Loading

0 comments on commit 8ed7d4a

Please sign in to comment.