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 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; }