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:
parent
3a75228242
commit
cb642699c8
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user