Azure IoT common library

Fork of azure_c_shared_utility by Azure IoT

Revision:
30:ce3813c5a692
Parent:
21:b92006c5b9ff
diff -r e3ed192c35fb -r ce3813c5a692 singlylinkedlist.c
--- a/singlylinkedlist.c	Fri Jun 30 10:42:00 2017 -0700
+++ b/singlylinkedlist.c	Fri Jul 14 16:38:40 2017 -0700
@@ -5,6 +5,7 @@
 #include "azure_c_shared_utility/gballoc.h"
 #include "azure_c_shared_utility/singlylinkedlist.h"
 #include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
 
 typedef struct LIST_ITEM_INSTANCE_TAG
 {
@@ -59,6 +60,7 @@
     if ((list == NULL) ||
         (item == NULL))
     {
+		LogError("Invalid argument (list=%p, item=%p)", list, item);
         result = NULL;
     }
     else
@@ -105,6 +107,7 @@
 	if ((list == NULL) ||
         (item == NULL))
     {
+		LogError("Invalid argument (list=%p, item=%p)", list, item);
         result = __FAILURE__;
     }
     else
@@ -156,7 +159,8 @@
     if (list == NULL)
     {
         /* Codes_SRS_LIST_01_009: [If the list argument is NULL, singlylinkedlist_get_head_item shall return NULL.] */
-        result = NULL;
+		LogError("Invalid argument (list=NULL)");
+		result = NULL;
     }
     else
     {
@@ -176,6 +180,7 @@
 
     if (item_handle == NULL)
     {
+		LogError("Invalid argument (list is NULL)");
         /* Codes_SRS_LIST_01_019: [If item_handle is NULL then singlylinkedlist_get_next_item shall return NULL.] */
         result = NULL;
     }
@@ -194,6 +199,7 @@
 
     if (item_handle == NULL)
     {
+		LogError("Invalid argument (item_handle is NULL)");
         /* Codes_SRS_LIST_01_021: [If item_handle is NULL, singlylinkedlist_item_get_value shall return NULL.] */
         result = NULL;
     }
@@ -213,6 +219,7 @@
     if ((list == NULL) ||
         (match_function == NULL))
     {
+		LogError("Invalid argument (list=%p, match_function=%p)", list, match_function);
         /* Codes_SRS_LIST_01_012: [If the list or the match_function argument is NULL, singlylinkedlist_find shall return NULL.] */
         result = NULL;
     }
@@ -249,3 +256,103 @@
 
     return result;
 }
+
+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 = __FAILURE__;
+	}
+	else
+	{
+		LIST_INSTANCE* 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 = (LIST_ITEM_INSTANCE*)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;
+				}
+
+				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;
+}
+
+int singlylinkedlist_foreach(SINGLYLINKEDLIST_HANDLE list, LIST_ACTION_FUNCTION action_function, const void* action_context)
+{
+	int result;
+
+	/* Codes_SRS_LIST_09_008: [ If the list or the action_function argument is NULL, singlylinkedlist_foreach shall return non-zero value. ] */
+	if ((list == NULL) ||
+		(action_function == NULL))
+	{
+		LogError("Invalid argument (list=%p, action_function=%p)", list, action_function);
+		result = __FAILURE__;
+	}
+	else
+	{
+		LIST_INSTANCE* list_instance = (LIST_INSTANCE*)list;
+		LIST_ITEM_INSTANCE* list_item = list_instance->head;
+
+		while (list_item != NULL)
+		{
+			bool continue_processing = false;
+
+			/* Codes_SRS_LIST_09_009: [ singlylinkedlist_foreach shall iterate through all items in a list and invoke action_function for each one of them. ] */
+			action_function(list_item->item, action_context, &continue_processing);
+
+			/* Codes_SRS_LIST_09_010: [ If the condition function returns continue_processing as false, singlylinkedlist_foreach shall stop iterating through the list and return. ] */
+			if (continue_processing == false)
+			{
+				break;
+			}
+
+			list_item = (LIST_ITEM_INSTANCE*)list_item->next;
+		}
+
+		/* Codes_SRS_LIST_09_011: [ If no errors occur, singlylinkedlist_foreach shall return zero. ] */
+		result = 0;
+	}
+
+	return result;
+}
\ No newline at end of file