Add functions to iterate over directory children.
This commit is contained in:
parent
e068fd1cf6
commit
051538b5c2
@ -13,6 +13,7 @@
|
|||||||
typedef struct Iso_Node IsoNode;
|
typedef struct Iso_Node IsoNode;
|
||||||
typedef struct Iso_Dir IsoDir;
|
typedef struct Iso_Dir IsoDir;
|
||||||
typedef struct Iso_Symlink IsoSymlink;
|
typedef struct Iso_Symlink IsoSymlink;
|
||||||
|
typedef struct Iso_Dir_Iter IsoDirIter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increments the reference counting of the given node.
|
* Increments the reference counting of the given node.
|
||||||
@ -134,4 +135,67 @@ int iso_dir_get_node(IsoDir *dir, const char *name, IsoNode **node);
|
|||||||
*/
|
*/
|
||||||
int iso_dir_get_nchildren(IsoDir *dir);
|
int iso_dir_get_nchildren(IsoDir *dir);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an iterator for the children of the given dir.
|
||||||
|
*
|
||||||
|
* You can iterate over the children with iso_dir_iter_next. When finished,
|
||||||
|
* you should free the iterator with iso_dir_iter_free.
|
||||||
|
* You musn't delete a child of the same dir, using iso_node_take() or
|
||||||
|
* iso_node_remove(), while you're using the iterator. You can use
|
||||||
|
* iso_node_take_iter() or iso_node_remove_iter() instead.
|
||||||
|
*
|
||||||
|
* You can use the iterator in the way like this
|
||||||
|
*
|
||||||
|
* IsoDirIter *iter;
|
||||||
|
* IsoNode *node;
|
||||||
|
* if ( iso_dir_get_children(dir, &iter) != 1 ) {
|
||||||
|
* // handle error
|
||||||
|
* }
|
||||||
|
* while ( iso_dir_iter_next(iter, &node) == 1 ) {
|
||||||
|
* // do something with the child
|
||||||
|
* }
|
||||||
|
* iso_dir_iter_free(iter);
|
||||||
|
*
|
||||||
|
* An iterator is intended to be used in a single iteration over the
|
||||||
|
* children of a dir. Thus, it should be treated as a temporary object,
|
||||||
|
* and free as soon as possible.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* 1 success, < 0 error
|
||||||
|
* Possible errors:
|
||||||
|
* ISO_NULL_POINTER, if dir or iter are NULL
|
||||||
|
* ISO_OUT_OF_MEM
|
||||||
|
*/
|
||||||
|
int iso_dir_get_children(const IsoDir *dir, IsoDirIter **iter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next child.
|
||||||
|
* Take care that the node is owned by its parent, and will be unref() when
|
||||||
|
* the parent is freed. If you want your own ref to it, call iso_node_ref()
|
||||||
|
* on it.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* 1 success, 0 if dir has no more elements, < 0 error
|
||||||
|
* Possible errors:
|
||||||
|
* ISO_NULL_POINTER, if node or iter are NULL
|
||||||
|
* ISO_ERROR, on wrong iter usage, usual caused by modiying the
|
||||||
|
* dir during iteration
|
||||||
|
*/
|
||||||
|
int iso_dir_iter_next(IsoDirIter *iter, IsoNode **node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if there're more children.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* 1 dir has more elements, 0 no, < 0 error
|
||||||
|
* Possible errors:
|
||||||
|
* ISO_NULL_POINTER, if iter is NULL
|
||||||
|
*/
|
||||||
|
int iso_dir_iter_has_next(IsoDirIter *iter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a dir iterator.
|
||||||
|
*/
|
||||||
|
void iso_dir_iter_free(IsoDirIter *iter);
|
||||||
|
|
||||||
#endif /*LIBISO_LIBISOFS_H_*/
|
#endif /*LIBISO_LIBISOFS_H_*/
|
||||||
|
54
src/node.c
54
src/node.c
@ -214,3 +214,57 @@ int iso_dir_get_nchildren(IsoDir *dir)
|
|||||||
}
|
}
|
||||||
return dir->nchildren;
|
return dir->nchildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int iso_dir_get_children(const IsoDir *dir, IsoDirIter **iter)
|
||||||
|
{
|
||||||
|
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 = dir;
|
||||||
|
it->pos = dir->children;
|
||||||
|
|
||||||
|
*iter = it;
|
||||||
|
return ISO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iso_dir_iter_next(IsoDirIter *iter, IsoNode **node)
|
||||||
|
{
|
||||||
|
IsoNode *n;
|
||||||
|
if (iter == NULL || node == NULL) {
|
||||||
|
return ISO_NULL_POINTER;
|
||||||
|
}
|
||||||
|
n = iter->pos;
|
||||||
|
if (n == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (n->parent != iter->dir) {
|
||||||
|
/* this can happen if the node has been moved to another dir */
|
||||||
|
return ISO_ERROR;
|
||||||
|
}
|
||||||
|
*node = n;
|
||||||
|
iter->pos = n->next;
|
||||||
|
return ISO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if there're more children.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* 1 dir has more elements, 0 no, < 0 error
|
||||||
|
* Possible errors:
|
||||||
|
* ISO_NULL_POINTER, if iter is NULL
|
||||||
|
*/
|
||||||
|
int iso_dir_iter_has_next(IsoDirIter *iter)
|
||||||
|
{
|
||||||
|
if (iter == NULL) {
|
||||||
|
return ISO_NULL_POINTER;
|
||||||
|
}
|
||||||
|
return iter->pos == NULL ? 0 : 1;
|
||||||
|
}
|
||||||
|
10
src/node.h
10
src/node.h
@ -107,4 +107,14 @@ struct Iso_Symlink
|
|||||||
char *dest;
|
char *dest;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An iterator for directory children.
|
||||||
|
*/
|
||||||
|
struct Iso_Dir_Iter
|
||||||
|
{
|
||||||
|
const IsoDir *dir;
|
||||||
|
IsoNode *pos;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /*LIBISO_NODE_H_*/
|
#endif /*LIBISO_NODE_H_*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user