diff --git a/winpr/include/winpr/collections.h b/winpr/include/winpr/collections.h index 03d06a9a8..4ef2e3b19 100644 --- a/winpr/include/winpr/collections.h +++ b/winpr/include/winpr/collections.h @@ -171,13 +171,39 @@ typedef struct _wDictionary wDictionary; /* System.Collections.Specialized.ListDictionary */ +typedef struct _wListDictionaryItem wListDictionaryItem; + +struct _wListDictionaryItem +{ + void* key; + void* value; + + wListDictionaryItem* next; +}; + struct _wListDictionary { BOOL synchronized; HANDLE mutex; + + wListDictionaryItem* head; }; typedef struct _wListDictionary wListDictionary; +WINPR_API int ListDictionary_Count(wListDictionary* listDictionary); + +WINPR_API void ListDictionary_Add(wListDictionary* listDictionary, void* key, void* value); +WINPR_API void ListDictionary_Remove(wListDictionary* listDictionary, void* key); +WINPR_API void ListDictionary_Clear(wListDictionary* listDictionary); + +WINPR_API BOOL ListDictionary_Contains(wListDictionary* listDictionary, void* key); + +WINPR_API void* ListDictionary_GetItemValue(wListDictionary* listDictionary, void* key); +WINPR_API BOOL ListDictionary_SetItemValue(wListDictionary* listDictionary, void* key, void* value); + +WINPR_API wListDictionary* ListDictionary_New(BOOL synchronized); +WINPR_API void ListDictionary_Free(wListDictionary* listDictionary); + /* System.Collections.Generic.KeyValuePair */ struct _wKeyValuePair diff --git a/winpr/libwinpr/utils/collections/ListDictionary.c b/winpr/libwinpr/utils/collections/ListDictionary.c index 2216384a7..d097035ef 100644 --- a/winpr/libwinpr/utils/collections/ListDictionary.c +++ b/winpr/libwinpr/utils/collections/ListDictionary.c @@ -26,6 +26,8 @@ /** * C equivalent of the C# ListDictionary Class: * http://msdn.microsoft.com/en-us/library/system.collections.specialized.listdictionary.aspx + * + * Internal implementation uses a singly-linked list */ /** @@ -38,7 +40,21 @@ int ListDictionary_Count(wListDictionary* listDictionary) { - return 0; + int count = 0; + wListDictionaryItem* item; + + if (!listDictionary->head) + return 0; + + item = listDictionary->head; + + while (item) + { + count++; + item = item->next; + } + + return count; } /** @@ -78,7 +94,28 @@ BOOL ListDictionary_IsSynchronized(wListDictionary* listDictionary) void ListDictionary_Add(wListDictionary* listDictionary, void* key, void* value) { + wListDictionaryItem* item; + wListDictionaryItem* lastItem; + item = (wListDictionaryItem*) malloc(sizeof(wListDictionaryItem)); + + item->key = key; + item->value = value; + + item->next = NULL; + + if (!listDictionary->head) + { + listDictionary->head = item; + return; + } + + lastItem = listDictionary->head; + + while (lastItem->next) + lastItem = lastItem->next; + + lastItem->next = item; } /** @@ -87,7 +124,22 @@ void ListDictionary_Add(wListDictionary* listDictionary, void* key, void* value) void ListDictionary_Clear(wListDictionary* listDictionary) { + wListDictionaryItem* item; + wListDictionaryItem* nextItem; + if (!listDictionary->head) + return; + + item = listDictionary->head; + + while (item) + { + nextItem = item->next; + free(item); + item = nextItem; + } + + listDictionary->head = NULL; } /** @@ -96,7 +148,22 @@ void ListDictionary_Clear(wListDictionary* listDictionary) BOOL ListDictionary_Contains(wListDictionary* listDictionary, void* key) { - return FALSE; + wListDictionaryItem* item; + + if (!listDictionary->head) + return FALSE; + + item = listDictionary->head; + + while (item) + { + if (item->key == key) + break; + + item = item->next; + } + + return (item) ? TRUE : FALSE; } /** @@ -105,7 +172,89 @@ BOOL ListDictionary_Contains(wListDictionary* listDictionary, void* key) void ListDictionary_Remove(wListDictionary* listDictionary, void* key) { + wListDictionaryItem* item; + wListDictionaryItem* prevItem; + if (!listDictionary->head) + return; + + item = listDictionary->head; + + if (listDictionary->head->key == key) + { + listDictionary->head = listDictionary->head->next; + free(item); + return; + } + + if (!item->next) + return; + + prevItem = item; + item = item->next; + + while (item) + { + if (item->key == key) + { + prevItem->next = item->next; + free(item); + break; + } + + item = item->next; + } +} + +/** + * Get an item value using key + */ + +void* ListDictionary_GetItemValue(wListDictionary* listDictionary, void* key) +{ + wListDictionaryItem* item; + + if (!listDictionary->head) + return NULL; + + item = listDictionary->head; + + while (item) + { + if (item->key == key) + break; + + item = item->next; + } + + return (item) ? item->value : NULL; +} + +/** + * Set an item value using key + */ + +BOOL ListDictionary_SetItemValue(wListDictionary* listDictionary, void* key, void* value) +{ + wListDictionaryItem* item; + + if (!listDictionary->head) + return FALSE; + + item = listDictionary->head; + + while (item) + { + if (item->key == key) + break; + + item = item->next; + } + + if (item) + item->value = value; + + return (item) ? TRUE : FALSE; } /** @@ -121,6 +270,8 @@ wListDictionary* ListDictionary_New(BOOL synchronized) if (listDictionary) { listDictionary->synchronized = synchronized; + + listDictionary->head = NULL; } return listDictionary; @@ -128,6 +279,10 @@ wListDictionary* ListDictionary_New(BOOL synchronized) void ListDictionary_Free(wListDictionary* listDictionary) { - free(listDictionary); + if (listDictionary) + { + ListDictionary_Clear(listDictionary); + free(listDictionary); + } } diff --git a/winpr/libwinpr/utils/test/CMakeLists.txt b/winpr/libwinpr/utils/test/CMakeLists.txt index 2656109b0..1455779ef 100644 --- a/winpr/libwinpr/utils/test/CMakeLists.txt +++ b/winpr/libwinpr/utils/test/CMakeLists.txt @@ -9,6 +9,7 @@ set(${MODULE_PREFIX}_TESTS TestPrint.c TestPubSub.c TestArrayList.c + TestListDictionary.c TestCmdLine.c TestStreamPool.c TestMessageQueue.c diff --git a/winpr/libwinpr/utils/test/TestListDictionary.c b/winpr/libwinpr/utils/test/TestListDictionary.c new file mode 100644 index 000000000..133271c23 --- /dev/null +++ b/winpr/libwinpr/utils/test/TestListDictionary.c @@ -0,0 +1,130 @@ + +#include +#include +#include + +static char* key1 = "key1"; +static char* key2 = "key2"; +static char* key3 = "key3"; + +static char* val1 = "val1"; +static char* val2 = "val2"; +static char* val3 = "val3"; + +int TestListDictionary(int argc, char* argv[]) +{ + int count; + char* value; + wListDictionary* list; + + list = ListDictionary_New(FALSE); + + ListDictionary_Add(list, key1, val1); + ListDictionary_Add(list, key2, val2); + ListDictionary_Add(list, key3, val3); + + count = ListDictionary_Count(list); + + if (count != 3) + { + printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 3, count); + return -1; + } + + ListDictionary_Remove(list, key2); + + count = ListDictionary_Count(list); + + if (count != 2) + { + printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 2, count); + return -1; + } + + ListDictionary_Remove(list, key3); + + count = ListDictionary_Count(list); + + if (count != 1) + { + printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 1, count); + return -1; + } + + ListDictionary_Remove(list, key1); + + count = ListDictionary_Count(list); + + if (count != 0) + { + printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 0, count); + return -1; + } + + ListDictionary_Add(list, key1, val1); + ListDictionary_Add(list, key2, val2); + ListDictionary_Add(list, key3, val3); + + count = ListDictionary_Count(list); + + if (count != 3) + { + printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 3, count); + return -1; + } + + value = (char*) ListDictionary_GetItemValue(list, key1); + + if (strcmp(value, val1) != 0) + { + printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", val1, value); + return -1; + } + + value = (char*) ListDictionary_GetItemValue(list, key2); + + if (strcmp(value, val2) != 0) + { + printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", val2, value); + return -1; + } + + value = (char*) ListDictionary_GetItemValue(list, key3); + + if (strcmp(value, val3) != 0) + { + printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", val3, value); + return -1; + } + + ListDictionary_SetItemValue(list, key2, "apple"); + + value = (char*) ListDictionary_GetItemValue(list, key2); + + if (strcmp(value, "apple") != 0) + { + printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", "apple", value); + return -1; + } + + if (!ListDictionary_Contains(list, key2)) + { + printf("ListDictionary_Contains: Expected : %d, Actual: %d\n", TRUE, FALSE); + return -1; + } + + ListDictionary_Clear(list); + + count = ListDictionary_Count(list); + + if (count != 0) + { + printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 0, count); + return -1; + } + + ListDictionary_Free(list); + + return 0; +} +