Implemented linked list compare and value copy functions.
authorArmin Novak <armin.novak@thincast.com>
Wed, 22 Aug 2018 10:33:34 +0000 (12:33 +0200)
committerArmin Novak <armin.novak@thincast.com>
Wed, 22 Aug 2018 10:39:11 +0000 (12:39 +0200)
winpr/include/winpr/collections.h
winpr/libwinpr/utils/collections/LinkedList.c

index e496788..af058a7 100644 (file)
@@ -35,7 +35,9 @@
 extern "C" {
 #endif
 
-typedef void* (*OBJECT_NEW_FN)(void);
+/* We don't know if the new function will require an argument.
+ * Leave the braces empty, C defines that as variable arguments. */
+typedef void* (*OBJECT_NEW_FN)();
 typedef void (*OBJECT_INIT_FN)(void* obj);
 typedef void (*OBJECT_UNINIT_FN)(void* obj);
 typedef void (*OBJECT_FREE_FN)(void* obj);
@@ -222,23 +224,6 @@ WINPR_API void ListDictionary_Free(wListDictionary* listDictionary);
 
 /* System.Collections.Generic.LinkedList<T> */
 
-typedef struct _wLinkedListItem wLinkedListNode;
-
-struct _wLinkedListItem
-{
-       void* value;
-       wLinkedListNode* prev;
-       wLinkedListNode* next;
-};
-
-struct _wLinkedList
-{
-       int count;
-       int initial;
-       wLinkedListNode* head;
-       wLinkedListNode* tail;
-       wLinkedListNode* current;
-};
 typedef struct _wLinkedList wLinkedList;
 
 WINPR_API int LinkedList_Count(wLinkedList* list);
@@ -262,6 +247,8 @@ WINPR_API BOOL LinkedList_Enumerator_MoveNext(wLinkedList* list);
 WINPR_API wLinkedList* LinkedList_New(void);
 WINPR_API void LinkedList_Free(wLinkedList* list);
 
+WINPR_API wObject* LinkedList_Object(wLinkedList* list);
+
 /* System.Collections.Generic.KeyValuePair<TKey,TValue> */
 
 typedef struct _wKeyValuePair wKeyValuePair;
@@ -299,7 +286,8 @@ typedef struct _wReferenceTable wReferenceTable;
 WINPR_API UINT32 ReferenceTable_Add(wReferenceTable* referenceTable, void* ptr);
 WINPR_API UINT32 ReferenceTable_Release(wReferenceTable* referenceTable, void* ptr);
 
-WINPR_API wReferenceTable* ReferenceTable_New(BOOL synchronized, void* context, REFERENCE_FREE ReferenceFree);
+WINPR_API wReferenceTable* ReferenceTable_New(BOOL synchronized, void* context,
+        REFERENCE_FREE ReferenceFree);
 WINPR_API void ReferenceTable_Free(wReferenceTable* referenceTable);
 
 /* Countdown Event */
@@ -327,7 +315,7 @@ WINPR_API void CountdownEvent_Free(wCountdownEvent* countdown);
 
 /* Hash Table */
 
-typedef UINT32 (*HASH_TABLE_HASH_FN)(void* key);
+typedef UINT32(*HASH_TABLE_HASH_FN)(void* key);
 typedef BOOL (*HASH_TABLE_KEY_COMPARE_FN)(void* key1, void* key2);
 typedef BOOL (*HASH_TABLE_VALUE_COMPARE_FN)(void* value1, void* value2);
 typedef void* (*HASH_TABLE_KEY_CLONE_FN)(void* key);
@@ -478,7 +466,8 @@ WINPR_API BOOL MessageQueue_Wait(wMessageQueue* queue);
 WINPR_API int MessageQueue_Size(wMessageQueue* queue);
 
 WINPR_API BOOL MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message);
-WINPR_API BOOL MessageQueue_Post(wMessageQueue* queue, void* context, UINT32 type, void* wParam, void* lParam);
+WINPR_API BOOL MessageQueue_Post(wMessageQueue* queue, void* context, UINT32 type, void* wParam,
+                                 void* lParam);
 WINPR_API BOOL MessageQueue_PostQuit(wMessageQueue* queue, int nExitCode);
 
 WINPR_API int MessageQueue_Get(wMessageQueue* queue, wMessage* message);
@@ -494,7 +483,7 @@ WINPR_API int MessageQueue_Peek(wMessageQueue* queue, wMessage* message, BOOL re
  *
  *  \return 0 in case of success or a error code otherwise.
  */
-WINPR_API int MessageQueue_Clear(wMessageQueue *queue);
+WINPR_API int MessageQueue_Clear(wMessageQueuequeue);
 
 /*! \brief Creates a new message queue.
  *                              If 'callback' is null, no custom cleanup will be done
@@ -508,7 +497,7 @@ WINPR_API int MessageQueue_Clear(wMessageQueue *queue);
  *
  * \return A pointer to a newly allocated MessageQueue or NULL.
  */
-WINPR_API wMessageQueue* MessageQueue_New(const wObject *callback);
+WINPR_API wMessageQueue* MessageQueue_New(const wObjectcallback);
 
 /*! \brief Frees resources allocated by a message queue.
  *                              This function will only free resources allocated
@@ -581,7 +570,7 @@ typedef struct _wEventType wEventType;
 
 #define DEFINE_EVENT_BEGIN(_name) \
        typedef struct _ ## _name ## EventArgs { \
-       wEventArgs e;
+               wEventArgs e;
 
 #define DEFINE_EVENT_END(_name) \
        } _name ## EventArgs; \
@@ -592,77 +581,78 @@ typedef struct _wEventType wEventType;
 
 #define DEFINE_EVENT_ENTRY(_name) \
        { #_name, { sizeof( _name ## EventArgs) }, 0, { \
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, \
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, \
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, \
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } },
-
-struct _wPubSub
-{
-       CRITICAL_SECTION lock;
-       BOOL synchronized;
-
-       int size;
-       int count;
-       wEventType* events;
-};
-typedef struct _wPubSub wPubSub;
-
-WINPR_API void PubSub_Lock(wPubSub* pubSub);
-WINPR_API void PubSub_Unlock(wPubSub* pubSub);
-
-WINPR_API wEventType* PubSub_GetEventTypes(wPubSub* pubSub, int* count);
-WINPR_API void PubSub_AddEventTypes(wPubSub* pubSub, wEventType* events, int count);
-WINPR_API wEventType* PubSub_FindEventType(wPubSub* pubSub, const char* EventName);
-
-WINPR_API int PubSub_Subscribe(wPubSub* pubSub, const char* EventName, pEventHandler EventHandler);
-WINPR_API int PubSub_Unsubscribe(wPubSub* pubSub, const char* EventName, pEventHandler EventHandler);
-
-WINPR_API int PubSub_OnEvent(wPubSub* pubSub, const char* EventName, void* context, wEventArgs* e);
-
-WINPR_API wPubSub* PubSub_New(BOOL synchronized);
-WINPR_API void PubSub_Free(wPubSub* pubSub);
-
-/* BipBuffer */
-
-struct _wBipBlock
-{
-       size_t index;
-       size_t size;
-};
-typedef struct _wBipBlock wBipBlock;
-
-struct _wBipBuffer
-{
-       size_t size;
-       BYTE* buffer;
-       size_t pageSize;
-       wBipBlock blockA;
-       wBipBlock blockB;
-       wBipBlock readR;
-       wBipBlock writeR;
-};
-typedef struct _wBipBuffer wBipBuffer;
-
-WINPR_API BOOL BipBuffer_Grow(wBipBuffer* bb, size_t size);
-WINPR_API void BipBuffer_Clear(wBipBuffer* bb);
-
-WINPR_API size_t BipBuffer_UsedSize(wBipBuffer* bb);
-WINPR_API size_t BipBuffer_BufferSize(wBipBuffer* bb);
-
-WINPR_API BYTE* BipBuffer_WriteReserve(wBipBuffer* bb, size_t size);
-WINPR_API BYTE* BipBuffer_WriteTryReserve(wBipBuffer* bb, size_t size, size_t* reserved);
-WINPR_API void BipBuffer_WriteCommit(wBipBuffer* bb, size_t size);
-
-WINPR_API BYTE* BipBuffer_ReadReserve(wBipBuffer* bb, size_t size);
-WINPR_API BYTE* BipBuffer_ReadTryReserve(wBipBuffer* bb, size_t size, size_t* reserved);
-WINPR_API void BipBuffer_ReadCommit(wBipBuffer* bb, size_t size);
-
-WINPR_API int BipBuffer_Read(wBipBuffer* bb, BYTE* data, size_t size);
-WINPR_API int BipBuffer_Write(wBipBuffer* bb, BYTE* data, size_t size);
-
-WINPR_API wBipBuffer* BipBuffer_New(size_t size);
-WINPR_API void BipBuffer_Free(wBipBuffer* bb);
+                       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, \
+                       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, \
+                       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, \
+                       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } },
+
+       struct _wPubSub
+       {
+               CRITICAL_SECTION lock;
+               BOOL synchronized;
+
+               int size;
+               int count;
+               wEventType* events;
+       };
+       typedef struct _wPubSub wPubSub;
+
+       WINPR_API void PubSub_Lock(wPubSub* pubSub);
+       WINPR_API void PubSub_Unlock(wPubSub* pubSub);
+
+       WINPR_API wEventType* PubSub_GetEventTypes(wPubSub* pubSub, int* count);
+       WINPR_API void PubSub_AddEventTypes(wPubSub* pubSub, wEventType* events, int count);
+       WINPR_API wEventType* PubSub_FindEventType(wPubSub* pubSub, const char* EventName);
+
+       WINPR_API int PubSub_Subscribe(wPubSub* pubSub, const char* EventName, pEventHandler EventHandler);
+       WINPR_API int PubSub_Unsubscribe(wPubSub* pubSub, const char* EventName,
+                                        pEventHandler EventHandler);
+
+       WINPR_API int PubSub_OnEvent(wPubSub* pubSub, const char* EventName, void* context, wEventArgs* e);
+
+       WINPR_API wPubSub* PubSub_New(BOOL synchronized);
+       WINPR_API void PubSub_Free(wPubSub* pubSub);
+
+       /* BipBuffer */
+
+       struct _wBipBlock
+       {
+               size_t index;
+               size_t size;
+       };
+       typedef struct _wBipBlock wBipBlock;
+
+       struct _wBipBuffer
+       {
+               size_t size;
+               BYTE* buffer;
+               size_t pageSize;
+               wBipBlock blockA;
+               wBipBlock blockB;
+               wBipBlock readR;
+               wBipBlock writeR;
+       };
+       typedef struct _wBipBuffer wBipBuffer;
+
+       WINPR_API BOOL BipBuffer_Grow(wBipBuffer* bb, size_t size);
+       WINPR_API void BipBuffer_Clear(wBipBuffer* bb);
+
+       WINPR_API size_t BipBuffer_UsedSize(wBipBuffer* bb);
+       WINPR_API size_t BipBuffer_BufferSize(wBipBuffer* bb);
+
+       WINPR_API BYTE* BipBuffer_WriteReserve(wBipBuffer* bb, size_t size);
+       WINPR_API BYTE* BipBuffer_WriteTryReserve(wBipBuffer* bb, size_t size, size_t* reserved);
+       WINPR_API void BipBuffer_WriteCommit(wBipBuffer* bb, size_t size);
+
+       WINPR_API BYTE* BipBuffer_ReadReserve(wBipBuffer* bb, size_t size);
+       WINPR_API BYTE* BipBuffer_ReadTryReserve(wBipBuffer* bb, size_t size, size_t* reserved);
+       WINPR_API void BipBuffer_ReadCommit(wBipBuffer* bb, size_t size);
+
+       WINPR_API int BipBuffer_Read(wBipBuffer* bb, BYTE* data, size_t size);
+       WINPR_API int BipBuffer_Write(wBipBuffer* bb, BYTE* data, size_t size);
+
+       WINPR_API wBipBuffer* BipBuffer_New(size_t size);
+       WINPR_API void BipBuffer_Free(wBipBuffer* bb);
 
 #ifdef __cplusplus
 }
index aafb325..fee1e80 100644 (file)
 
 #include <winpr/collections.h>
 
+typedef struct _wLinkedListItem wLinkedListNode;
+
+struct _wLinkedListItem
+{
+       void* value;
+       wLinkedListNode* prev;
+       wLinkedListNode* next;
+};
+
+struct _wLinkedList
+{
+       int count;
+       int initial;
+       wLinkedListNode* head;
+       wLinkedListNode* tail;
+       wLinkedListNode* current;
+       wObject object;
+};
+
 /**
  * C equivalent of the C# LinkedList<T> Class:
  * http://msdn.microsoft.com/en-us/library/he2s3bh7.aspx
@@ -78,15 +97,17 @@ void* LinkedList_Last(wLinkedList* list)
 BOOL LinkedList_Contains(wLinkedList* list, void* value)
 {
        wLinkedListNode* item;
+       OBJECT_EQUALS_FN keyEquals;
 
        if (!list->head)
                return FALSE;
 
        item = list->head;
+       keyEquals = list->object.fnObjectEquals;
 
        while (item)
        {
-               if (item->value == value)
+               if (keyEquals(item->value, value))
                        break;
 
                item = item->next;
@@ -95,6 +116,34 @@ BOOL LinkedList_Contains(wLinkedList* list, void* value)
        return (item) ? TRUE : FALSE;
 }
 
+static wLinkedListNode* LinkedList_FreeNode(wLinkedList* list, wLinkedListNode* node)
+{
+       wLinkedListNode* next = node->next;
+       wLinkedListNode* prev = node->prev;
+
+       if (prev)
+               prev->next = next;
+
+       if (next)
+               next->prev = prev;
+
+       if (node == list->head)
+               list->head = node->next;
+
+       if (node == list->tail)
+               list->tail = node->prev;
+
+       if (list->object.fnObjectUninit)
+               list->object.fnObjectUninit(node);
+
+       if (list->object.fnObjectFree)
+               list->object.fnObjectFree(node);
+
+       free(node);
+       list->count--;
+       return next;
+}
+
 /**
  * Removes all entries from the LinkedList.
  */
@@ -102,7 +151,6 @@ BOOL LinkedList_Contains(wLinkedList* list, void* value)
 void LinkedList_Clear(wLinkedList* list)
 {
        wLinkedListNode* node;
-       wLinkedListNode* nextNode;
 
        if (!list->head)
                return;
@@ -110,29 +158,39 @@ void LinkedList_Clear(wLinkedList* list)
        node = list->head;
 
        while (node)
-       {
-               nextNode = node->next;
-               free(node);
-               node = nextNode;
-       }
+               node = LinkedList_FreeNode(list, node);
 
        list->head = list->tail = NULL;
        list->count = 0;
 }
 
+static wLinkedListNode* LinkedList_Create(wLinkedList* list, void* value)
+{
+       wLinkedListNode* node = (wLinkedListNode*) calloc(1, sizeof(wLinkedListNode));
+
+       if (!node)
+               return NULL;
+
+       if (list->object.fnObjectNew)
+               node->value = list->object.fnObjectNew(value);
+       else
+               node->value = value;
+
+       if (list->object.fnObjectInit)
+               list->object.fnObjectInit(node);
+
+       return node;
+}
 /**
  * Adds a new node containing the specified value at the start of the LinkedList.
  */
 
 BOOL LinkedList_AddFirst(wLinkedList* list, void* value)
 {
-       wLinkedListNode* node;
+       wLinkedListNode* node = LinkedList_Create(list, value);
 
-       node = (wLinkedListNode*) malloc(sizeof(wLinkedListNode));
        if (!node)
                return FALSE;
-       node->prev = node->next = NULL;
-       node->value = value;
 
        if (!list->head)
        {
@@ -155,13 +213,10 @@ BOOL LinkedList_AddFirst(wLinkedList* list, void* value)
 
 BOOL LinkedList_AddLast(wLinkedList* list, void* value)
 {
-       wLinkedListNode* node;
+       wLinkedListNode* node = LinkedList_Create(list, value);
 
-       node = (wLinkedListNode*) malloc(sizeof(wLinkedListNode));
        if (!node)
                return FALSE;
-       node->prev = node->next = NULL;
-       node->value = value;
 
        if (!list->tail)
        {
@@ -185,33 +240,21 @@ BOOL LinkedList_AddLast(wLinkedList* list, void* value)
 BOOL LinkedList_Remove(wLinkedList* list, void* value)
 {
        wLinkedListNode* node;
-
+       OBJECT_EQUALS_FN keyEquals;
+       keyEquals = list->object.fnObjectEquals;
        node = list->head;
 
        while (node)
        {
-               if (node->value == value)
+               if (keyEquals(node->value, value))
                {
-                       if (node->prev)
-                               node->prev->next = node->next;
-
-                       if (node->next)
-                               node->next->prev = node->prev;
-
-                       if (node == list->head)
-                               list->head = node->next;
-
-                       if (node == list->tail)
-                               list->tail = node->prev;
-
-                       free(node);
-
-                       list->count--;
+                       LinkedList_FreeNode(list, node);
                        return TRUE;
                }
 
                node = node->next;
        }
+
        return FALSE;
 }
 
@@ -221,27 +264,8 @@ BOOL LinkedList_Remove(wLinkedList* list, void* value)
 
 void LinkedList_RemoveFirst(wLinkedList* list)
 {
-       wLinkedListNode* node;
-
        if (list->head)
-       {
-               node = list->head;
-
-               list->head = list->head->next;
-
-               if (!list->head)
-               {
-                       list->tail = NULL;
-               }
-               else
-               {
-                       list->head->prev = NULL;
-               }
-
-               free(node);
-
-               list->count--;
-       }
+               LinkedList_FreeNode(list, list->head);
 }
 
 /**
@@ -250,27 +274,8 @@ void LinkedList_RemoveFirst(wLinkedList* list)
 
 void LinkedList_RemoveLast(wLinkedList* list)
 {
-       wLinkedListNode* node;
-
        if (list->tail)
-       {
-               node = list->tail;
-
-               list->tail = list->tail->prev;
-
-               if (!list->tail)
-               {
-                       list->head = NULL;
-               }
-               else
-               {
-                       list->tail->next = NULL;
-               }
-
-               free(node);
-
-               list->count--;
-       }
+               LinkedList_FreeNode(list, list->tail);
 }
 
 /**
@@ -315,16 +320,25 @@ BOOL LinkedList_Enumerator_MoveNext(wLinkedList* list)
        return TRUE;
 }
 
+static BOOL default_equal_function(void* objA, void* objB)
+{
+       return objA == objB;
+}
+
 /**
  * Construction, Destruction
  */
 
-wLinkedList* LinkedList_New()
+wLinkedList* LinkedList_New(void)
 {
        wLinkedList* list = NULL;
-
        list = (wLinkedList*) calloc(1, sizeof(wLinkedList));
 
+       if (list)
+       {
+               list->object.fnObjectEquals = default_equal_function;
+       }
+
        return list;
 }
 
@@ -337,3 +351,10 @@ void LinkedList_Free(wLinkedList* list)
        }
 }
 
+wObject* LinkedList_Object(wLinkedList* list)
+{
+       if (!list)
+               return NULL;
+
+       return &list->object;
+}