improve conf_io

This commit is contained in:
lixianjing 2020-06-13 22:04:07 +08:00
parent cc9aaf59df
commit 91a14e7d1b
7 changed files with 298 additions and 12 deletions

View File

@ -5,7 +5,8 @@
* 完善 str\_count\_sub\_str感谢朝泽提供补丁
* 完善 《自定义控件规范》(感谢朝泽提供补丁)。
* 增加 data\_reader\_asset。
* 完善 conf_io支持移动配置项的顺序增加#index 获得序数。
* 2020/06/12
* 增加 app\_conf\_set\_wstr/app\_conf\_get\_wstr
* 完善 window\_manager\_back\_to\_home 对软键盘窗口的处理。

View File

@ -538,6 +538,24 @@ ret_t application_exit() {
assert(strcmp(app_conf_get_str("wifi.[0].#name", NULL), "on") == 0);
```
* 用 #index 获取配置项在兄弟节点中的序数。
```ini
[wifi]
on = 1
name = awtk
[server]
port = 8080
timeout = 1.000000
```
在上面的例子中,"wifi.#index" 获取 wifi 的序数为 0"server.#index" 获取 server 的序数为 1。
```c
assert(app_conf_get_int("wifi.#index", -1) == 0);
assert(app_conf_get_int("server.#index", -1) == 1);
```
## 8. 注意事项
* . 作为 key 的分隔符。

View File

@ -287,6 +287,23 @@ uint32_t conf_node_count_children(conf_node_t* node) {
return i;
}
static int32_t conf_node_get_index(conf_node_t* node) {
uint32_t i = 0;
conf_node_t* iter = NULL;
return_value_if_fail(node != NULL, 0);
iter = conf_node_get_first_child(node->parent);
while (iter != NULL) {
if (iter == node) {
return i;
}
i++;
iter = iter->next;
}
assert(!"impossible");
return -1;
}
conf_node_t* conf_node_find_sibling(conf_node_t* node, const char* name) {
conf_node_t* iter = NULL;
if (node == NULL) {
@ -438,7 +455,9 @@ ret_t conf_node_set_value(conf_node_t* node, const value_t* v) {
}
break;
}
default: { return RET_NOT_IMPL; }
default: {
return RET_NOT_IMPL;
}
}
node->node_type = CONF_NODE_SIMPLE;
@ -502,7 +521,9 @@ ret_t conf_node_get_value(conf_node_t* node, value_t* v) {
value_set_str(v, node->value.small_str);
break;
}
default: { return RET_NOT_IMPL; }
default: {
return RET_NOT_IMPL;
}
}
return RET_OK;
@ -600,11 +621,13 @@ ret_t conf_doc_get(conf_doc_t* doc, const char* path, value_t* v) {
} else if (tk_str_eq(special, CONF_SPECIAL_ATTR_SIZE)) {
value_set_uint32(v, conf_node_count_children(node));
return RET_OK;
} else if (tk_str_eq(special, CONF_SPECIAL_ATTR_INDEX)) {
value_set_uint32(v, conf_node_get_index(node));
return RET_OK;
}
} else {
value_set_int(v, 0);
return RET_NOT_FOUND;
}
value_set_int(v, 0);
return RET_NOT_FOUND;
}
ret_t conf_doc_remove(conf_doc_t* doc, const char* path) {
@ -621,6 +644,105 @@ ret_t conf_doc_remove(conf_doc_t* doc, const char* path) {
}
}
static conf_node_t* conf_node_get_prev(conf_node_t* node) {
conf_node_t* iter = NULL;
return_value_if_fail(node != NULL && node->parent != NULL, NULL);
iter = conf_node_get_first_child(node->parent);
if (iter == node) {
return NULL;
}
while (iter->next != NULL) {
if (iter->next == node) {
return iter;
}
iter = iter->next;
}
return NULL;
}
bool_t conf_doc_is_first(conf_doc_t* doc, const char* path) {
conf_node_t* node = NULL;
return_value_if_fail(doc != NULL && path != NULL, FALSE);
node = conf_doc_get_node(doc, path, FALSE);
return_value_if_fail(node != NULL, FALSE);
return conf_node_get_first_child(node->parent) == node;
}
bool_t conf_doc_is_last(conf_doc_t* doc, const char* path) {
conf_node_t* node = NULL;
return_value_if_fail(doc != NULL && path != NULL, FALSE);
node = conf_doc_get_node(doc, path, FALSE);
return_value_if_fail(node != NULL, FALSE);
return node->next == NULL;
}
ret_t conf_doc_move_up(conf_doc_t* doc, const char* path) {
conf_node_t* node = NULL;
return_value_if_fail(doc != NULL && path != NULL, RET_BAD_PARAMS);
node = conf_doc_get_node(doc, path, FALSE);
if (node != NULL) {
conf_node_t* pprev = NULL;
conf_node_t* prev = conf_node_get_prev(node);
if (prev == NULL) {
return RET_FAIL;
}
pprev = conf_node_get_prev(prev);
prev->next = node->next;
node->next = prev;
if (pprev != NULL) {
pprev->next = node;
} else {
conf_node_set_first_child(node->parent, node);
}
return RET_OK;
} else {
return RET_NOT_FOUND;
}
}
ret_t conf_doc_move_down(conf_doc_t* doc, const char* path) {
conf_node_t* node = NULL;
return_value_if_fail(doc != NULL && path != NULL, RET_BAD_PARAMS);
node = conf_doc_get_node(doc, path, FALSE);
if (node != NULL) {
conf_node_t* prev = conf_node_get_prev(node);
conf_node_t* next = node->next;
if (next == NULL) {
return RET_FAIL;
}
node->next = next->next;
next->next = node;
if (prev != NULL) {
prev->next = next;
}
if (conf_node_get_first_child(node->parent) == node) {
conf_node_set_first_child(node->parent, next);
}
return RET_OK;
} else {
return RET_NOT_FOUND;
}
}
bool_t conf_doc_exists(conf_doc_t* doc, const char* path) {
return_value_if_fail(doc != NULL && path != NULL, RET_BAD_PARAMS);

View File

@ -201,6 +201,30 @@ ret_t conf_doc_get(conf_doc_t* doc, const char* path, value_t* v);
*/
ret_t conf_doc_remove(conf_doc_t* doc, const char* path);
/**
* @method conf_doc_move_up
*
*
*
* @param {conf_doc_t*} doc
* @param {const char*} path
*
* @return {ret_t} RET_OK表示成功
*/
ret_t conf_doc_move_up(conf_doc_t* doc, const char* path);
/**
* @method conf_doc_move_down
*
*
*
* @param {conf_doc_t*} doc
* @param {const char*} path
*
* @return {ret_t} RET_OK表示成功
*/
ret_t conf_doc_move_down(conf_doc_t* doc, const char* path);
/**
* @method conf_doc_exists
*
@ -471,10 +495,35 @@ conf_node_t* conf_node_get_first_child(conf_node_t* node);
*/
ret_t conf_node_set_first_child(conf_node_t* node, conf_node_t* child);
/**
* @method conf_doc_is_first
*
*
*
* @param {conf_node_t*} node
* @param {const char*} path
*
* @return {bool_t} TRUE表示是
*/
bool_t conf_doc_is_first(conf_doc_t* doc, const char* path);
/**
* @method conf_doc_is_last
*
*
*
* @param {conf_node_t*} node
* @param {const char*} path
*
* @return {bool_t} TRUE表示是
*/
bool_t conf_doc_is_last(conf_doc_t* doc, const char* path);
#define CONF_NODE_ROOT_NAME "root"
#define CONF_SPECIAL_ATTR_SIZE "#size"
#define CONF_SPECIAL_ATTR_NAME "#name"
#define CONF_SPECIAL_ATTR_INDEX "#index"
END_C_DECLS

View File

@ -27,10 +27,6 @@
#include "tkc/data_reader_factory.h"
#include "tkc/data_writer_factory.h"
#define CMD_LOCK "lock"
#define CMD_SAVE "save"
#define CMD_UNLOCK "unlock"
typedef struct _conf_obj_t {
object_t object;
@ -44,6 +40,19 @@ typedef struct _conf_obj_t {
static conf_obj_t* conf_obj_cast(object_t* obj);
#define CONF_OBJ(obj) conf_obj_cast((object_t*)obj)
static ret_t conf_obj_move_up(object_t* obj, const char* name) {
conf_obj_t* o = CONF_OBJ(obj);
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
return conf_doc_move_up(o->doc, name);
}
static ret_t conf_obj_move_down(object_t* obj, const char* name) {
conf_obj_t* o = CONF_OBJ(obj);
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
return conf_doc_move_down(o->doc, name);
}
static ret_t conf_obj_remove_prop(object_t* obj, const char* name) {
conf_obj_t* o = CONF_OBJ(obj);
@ -70,8 +79,12 @@ static bool_t conf_obj_can_exec(object_t* obj, const char* name, const char* arg
conf_obj_t* o = CONF_OBJ(obj);
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
if (tk_str_ieq(name, CMD_SAVE)) {
if (tk_str_ieq(name, CONF_CMD_SAVE)) {
return TRUE;
} else if (tk_str_ieq(name, CONF_CMD_MOVE_UP)) {
return !conf_doc_is_first(o->doc, name);
} else if (tk_str_ieq(name, CONF_CMD_MOVE_DOWN)) {
return !conf_doc_is_last(o->doc, name);
}
return FALSE;
@ -114,8 +127,12 @@ static ret_t conf_obj_exec(object_t* obj, const char* name, const char* args) {
conf_obj_t* o = CONF_OBJ(obj);
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
if (tk_str_ieq(name, CMD_SAVE)) {
if (tk_str_ieq(name, CONF_CMD_SAVE)) {
return conf_obj_save(obj);
} else if (tk_str_ieq(name, CONF_CMD_MOVE_UP)) {
return conf_obj_move_up(obj, args);
} else if (tk_str_ieq(name, CONF_CMD_MOVE_DOWN)) {
return conf_obj_move_down(obj, args);
}
return RET_NOT_IMPL;

View File

@ -79,6 +79,15 @@ conf_doc_t* conf_obj_get_doc(object_t* conf);
*/
ret_t conf_obj_save(object_t* conf);
/*保存命令*/
#define CONF_CMD_SAVE "save"
/*和前一个兄弟节点交换位置*/
#define CONF_CMD_MOVE_UP "move_up"
/*和后一个兄弟节点交换位置*/
#define CONF_CMD_MOVE_DOWN "move_down"
END_C_DECLS
#endif /*TK_CONF_OBJ_H*/

View File

@ -271,3 +271,73 @@ TEST(Ini, file) {
OBJECT_UNREF(conf);
}
TEST(Ini, index) {
value_t v;
conf_node_t* node = NULL;
conf_doc_t* doc = conf_doc_load_ini("[hello]\n[ world ]\n[awtk]\nname=aaa\n");
ASSERT_EQ(conf_doc_get(doc, "hello.#index", &v), RET_OK);
ASSERT_EQ(value_int(&v), 0);
ASSERT_EQ(conf_doc_get(doc, "world.#index", &v), RET_OK);
ASSERT_EQ(value_int(&v), 1);
ASSERT_EQ(conf_doc_get(doc, "awtk.#index", &v), RET_OK);
ASSERT_EQ(value_int(&v), 2);
conf_doc_destroy(doc);
}
TEST(Ini, last_first) {
value_t v;
conf_node_t* node = NULL;
conf_doc_t* doc = conf_doc_load_ini("[hello]\n[ world ]\n[awtk]\nname=aaa\n");
ASSERT_EQ(conf_doc_is_last(doc, "hello"), FALSE);
ASSERT_EQ(conf_doc_is_last(doc, "world"), FALSE);
ASSERT_EQ(conf_doc_is_last(doc, "awtk"), TRUE);
ASSERT_EQ(conf_doc_is_first(doc, "hello"), TRUE);
ASSERT_EQ(conf_doc_is_first(doc, "world"), FALSE);
ASSERT_EQ(conf_doc_is_first(doc, "awtk"), FALSE);
conf_doc_destroy(doc);
}
TEST(Ini, move_up) {
value_t v;
conf_node_t* node = NULL;
conf_doc_t* doc = conf_doc_load_ini("[hello]\n[ world ]\n[awtk]\nname=aaa\n");
ASSERT_EQ(conf_doc_move_up(doc, "hello"), RET_FAIL);
ASSERT_EQ(conf_doc_is_first(doc, "hello"), TRUE);
ASSERT_EQ(conf_doc_get(doc, "hello.#index", &v), RET_OK);
ASSERT_EQ(value_int(&v), 0);
ASSERT_EQ(conf_doc_move_down(doc, "hello"), RET_OK);
ASSERT_EQ(conf_doc_is_first(doc, "hello"), FALSE);
ASSERT_EQ(conf_doc_is_first(doc, "world"), TRUE);
ASSERT_EQ(conf_doc_get(doc, "hello.#index", &v), RET_OK);
ASSERT_EQ(value_int(&v), 1);
ASSERT_EQ(conf_doc_move_down(doc, "hello"), RET_OK);
ASSERT_EQ(conf_doc_is_last(doc, "hello"), TRUE);
ASSERT_EQ(conf_doc_get(doc, "hello.#index", &v), RET_OK);
ASSERT_EQ(value_int(&v), 2);
ASSERT_EQ(conf_doc_move_down(doc, "hello"), RET_FAIL);
ASSERT_EQ(conf_doc_move_up(doc, "hello"), RET_OK);
ASSERT_EQ(conf_doc_is_last(doc, "hello"), FALSE);
ASSERT_EQ(conf_doc_get(doc, "hello.#index", &v), RET_OK);
ASSERT_EQ(value_int(&v), 1);
ASSERT_EQ(conf_doc_move_up(doc, "hello"), RET_OK);
ASSERT_EQ(conf_doc_is_last(doc, "hello"), FALSE);
ASSERT_EQ(conf_doc_get(doc, "hello.#index", &v), RET_OK);
ASSERT_EQ(value_int(&v), 0);
ASSERT_EQ(conf_doc_move_up(doc, "hello"), RET_FAIL);
conf_doc_destroy(doc);
}