Improve find iterator, to make has_next() actually work.
This commit is contained in:
parent
166f1d83bd
commit
987fa4b323
@ -39,22 +39,49 @@ struct find_iter_data
|
|||||||
{
|
{
|
||||||
IsoDirIter *iter;
|
IsoDirIter *iter;
|
||||||
IsoFindCondition *cond;
|
IsoFindCondition *cond;
|
||||||
|
int err; /**< error? */
|
||||||
|
IsoNode *current; /**< node to be returned next */
|
||||||
|
IsoNode *prev; /**< last returned node, needed for removal */
|
||||||
|
int free_cond; /**< whether to free cond on iter_free */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
void update_next(struct find_iter_data *iter)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
IsoNode *n;
|
||||||
|
|
||||||
|
if (iter->prev) {
|
||||||
|
iso_node_unref(iter->prev);
|
||||||
|
}
|
||||||
|
iter->prev = iter->current;
|
||||||
|
while ((ret = iso_dir_iter_next(iter->iter, &n)) == 1) {
|
||||||
|
if (iter->cond->matches(iter->cond, n)) {
|
||||||
|
iter->current = n;
|
||||||
|
iso_node_ref(n);
|
||||||
|
iter->err = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iter->current = NULL;
|
||||||
|
iter->err = ret;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int find_iter_next(IsoDirIter *iter, IsoNode **node)
|
int find_iter_next(IsoDirIter *iter, IsoNode **node)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
IsoNode *n;
|
|
||||||
struct find_iter_data *data = iter->data;
|
struct find_iter_data *data = iter->data;
|
||||||
|
|
||||||
while ((ret = iso_dir_iter_next(data->iter, &n)) == 1) {
|
if (iter == NULL || node == NULL) {
|
||||||
if (data->cond->matches(data->cond, n)) {
|
return ISO_NULL_POINTER;
|
||||||
*node = n;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
|
if (data->err < 0) {
|
||||||
|
return data->err;
|
||||||
|
}
|
||||||
|
*node = data->current;
|
||||||
|
update_next(data);
|
||||||
|
return (*node == NULL) ? 0 : ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -62,19 +89,27 @@ int find_iter_has_next(IsoDirIter *iter)
|
|||||||
{
|
{
|
||||||
struct find_iter_data *data = iter->data;
|
struct find_iter_data *data = iter->data;
|
||||||
|
|
||||||
/*
|
return (data->current != NULL);
|
||||||
* FIXME wrong implementation!!!! the underlying iter may have more nodes,
|
|
||||||
* but they may not match find conditions
|
|
||||||
*/
|
|
||||||
return iso_dir_iter_has_next(data->iter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void find_iter_free(IsoDirIter *iter)
|
void find_iter_free(IsoDirIter *iter)
|
||||||
{
|
{
|
||||||
struct find_iter_data *data = iter->data;
|
struct find_iter_data *data = iter->data;
|
||||||
data->cond->free(data->cond);
|
if (data->free_cond) {
|
||||||
free(data->cond);
|
data->cond->free(data->cond);
|
||||||
|
free(data->cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free refs to nodes */
|
||||||
|
if (data->prev) {
|
||||||
|
iso_node_unref(data->prev);
|
||||||
|
}
|
||||||
|
if (data->current) {
|
||||||
|
iso_node_unref(data->current);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free underlying iter */
|
||||||
iso_dir_iter_free(data->iter);
|
iso_dir_iter_free(data->iter);
|
||||||
free(iter->data);
|
free(iter->data);
|
||||||
}
|
}
|
||||||
@ -83,20 +118,37 @@ static
|
|||||||
int find_iter_take(IsoDirIter *iter)
|
int find_iter_take(IsoDirIter *iter)
|
||||||
{
|
{
|
||||||
struct find_iter_data *data = iter->data;
|
struct find_iter_data *data = iter->data;
|
||||||
return iso_dir_iter_take(data->iter);
|
|
||||||
|
if (data->prev == NULL) {
|
||||||
|
return ISO_ERROR; /* next not called or end of dir */
|
||||||
|
}
|
||||||
|
return iso_node_take(data->prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int find_iter_remove(IsoDirIter *iter)
|
int find_iter_remove(IsoDirIter *iter)
|
||||||
{
|
{
|
||||||
struct find_iter_data *data = iter->data;
|
struct find_iter_data *data = iter->data;
|
||||||
return iso_dir_iter_remove(data->iter);
|
|
||||||
|
if (data->prev == NULL) {
|
||||||
|
return ISO_ERROR; /* next not called or end of dir */
|
||||||
|
}
|
||||||
|
return iso_node_remove(data->prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void find_notify_child_taken(IsoDirIter *iter, IsoNode *node)
|
void find_notify_child_taken(IsoDirIter *iter, IsoNode *node)
|
||||||
{
|
{
|
||||||
/* nothing to do */
|
struct find_iter_data *data = iter->data;
|
||||||
return;
|
|
||||||
|
if (data->prev == node) {
|
||||||
|
/* free our ref */
|
||||||
|
iso_node_unref(node);
|
||||||
|
data->prev = NULL;
|
||||||
|
} else if (data->current == node) {
|
||||||
|
iso_node_unref(node);
|
||||||
|
data->current = NULL;
|
||||||
|
update_next(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -140,6 +192,9 @@ int iso_dir_find_children(IsoDir* dir, IsoFindCondition *cond,
|
|||||||
it->dir = (IsoDir*)dir;
|
it->dir = (IsoDir*)dir;
|
||||||
data->iter = children;
|
data->iter = children;
|
||||||
data->cond = cond;
|
data->cond = cond;
|
||||||
|
data->free_cond = 1;
|
||||||
|
data->err = 0;
|
||||||
|
data->prev = data->current = NULL;
|
||||||
it->data = data;
|
it->data = data;
|
||||||
|
|
||||||
if (iso_dir_iter_register(it) < 0) {
|
if (iso_dir_iter_register(it) < 0) {
|
||||||
@ -147,6 +202,7 @@ int iso_dir_find_children(IsoDir* dir, IsoFindCondition *cond,
|
|||||||
return ISO_OUT_OF_MEM;
|
return ISO_OUT_OF_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_next(data);
|
||||||
*iter = it;
|
*iter = it;
|
||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user