Modified HashTable API to be opaque

* Reuse wObject function pointers
* Add missing getters/setters
* Clean up return types, const correctness of arguments
This commit is contained in:
Armin Novak 2021-05-17 09:40:18 +02:00 committed by akallabeth
parent 3a75228242
commit cb642699c8
8 changed files with 324 additions and 238 deletions

View File

@ -72,13 +72,16 @@ struct _GEOMETRY_PLUGIN
};
typedef struct _GEOMETRY_PLUGIN GEOMETRY_PLUGIN;
static UINT32 mappedGeometryHash(UINT64* g)
static UINT32 mappedGeometryHash(const void* v)
{
const UINT64* g = (const UINT64*)v;
return (UINT32)((*g >> 32) + (*g & 0xffffffff));
}
static BOOL mappedGeometryKeyCompare(UINT64* g1, UINT64* g2)
static BOOL mappedGeometryKeyCompare(const void* v1, const void* v2)
{
const UINT64* g1 = (UINT64*)v1;
const UINT64* g2 = (UINT64*)v2;
return *g1 == *g2;
}
@ -433,6 +436,12 @@ static UINT geometry_plugin_terminated(IWTSPlugin* pPlugin)
return CHANNEL_RC_OK;
}
static void mappedGeometryUnref_void(void* arg)
{
MAPPED_GEOMETRY* g = (MAPPED_GEOMETRY*)arg;
mappedGeometryUnref(g);
}
/**
* Channel Client Interface
*/
@ -478,9 +487,15 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
}
context->geometries = HashTable_New(FALSE);
context->geometries->hash = (HASH_TABLE_HASH_FN)mappedGeometryHash;
context->geometries->keyCompare = (HASH_TABLE_KEY_COMPARE_FN)mappedGeometryKeyCompare;
context->geometries->valueFree = (HASH_TABLE_VALUE_FREE_FN)mappedGeometryUnref;
HashTable_SetHashFunction(context->geometries, mappedGeometryHash);
{
wObject* obj = HashTable_KeyObject(context->geometries);
obj->fnObjectEquals = mappedGeometryKeyCompare;
}
{
wObject* obj = HashTable_ValueObject(context->geometries);
obj->fnObjectFree = mappedGeometryUnref_void;
}
context->handle = (void*)geometry;
geometry->iface.pInterface = (void*)context;

View File

@ -1782,10 +1782,16 @@ static BOOL xf_cliprdr_fuse_create_nodes(xfClipboard* clipboard, wStream* s, siz
WLog_ERR(TAG, "fail to alloc hashtable");
return FALSE;
}
mapDir->keyFree = HashTable_StringFree;
mapDir->keyClone = HashTable_StringClone;
mapDir->keyCompare = HashTable_StringCompare;
mapDir->hash = HashTable_StringHash;
if (!HashTable_SetHashFunction(mapDir, HashTable_StringHash))
goto error;
{
wObject* obj = HashTable_KeyObject(mapDir);
if (!obj)
goto error;
obj->fnObjectNew = HashTable_StringClone;
obj->fnObjectFree = HashTable_StringFree;
obj->fnObjectEquals = HashTable_StringCompare;
}
FILEDESCRIPTORW* descriptor = (FILEDESCRIPTORW*)calloc(1, sizeof(FILEDESCRIPTORW));
if (!descriptor)

View File

@ -1051,7 +1051,7 @@ static UINT xf_rail_server_get_appid_response(RailClientContext* context,
return CHANNEL_RC_OK;
}
static BOOL rail_window_key_equals(void* key1, void* key2)
static BOOL rail_window_key_equals(const void* key1, const void* key2)
{
const UINT64* k1 = (const UINT64*)key1;
const UINT64* k2 = (const UINT64*)key2;
@ -1062,7 +1062,7 @@ static BOOL rail_window_key_equals(void* key1, void* key2)
return *k1 == *k2;
}
static UINT32 rail_window_key_hash(void* key)
static UINT32 rail_window_key_hash(const void* key)
{
const UINT64* k1 = (const UINT64*)key;
return (UINT32)*k1;
@ -1101,18 +1101,30 @@ int xf_rail_init(xfContext* xfc, RailClientContext* rail)
if (!xfc->railWindows)
return 0;
xfc->railWindows->keyCompare = rail_window_key_equals;
xfc->railWindows->hash = rail_window_key_hash;
xfc->railWindows->valueFree = rail_window_free;
if (!HashTable_SetHashFunction(xfc->railWindows, rail_window_key_hash))
goto fail;
{
wObject* obj = HashTable_KeyObject(xfc->railWindows);
if (!obj)
goto fail;
obj->fnObjectEquals = rail_window_key_equals;
}
{
wObject* obj = HashTable_ValueObject(xfc->railWindows);
if (!obj)
goto fail;
obj->fnObjectFree = rail_window_free;
}
xfc->railIconCache = RailIconCache_New(xfc->context.settings);
if (!xfc->railIconCache)
{
HashTable_Free(xfc->railWindows);
return 0;
}
return 1;
fail:
HashTable_Free(xfc->railWindows);
return 0;
}
int xf_rail_uninit(xfContext* xfc, RailClientContext* rail)

View File

@ -31,11 +31,13 @@ static wHashTable* create_channel_ids_map()
if (!table)
return NULL;
table->hash = HashTable_StringHash;
table->keyCompare = HashTable_StringCompare;
table->keyClone = HashTable_StringClone;
table->keyFree = HashTable_StringFree;
if (!HashTable_SetupForStringData(table, FALSE))
goto fail;
return table;
fail:
HashTable_Free(table);
return NULL;
}
/* Proxy context initialization callback */
@ -229,10 +231,8 @@ proxyData* proxy_data_new(void)
goto error;
/* modules_info maps between plugin name to custom data */
pdata->modules_info->hash = HashTable_StringHash;
pdata->modules_info->keyCompare = HashTable_StringCompare;
pdata->modules_info->keyClone = HashTable_StringClone;
pdata->modules_info->keyFree = HashTable_StringFree;
if (!HashTable_SetupForStringData(pdata->modules_info, FALSE))
goto error;
return pdata;
error:

View File

@ -229,19 +229,6 @@ extern "C"
/* System.Collections.Generic.KeyValuePair<TKey,TValue> */
typedef struct _wKeyValuePair wKeyValuePair;
/* WARNING: Do not access structs directly, the API will be reworked
* to make this opaque. */
struct _wKeyValuePair
{
void* key;
void* value;
wKeyValuePair* next;
BOOL markedForRemove;
};
/* Reference Table */
/* WARNING: Do not access structs directly, the API will be reworked
@ -302,66 +289,67 @@ extern "C"
/* Hash Table */
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);
typedef void* (*HASH_TABLE_VALUE_CLONE_FN)(void* value);
typedef void (*HASH_TABLE_KEY_FREE_FN)(void* key);
typedef void (*HASH_TABLE_VALUE_FREE_FN)(void* value);
typedef UINT32 (*HASH_TABLE_HASH_FN)(const void* key);
/* WARNING: Do not access structs directly, the API will be reworked
* to make this opaque. */
struct _wHashTable
{
BOOL synchronized;
CRITICAL_SECTION lock;
int numOfBuckets;
int numOfElements;
float idealRatio;
float lowerRehashThreshold;
float upperRehashThreshold;
wKeyValuePair** bucketArray;
HASH_TABLE_HASH_FN hash;
HASH_TABLE_KEY_COMPARE_FN keyCompare;
HASH_TABLE_VALUE_COMPARE_FN valueCompare;
HASH_TABLE_KEY_CLONE_FN keyClone;
HASH_TABLE_VALUE_CLONE_FN valueClone;
HASH_TABLE_KEY_FREE_FN keyFree;
HASH_TABLE_VALUE_FREE_FN valueFree;
DWORD foreachRecursionLevel;
DWORD pendingRemoves;
};
typedef struct _wHashTable wHashTable;
typedef BOOL (*HASH_TABLE_FOREACH_FN)(const void* key, void* value, void* arg);
typedef BOOL (*HASH_TABLE_FOREACH_FN)(const void* key, const void* value, void* arg);
WINPR_API int HashTable_Count(wHashTable* table);
WINPR_API int HashTable_Add(wHashTable* table, void* key, void* value);
WINPR_API BOOL HashTable_Remove(wHashTable* table, void* key);
WINPR_API size_t HashTable_Count(wHashTable* table);
WINPR_API BOOL HashTable_Add(wHashTable* table, const void* key, const void* value);
WINPR_API BOOL HashTable_Remove(wHashTable* table, const void* key);
WINPR_API void HashTable_Clear(wHashTable* table);
WINPR_API BOOL HashTable_Contains(wHashTable* table, void* key);
WINPR_API BOOL HashTable_ContainsKey(wHashTable* table, void* key);
WINPR_API BOOL HashTable_ContainsValue(wHashTable* table, void* value);
WINPR_API void* HashTable_GetItemValue(wHashTable* table, void* key);
WINPR_API BOOL HashTable_SetItemValue(wHashTable* table, void* key, void* value);
WINPR_API int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys);
WINPR_API BOOL HashTable_Contains(wHashTable* table, const void* key);
WINPR_API BOOL HashTable_ContainsKey(wHashTable* table, const void* key);
WINPR_API BOOL HashTable_ContainsValue(wHashTable* table, const void* value);
WINPR_API void* HashTable_GetItemValue(wHashTable* table, const void* key);
WINPR_API BOOL HashTable_SetItemValue(wHashTable* table, const void* key, const void* value);
WINPR_API size_t HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys);
WINPR_API BOOL HashTable_Foreach(wHashTable* table, HASH_TABLE_FOREACH_FN fn, VOID* arg);
WINPR_API UINT32 HashTable_PointerHash(void* pointer);
WINPR_API BOOL HashTable_PointerCompare(void* pointer1, void* pointer2);
WINPR_API UINT32 HashTable_PointerHash(const void* pointer);
WINPR_API BOOL HashTable_PointerCompare(const void* pointer1, const void* pointer2);
WINPR_API UINT32 HashTable_StringHash(void* key);
WINPR_API BOOL HashTable_StringCompare(void* string1, void* string2);
WINPR_API void* HashTable_StringClone(void* str);
WINPR_API UINT32 HashTable_StringHash(const void* key);
WINPR_API BOOL HashTable_StringCompare(const void* string1, const void* string2);
WINPR_API void* HashTable_StringClone(const void* str);
WINPR_API void HashTable_StringFree(void* str);
WINPR_API wHashTable* HashTable_New(BOOL synchronized);
WINPR_API void HashTable_Free(wHashTable* table);
WINPR_API wObject* HashTable_KeyObject(wHashTable* table);
WINPR_API wObject* HashTable_ValueObject(wHashTable* table);
WINPR_API BOOL HashTable_SetHashFunction(wHashTable* table, HASH_TABLE_HASH_FN fn);
/* Utility function to setup hash table for strings */
static INLINE BOOL HashTable_SetupForStringData(wHashTable* table, BOOL stringValues)
{
wObject* obj;
if (!HashTable_SetHashFunction(table, HashTable_StringHash))
return FALSE;
obj = HashTable_KeyObject(table);
if (!obj)
return FALSE;
obj->fnObjectEquals = HashTable_StringCompare;
obj->fnObjectNew = HashTable_StringClone;
obj->fnObjectFree = HashTable_StringFree;
if (stringValues)
{
obj = HashTable_ValueObject(table);
if (!obj)
return FALSE;
obj->fnObjectEquals = HashTable_StringCompare;
obj->fnObjectNew = HashTable_StringClone;
obj->fnObjectFree = HashTable_StringFree;
}
return TRUE;
}
/* BufferPool */
typedef struct _wBufferPool wBufferPool;

View File

@ -396,12 +396,15 @@ static PCSC_SCARDCONTEXT* PCSC_EstablishCardContext(SCARDCONTEXT hContext)
pContext->cache = HashTable_New(FALSE);
if (!pContext->cache)
goto errors;
if (!HashTable_SetupForStringData(pContext->cache, FALSE))
goto errors;
{
wObject* obj = HashTable_ValueObject(pContext->cache);
if (!obj)
goto errors;
obj->fnObjectFree = pcsc_cache_item_free;
}
pContext->cache->hash = HashTable_StringHash;
pContext->cache->keyCompare = HashTable_StringCompare;
pContext->cache->keyClone = HashTable_StringClone;
pContext->cache->keyFree = free;
pContext->cache->valueFree = pcsc_cache_item_free;
if (!g_CardContexts)
{
g_CardContexts = ListDictionary_New(TRUE);
@ -415,6 +418,7 @@ static PCSC_SCARDCONTEXT* PCSC_EstablishCardContext(SCARDCONTEXT hContext)
return pContext;
errors:
HashTable_Free(pContext->cache);
DeleteCriticalSection(&(pContext->lock));
error_spinlock:
free(pContext);

View File

@ -33,17 +33,48 @@
* http://www.pomakis.com/hashtable/hashtable.h
*/
BOOL HashTable_PointerCompare(void* pointer1, void* pointer2)
typedef struct _wKeyValuePair wKeyValuePair;
struct _wKeyValuePair
{
void* key;
void* value;
wKeyValuePair* next;
BOOL markedForRemove;
};
struct _wHashTable
{
BOOL synchronized;
CRITICAL_SECTION lock;
size_t numOfBuckets;
size_t numOfElements;
float idealRatio;
float lowerRehashThreshold;
float upperRehashThreshold;
wKeyValuePair** bucketArray;
HASH_TABLE_HASH_FN hash;
wObject key;
wObject value;
DWORD foreachRecursionLevel;
DWORD pendingRemoves;
};
BOOL HashTable_PointerCompare(const void* pointer1, const void* pointer2)
{
return (pointer1 == pointer2);
}
UINT32 HashTable_PointerHash(void* pointer)
UINT32 HashTable_PointerHash(const void* pointer)
{
return ((UINT32)(UINT_PTR)pointer) >> 4;
}
BOOL HashTable_StringCompare(void* string1, void* string2)
BOOL HashTable_StringCompare(const void* string1, const void* string2)
{
if (!string1 || !string2)
return (string1 == string2);
@ -51,7 +82,7 @@ BOOL HashTable_StringCompare(void* string1, void* string2)
return (strcmp((char*)string1, (char*)string2) == 0);
}
UINT32 HashTable_StringHash(void* key)
UINT32 HashTable_StringHash(const void* key)
{
UINT32 c;
UINT32 hash = 5381;
@ -64,7 +95,7 @@ UINT32 HashTable_StringHash(void* key)
return hash;
}
void* HashTable_StringClone(void* str)
void* HashTable_StringClone(const void* str)
{
return _strdup((char*)str);
}
@ -74,24 +105,24 @@ void HashTable_StringFree(void* str)
free(str);
}
static int HashTable_IsProbablePrime(int oddNumber)
static BOOL HashTable_IsProbablePrime(size_t oddNumber)
{
int i;
size_t i;
for (i = 3; i < 51; i += 2)
{
if (oddNumber == i)
return 1;
return TRUE;
else if (oddNumber % i == 0)
return 0;
return FALSE;
}
return 1; /* maybe */
return TRUE; /* maybe */
}
static long HashTable_CalculateIdealNumOfBuckets(wHashTable* table)
static size_t HashTable_CalculateIdealNumOfBuckets(wHashTable* table)
{
int idealNumOfBuckets = table->numOfElements / ((int)table->idealRatio);
size_t idealNumOfBuckets = table->numOfElements / (table->idealRatio);
if (idealNumOfBuckets < 5)
idealNumOfBuckets = 5;
@ -104,9 +135,9 @@ static long HashTable_CalculateIdealNumOfBuckets(wHashTable* table)
return idealNumOfBuckets;
}
static void HashTable_Rehash(wHashTable* table, int numOfBuckets)
static void HashTable_Rehash(wHashTable* table, size_t numOfBuckets)
{
int index;
size_t index;
UINT32 hashValue;
wKeyValuePair* pair;
wKeyValuePair* nextPair;
@ -148,19 +179,69 @@ static void HashTable_Rehash(wHashTable* table, int numOfBuckets)
table->numOfBuckets = numOfBuckets;
}
wKeyValuePair* HashTable_Get(wHashTable* table, void* key)
static BOOL HashTable_Equals(wHashTable* table, const wKeyValuePair* pair, const void* key)
{
if (!key || !pair || !table)
return FALSE;
return table->key.fnObjectEquals(key, pair->key);
}
static wKeyValuePair* HashTable_Get(wHashTable* table, const void* key)
{
UINT32 hashValue;
wKeyValuePair* pair;
hashValue = table->hash(key) % table->numOfBuckets;
pair = table->bucketArray[hashValue];
while (pair && !table->keyCompare(key, pair->key))
while (pair && !HashTable_Equals(table, pair, key))
pair = pair->next;
return pair;
}
static INLINE void disposeKey(wHashTable* table, void* key)
{
if (table && table->key.fnObjectFree)
table->key.fnObjectFree(key);
}
static INLINE void disposeValue(wHashTable* table, void* value)
{
if (table && table->value.fnObjectFree)
table->value.fnObjectFree(value);
}
static INLINE void disposePair(wHashTable* table, wKeyValuePair* pair)
{
if (!pair)
return;
disposeKey(table, pair->key);
disposeValue(table, pair->value);
free(pair);
}
static INLINE void setKey(wHashTable* table, wKeyValuePair* pair, const void* key)
{
if (!table || !pair)
return;
disposeKey(table, pair->key);
if (table->key.fnObjectNew)
pair->key = table->key.fnObjectNew(key);
else
pair->key = (void*)key;
}
static INLINE void setValue(wHashTable* table, wKeyValuePair* pair, const void* value)
{
if (!table || !pair)
return;
disposeValue(table, pair->value);
if (table->key.fnObjectNew)
pair->value = table->value.fnObjectNew(value);
else
pair->value = (void*)value;
}
/**
* C equivalent of the C# Hashtable Class:
* http://msdn.microsoft.com/en-us/library/system.collections.hashtable.aspx
@ -174,7 +255,7 @@ wKeyValuePair* HashTable_Get(wHashTable* table, void* key)
* Gets the number of key/value pairs contained in the HashTable.
*/
int HashTable_Count(wHashTable* table)
size_t HashTable_Count(wHashTable* table)
{
return table->numOfElements;
}
@ -187,31 +268,15 @@ int HashTable_Count(wHashTable* table)
* Adds an element with the specified key and value into the HashTable.
*/
int HashTable_Add(wHashTable* table, void* key, void* value)
BOOL HashTable_Add(wHashTable* table, const void* key, const void* value)
{
int status = 0;
BOOL rc = FALSE;
UINT32 hashValue;
wKeyValuePair* pair;
wKeyValuePair* newPair;
if (!key || !value)
return -1;
if (table->keyClone)
{
key = table->keyClone(key);
if (!key)
return -1;
}
if (table->valueClone)
{
value = table->valueClone(value);
if (!value)
return -1;
}
return FALSE;
if (table->synchronized)
EnterCriticalSection(&table->lock);
@ -219,7 +284,7 @@ int HashTable_Add(wHashTable* table, void* key, void* value)
hashValue = table->hash(key) % table->numOfBuckets;
pair = table->bucketArray[hashValue];
while (pair && !table->keyCompare(key, pair->key))
while (pair && !HashTable_Equals(table, pair, key))
pair = pair->next;
if (pair)
@ -234,32 +299,23 @@ int HashTable_Add(wHashTable* table, void* key, void* value)
if (pair->key != key)
{
if (table->keyFree)
table->keyFree(pair->key);
pair->key = key;
setKey(table, pair, key);
}
if (pair->value != value)
{
if (table->valueFree)
table->valueFree(pair->value);
pair->value = value;
setValue(table, pair, value);
}
rc = TRUE;
}
else
{
newPair = (wKeyValuePair*)malloc(sizeof(wKeyValuePair));
newPair = (wKeyValuePair*)calloc(1, sizeof(wKeyValuePair));
if (!newPair)
if (newPair)
{
status = -1;
}
else
{
newPair->key = key;
newPair->value = value;
setKey(table, newPair, key);
setValue(table, newPair, value);
newPair->next = table->bucketArray[hashValue];
newPair->markedForRemove = FALSE;
table->bucketArray[hashValue] = newPair;
@ -273,29 +329,21 @@ int HashTable_Add(wHashTable* table, void* key, void* value)
if (elementToBucketRatio > table->upperRehashThreshold)
HashTable_Rehash(table, 0);
}
rc = TRUE;
}
}
if (table->synchronized)
LeaveCriticalSection(&table->lock);
return status;
}
static void disposePair(wHashTable* table, wKeyValuePair* pair)
{
if (table->keyFree)
table->keyFree(pair->key);
if (table->valueFree)
table->valueFree(pair->value);
return rc;
}
/**
* Removes the element with the specified key from the HashTable.
*/
BOOL HashTable_Remove(wHashTable* table, void* key)
BOOL HashTable_Remove(wHashTable* table, const void* key)
{
UINT32 hashValue;
BOOL status = TRUE;
@ -308,7 +356,7 @@ BOOL HashTable_Remove(wHashTable* table, void* key)
hashValue = table->hash(key) % table->numOfBuckets;
pair = table->bucketArray[hashValue];
while (pair && !table->keyCompare(key, pair->key))
while (pair && !HashTable_Equals(table, pair, key))
{
previousPair = pair;
pair = pair->next;
@ -329,14 +377,12 @@ BOOL HashTable_Remove(wHashTable* table, void* key)
goto out;
}
disposePair(table, pair);
if (previousPair)
previousPair->next = pair->next;
else
table->bucketArray[hashValue] = pair->next;
free(pair);
disposePair(table, pair);
table->numOfElements--;
if (!table->foreachRecursionLevel && table->lowerRehashThreshold > 0.0)
@ -358,7 +404,7 @@ out:
* Get an item value using key
*/
void* HashTable_GetItemValue(wHashTable* table, void* key)
void* HashTable_GetItemValue(wHashTable* table, const void* key)
{
void* value = NULL;
wKeyValuePair* pair;
@ -381,19 +427,11 @@ void* HashTable_GetItemValue(wHashTable* table, void* key)
* Set an item value using key
*/
BOOL HashTable_SetItemValue(wHashTable* table, void* key, void* value)
BOOL HashTable_SetItemValue(wHashTable* table, const void* key, const void* value)
{
BOOL status = TRUE;
wKeyValuePair* pair;
if (table->valueClone && value)
{
value = table->valueClone(value);
if (!value)
return FALSE;
}
if (table->synchronized)
EnterCriticalSection(&table->lock);
@ -403,10 +441,7 @@ BOOL HashTable_SetItemValue(wHashTable* table, void* key, void* value)
status = FALSE;
else
{
if (table->valueClone && table->valueFree)
table->valueFree(pair->value);
pair->value = value;
setValue(table, pair, value);
}
if (table->synchronized)
@ -421,7 +456,7 @@ BOOL HashTable_SetItemValue(wHashTable* table, void* key, void* value)
void HashTable_Clear(wHashTable* table)
{
int index;
size_t index;
wKeyValuePair* pair;
wKeyValuePair* nextPair;
@ -445,8 +480,6 @@ void HashTable_Clear(wHashTable* table)
else
{
disposePair(table, pair);
free(pair);
pair = nextPair;
}
}
@ -466,11 +499,11 @@ void HashTable_Clear(wHashTable* table)
* Gets the list of keys as an array
*/
int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys)
size_t HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys)
{
int iKey;
int count;
int index;
size_t iKey;
size_t count;
size_t index;
ULONG_PTR* pKeys;
wKeyValuePair* pair;
wKeyValuePair* nextPair;
@ -523,7 +556,7 @@ int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys)
BOOL HashTable_Foreach(wHashTable* table, HASH_TABLE_FOREACH_FN fn, VOID* arg)
{
BOOL ret = TRUE;
int index;
size_t index;
wKeyValuePair* pair;
if (!fn)
@ -561,7 +594,6 @@ BOOL HashTable_Foreach(wHashTable* table, HASH_TABLE_FOREACH_FN fn, VOID* arg)
if (pair->markedForRemove)
{
disposePair(table, pair);
free(pair);
*prevPtr = nextPair;
}
else
@ -584,7 +616,7 @@ out:
* Determines whether the HashTable contains a specific key.
*/
BOOL HashTable_Contains(wHashTable* table, void* key)
BOOL HashTable_Contains(wHashTable* table, const void* key)
{
BOOL status;
wKeyValuePair* pair;
@ -605,7 +637,7 @@ BOOL HashTable_Contains(wHashTable* table, void* key)
* Determines whether the HashTable contains a specific key.
*/
BOOL HashTable_ContainsKey(wHashTable* table, void* key)
BOOL HashTable_ContainsKey(wHashTable* table, const void* key)
{
BOOL status;
wKeyValuePair* pair;
@ -626,9 +658,9 @@ BOOL HashTable_ContainsKey(wHashTable* table, void* key)
* Determines whether the HashTable contains a specific value.
*/
BOOL HashTable_ContainsValue(wHashTable* table, void* value)
BOOL HashTable_ContainsValue(wHashTable* table, const void* value)
{
int index;
size_t index;
BOOL status = FALSE;
wKeyValuePair* pair;
@ -641,7 +673,7 @@ BOOL HashTable_ContainsValue(wHashTable* table, void* value)
while (pair)
{
if (!pair->markedForRemove && table->valueCompare(value, pair->value))
if (!pair->markedForRemove && HashTable_Equals(table, pair, value))
{
status = TRUE;
break;
@ -687,12 +719,8 @@ wHashTable* HashTable_New(BOOL synchronized)
table->lowerRehashThreshold = 0.0;
table->upperRehashThreshold = 15.0;
table->hash = HashTable_PointerHash;
table->keyCompare = HashTable_PointerCompare;
table->valueCompare = HashTable_PointerCompare;
table->keyClone = NULL;
table->valueClone = NULL;
table->keyFree = NULL;
table->valueFree = NULL;
table->key.fnObjectEquals = HashTable_PointerCompare;
table->value.fnObjectEquals = HashTable_PointerCompare;
}
return table;
@ -700,7 +728,7 @@ wHashTable* HashTable_New(BOOL synchronized)
void HashTable_Free(wHashTable* table)
{
int index;
size_t index;
wKeyValuePair* pair;
wKeyValuePair* nextPair;
@ -714,13 +742,7 @@ void HashTable_Free(wHashTable* table)
{
nextPair = pair->next;
if (table->keyFree)
table->keyFree(pair->key);
if (table->valueFree)
table->valueFree(pair->value);
free(pair);
disposePair(table, pair);
pair = nextPair;
}
}
@ -730,3 +752,25 @@ void HashTable_Free(wHashTable* table)
free(table);
}
}
wObject* HashTable_KeyObject(wHashTable* table)
{
if (!table)
return NULL;
return &table->key;
}
wObject* HashTable_ValueObject(wHashTable* table)
{
if (!table)
return NULL;
return &table->value;
}
BOOL HashTable_SetHashFunction(wHashTable* table, HASH_TABLE_HASH_FN fn)
{
if (!table)
return FALSE;
table->hash = fn;
return TRUE;
}

View File

@ -22,9 +22,12 @@ static int test_hash_table_pointer(void)
if (!table)
return -1;
HashTable_Add(table, key1, val1);
HashTable_Add(table, key2, val2);
HashTable_Add(table, key3, val3);
if (!HashTable_Add(table, key1, val1))
goto fail;
if (!HashTable_Add(table, key2, val2))
goto fail;
if (!HashTable_Add(table, key3, val3))
goto fail;
count = HashTable_Count(table);
if (count != 3)
@ -33,7 +36,8 @@ static int test_hash_table_pointer(void)
goto fail;
}
HashTable_Remove(table, key2);
if (!HashTable_Remove(table, key2))
goto fail;
count = HashTable_Count(table);
if (count != 2)
@ -42,7 +46,8 @@ static int test_hash_table_pointer(void)
goto fail;
}
HashTable_Remove(table, key3);
if (!HashTable_Remove(table, key3))
goto fail;
count = HashTable_Count(table);
if (count != 1)
@ -51,7 +56,8 @@ static int test_hash_table_pointer(void)
goto fail;
}
HashTable_Remove(table, key1);
if (!HashTable_Remove(table, key1))
goto fail;
count = HashTable_Count(table);
if (count != 0)
@ -60,9 +66,12 @@ static int test_hash_table_pointer(void)
goto fail;
}
HashTable_Add(table, key1, val1);
HashTable_Add(table, key2, val2);
HashTable_Add(table, key3, val3);
if (!HashTable_Add(table, key1, val1))
goto fail;
if (!HashTable_Add(table, key2, val2))
goto fail;
if (!HashTable_Add(table, key3, val3))
goto fail;
count = HashTable_Count(table);
if (count != 3)
@ -95,7 +104,8 @@ static int test_hash_table_pointer(void)
goto fail;
}
HashTable_SetItemValue(table, key2, "apple");
if (!HashTable_SetItemValue(table, key2, "apple"))
goto fail;
value = (char*)HashTable_GetItemValue(table, key2);
if (strcmp(value, "apple") != 0)
@ -142,22 +152,20 @@ static int test_hash_table_string(void)
int rc = -1;
int count;
char* value;
wHashTable* table;
table = HashTable_New(TRUE);
wHashTable* table = HashTable_New(TRUE);
if (!table)
return -1;
table->hash = HashTable_StringHash;
table->keyCompare = HashTable_StringCompare;
table->valueCompare = HashTable_StringCompare;
table->keyClone = HashTable_StringClone;
table->valueClone = HashTable_StringClone;
table->keyFree = HashTable_StringFree;
table->valueFree = HashTable_StringFree;
HashTable_Add(table, key1, val1);
HashTable_Add(table, key2, val2);
HashTable_Add(table, key3, val3);
if (!HashTable_SetupForStringData(table, TRUE))
goto fail;
if (!HashTable_Add(table, key1, val1))
goto fail;
if (!HashTable_Add(table, key2, val2))
goto fail;
if (!HashTable_Add(table, key3, val3))
goto fail;
count = HashTable_Count(table);
if (count != 3)
@ -166,7 +174,8 @@ static int test_hash_table_string(void)
goto fail;
}
HashTable_Remove(table, key2);
if (!HashTable_Remove(table, key2))
goto fail;
count = HashTable_Count(table);
if (count != 2)
@ -175,7 +184,8 @@ static int test_hash_table_string(void)
goto fail;
}
HashTable_Remove(table, key3);
if (!HashTable_Remove(table, key3))
goto fail;
count = HashTable_Count(table);
if (count != 1)
@ -184,7 +194,8 @@ static int test_hash_table_string(void)
goto fail;
}
HashTable_Remove(table, key1);
if (!HashTable_Remove(table, key1))
goto fail;
count = HashTable_Count(table);
if (count != 0)
@ -193,9 +204,12 @@ static int test_hash_table_string(void)
goto fail;
}
HashTable_Add(table, key1, val1);
HashTable_Add(table, key2, val2);
HashTable_Add(table, key3, val3);
if (!HashTable_Add(table, key1, val1))
goto fail;
if (!HashTable_Add(table, key2, val2))
goto fail;
if (!HashTable_Add(table, key3, val3))
goto fail;
count = HashTable_Count(table);
if (count != 3)
@ -228,7 +242,8 @@ static int test_hash_table_string(void)
goto fail;
}
HashTable_SetItemValue(table, key2, "apple");
if (!HashTable_SetItemValue(table, key2, "apple"))
goto fail;
value = (char*)HashTable_GetItemValue(table, key2);
if (strcmp(value, "apple") != 0)
@ -279,16 +294,19 @@ typedef struct
BOOL test3error;
} ForeachData;
BOOL foreachFn1(const void* key, void* value, void* arg)
BOOL foreachFn1(const void* key, const void* value, void* arg)
{
ForeachData* d = (ForeachData*)arg;
WINPR_UNUSED(key);
d->strlenCounter += strlen((const char*)value);
return TRUE;
}
BOOL foreachFn2(const void* key, void* value, void* arg)
BOOL foreachFn2(const void* key, const void* value, void* arg)
{
ForeachData* d = (ForeachData*)arg;
WINPR_UNUSED(key);
WINPR_UNUSED(value);
d->foreachCalls++;
if (d->foreachCalls == 2)
@ -296,13 +314,14 @@ BOOL foreachFn2(const void* key, void* value, void* arg)
return TRUE;
}
BOOL foreachFn3(const void* key, void* value, void* arg)
BOOL foreachFn3(const void* key, const void* value, void* arg)
{
char* keyStr = (char*)key;
ForeachData* d = (ForeachData*)arg;
ForeachData d2;
WINPR_UNUSED(value);
if (strcmp(keyStr, "key1") == 0)
{
/* when we pass on key1, let's remove key2 and check that the value is not
@ -356,13 +375,8 @@ int test_hash_foreach(void)
if (!table)
return -1;
table->hash = HashTable_StringHash;
table->keyCompare = HashTable_StringCompare;
table->valueCompare = HashTable_StringCompare;
table->keyClone = HashTable_StringClone;
table->valueClone = HashTable_StringClone;
table->keyFree = HashTable_StringFree;
table->valueFree = HashTable_StringFree;
if (!HashTable_SetupForStringData(table, TRUE))
goto out;
if (HashTable_Add(table, key1, val1) < 0 || HashTable_Add(table, key2, val2) < 0 ||
HashTable_Add(table, key3, val3) < 0)
@ -417,6 +431,9 @@ out:
int TestHashTable(int argc, char* argv[])
{
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
if (test_hash_table_pointer() < 0)
return 1;