int singlylinkedlist_remove_if()

in src/singlylinkedlist.c [270:334]


int singlylinkedlist_remove_if(SINGLYLINKEDLIST_HANDLE list, LIST_CONDITION_FUNCTION condition_function, const void* match_context)
{
    int result;
    /* Codes_SRS_LIST_09_001: [ If the list or the condition_function argument is NULL, singlylinkedlist_remove_if shall return non-zero value. ] */
    if ((list == NULL) ||
        (condition_function == NULL))
    {
        LogError("Invalid argument (list=%p, condition_function=%p)", list, condition_function);
        result = MU_FAILURE;
    }
    else
    {
        LIST_INSTANCE* list_instance = list;
        LIST_ITEM_INSTANCE* current_item = list_instance->head;
        LIST_ITEM_INSTANCE* next_item = NULL;
        LIST_ITEM_INSTANCE* previous_item = NULL;

        /* Codes_SRS_LIST_09_002: [ singlylinkedlist_remove_if shall iterate through all items in a list and remove all that satisfies a certain condition function. ] */
        while (current_item != NULL)
        {
            bool continue_processing = false;

            next_item = current_item->next;

            /* Codes_SRS_LIST_09_003: [ singlylinkedlist_remove_if shall determine whether an item satisfies the condition criteria by invoking the condition function for that item. ] */
            /* Codes_SRS_LIST_09_004: [ If the condition function returns true, singlylinkedlist_find shall consider that item as to be removed. ] */
            if (condition_function(current_item->item, match_context, &continue_processing) == true)
            {
                if (previous_item != NULL)
                {
                    previous_item->next = next_item;
                }
                else
                {
                    list_instance->head = next_item;
                }

                if (current_item == list_instance->tail)
                {
                    list_instance->tail = previous_item;
                }

                free(current_item);
            }
            /* Codes_SRS_LIST_09_005: [ If the condition function returns false, singlylinkedlist_find shall consider that item as not to be removed. ] */
            else
            {
                previous_item = current_item;
            }

            /* Codes_SRS_LIST_09_006: [ If the condition function returns continue_processing as false, singlylinkedlist_remove_if shall stop iterating through the list and return. ] */
            if (continue_processing == false)
            {
                break;
            }

            current_item = next_item;
        }

        /* Codes_SRS_LIST_09_007: [ If no errors occur, singlylinkedlist_remove_if shall return zero. ] */
        result = 0;
    }

    return result;
}