Convert IsoDirIter in an interface.
This commit is contained in:
parent
c75f1a430e
commit
dd02d1d976
192
libisofs/node.c
192
libisofs/node.c
@ -15,6 +15,17 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
struct dir_iter_data
|
||||||
|
{
|
||||||
|
/* points to the last visited child, to NULL before start */
|
||||||
|
IsoNode *pos;
|
||||||
|
|
||||||
|
/* Some control flags.
|
||||||
|
* bit 0 -> 1 if next called, 0 reseted at start or on deletion
|
||||||
|
*/
|
||||||
|
int flag;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increments the reference counting of the given node.
|
* Increments the reference counting of the given node.
|
||||||
*/
|
*/
|
||||||
@ -354,69 +365,53 @@ int iso_dir_get_children_count(IsoDir *dir)
|
|||||||
return dir->nchildren;
|
return dir->nchildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
int iso_dir_get_children(const IsoDir *dir, IsoDirIter **iter)
|
static
|
||||||
{
|
int iter_next(IsoDirIter *iter, IsoNode **node)
|
||||||
IsoDirIter *it;
|
|
||||||
|
|
||||||
if (dir == NULL || iter == NULL) {
|
|
||||||
return ISO_NULL_POINTER;
|
|
||||||
}
|
|
||||||
it = malloc(sizeof(IsoDirIter));
|
|
||||||
if (it == NULL) {
|
|
||||||
return ISO_OUT_OF_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
it->dir = (IsoDir*)dir;
|
|
||||||
it->pos = NULL;
|
|
||||||
it->flag = 0x00;
|
|
||||||
|
|
||||||
*iter = it;
|
|
||||||
return ISO_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int iso_dir_iter_next(IsoDirIter *iter, IsoNode **node)
|
|
||||||
{
|
{
|
||||||
|
struct dir_iter_data *data;
|
||||||
if (iter == NULL || node == NULL) {
|
if (iter == NULL || node == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clear next flag */
|
data = iter->data;
|
||||||
iter->flag &= ~0x01;
|
|
||||||
|
|
||||||
if (iter->pos == NULL) {
|
/* clear next flag */
|
||||||
|
data->flag &= ~0x01;
|
||||||
|
|
||||||
|
if (data->pos == NULL) {
|
||||||
/* we are at the beginning */
|
/* we are at the beginning */
|
||||||
iter->pos = iter->dir->children;
|
data->pos = iter->dir->children;
|
||||||
if (iter->pos == NULL) {
|
if (data->pos == NULL) {
|
||||||
/* empty dir */
|
/* empty dir */
|
||||||
*node = NULL;
|
*node = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (iter->pos->parent != iter->dir) {
|
if (data->pos->parent != iter->dir) {
|
||||||
/* this can happen if the node has been moved to another dir */
|
/* this can happen if the node has been moved to another dir */
|
||||||
/* TODO specific error */
|
/* TODO specific error */
|
||||||
return ISO_ERROR;
|
return ISO_ERROR;
|
||||||
}
|
}
|
||||||
if (iter->pos->next == NULL) {
|
if (data->pos->next == NULL) {
|
||||||
/* no more children */
|
/* no more children */
|
||||||
*node = NULL;
|
*node = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
/* free reference to current position */
|
/* free reference to current position */
|
||||||
iso_node_unref(iter->pos); /* it is never last ref!! */
|
iso_node_unref(data->pos); /* it is never last ref!! */
|
||||||
|
|
||||||
/* advance a position */
|
/* advance a position */
|
||||||
iter->pos = iter->pos->next;
|
data->pos = data->pos->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ok, take a ref to the current position, to prevent internal errors
|
/* ok, take a ref to the current position, to prevent internal errors
|
||||||
* if deleted somewhere */
|
* if deleted somewhere */
|
||||||
iso_node_ref(iter->pos);
|
iso_node_ref(data->pos);
|
||||||
iter->flag |= 0x01; /* set next flag */
|
data->flag |= 0x01; /* set next flag */
|
||||||
|
|
||||||
/* return pointed node */
|
/* return pointed node */
|
||||||
*node = iter->pos;
|
*node = data->pos;
|
||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,24 +423,30 @@ int iso_dir_iter_next(IsoDirIter *iter, IsoNode **node)
|
|||||||
* Possible errors:
|
* Possible errors:
|
||||||
* ISO_NULL_POINTER, if iter is NULL
|
* ISO_NULL_POINTER, if iter is NULL
|
||||||
*/
|
*/
|
||||||
int iso_dir_iter_has_next(IsoDirIter *iter)
|
static
|
||||||
|
int iter_has_next(IsoDirIter *iter)
|
||||||
{
|
{
|
||||||
|
struct dir_iter_data *data;
|
||||||
if (iter == NULL) {
|
if (iter == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
if (iter->pos == NULL) {
|
data = iter->data;
|
||||||
|
if (data->pos == NULL) {
|
||||||
return iter->dir->children == NULL ? 0 : 1;
|
return iter->dir->children == NULL ? 0 : 1;
|
||||||
} else {
|
} else {
|
||||||
return iter->pos->next == NULL ? 0 : 1;
|
return data->pos->next == NULL ? 0 : 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void iso_dir_iter_free(IsoDirIter *iter)
|
static
|
||||||
|
void iter_free(IsoDirIter *iter)
|
||||||
{
|
{
|
||||||
if (iter->pos != NULL) {
|
struct dir_iter_data *data;
|
||||||
iso_node_unref(iter->pos);
|
data = iter->data;
|
||||||
|
if (data->pos != NULL) {
|
||||||
|
iso_node_unref(data->pos);
|
||||||
}
|
}
|
||||||
free(iter);
|
free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static IsoNode** iso_dir_find_node(IsoDir *dir, IsoNode *node)
|
static IsoNode** iso_dir_find_node(IsoDir *dir, IsoNode *node)
|
||||||
@ -526,27 +527,31 @@ IsoDir *iso_node_get_parent(IsoNode *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* TODO #00005 optimize iso_dir_iter_take */
|
/* TODO #00005 optimize iso_dir_iter_take */
|
||||||
int iso_dir_iter_take(IsoDirIter *iter)
|
static
|
||||||
|
int iter_take(IsoDirIter *iter)
|
||||||
{
|
{
|
||||||
|
struct dir_iter_data *data;
|
||||||
IsoNode *pos, *pre;
|
IsoNode *pos, *pre;
|
||||||
if (iter == NULL) {
|
if (iter == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(iter->flag & 0x01)) {
|
data = iter->data;
|
||||||
|
|
||||||
|
if (!(data->flag & 0x01)) {
|
||||||
return ISO_ERROR; /* next not called or end of dir */
|
return ISO_ERROR; /* next not called or end of dir */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iter->pos == NULL) {
|
if (data->pos == NULL) {
|
||||||
return ISO_ASSERT_FAILURE;
|
return ISO_ASSERT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clear next flag */
|
/* clear next flag */
|
||||||
iter->flag &= ~0x01;
|
data->flag &= ~0x01;
|
||||||
|
|
||||||
pos = iter->dir->children;
|
pos = iter->dir->children;
|
||||||
pre = NULL;
|
pre = NULL;
|
||||||
while (pos != NULL && pos != iter->pos) {
|
while (pos != NULL && pos != data->pos) {
|
||||||
pre = pos;
|
pre = pos;
|
||||||
pos = pos->next;
|
pos = pos->next;
|
||||||
}
|
}
|
||||||
@ -554,20 +559,20 @@ int iso_dir_iter_take(IsoDirIter *iter)
|
|||||||
return ISO_ERROR; /* node not in dir */
|
return ISO_ERROR; /* node not in dir */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos != iter->pos) {
|
if (pos != data->pos) {
|
||||||
return ISO_ASSERT_FAILURE;
|
return ISO_ASSERT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dispose iterator reference */
|
/* dispose iterator reference */
|
||||||
iso_node_unref(iter->pos);
|
iso_node_unref(data->pos);
|
||||||
|
|
||||||
if (pre == NULL) {
|
if (pre == NULL) {
|
||||||
/* node is a first position */
|
/* node is a first position */
|
||||||
iter->dir->children = pos->next;
|
iter->dir->children = pos->next;
|
||||||
iter->pos = NULL;
|
data->pos = NULL;
|
||||||
} else {
|
} else {
|
||||||
pre->next = pos->next;
|
pre->next = pos->next;
|
||||||
iter->pos = pre;
|
data->pos = pre;
|
||||||
iso_node_ref(pre); /* take iter ref */
|
iso_node_ref(pre); /* take iter ref */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,27 +583,108 @@ int iso_dir_iter_take(IsoDirIter *iter)
|
|||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int iso_dir_iter_remove(IsoDirIter *iter)
|
static
|
||||||
|
int iter_remove(IsoDirIter *iter)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
IsoNode *pos;
|
IsoNode *pos;
|
||||||
|
struct dir_iter_data *data;
|
||||||
|
|
||||||
if (iter == NULL) {
|
if (iter == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
pos = iter->pos;
|
data = iter->data;
|
||||||
|
pos = data->pos;
|
||||||
|
|
||||||
ret = iso_dir_iter_take(iter);
|
ret = iter_take(iter);
|
||||||
if (ret == ISO_SUCCESS) {
|
if (ret == ISO_SUCCESS) {
|
||||||
/* remove node */
|
/* remove node */
|
||||||
iso_node_unref(pos);
|
iso_node_unref(pos);
|
||||||
}
|
}
|
||||||
if (iter->pos == pos) {
|
if (data->pos == pos) {
|
||||||
return ISO_ERROR;
|
return ISO_ERROR;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
struct iso_dir_iter_iface iter_class = {
|
||||||
|
iter_next,
|
||||||
|
iter_has_next,
|
||||||
|
iter_free,
|
||||||
|
iter_take,
|
||||||
|
iter_remove
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int iso_dir_get_children(const IsoDir *dir, IsoDirIter **iter)
|
||||||
|
{
|
||||||
|
IsoDirIter *it;
|
||||||
|
struct dir_iter_data *data;
|
||||||
|
|
||||||
|
if (dir == NULL || iter == NULL) {
|
||||||
|
return ISO_NULL_POINTER;
|
||||||
|
}
|
||||||
|
it = malloc(sizeof(IsoDirIter));
|
||||||
|
if (it == NULL) {
|
||||||
|
return ISO_OUT_OF_MEM;
|
||||||
|
}
|
||||||
|
data = malloc(sizeof(struct dir_iter_data));
|
||||||
|
if (data == NULL) {
|
||||||
|
free(it);
|
||||||
|
return ISO_OUT_OF_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
it->class = &iter_class;
|
||||||
|
it->dir = (IsoDir*)dir;
|
||||||
|
data->pos = NULL;
|
||||||
|
data->flag = 0x00;
|
||||||
|
it->data = data;
|
||||||
|
|
||||||
|
*iter = it;
|
||||||
|
return ISO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iso_dir_iter_next(IsoDirIter *iter, IsoNode **node)
|
||||||
|
{
|
||||||
|
if (iter == NULL || node == NULL) {
|
||||||
|
return ISO_NULL_POINTER;
|
||||||
|
}
|
||||||
|
return iter->class->next(iter, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
int iso_dir_iter_has_next(IsoDirIter *iter)
|
||||||
|
{
|
||||||
|
if (iter == NULL) {
|
||||||
|
return ISO_NULL_POINTER;
|
||||||
|
}
|
||||||
|
return iter->class->has_next(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void iso_dir_iter_free(IsoDirIter *iter)
|
||||||
|
{
|
||||||
|
if (iter != NULL) {
|
||||||
|
iter->class->free(iter);
|
||||||
|
free(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int iso_dir_iter_take(IsoDirIter *iter)
|
||||||
|
{
|
||||||
|
if (iter == NULL) {
|
||||||
|
return ISO_NULL_POINTER;
|
||||||
|
}
|
||||||
|
return iter->class->take(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
int iso_dir_iter_remove(IsoDirIter *iter)
|
||||||
|
{
|
||||||
|
if (iter == NULL) {
|
||||||
|
return ISO_NULL_POINTER;
|
||||||
|
}
|
||||||
|
return iter->class->remove(iter);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the destination of a node.
|
* Get the destination of a node.
|
||||||
* The returned string belongs to the node and should not be modified nor
|
* The returned string belongs to the node and should not be modified nor
|
||||||
|
@ -148,20 +148,32 @@ struct Iso_Special
|
|||||||
dev_t dev;
|
dev_t dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct iso_dir_iter_iface
|
||||||
|
{
|
||||||
|
|
||||||
|
int (*next)(IsoDirIter *iter, IsoNode **node);
|
||||||
|
|
||||||
|
int (*has_next)(IsoDirIter *iter);
|
||||||
|
|
||||||
|
void (*free)(IsoDirIter *iter);
|
||||||
|
|
||||||
|
int (*take)(IsoDirIter *iter);
|
||||||
|
|
||||||
|
int (*remove)(IsoDirIter *iter);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An iterator for directory children.
|
* An iterator for directory children.
|
||||||
*/
|
*/
|
||||||
struct Iso_Dir_Iter
|
struct Iso_Dir_Iter
|
||||||
{
|
{
|
||||||
|
struct iso_dir_iter_iface *class;
|
||||||
|
|
||||||
|
/* the directory this iterator iterates over */
|
||||||
IsoDir *dir;
|
IsoDir *dir;
|
||||||
|
|
||||||
/* points to the last visited child, to NULL before start */
|
void *data;
|
||||||
IsoNode *pos;
|
|
||||||
|
|
||||||
/* Some control flags.
|
|
||||||
* bit 0 -> 1 if next called, 0 reseted at start or on deletion
|
|
||||||
*/
|
|
||||||
int flag;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int iso_node_new_root(IsoDir **root);
|
int iso_node_new_root(IsoDir **root);
|
||||||
|
Loading…
Reference in New Issue
Block a user