int ListRemove(List *list, void *payload) { if (!list || !payload) return -1; ListNode *node = NULL; /* * This is a complicated matter. We could detach the list before * we know that we have a new node, but that will mean that we * might have copied the whole list without real reasons. On the * other hand, it saves us a whole traversal of the list if we * just do it. */ int found = ListFindNode(list, payload); if (!found) return -1; ListDetach(list); node = NULL; /* * We need to find the node again since we have a new list. * In theory we don't have to worry about the existence of the node, * since the list has not changed, it might have been copied but * it is still the same as before. */ for (node = list->list; node; node = node->next) { if (list->compare) { if (!list->compare(node->payload, payload)) { found = 1; break; } } else { if (node->payload == payload) { found = 1; break; } } } /* * Before deleting the node we have to update the mutable iterator. * We might need to advance it! */ ListUpdateMutableIterator(list, node); ListRemoveNode(list, node); if (list->destroy && node->payload) { list->destroy(node->payload); } free(node); ListUpdateListState(list); return 0; }
int ListMutableIteratorRemove(ListMutableIterator *iterator) { if (!iterator) return -1; if (IsMutableIteratorValid(iterator)) return -1; ListDetach(iterator->origin); /* * Removing an element is not as simple as it sounds. We need to inform the list * and make sure we move out of the way. */ ListNode *node = NULL; if (iterator->current->next) { /* * We are not the last element, therefore we proceed as normal. */ node = iterator->current->next; } else { /* * We might be the last element or the only element on the list. * If we are the only element we do not destroy the element otherwise the iterator * would become invalid. */ if (iterator->current->previous) { /* * last element */ node = iterator->current->previous; } else return -1; } ListRemoveNode(iterator->origin, iterator->current); if (iterator->origin->destroy) iterator->origin->destroy(iterator->current->payload); free (iterator->current); iterator->current = node; ListUpdateListState(iterator->origin); return 0; }
int ListRemove(List *list, void *payload) { if (!list || !payload) return -1; ListNode *node = NULL; /* * This is a complicated matter. We could detach the list before * we know that we have a new node, but that will mean that we * might have copied the whole list without real reasons. On the * other hand, it saves us a whole traversal of the list if we * just do it. */ int found = ListFindNode(list, payload); if (!found) return -1; found = 0; ListDetach(list); node = NULL; /* * We need to find the node again since we have a new list. * In theory we don't have to worry about the existence of the node, * since the list has not changed, it might have been copied but * it is still the same as before. */ for (node = list->list; node; node = node->next) { if (list->compare) { if (!list->compare(node->payload, payload)) { found = 1; break; } } else { if (node->payload == payload) { found = 1; break; } } } /* * This is nearly impossible, so we will only assert it. */ assert(found == 1); /* * Before deleting the node we have to update the mutable iterator. * We might need to advance it! */ if (list->iterator) { if (list->iterator->current == node) { /* * So lucky, it is the same node! * Move the iterator so it is not dangling. * Rules for moving: * 1. Move forward. * 2. if not possible, move backward. * 3. If not possible, then invalidate the iterator. */ if (list->iterator->current->next) { list->iterator->current = list->iterator->current->next; } else if (list->iterator->current->previous) { list->iterator->current = list->iterator->current->previous; } else { list->iterator->valid = 0; } } } /* * Now, remove the node from the list and delete it. */ if (node->next && node->previous) { // Middle of the list node->next->previous = node->previous; node->previous->next = node->next; } else if (node->next) { // First element of the list list->list = node->next; list->first = node->next; node->next->previous = NULL; } else if (node->previous) { // Last element node->previous->next = NULL; list->last = node->previous; } else { // Single element list->list = NULL; list->first = NULL; list->last = NULL; } if (list->destroy && node->payload) { list->destroy(node->payload); } else { free (node->payload); } free(node); ListUpdateListState(list); return 0; }