Add functions to remove nodes from a dir. Handle deletion of dirs

propertly.
This commit is contained in:
Vreixo Formoso 2007-12-01 02:43:37 +01:00
parent 051538b5c2
commit 5ec93b50f4
3 changed files with 104 additions and 1 deletions

View File

@ -23,6 +23,7 @@
#define ISO_NODE_ALREADY_ADDED -50 #define ISO_NODE_ALREADY_ADDED -50
#define ISO_NODE_NAME_NOT_UNIQUE -51 #define ISO_NODE_NAME_NOT_UNIQUE -51
#define ISO_NODE_NOT_ADDED_TO_DIR -52
#define ISO_FILE_ERROR -100 #define ISO_FILE_ERROR -100
#define ISO_FILE_ALREADY_OPENNED -101 #define ISO_FILE_ALREADY_OPENNED -101

View File

@ -198,4 +198,29 @@ int iso_dir_iter_has_next(IsoDirIter *iter);
*/ */
void iso_dir_iter_free(IsoDirIter *iter); void iso_dir_iter_free(IsoDirIter *iter);
/**
* Removes a child from a directory.
* The child is not freed, so you will become the owner of the node. Later
* you can add the node to another dir (calling iso_dir_add_node), or free
* it if you don't need it (with iso_node_unref).
*
* @return
* 1 on success, < 0 error
* Possible errors:
* ISO_NULL_POINTER, if node is NULL
* ISO_NODE_NOT_ADDED_TO_DIR, if node doesn't belong to a dir
*/
int iso_node_take(IsoNode *node);
/**
* Removes a child from a directory and free (unref) it.
* If you want to keep the child alive, you need to iso_node_ref() it
* before this call, but in that case iso_node_take() is a better
* alternative.
*
* @return
* 1 on success, < 0 error
*/
int iso_node_remove(IsoNode *node);
#endif /*LIBISO_LIBISOFS_H_*/ #endif /*LIBISO_LIBISOFS_H_*/

View File

@ -29,7 +29,21 @@ void iso_node_ref(IsoNode *node)
void iso_node_unref(IsoNode *node) void iso_node_unref(IsoNode *node)
{ {
if (--node->refcount == 0) { if (--node->refcount == 0) {
switch(node->type) {
case LIBISO_DIR:
{
IsoNode *child = ((IsoDir*)node)->children;
while (child != NULL) {
IsoNode *tmp = child->next;
iso_node_unref(child);
child = tmp;
}
}
break;
default:
/* TODO #00002 handle deletion of each kind of node */ /* TODO #00002 handle deletion of each kind of node */
break;
}
free(node->name); free(node->name);
free(node); free(node);
} }
@ -268,3 +282,66 @@ int iso_dir_iter_has_next(IsoDirIter *iter)
} }
return iter->pos == NULL ? 0 : 1; return iter->pos == NULL ? 0 : 1;
} }
static IsoNode**
iso_dir_find_node(IsoDir *dir, IsoNode *node)
{
IsoNode **pos;
pos = &(dir->children);
while (*pos != NULL && *pos != node) {
pos = &((*pos)->next);
}
return pos;
}
/**
* Removes a child from a directory.
* The child is not freed, so you will become the owner of the node. Later
* you can add the node to another dir (calling iso_dir_add_node), or free
* it if you don't need it (with iso_node_unref).
*
* @return
* 1 on success, < 0 error
*/
int iso_node_take(IsoNode *node)
{
IsoNode **pos;
IsoDir* dir;
if (node == NULL) {
return ISO_NULL_POINTER;
}
dir = node->parent;
if (dir == NULL) {
return ISO_NODE_NOT_ADDED_TO_DIR;
}
pos = iso_dir_find_node(dir, node);
if (pos == NULL) {
/* should never occur */
return ISO_ERROR;
}
*pos = node->next;
node->parent = NULL;
node->next = NULL;
dir->nchildren--;
return ISO_SUCCESS;
}
/**
* Removes a child from a directory and free (unref) it.
* If you want to keep the child alive, you need to iso_node_ref() it
* before this call, but in that case iso_node_take() is a better
* alternative.
*
* @return
* 1 on success, < 0 error
*/
int iso_node_remove(IsoNode *node)
{
int ret;
ret = iso_node_take(node);
if (ret == ISO_SUCCESS) {
iso_node_unref(node);
}
return ret;
}