加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
tree.c 5.99 KB
一键复制 编辑 原始数据 按行查看 历史
江二十三 提交于 2017-09-13 18:42 . format
/* Copyright (C) 2014 by Maxim Bublis <b@codemonkey.ru>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "tree.h"
#include <svn_hash.h>
#include <svn_path.h>
tree_t *tree_create(apr_pool_t *pool) {
tree_t *t = apr_pcalloc(pool, sizeof(tree_t));
t->pool = pool;
t->nodes = apr_hash_make(pool);
t->value = NULL;
return t;
}
void tree_copy(tree_t **dst, const tree_t *src, apr_pool_t *pool) {
apr_hash_index_t *idx;
tree_t *t = tree_create(pool);
t->value = src->value;
for (idx = apr_hash_first(pool, src->nodes); idx; idx = apr_hash_next(idx)) {
const char *key = apr_hash_this_key(idx);
const tree_t *val = apr_hash_this_val(idx);
tree_t *subtree;
tree_copy(&subtree, val, pool);
svn_hash_sets(t->nodes, apr_pstrdup(t->pool, key), subtree);
}
*dst = t;
}
void tree_merge(tree_t **dst, const tree_t *t1, const tree_t *t2,
apr_pool_t *pool) {
apr_hash_index_t *idx;
if (t1 == NULL && t2 == NULL) {
return;
}
if (t1 == NULL) {
tree_copy(dst, t2, pool);
return;
}
if (t2 == NULL) {
tree_copy(dst, t1, pool);
return;
}
tree_t *t = tree_create(pool);
t->value = t1->value != NULL ? t1->value : t2->value;
for (idx = apr_hash_first(pool, t1->nodes); idx; idx = apr_hash_next(idx)) {
const char *key1 = apr_hash_this_key(idx);
const tree_t *val1 = apr_hash_this_val(idx);
const tree_t *val2 = svn_hash_gets(t2->nodes, key1);
tree_t *subtree;
tree_merge(&subtree, val1, val2, pool);
svn_hash_sets(t->nodes, apr_pstrdup(t->pool, key1), subtree);
}
for (idx = apr_hash_first(pool, t2->nodes); idx; idx = apr_hash_next(idx)) {
const char *key2 = apr_hash_this_key(idx);
const tree_t *val2 = apr_hash_this_val(idx);
const tree_t *val1 = svn_hash_gets(t1->nodes, key2);
if (val1 == NULL) {
tree_t *subtree;
tree_copy(&subtree, val2, pool);
svn_hash_sets(t->nodes, apr_pstrdup(t->pool, key2), subtree);
}
}
*dst = t;
}
void tree_diff(tree_t **dst, const tree_t *t1, const tree_t *t2,
apr_pool_t *pool) {
apr_hash_index_t *idx;
tree_t *t = tree_create(pool);
if (t1 == NULL) {
*dst = t;
return;
}
if (t2 == NULL) {
tree_copy(dst, t1, pool);
return;
}
for (idx = apr_hash_first(pool, t1->nodes); idx; idx = apr_hash_next(idx)) {
const char *key1 = apr_hash_this_key(idx);
const tree_t *val1 = apr_hash_this_val(idx);
const tree_t *val2 = svn_hash_gets(t2->nodes, key1);
tree_t *subtree;
tree_diff(&subtree, val1, val2, pool);
if (val2 == NULL || val2->value == NULL) {
subtree->value = val1->value;
}
svn_hash_sets(t->nodes, apr_pstrdup(t->pool, key1), subtree);
}
*dst = t;
}
void tree_insert(tree_t *t, const char *path, const void *value,
apr_pool_t *pool) {
apr_array_header_t *components = svn_path_decompose(path, pool);
for (int i = 0; i < components->nelts; i++) {
const char *key = APR_ARRAY_IDX(components, i, const char *);
tree_t *subtree = svn_hash_gets(t->nodes, key);
if (subtree == NULL) {
subtree = tree_create(t->pool);
svn_hash_sets(t->nodes, apr_pstrdup(t->pool, key), subtree);
}
t = subtree;
}
t->value = value;
}
const void *tree_match(const tree_t *t, const char *path, apr_pool_t *pool) {
const void *value = t->value;
apr_array_header_t *components = svn_path_decompose(path, pool);
for (int i = 0; i < components->nelts; i++) {
const char *key = APR_ARRAY_IDX(components, i, const char *);
tree_t *subtree = svn_hash_gets(t->nodes, key);
if (subtree == NULL) {
break;
}
if (subtree->value != NULL) {
value = subtree->value;
}
t = subtree;
}
return value;
}
const tree_t *tree_subtree(const tree_t *t, const char *path,
apr_pool_t *pool) {
apr_array_header_t *components = svn_path_decompose(path, pool);
for (int i = 0; i < components->nelts; i++) {
const char *key = APR_ARRAY_IDX(components, i, const char *);
t = svn_hash_gets(t->nodes, key);
if (t == NULL) {
break;
}
}
return t;
}
apr_array_header_t *tree_values(const tree_t *t, const char *path,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool) {
apr_array_header_t *values, *queue;
const tree_t *subtree;
values = apr_array_make(result_pool, 0, sizeof(void *));
queue = apr_array_make(scratch_pool, 0, sizeof(tree_t *));
subtree = tree_subtree(t, path, scratch_pool);
if (subtree == NULL) {
return values;
}
APR_ARRAY_PUSH(queue, const tree_t *) = subtree;
while (queue->nelts) {
apr_hash_index_t *idx;
const tree_t *node = *((const tree_t **)apr_array_pop(queue));
if (node->value != NULL) {
APR_ARRAY_PUSH(values, const void *) = node->value;
}
for (idx = apr_hash_first(scratch_pool, node->nodes); idx;
idx = apr_hash_next(idx)) {
APR_ARRAY_PUSH(queue, const tree_t *) = apr_hash_this_val(idx);
}
}
return values;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化