diff --git a/lib_acl/include/json/acl_json.h b/lib_acl/include/json/acl_json.h index 591ed93fe..cacf09dc6 100644 --- a/lib_acl/include/json/acl_json.h +++ b/lib_acl/include/json/acl_json.h @@ -28,6 +28,9 @@ struct ACL_JSON_NODE { #define ACL_JSON_T_A_NULL (1 << 3) #define ACL_JSON_T_A_DOUBLE (1 << 4) +#define ACL_JSON_T_A_TYPES (ACL_JSON_T_A_NULL | ACL_JSON_T_A_BOOL | \ + ACL_JSON_T_A_NUMBER | ACL_JSON_T_A_DOUBLE | ACL_JSON_T_A_STRING) + #define ACL_JSON_T_STRING (1 << 5) #define ACL_JSON_T_NUMBER (1 << 6) #define ACL_JSON_T_BOOL (1 << 7) @@ -49,6 +52,7 @@ struct ACL_JSON_NODE { unsigned char right_ch; /**< 本节点的最后一个字符: } or ] */ unsigned backslash:1; /**< 转义字符 \ */ unsigned part_word:1; /**< 半个汉字的情况处理标志位 */ + unsigned disabled:1; /**< 该节点是否被禁止 */ ACL_JSON *json; /**< json 对象 */ ACL_RING node; /**< 当前节点 */ @@ -126,6 +130,21 @@ ACL_API ACL_JSON_NODE *acl_json_node_alloc(ACL_JSON *json); */ ACL_API int acl_json_node_delete(ACL_JSON_NODE *node); +/** + * 禁止/启用某个 json 节点,被禁止的节点在构造 json 字符串时将不被添加,但在遍历 json 时 + * 却可以被获得,以方便再次将其启用 + * @param node {ACL_JSON_NODE*} json 节点 + * @param yes {int} 是否禁止该 json 节点 + */ +ACL_API void acl_json_node_disable(ACL_JSON_NODE *node, int yes); + +/** + * 判断指定 json 节点是否已经被禁止 + * @param node {ACL_JSON_NODE*} json 节点 + * @return {int} 返回 0 表示未被禁止(即处于启用状态),否则表示被禁止了 + */ +ACL_API int acl_json_node_disabled(ACL_JSON_NODE *node); + /** * 向某个 json 节点添加兄弟节点(该兄弟节点必须是独立的 json 节点) * @param node1 {ACL_JSON_NODE*} 向本节点添加 json 节点 diff --git a/lib_acl/src/json/acl_json.c b/lib_acl/src/json/acl_json.c index 1314660bf..71315fab6 100644 --- a/lib_acl/src/json/acl_json.c +++ b/lib_acl/src/json/acl_json.c @@ -1,5 +1,4 @@ #include "StdAfx.h" -#include #ifndef ACL_PREPARE_COMPILE #include "stdlib/acl_define.h" #include "stdlib/acl_mymalloc.h" @@ -105,6 +104,7 @@ ACL_JSON_NODE *acl_json_node_alloc(ACL_JSON *json) node->right_ch = 0; node->backslash = 0; node->part_word = 0; + node->disabled = 0; node->json = json; node->iter_head = node_iter_head; @@ -133,6 +133,16 @@ int acl_json_node_delete(ACL_JSON_NODE *node) return n; } +void acl_json_node_disable(ACL_JSON_NODE *node, int yes) +{ + node->disabled = yes ? 1 : (unsigned) 0; +} + +int acl_json_node_disabled(ACL_JSON_NODE *node) +{ + return node->disabled != (unsigned) 0; +} + void acl_json_node_append(ACL_JSON_NODE *node1, ACL_JSON_NODE *node2) { acl_ring_append(&node1->node, &node2->node); @@ -155,12 +165,14 @@ ACL_JSON_NODE *acl_json_node_next(ACL_JSON_NODE *node) ACL_RING *ring_ptr = acl_ring_succ(&node->node); ACL_JSON_NODE *parent; - if (ring_ptr == &node->node) + if (ring_ptr == &node->node) { return NULL; + } parent = node->parent; acl_assert(parent != NULL); - if (ring_ptr == &parent->children) + if (ring_ptr == &parent->children) { return NULL; + } return acl_ring_to_appl(ring_ptr, ACL_JSON_NODE, node); } @@ -173,8 +185,9 @@ ACL_JSON_NODE *acl_json_node_prev(ACL_JSON_NODE *node) return NULL; parent = node->parent; acl_assert(parent != NULL); - if (ring_ptr == &parent->children) + if (ring_ptr == &parent->children) { return NULL; + } return acl_ring_to_appl(ring_ptr, ACL_JSON_NODE, node); } @@ -236,8 +249,9 @@ static ACL_JSON_NODE *json_iter_next(ACL_ITER *it, ACL_JSON *json) /* 当前节点的兄弟节点遍历完毕,最后遍历当前节点的父节点的兄弟节点 */ do { - if (parent == json->root) + if (parent == json->root) { break; + } ring_ptr = acl_ring_succ(&parent->node); parent = acl_json_node_parent(parent); @@ -310,8 +324,9 @@ static ACL_JSON_NODE *json_iter_prev(ACL_ITER *it, ACL_JSON *json) /* 当前节点的兄弟节点遍历完毕,最后遍历当前节点的父节点的兄弟节点 */ do { - if (parent == json->root) + if (parent == json->root) { break; + } ring_ptr = acl_ring_pred(&parent->node); parent = acl_json_node_parent(parent); if (parent == NULL) @@ -388,6 +403,7 @@ ACL_JSON_NODE *acl_json_node_duplicate(ACL_JSON *json, ACL_JSON_NODE *from) to->right_ch = from->right_ch; to->type = from->type; to->depth = from->depth; /* XXX? */ + to->disabled = from->disabled; acl_vstring_strcpy(to->ltag, STR(from->ltag)); acl_vstring_strcpy(to->text, STR(from->text)); @@ -395,8 +411,9 @@ ACL_JSON_NODE *acl_json_node_duplicate(ACL_JSON *json, ACL_JSON_NODE *from) child_from = acl_ring_to_appl(iter.ptr, ACL_JSON_NODE, node); child_to = acl_json_node_duplicate(json, child_from); acl_json_node_add_child(to, child_to); - if (from->tag_node == child_from) + if (from->tag_node == child_from) { to->tag_node = child_to; + } } return to; @@ -418,7 +435,7 @@ ACL_JSON *acl_json_dbuf_create(ACL_DBUF_POOL *dbuf, ACL_JSON_NODE *node) json = (ACL_JSON*) acl_dbuf_pool_calloc(dbuf, sizeof(ACL_JSON)); json->dbuf = dbuf; - json->dbuf_inner = NULL; + json->dbuf_inner = NULL; /* 如果传入的节点为 root 节点,则直接赋值创建 root 即可 */ if (node == root) { @@ -463,14 +480,16 @@ void acl_json_foreach_init(ACL_JSON *json, ACL_JSON_NODE *node) void acl_json_free(ACL_JSON *json) { - if (json->dbuf_inner) + if (json->dbuf_inner) { acl_dbuf_pool_destroy(json->dbuf_inner); + } } void acl_json_reset(ACL_JSON *json) { - if (json->dbuf_inner != NULL) + if (json->dbuf_inner != NULL) { acl_dbuf_pool_reset(json->dbuf, json->dbuf_keep); + } json->root = acl_json_node_alloc(json); #if 0 diff --git a/lib_acl/src/json/acl_json_util.c b/lib_acl/src/json/acl_json_util.c index 0c11c2c96..c0cf093cf 100644 --- a/lib_acl/src/json/acl_json_util.c +++ b/lib_acl/src/json/acl_json_util.c @@ -20,8 +20,9 @@ ACL_JSON_NODE *acl_json_getFirstElementByTagName( acl_foreach(iter, json) { ACL_JSON_NODE *node = (ACL_JSON_NODE*) iter.data; - if (strcasecmp(tag, STR(node->ltag)) == 0) + if (strcasecmp(tag, STR(node->ltag)) == 0) { return node; + } } return NULL; @@ -257,9 +258,8 @@ void acl_json_node_append_child(ACL_JSON_NODE *parent, ACL_JSON_NODE *child) const char *myname = "acl_json_node_append_child"; if (parent->type != ACL_JSON_T_ARRAY - && parent->type != ACL_JSON_T_OBJ - && parent != parent->json->root) - { + && parent->type != ACL_JSON_T_OBJ + && parent != parent->json->root) { acl_msg_fatal("%s(%d): parent's type not array or obj", myname, __LINE__); } @@ -299,6 +299,26 @@ static void json_escape_append(ACL_VSTRING *buf, const char *src) ACL_VSTRING_TERMINATE(buf); } +static void child_end(ACL_JSON *json, ACL_JSON_NODE *node, ACL_VSTRING *buf) +{ + /* 当本节点为叶节点且后面没有兄弟节点时,需要一级一级回溯 + * 将父节点的分隔符添加至本叶节点尾部,直到遇到根节点或父 + * 节点的下一个兄弟节点非空 + */ + while (acl_json_node_next(node) == NULL) { + if (node->parent == json->root) { + break; + } + + node = node->parent; + + /* right_ch: '}' or ']' */ + if (node->right_ch != 0) { + ACL_VSTRING_ADDCH(buf, node->right_ch); + } + } +} + void acl_json_building(ACL_JSON *json, size_t length, int (*callback)(ACL_JSON *, ACL_VSTRING *, void *), void *ctx) { @@ -325,8 +345,9 @@ void acl_json_building(ACL_JSON *json, size_t length, json->root->right_ch = '}'; } - if (json->root->left_ch > 0) + if (json->root->left_ch > 0) { ACL_VSTRING_ADDCH(buf, json->root->left_ch); + } acl_foreach(iter, json) { if (ACL_VSTRING_LEN(buf) >= length && callback != NULL) { @@ -341,10 +362,11 @@ void acl_json_building(ACL_JSON *json, size_t length, node = (ACL_JSON_NODE*) iter.data; prev = acl_json_node_prev(node); if (prev != NULL) { - if ((json->flag & ACL_JSON_FLAG_ADD_SPACE)) + if ((json->flag & ACL_JSON_FLAG_ADD_SPACE)) { acl_vstring_strcat(buf, ", "); - else + } else { acl_vstring_strcat(buf, ","); + } } /* 只有当标签的对应值为 JSON 对象或数组对象时 tag_node 非空 */ @@ -352,21 +374,24 @@ void acl_json_building(ACL_JSON *json, size_t length, if (LEN(node->ltag) > 0) { json_escape_append(buf, STR(node->ltag)); ACL_VSTRING_ADDCH(buf, ':'); - if ((json->flag & ACL_JSON_FLAG_ADD_SPACE)) + if ((json->flag & ACL_JSON_FLAG_ADD_SPACE)) { ACL_VSTRING_ADDCH(buf, ' '); + } } /* '{' or '[' */ - if (node->left_ch != 0) + if (node->left_ch != 0) { ACL_VSTRING_ADDCH(buf, node->left_ch); + } } /* 当节点有标签名时 */ else if (LEN(node->ltag) > 0) { json_escape_append(buf, STR(node->ltag)); ACL_VSTRING_ADDCH(buf, ':'); - if ((json->flag & ACL_JSON_FLAG_ADD_SPACE)) + if ((json->flag & ACL_JSON_FLAG_ADD_SPACE)) { ACL_VSTRING_ADDCH(buf, ' '); + } switch (node->type & ~ACL_JSON_T_LEAF) { case ACL_JSON_T_NULL: @@ -384,9 +409,8 @@ void acl_json_building(ACL_JSON *json, size_t length, } /* 当节点为数组的成员时 */ - else if (LEN(node->text) > 0 && node->parent - && node->parent->left_ch != 0) - { + else if (node->parent && node->parent->type == ACL_JSON_T_ARRAY + && (node->type & ACL_JSON_T_A_TYPES)) { switch (node->type & ~ACL_JSON_T_LEAF) { case ACL_JSON_T_A_NULL: acl_vstring_strcat(buf, "null"); @@ -417,8 +441,9 @@ void acl_json_building(ACL_JSON *json, size_t length, if (acl_ring_size(&node->children) > 0) { continue; } else if (acl_json_node_next(node) != NULL) { - if (node->right_ch > 0) + if (node->right_ch > 0) { ACL_VSTRING_ADDCH(buf, node->right_ch); + } continue; } @@ -430,20 +455,12 @@ void acl_json_building(ACL_JSON *json, size_t length, * 将父节点的分隔符添加至本叶节点尾部,直到遇到根节点或父 * 节点的下一个兄弟节点非空 */ - while (acl_json_node_next(node) == NULL) { - if (node->parent == json->root) - break; - - node = node->parent; - - /* right_ch: '}' or ']' */ - if (node->right_ch != 0) - ACL_VSTRING_ADDCH(buf, node->right_ch); - } + child_end(json, node, buf); } - if (json->root->right_ch > 0) + if (json->root->right_ch > 0) { ACL_VSTRING_ADDCH(buf, json->root->right_ch); + } ACL_VSTRING_TERMINATE(buf); if (ACL_VSTRING_LEN(buf) > 0 && callback != NULL) { @@ -456,8 +473,29 @@ void acl_json_building(ACL_JSON *json, size_t length, acl_vstring_free(buf); /* 将第二个参数置 NULL 表示处理完毕 */ - if (callback != NULL) + if (callback != NULL) { (void) callback(json, NULL, ctx); + } +} + +static int is_parents_disabled(ACL_JSON_NODE *node) +{ + while ((node = node->parent)) { + if (node->disabled) { + return 1; + } + } + return 0; +} + +static int is_first_node(ACL_JSON_NODE *node) +{ + while ((node = acl_json_node_prev(node))) { + if (!node->disabled) { + return 0; + } + } + return 1; } ACL_VSTRING *acl_json_build(ACL_JSON *json, ACL_VSTRING *buf) @@ -466,8 +504,9 @@ ACL_VSTRING *acl_json_build(ACL_JSON *json, ACL_VSTRING *buf) ACL_ITER iter; ACL_RING *ring_ptr = acl_ring_succ(&json->root->children); - if (buf == NULL) + if (buf == NULL) { buf = acl_vstring_alloc(256); + } /* 为了兼容历史的BUG,所以此处只能如此处理了--zsx, 2021.3.27 */ @@ -487,17 +526,28 @@ ACL_VSTRING *acl_json_build(ACL_JSON *json, ACL_VSTRING *buf) json->root->right_ch = '}'; } - if (json->root->left_ch > 0) + if (json->root->left_ch > 0) { ACL_VSTRING_ADDCH(buf, json->root->left_ch); + } acl_foreach(iter, json) { node = (ACL_JSON_NODE*) iter.data; + if (node->disabled) { // 跳过被禁止的 json 节点 + child_end(json, node, buf); + continue; + } + + if (is_parents_disabled(node)) { + continue; + } + prev = acl_json_node_prev(node); - if (prev != NULL) { - if ((json->flag & ACL_JSON_FLAG_ADD_SPACE)) + if (prev != NULL && (!prev->disabled || !is_first_node(node))) { + if ((json->flag & ACL_JSON_FLAG_ADD_SPACE)) { acl_vstring_strcat(buf, ", "); - else + } else { acl_vstring_strcat(buf, ","); + } } /* 只有当标签的对应值为 JSON 对象或数组对象时 tag_node 非空 */ @@ -505,21 +555,24 @@ ACL_VSTRING *acl_json_build(ACL_JSON *json, ACL_VSTRING *buf) if (LEN(node->ltag) > 0) { json_escape_append(buf, STR(node->ltag)); ACL_VSTRING_ADDCH(buf, ':'); - if ((json->flag & ACL_JSON_FLAG_ADD_SPACE)) + if ((json->flag & ACL_JSON_FLAG_ADD_SPACE)) { ACL_VSTRING_ADDCH(buf, ' '); + } } /* '{' or '[' */ - if (node->left_ch != 0) + if (node->left_ch != 0) { ACL_VSTRING_ADDCH(buf, node->left_ch); + } } /* 当节点有标签名时 */ else if (LEN(node->ltag) > 0) { json_escape_append(buf, STR(node->ltag)); ACL_VSTRING_ADDCH(buf, ':'); - if ((json->flag & ACL_JSON_FLAG_ADD_SPACE)) + if ((json->flag & ACL_JSON_FLAG_ADD_SPACE)) { ACL_VSTRING_ADDCH(buf, ' '); + } switch (node->type & ~ACL_JSON_T_LEAF) { case ACL_JSON_T_NULL: @@ -537,22 +590,8 @@ ACL_VSTRING *acl_json_build(ACL_JSON *json, ACL_VSTRING *buf) } /* 当节点为数组的成员时 */ -#if 0 - else if (LEN(node->text) > 0 && node->parent - /* 应该依据父节点类型来确定当前节点是否为数组节点 - * && node->parent->left_ch != 0) - */ - && node->parent->type == ACL_JSON_T_ARRAY) -#elif 0 else if (node->parent && node->parent->type == ACL_JSON_T_ARRAY - && (LEN(node->text) > 0 || (node->type & ACL_JSON_T_A_STRING))) -#else - else if (node->parent && node->parent->type == ACL_JSON_T_ARRAY - && (node->type & (ACL_JSON_T_A_NULL - | ACL_JSON_T_A_BOOL | ACL_JSON_T_A_NUMBER - | ACL_JSON_T_A_DOUBLE | ACL_JSON_T_A_STRING))) -#endif - { + && (node->type & ACL_JSON_T_A_TYPES)) { switch (node->type & ~ACL_JSON_T_LEAF) { case ACL_JSON_T_A_NULL: acl_vstring_strcat(buf, "null"); @@ -582,35 +621,29 @@ ACL_VSTRING *acl_json_build(ACL_JSON *json, ACL_VSTRING *buf) /* 当本节点有子节点或虽为叶节点,但该节点的下一个兄弟节点 * 非空时继续下一个循环过程 */ - if (acl_ring_size(&node->children) > 0) + if (acl_ring_size(&node->children) > 0) { continue; - else if (acl_json_node_next(node) != NULL) { - if (node->right_ch > 0) + } else if (acl_json_node_next(node) != NULL) { + if (node->right_ch > 0) { ACL_VSTRING_ADDCH(buf, node->right_ch); + } continue; } - if (node->right_ch > 0) + if (node->right_ch > 0) { ACL_VSTRING_ADDCH(buf, node->right_ch); + } /* 当本节点为叶节点且后面没有兄弟节点时,需要一级一级回溯 * 将父节点的分隔符添加至本叶节点尾部,直到遇到根节点或父 * 节点的下一个兄弟节点非空 */ - while (acl_json_node_next(node) == NULL) { - if (node->parent == json->root) - break; - - node = node->parent; - - /* right_ch: '}' or ']' */ - if (node->right_ch != 0) - ACL_VSTRING_ADDCH(buf, node->right_ch); - } + child_end(json, node, buf); } - if (json->root->right_ch > 0) + if (json->root->right_ch > 0) { ACL_VSTRING_ADDCH(buf, json->root->right_ch); + } ACL_VSTRING_TERMINATE(buf); return buf; @@ -621,13 +654,15 @@ ACL_VSTRING *acl_json_node_build(ACL_JSON_NODE *node, ACL_VSTRING *buf) ACL_JSON *json = acl_json_alloc(); ACL_JSON_NODE *first; - if (buf == NULL) + if (buf == NULL) { buf = acl_vstring_alloc(256); + } - if (node == node->json->root && node->tag_node != NULL) + if (node == node->json->root && node->tag_node != NULL) { node = node->tag_node; - else + } else { json->root->left_ch = json->root->right_ch = 0; + } first = acl_json_node_duplicate(json, node); acl_json_node_add_child(json->root, first); diff --git a/lib_acl_cpp/include/acl_cpp/stdlib/json.hpp b/lib_acl_cpp/include/acl_cpp/stdlib/json.hpp index f46b51450..d17895d5a 100644 --- a/lib_acl_cpp/include/acl_cpp/stdlib/json.hpp +++ b/lib_acl_cpp/include/acl_cpp/stdlib/json.hpp @@ -374,6 +374,19 @@ public: */ int detach(); + /** + * 禁止当前 json 节点,在生成 json 字符串时被禁止的节点将被忽略,但该节点并未 + * 从 json 节点树中删除,这样在下次遍历时还可以再启用该节点 + * @param yes {bool} 是否禁止该 json 节点,false 表示启用,true 表示禁用 + */ + void disable(bool yes); + + /** + * 判断当前 json 节点是否被禁止了 + * @return {bool} + */ + bool disabled() const; + /** * 当在遍历该 json 节点时,内部会动态产生一些临时 json_node 对象,调用 * 此函数可以清空这些对象,一旦调用此函数进行了清除,则由 first_child, diff --git a/lib_acl_cpp/src/stdlib/json.cpp b/lib_acl_cpp/src/stdlib/json.cpp index f25b0a4de..22f81c53b 100644 --- a/lib_acl_cpp/src/stdlib/json.cpp +++ b/lib_acl_cpp/src/stdlib/json.cpp @@ -351,6 +351,16 @@ int json_node::detach() return acl_json_node_delete(node_me_); } +void json_node::disable(bool yes) +{ + acl_json_node_disable(node_me_, yes ? 1 : 0); +} + +bool json_node::disabled() const +{ + return acl_json_node_disabled(node_me_) != 0; +} + json_node& json_node::get_parent() const { if (parent_) {