mirror of
https://gitee.com/zlgopen/awtk.git
synced 2024-12-02 03:58:33 +08:00
improve conf_io
This commit is contained in:
parent
cc9aaf59df
commit
91a14e7d1b
@ -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 对软键盘窗口的处理。
|
||||
|
@ -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 的分隔符。
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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*/
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user