Make iso_dir_find_children() work recursivelly.
This commit is contained in:
parent
8b10d3107a
commit
2374976b6d
103
libisofs/find.c
103
libisofs/find.c
@ -37,7 +37,9 @@ struct iso_find_condition
|
|||||||
|
|
||||||
struct find_iter_data
|
struct find_iter_data
|
||||||
{
|
{
|
||||||
|
IsoDir *dir; /**< original dir of the iterator */
|
||||||
IsoDirIter *iter;
|
IsoDirIter *iter;
|
||||||
|
IsoDirIter *itersec; /**< iterator to deal with child dirs */
|
||||||
IsoFindCondition *cond;
|
IsoFindCondition *cond;
|
||||||
int err; /**< error? */
|
int err; /**< error? */
|
||||||
IsoNode *current; /**< node to be returned next */
|
IsoNode *current; /**< node to be returned next */
|
||||||
@ -45,26 +47,90 @@ struct find_iter_data
|
|||||||
int free_cond; /**< whether to free cond on iter_free */
|
int free_cond; /**< whether to free cond on iter_free */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
int get_next(struct find_iter_data *iter, IsoNode **n)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (iter->itersec != NULL) {
|
||||||
|
ret = iso_dir_iter_next(iter->itersec, n);
|
||||||
|
if (ret <= 0) {
|
||||||
|
/* secondary item no more needed */
|
||||||
|
iso_dir_iter_free(iter->itersec);
|
||||||
|
iter->itersec = NULL;
|
||||||
|
}
|
||||||
|
if (ret != 0) {
|
||||||
|
/* succes or error */
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we reach here if:
|
||||||
|
* - no secondary item is present
|
||||||
|
* - secondary item has no more items
|
||||||
|
*/
|
||||||
|
|
||||||
|
while ((ret = iso_dir_iter_next(iter->iter, n)) == 1) {
|
||||||
|
if (iter->cond->matches(iter->cond, *n)) {
|
||||||
|
return ISO_SUCCESS;
|
||||||
|
} else if (ISO_NODE_IS_DIR(*n)) {
|
||||||
|
/* recurse on child dir */
|
||||||
|
struct find_iter_data *data;
|
||||||
|
ret = iso_dir_find_children((IsoDir*)*n, iter->cond,
|
||||||
|
&iter->itersec);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
data = iter->itersec->data;
|
||||||
|
data->free_cond = 0; /* we don't need sec iter to free cond */
|
||||||
|
return get_next(iter, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void update_next(struct find_iter_data *iter)
|
void update_next(IsoDirIter *iter)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
IsoNode *n;
|
IsoNode *n;
|
||||||
|
struct find_iter_data *data = iter->data;
|
||||||
|
|
||||||
if (iter->prev) {
|
if (data->prev) {
|
||||||
iso_node_unref(iter->prev);
|
iso_node_unref(data->prev);
|
||||||
}
|
}
|
||||||
iter->prev = iter->current;
|
data->prev = data->current;
|
||||||
while ((ret = iso_dir_iter_next(iter->iter, &n)) == 1) {
|
|
||||||
if (iter->cond->matches(iter->cond, n)) {
|
if (data->itersec == NULL && data->current != NULL
|
||||||
iter->current = n;
|
&& ISO_NODE_IS_DIR(data->current)) {
|
||||||
iso_node_ref(n);
|
|
||||||
iter->err = 0;
|
/* we need to recurse on child dir */
|
||||||
|
struct find_iter_data *data2;
|
||||||
|
ret = iso_dir_find_children((IsoDir*)data->current, data->cond,
|
||||||
|
&data->itersec);
|
||||||
|
if (ret < 0) {
|
||||||
|
data->current = NULL;
|
||||||
|
data->err = ret;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
data2 = data->itersec->data;
|
||||||
|
data2->free_cond = 0; /* we don't need sec iter to free cond */
|
||||||
}
|
}
|
||||||
iter->current = NULL;
|
|
||||||
iter->err = ret;
|
ret = get_next(data, &n);
|
||||||
|
iso_node_unref((IsoNode*)iter->dir);
|
||||||
|
if (ret == 1) {
|
||||||
|
data->current = n;
|
||||||
|
iso_node_ref(n);
|
||||||
|
data->err = 0;
|
||||||
|
iter->dir = n->parent;
|
||||||
|
} else {
|
||||||
|
data->current = NULL;
|
||||||
|
data->err = ret;
|
||||||
|
iter->dir = data->dir;
|
||||||
|
}
|
||||||
|
iso_node_ref((IsoNode*)iter->dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -80,7 +146,7 @@ int find_iter_next(IsoDirIter *iter, IsoNode **node)
|
|||||||
return data->err;
|
return data->err;
|
||||||
}
|
}
|
||||||
*node = data->current;
|
*node = data->current;
|
||||||
update_next(data);
|
update_next(iter);
|
||||||
return (*node == NULL) ? 0 : ISO_SUCCESS;
|
return (*node == NULL) ? 0 : ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +166,8 @@ void find_iter_free(IsoDirIter *iter)
|
|||||||
data->cond->free(data->cond);
|
data->cond->free(data->cond);
|
||||||
free(data->cond);
|
free(data->cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iso_node_unref((IsoNode*)data->dir);
|
||||||
|
|
||||||
/* free refs to nodes */
|
/* free refs to nodes */
|
||||||
if (data->prev) {
|
if (data->prev) {
|
||||||
@ -147,7 +215,7 @@ void find_notify_child_taken(IsoDirIter *iter, IsoNode *node)
|
|||||||
} else if (data->current == node) {
|
} else if (data->current == node) {
|
||||||
iso_node_unref(node);
|
iso_node_unref(node);
|
||||||
data->current = NULL;
|
data->current = NULL;
|
||||||
update_next(data);
|
update_next(iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,6 +259,7 @@ int iso_dir_find_children(IsoDir* dir, IsoFindCondition *cond,
|
|||||||
it->class = &find_iter_class;
|
it->class = &find_iter_class;
|
||||||
it->dir = (IsoDir*)dir;
|
it->dir = (IsoDir*)dir;
|
||||||
data->iter = children;
|
data->iter = children;
|
||||||
|
data->itersec = NULL;
|
||||||
data->cond = cond;
|
data->cond = cond;
|
||||||
data->free_cond = 1;
|
data->free_cond = 1;
|
||||||
data->err = 0;
|
data->err = 0;
|
||||||
@ -202,8 +271,14 @@ int iso_dir_find_children(IsoDir* dir, IsoFindCondition *cond,
|
|||||||
return ISO_OUT_OF_MEM;
|
return ISO_OUT_OF_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_next(data);
|
|
||||||
iso_node_ref((IsoNode*)dir);
|
iso_node_ref((IsoNode*)dir);
|
||||||
|
|
||||||
|
/* take another ref to the original dir */
|
||||||
|
data->dir = (IsoDir*)dir;
|
||||||
|
iso_node_ref((IsoNode*)dir);
|
||||||
|
|
||||||
|
update_next(it);
|
||||||
|
|
||||||
*iter = it;
|
*iter = it;
|
||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user