diff --git a/winpr/include/winpr/collections.h b/winpr/include/winpr/collections.h index e4967888b..af058a769 100644 --- a/winpr/include/winpr/collections.h +++ b/winpr/include/winpr/collections.h @@ -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 */ -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 */ 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(wMessageQueue* queue); /*! \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 wObject* callback); /*! \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 } }, + 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; + struct _wPubSub + { + CRITICAL_SECTION lock; + BOOL synchronized; - int size; - int count; - wEventType* events; -}; -typedef struct _wPubSub wPubSub; + 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 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 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_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 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); + WINPR_API wPubSub* PubSub_New(BOOL synchronized); + WINPR_API void PubSub_Free(wPubSub* pubSub); -/* BipBuffer */ + /* BipBuffer */ -struct _wBipBlock -{ - size_t index; - size_t size; -}; -typedef struct _wBipBlock wBipBlock; + 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; + 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 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 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_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 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 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); + WINPR_API wBipBuffer* BipBuffer_New(size_t size); + WINPR_API void BipBuffer_Free(wBipBuffer* bb); #ifdef __cplusplus } diff --git a/winpr/libwinpr/utils/collections/LinkedList.c b/winpr/libwinpr/utils/collections/LinkedList.c index aafb32514..fee1e8046 100644 --- a/winpr/libwinpr/utils/collections/LinkedList.c +++ b/winpr/libwinpr/utils/collections/LinkedList.c @@ -23,6 +23,25 @@ #include +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 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; +}