ICU-149 cleanup uhash/hash
X-SVN-Rev: 1033
This commit is contained in:
parent
50eb0cfdf0
commit
327165d913
@ -27,6 +27,12 @@ class Hashtable {
|
||||
public:
|
||||
Hashtable(UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Construct a hashtable, _disregarding any error_. Use this constructor
|
||||
* with caution.
|
||||
*/
|
||||
Hashtable();
|
||||
|
||||
/**
|
||||
* Non-virtual destructor; make this virtual if Hashtable is subclassed
|
||||
* in the future.
|
||||
@ -43,7 +49,7 @@ public:
|
||||
|
||||
void* remove(const UnicodeString& key);
|
||||
|
||||
bool_t nextElement(const UnicodeString*& key, void*& value, int32_t& pos) const;
|
||||
const UHashElement* nextElement(int32_t& pos) const;
|
||||
};
|
||||
|
||||
/*********************************************************************
|
||||
@ -61,6 +67,15 @@ inline Hashtable::Hashtable(UErrorCode& status) : hash(0) {
|
||||
}
|
||||
}
|
||||
|
||||
inline Hashtable::Hashtable() : hash(0) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
hash = uhash_open(uhash_hashUnicodeString,
|
||||
uhash_compareUnicodeString, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
uhash_setKeyDeleter(hash, uhash_deleteUnicodeString);
|
||||
}
|
||||
}
|
||||
|
||||
inline Hashtable::~Hashtable() {
|
||||
if (hash != 0) {
|
||||
uhash_close(hash);
|
||||
@ -88,15 +103,8 @@ inline void* Hashtable::remove(const UnicodeString& key) {
|
||||
return uhash_remove(hash, &key);
|
||||
}
|
||||
|
||||
inline bool_t Hashtable::nextElement(const UnicodeString*& key, void*& value, int32_t& pos) const {
|
||||
UHashElement *e = uhash_nextElement(hash, &pos);
|
||||
if (e != 0) {
|
||||
key = (const UnicodeString*) e->key;
|
||||
value = e->value;
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
inline const UHashElement* Hashtable::nextElement(int32_t& pos) const {
|
||||
return uhash_nextElement(hash, &pos);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -17,32 +17,14 @@
|
||||
|
||||
#include "rbcache.h"
|
||||
|
||||
ResourceBundleCache::ResourceBundleCache() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
hash = new Hashtable(status);
|
||||
hash->setValueDeleter(deleteUHashtable);
|
||||
}
|
||||
|
||||
ResourceBundleCache::~ResourceBundleCache() {
|
||||
delete hash;
|
||||
ResourceBundleCache::ResourceBundleCache() : hash() {
|
||||
hash.setValueDeleter(deleteUHashtable);
|
||||
}
|
||||
|
||||
void ResourceBundleCache::deleteUHashtable(void* value) {
|
||||
uhash_close((UHashtable*)value);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
VisitedFileCache::VisitedFileCache() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
hash = new Hashtable(status);
|
||||
}
|
||||
|
||||
VisitedFileCache::~VisitedFileCache() {
|
||||
delete hash;
|
||||
}
|
||||
|
||||
|
||||
//eof
|
||||
|
||||
|
||||
|
@ -19,7 +19,14 @@
|
||||
|
||||
#include "hash.h"
|
||||
#include "unicode/unistr.h"
|
||||
struct UHashtable;
|
||||
|
||||
/* Disable these warnings:
|
||||
d:\icu\source\common\rbcache.h(31) : warning C4251: 'hash' : class 'Hashtable' needs to have dll-interface to be used by clients of class 'ResourceBundleCache'
|
||||
d:\icu\source\common\rbcache.h(57) : warning C4251: 'hash' : class 'Hashtable' needs to have dll-interface to be used by clients of class 'VisitedFileCache'
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#pragma warning( disable : 4251 )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A class that maps UnicodeString keys to UHashtable objects. It
|
||||
@ -28,22 +35,22 @@ struct UHashtable;
|
||||
*/
|
||||
class U_COMMON_API ResourceBundleCache { // Not really external; just making the compiler happy
|
||||
private:
|
||||
Hashtable* hash;
|
||||
Hashtable hash;
|
||||
static void U_CALLCONV deleteUHashtable(void* value);
|
||||
public:
|
||||
ResourceBundleCache();
|
||||
~ResourceBundleCache();
|
||||
inline ~ResourceBundleCache() {}
|
||||
inline void put(const UnicodeString& key, UHashtable* adoptedValue);
|
||||
inline const UHashtable* get(const UnicodeString& key) const;
|
||||
};
|
||||
|
||||
inline void ResourceBundleCache::put(const UnicodeString& key, UHashtable* adoptedValue) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
hash->put(key, adoptedValue, status);
|
||||
hash.put(key, adoptedValue, status);
|
||||
}
|
||||
|
||||
inline const UHashtable* ResourceBundleCache::get(const UnicodeString& key) const {
|
||||
return (const UHashtable*) hash->get(key);
|
||||
return (const UHashtable*) hash.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,21 +61,21 @@ inline const UHashtable* ResourceBundleCache::get(const UnicodeString& key) cons
|
||||
*/
|
||||
class U_COMMON_API VisitedFileCache { // Not really external; just making the compiler happy
|
||||
private:
|
||||
Hashtable* hash;
|
||||
Hashtable hash;
|
||||
public:
|
||||
VisitedFileCache();
|
||||
~VisitedFileCache();
|
||||
inline VisitedFileCache() {}
|
||||
inline ~VisitedFileCache() {}
|
||||
inline bool_t wasVisited(const UnicodeString& filename) const;
|
||||
inline void markAsVisited(const UnicodeString& filename);
|
||||
};
|
||||
|
||||
inline bool_t VisitedFileCache::wasVisited(const UnicodeString& filename) const {
|
||||
return (hash->get(filename) != 0);
|
||||
return (hash.get(filename) != 0);
|
||||
}
|
||||
|
||||
inline void VisitedFileCache::markAsVisited(const UnicodeString& filename) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
hash->put(filename, (void*)1, status);
|
||||
hash.put(filename, (void*)1, status);
|
||||
}
|
||||
|
||||
//eof
|
||||
|
@ -108,7 +108,14 @@ TaggedList::get(const UnicodeString& tag) const {
|
||||
bool_t TaggedList::nextElement(const UnicodeString*& key,
|
||||
const UnicodeString*& value,
|
||||
int32_t& pos) const {
|
||||
return hash->nextElement(key, (void*&)value, pos);
|
||||
const UHashElement *e = hash->nextElement(pos);
|
||||
if (e != NULL) {
|
||||
key = (const UnicodeString*) e->key;
|
||||
value = (const UnicodeString*) e->value;
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
UClassID
|
||||
|
@ -137,7 +137,7 @@ int32_t ucnv_flushCache ()
|
||||
UConverterSharedData *mySharedData = NULL;
|
||||
int32_t pos = -1;
|
||||
int32_t tableDeletedNum = 0;
|
||||
UHashElement *e;
|
||||
const UHashElement *e;
|
||||
|
||||
/*if shared data hasn't even been lazy evaluated yet
|
||||
* return 0
|
||||
|
@ -78,6 +78,19 @@ static int32_t PRIMES[] = {
|
||||
|
||||
#define PRIMES_LENGTH (sizeof(PRIMES) / sizeof(PRIMES[0]))
|
||||
|
||||
/* These ratios are tuned to the PRIMES array such that a resize
|
||||
* places the table back into the zone of non-resizing. That is,
|
||||
* after a call to _uhash_rehash(), a subsequent call to
|
||||
* _uhash_rehash() should do nothing (should not churn). This is only
|
||||
* a potential problem with U_GROW_AND_SHRINK.
|
||||
*/
|
||||
static const float RESIZE_POLICY_RATIO_TABLE[6] = {
|
||||
/* low, high water ratio */
|
||||
0.0F, 0.5F, /* U_GROW: Grow on demand, do not shrink */
|
||||
0.1F, 0.5F, /* U_GROW_AND_SHRINK: Grow and shrink on demand */
|
||||
0.0F, 1.0F /* U_FIXED: Never change size */
|
||||
};
|
||||
|
||||
/*
|
||||
Invariants for hashcode values:
|
||||
|
||||
@ -111,18 +124,18 @@ static int32_t PRIMES[] = {
|
||||
/* #define HASH_DEBUG */
|
||||
#ifdef HASH_DEBUG
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define assert(exp) (void)( (exp) || (_assert(#exp, __FILE__, __LINE__), 0) )
|
||||
#define assert(exp) (void)( (exp) || (_assert(#exp, __FILE__, __LINE__), 0) )
|
||||
|
||||
static void _assert(const char* exp, const char* file, int line) {
|
||||
printf("ERROR: assert(%s) failed: %s, line %d\n",
|
||||
exp, file, line);
|
||||
}
|
||||
static void _assert(const char* exp, const char* file, int line) {
|
||||
printf("ERROR: assert(%s) failed: %s, line %d\n",
|
||||
exp, file, line);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define assert(exp)
|
||||
#define assert(exp)
|
||||
|
||||
#endif
|
||||
|
||||
@ -130,21 +143,23 @@ static void _assert(const char* exp, const char* file, int line) {
|
||||
* PRIVATE Prototypes
|
||||
********************************************************************/
|
||||
|
||||
UHashtable* _uhash_create(UHashFunction keyHash, UKeyComparator keyComp,
|
||||
int32_t primeIndex, UErrorCode *status);
|
||||
static UHashtable* _uhash_create(UHashFunction keyHash, UKeyComparator keyComp,
|
||||
int32_t primeIndex, UErrorCode *status);
|
||||
|
||||
void _uhash_allocate(UHashtable *hash, int32_t primeIndex,
|
||||
UErrorCode *status);
|
||||
static void _uhash_allocate(UHashtable *hash, int32_t primeIndex,
|
||||
UErrorCode *status);
|
||||
|
||||
void _uhash_rehash(UHashtable *hash);
|
||||
static void _uhash_rehash(UHashtable *hash);
|
||||
|
||||
UHashElement* _uhash_find(const UHashtable *hash, const void* key,
|
||||
int32_t hashcode);
|
||||
static UHashElement* _uhash_find(const UHashtable *hash, const void* key,
|
||||
int32_t hashcode);
|
||||
|
||||
void* _uhash_internalRemoveElement(UHashtable *hash, UHashElement* e);
|
||||
static void* _uhash_internalRemoveElement(UHashtable *hash, UHashElement* e);
|
||||
|
||||
void* _uhash_setElement(UHashtable* hash, UHashElement* e,
|
||||
int32_t hashcode, void* key, void* value);
|
||||
static void* _uhash_setElement(UHashtable* hash, UHashElement* e,
|
||||
int32_t hashcode, void* key, void* value);
|
||||
|
||||
static void _uhash_internalSetResizePolicy(UHashtable *hash, enum UHashResizePolicy policy);
|
||||
|
||||
/********************************************************************
|
||||
* PUBLIC API
|
||||
@ -174,12 +189,11 @@ uhash_openSize(UHashFunction keyHash, UKeyComparator keyComp,
|
||||
U_CAPI void
|
||||
uhash_close(UHashtable *hash) {
|
||||
assert(hash != NULL);
|
||||
|
||||
if (hash->elements != NULL) {
|
||||
if (hash->keyDeleter != NULL || hash->valueDeleter != NULL) {
|
||||
int32_t pos=-1;
|
||||
UHashElement *e;
|
||||
while ((e = uhash_nextElement(hash, &pos)) != NULL) {
|
||||
while ((e = (UHashElement*) uhash_nextElement(hash, &pos)) != NULL) {
|
||||
HASH_DELETE_KEY_VALUE(hash, e->key, e->value);
|
||||
}
|
||||
}
|
||||
@ -217,6 +231,14 @@ uhash_setValueDeleter(UHashtable *hash, UObjectDeleter fn) {
|
||||
return result;
|
||||
}
|
||||
|
||||
U_CAPI void
|
||||
uhash_setResizePolicy(UHashtable *hash, enum UHashResizePolicy policy) {
|
||||
_uhash_internalSetResizePolicy(hash, policy);
|
||||
hash->lowWaterMark = (int32_t)(hash->length * hash->lowWaterRatio);
|
||||
hash->highWaterMark = (int32_t)(hash->length * hash->highWaterRatio);
|
||||
_uhash_rehash(hash);
|
||||
}
|
||||
|
||||
U_CAPI int32_t
|
||||
uhash_count(const UHashtable *hash) {
|
||||
return hash->count;
|
||||
@ -245,6 +267,13 @@ uhash_put(UHashtable *hash,
|
||||
if (U_FAILURE(*status)) {
|
||||
goto err;
|
||||
}
|
||||
assert(hash != NULL);
|
||||
if (value == NULL) {
|
||||
/* Disallow storage of NULL values, since NULL is returned by
|
||||
* get() to indicate an absent key. Storing NULL == removing.
|
||||
*/
|
||||
return uhash_remove(hash, key);
|
||||
}
|
||||
if (hash->count > hash->highWaterMark) {
|
||||
_uhash_rehash(hash);
|
||||
}
|
||||
@ -307,12 +336,26 @@ uhash_remove(UHashtable *hash,
|
||||
return result;
|
||||
}
|
||||
|
||||
U_CAPI UHashElement*
|
||||
U_CAPI void
|
||||
uhash_removeAll(UHashtable *hash) {
|
||||
int32_t pos = -1;
|
||||
const UHashElement *e;
|
||||
assert(hash != NULL);
|
||||
if (hash->count != 0) {
|
||||
while ((e = uhash_nextElement(hash, &pos)) != NULL) {
|
||||
uhash_removeElement(hash, e);
|
||||
}
|
||||
}
|
||||
assert(hash->count == 0);
|
||||
}
|
||||
|
||||
U_CAPI const UHashElement*
|
||||
uhash_nextElement(const UHashtable *hash, int32_t *pos) {
|
||||
/* Walk through the array until we find an element that is not
|
||||
* EMPTY and not DELETED.
|
||||
*/
|
||||
int32_t i;
|
||||
assert(hash != NULL);
|
||||
for (i = *pos + 1; i < hash->length; ++i) {
|
||||
if (!IS_EMPTY_OR_DELETED(hash->elements[i].hashcode)) {
|
||||
*pos = i;
|
||||
@ -325,10 +368,11 @@ uhash_nextElement(const UHashtable *hash, int32_t *pos) {
|
||||
}
|
||||
|
||||
U_CAPI void*
|
||||
uhash_removeElement(UHashtable *hash, UHashElement* e) {
|
||||
uhash_removeElement(UHashtable *hash, const UHashElement* e) {
|
||||
assert(hash != NULL);
|
||||
assert(e != NULL);
|
||||
if (!IS_EMPTY_OR_DELETED(e->hashcode)) {
|
||||
return _uhash_internalRemoveElement(hash, e);
|
||||
return _uhash_internalRemoveElement(hash, (UHashElement*) e);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -375,11 +419,6 @@ uhash_hashIChars(const void *key) {
|
||||
STRING_HASH(uint8_t, uprv_strlen((char*)p), uprv_tolower(*p));
|
||||
}
|
||||
|
||||
U_CAPI int32_t
|
||||
uhash_hashLong(const void *key) {
|
||||
return (int32_t) key;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* PUBLIC Comparator Functions
|
||||
********************************************************************/
|
||||
@ -435,6 +474,20 @@ uhash_compareIChars(const void *key1, const void *key2) {
|
||||
return (*p1 == *p2);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* PUBLIC int32_t Support Functions
|
||||
********************************************************************/
|
||||
|
||||
U_CAPI int32_t
|
||||
uhash_hashLong(const void *key) {
|
||||
return (int32_t) key;
|
||||
}
|
||||
|
||||
U_CAPI bool_t
|
||||
uhash_compareLong(const void *key1, const void *key2) {
|
||||
return key1 == key2;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* PUBLIC Deleter Functions
|
||||
********************************************************************/
|
||||
@ -448,13 +501,15 @@ uhash_freeBlock(void *obj) {
|
||||
* PRIVATE Implementation
|
||||
********************************************************************/
|
||||
|
||||
UHashtable*
|
||||
static UHashtable*
|
||||
_uhash_create(UHashFunction keyHash, UKeyComparator keyComp,
|
||||
int32_t primeIndex,
|
||||
UErrorCode *status) {
|
||||
UHashtable *result;
|
||||
|
||||
if (U_FAILURE(*status)) return NULL;
|
||||
assert(keyHash != NULL);
|
||||
assert(keyComp != NULL);
|
||||
|
||||
result = (UHashtable*) uprv_malloc(sizeof(UHashtable));
|
||||
if (result == NULL) {
|
||||
@ -462,13 +517,11 @@ _uhash_create(UHashFunction keyHash, UKeyComparator keyComp,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The high water ratio should match the PRIMES array */
|
||||
result->highWaterRatio = 0.5F;
|
||||
result->lowWaterRatio = 0.0F;
|
||||
result->keyHasher = keyHash;
|
||||
result->keyComparator = keyComp;
|
||||
result->keyDeleter = NULL;
|
||||
result->valueDeleter = NULL;
|
||||
_uhash_internalSetResizePolicy(result, U_GROW);
|
||||
|
||||
_uhash_allocate(result, primeIndex, status);
|
||||
|
||||
@ -489,7 +542,7 @@ _uhash_create(UHashFunction keyHash, UKeyComparator keyComp,
|
||||
*
|
||||
* Caller must ensure primeIndex is in range 0..PRIME_LENGTH-1.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
_uhash_allocate(UHashtable *hash,
|
||||
int32_t primeIndex,
|
||||
UErrorCode *status) {
|
||||
@ -533,7 +586,7 @@ _uhash_allocate(UHashtable *hash,
|
||||
* already at the low or high limit. In any case, upon return the
|
||||
* arrays will be valid.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
_uhash_rehash(UHashtable *hash) {
|
||||
|
||||
UHashElement *old = hash->elements;
|
||||
@ -604,9 +657,8 @@ _uhash_rehash(UHashtable *hash) {
|
||||
* The size of the table should be prime for this algorithm to work;
|
||||
* otherwise we are not guaranteed that the jump value (the secondary
|
||||
* hash) is relatively prime to the table length.
|
||||
|
||||
*/
|
||||
UHashElement*
|
||||
static UHashElement*
|
||||
_uhash_find(const UHashtable *hash, const void* key,
|
||||
int32_t hashcode) {
|
||||
|
||||
@ -658,7 +710,7 @@ _uhash_find(const UHashtable *hash, const void* key,
|
||||
return &(hash->elements[index]);
|
||||
}
|
||||
|
||||
void*
|
||||
static void*
|
||||
_uhash_setElement(UHashtable *hash, UHashElement* e,
|
||||
int32_t hashcode, void* key, void* value) {
|
||||
|
||||
@ -684,89 +736,18 @@ _uhash_setElement(UHashtable *hash, UHashElement* e,
|
||||
/**
|
||||
* Assumes that the given element is not empty or deleted.
|
||||
*/
|
||||
void*
|
||||
static void*
|
||||
_uhash_internalRemoveElement(UHashtable *hash, UHashElement* e) {
|
||||
assert(!IS_EMPTY_OR_DELETED(e->hashcode));
|
||||
--hash->count;
|
||||
return _uhash_setElement(hash, e, HASH_DELETED, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* BEGIN BACKWARD COMPATIBLITY */
|
||||
|
||||
U_CAPI int32_t
|
||||
uhash_OLD_put(UHashtable *hash,
|
||||
void *value,
|
||||
UErrorCode *status) {
|
||||
void *v;
|
||||
UHashFunction fn = uhash_setKeyHasher(hash, uhash_hashLong);
|
||||
int32_t hashcode = (fn)(value) & 0x7FFFFFFF;
|
||||
uhash_put(hash, (void*) hashcode, value, status);
|
||||
uhash_setKeyHasher(hash, fn);
|
||||
v = uhash_OLD_get(hash, hashcode);
|
||||
assert(v == value);
|
||||
return hashcode;
|
||||
static void
|
||||
_uhash_internalSetResizePolicy(UHashtable *hash, enum UHashResizePolicy policy) {
|
||||
assert(hash == 0);
|
||||
assert(((int32_t)policy) >= 0);
|
||||
assert(((int32_t)policy) < 3);
|
||||
hash->lowWaterRatio = RESIZE_POLICY_RATIO_TABLE[policy * 2];
|
||||
hash->highWaterRatio = RESIZE_POLICY_RATIO_TABLE[policy * 2 + 1];
|
||||
}
|
||||
|
||||
U_CAPI int32_t
|
||||
uhash_OLD_putKey(UHashtable *hash,
|
||||
int32_t hashcode,
|
||||
void *value,
|
||||
UErrorCode *status) {
|
||||
void *v;
|
||||
UHashFunction fn = uhash_setKeyHasher(hash, uhash_hashLong);
|
||||
uhash_put(hash, (void*) hashcode, value, status);
|
||||
uhash_setKeyHasher(hash, fn);
|
||||
v = uhash_OLD_get(hash, hashcode);
|
||||
assert(v == value);
|
||||
return hashcode;
|
||||
}
|
||||
|
||||
U_CAPI void*
|
||||
uhash_OLD_get(const UHashtable *hash,
|
||||
int32_t hashcode) {
|
||||
hashcode &= 0x7FFFFFFF;
|
||||
return _uhash_find(hash, (void*) hashcode, hashcode)->value;
|
||||
}
|
||||
|
||||
U_CAPI void*
|
||||
uhash_OLD_remove(UHashtable *hash,
|
||||
int32_t hashcode,
|
||||
UErrorCode *status) {
|
||||
void *v;
|
||||
UHashFunction fn = uhash_setKeyHasher(hash, uhash_hashLong);
|
||||
void* result = uhash_remove(hash, (void*) hashcode);
|
||||
uhash_setKeyHasher(hash, fn);
|
||||
v = uhash_OLD_get(hash, hashcode);
|
||||
assert(v == NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
U_CAPI void*
|
||||
uhash_OLD_nextElement(const UHashtable *hash,
|
||||
int32_t *pos) {
|
||||
UHashElement *e = uhash_nextElement(hash, pos);
|
||||
return (e == NULL) ? NULL : e->value;
|
||||
}
|
||||
|
||||
U_CAPI int32_t
|
||||
uhash_OLD_hashUString(const void *parm)
|
||||
{
|
||||
return uhash_hashUChars(parm) & 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
U_CAPI bool_t
|
||||
uhash_OLD_pointerComparator(const void* key1, const void* key2) {
|
||||
return key1 == key2;
|
||||
}
|
||||
|
||||
/* END BACKWARD COMPATIBLITY */
|
||||
|
@ -14,21 +14,30 @@
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
/**
|
||||
* UHashtable stores key-value pairs and does efficient lookup based
|
||||
* on keys. It also provides a protocol for enumerating through the
|
||||
* key-value pairs (in no particular order). Both keys and values are
|
||||
* stored as void* pointers. Hashing of keys and comparison of keys
|
||||
* are accomplished by user-supplied functions. Several prebuilt
|
||||
* UHashtable stores key-value pairs and does moderately fast lookup
|
||||
* based on keys. It provides a good tradeoff between access time and
|
||||
* storage space. As elements are added to it, it grows to accomodate
|
||||
* them. In its current implementation, the table never shrinks, even
|
||||
* if all elements are removed from it. Keys and values are stored as
|
||||
* void* pointers. Hashing of keys and comparison of keys are
|
||||
* accomplished by user-supplied functions. Several prebuilt
|
||||
* functions exist for common key types.
|
||||
*
|
||||
* UHashtable may optionally own either its keys or its values. To
|
||||
* accomplish this the key and/or value deleter function pointers must
|
||||
* be set to non-NULL values. If keys and/or values are owned, then
|
||||
* keys and/or values passed to uhash_put() are owned by the hashtable
|
||||
* and will be deleted by it at some point, either as keys and/or
|
||||
* values are replaced, or when uhash_close() is finally called. Keys
|
||||
* passed to methods other than uhash_put() are never owned by the
|
||||
* hashtable.
|
||||
* User-supplied functions also control ownership of keys and values.
|
||||
* If a void* key is actually a pointer to a deletable object, then
|
||||
* UHashtable can be made to delete that object by setting the key
|
||||
* deleter function pointer to a non-NULL value. If this is done,
|
||||
* then keys passed to uhash_put() are owned by the hashtable and will
|
||||
* be deleted by it at some point, either as keys are replaced, or
|
||||
* when uhash_close() is finally called. The same is true of values
|
||||
* and the value deleter function pointer. Keys passed to methods
|
||||
* other than uhash_put() are never owned by the hashtable.
|
||||
*
|
||||
* NULL values are not allowed, since uhash_get() returns NULL to
|
||||
* indicate a key that is not in the table. If a key and a NULL value
|
||||
* is passed to uhash_put(), this has the effect of doing a
|
||||
* uhash_remove() on that key. This keeps uhash_get(), uhash_count(),
|
||||
* and uhash_nextElement() consistent with one another.
|
||||
*
|
||||
* To see what's in a hashtable, use uhash_nextElement() to iterate
|
||||
* through its contents. Each call to this function returns a
|
||||
@ -38,6 +47,14 @@
|
||||
* However, if uhash_put() is called during iteration then the
|
||||
* iteration will be out of sync. Under no circumstances should the
|
||||
* hash element be modified directly.
|
||||
*
|
||||
* By default, the hashtable grows when necessary, but never shrinks,
|
||||
* even if all items are removed. For most applications this is
|
||||
* optimal. However, in a highly dynamic use where memory is at a
|
||||
* premium, the table can be set to both grow and shrink by calling
|
||||
* uhash_setResizePolicy() with the policy U_GROW_AND_SHRINK. In a
|
||||
* situation where memory the client wants a table that does not grow
|
||||
* at all, the constant U_FIXED can be used.
|
||||
*/
|
||||
|
||||
/********************************************************************
|
||||
@ -84,8 +101,18 @@ struct UHashElement {
|
||||
typedef struct UHashElement UHashElement;
|
||||
|
||||
/**
|
||||
* The UHashtable struct. Clients should treat this as an opaque data type
|
||||
* and manipulate it only through the uhash_... API.
|
||||
* This specifies whether or not, and how, the hastable resizes itself.
|
||||
* See uhash_setResizePolicy().
|
||||
*/
|
||||
enum UHashResizePolicy {
|
||||
U_GROW, /* Grow on demand, do not shrink */
|
||||
U_GROW_AND_SHRINK, /* Grow and shrink on demand */
|
||||
U_FIXED /* Never change size */
|
||||
};
|
||||
|
||||
/**
|
||||
* The UHashtable struct. Clients should treat this as an opaque data
|
||||
* type and manipulate it only through the uhash_... API.
|
||||
*/
|
||||
struct UHashtable {
|
||||
|
||||
@ -168,6 +195,8 @@ uhash_openSize(UHashFunction keyHash,
|
||||
U_CAPI void
|
||||
uhash_close(UHashtable *hash);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the function used to hash keys.
|
||||
* @param fn the function to be used hash keys; must not be NULL
|
||||
@ -209,6 +238,13 @@ uhash_setKeyDeleter(UHashtable *hash, UObjectDeleter fn);
|
||||
U_CAPI UObjectDeleter
|
||||
uhash_setValueDeleter(UHashtable *hash, UObjectDeleter fn);
|
||||
|
||||
/**
|
||||
* Specify whether or not, and how, the hastable resizes itself.
|
||||
* See enum UHashResizePolicy.
|
||||
*/
|
||||
U_CAPI void
|
||||
uhash_setResizePolicy(UHashtable *hash, enum UHashResizePolicy policy);
|
||||
|
||||
/**
|
||||
* Get the number of key-value pairs stored in a UHashtable.
|
||||
* @param hash The UHashtable to query.
|
||||
@ -221,9 +257,10 @@ uhash_count(const UHashtable *hash);
|
||||
* Put an item in a UHashtable. If the keyDeleter is non-NULL, then
|
||||
* the hashtable owns 'key' after this call. If the valueDeleter is
|
||||
* non-NULL, then the hashtable owns 'value' after this call.
|
||||
* Storing a NULL value is the same as calling uhash_remove().
|
||||
* @param hash The target UHashtable.
|
||||
* @param key The key to store.
|
||||
* @param value The value to store.
|
||||
* @param value The value to store, may be NULL (see above).
|
||||
* @param status A pointer to an UErrorCode to receive any errors.
|
||||
* @return The previous value, or NULL if none.
|
||||
* @see uhash_get
|
||||
@ -248,13 +285,19 @@ uhash_get(const UHashtable *hash,
|
||||
* Remove an item from a UHashtable.
|
||||
* @param hash The target UHashtable.
|
||||
* @param key The hash code of the value to be removed.
|
||||
* @param status A pointer to an UErrorCode to receive any errors.
|
||||
* @return The item removed, or 0 if not found.
|
||||
*/
|
||||
U_CAPI void*
|
||||
uhash_remove(UHashtable *hash,
|
||||
const void *key);
|
||||
|
||||
/**
|
||||
* Remove all items from a UHashtable.
|
||||
* @param hash The target UHashtable.
|
||||
*/
|
||||
U_CAPI void
|
||||
uhash_removeAll(UHashtable *hash);
|
||||
|
||||
/**
|
||||
* Iterate through the elements of a UHashtable. The caller must not
|
||||
* modify the returned object. However, uhash_removeElement() may be
|
||||
@ -268,7 +311,7 @@ uhash_remove(UHashtable *hash,
|
||||
* @return a hash element, or NULL if no further key-value pairs
|
||||
* exist in the table.
|
||||
*/
|
||||
U_CAPI UHashElement*
|
||||
U_CAPI const UHashElement*
|
||||
uhash_nextElement(const UHashtable *hash,
|
||||
int32_t *pos);
|
||||
|
||||
@ -279,14 +322,15 @@ uhash_nextElement(const UHashtable *hash,
|
||||
* @param e The element, returned by uhash_nextElement(), to remove.
|
||||
* Must not be NULL. Must not be an empty or deleted element (as long
|
||||
* as this was returned by uhash_nextElement() it will not be empty or
|
||||
* deleted).
|
||||
* deleted). Note: Although this parameter is const, it will be
|
||||
* modified.
|
||||
* @return the value that was removed.
|
||||
*/
|
||||
U_CAPI void*
|
||||
uhash_removeElement(UHashtable *hash, UHashElement* e);
|
||||
uhash_removeElement(UHashtable *hash, const UHashElement* e);
|
||||
|
||||
/********************************************************************
|
||||
* Key Hash Functions
|
||||
* UChar* and char* Support Functions
|
||||
********************************************************************/
|
||||
|
||||
/**
|
||||
@ -319,19 +363,6 @@ uhash_hashChars(const void *key);
|
||||
U_CAPI int32_t
|
||||
uhash_hashIChars(const void *key);
|
||||
|
||||
/**
|
||||
* Generate a hash code for a 32-bit integer. The hashcode is
|
||||
* identical to the void* value itself.
|
||||
* @param key The 32-bit integer (cast to void*) to hash.
|
||||
* @return A hash code for the key.
|
||||
*/
|
||||
U_CAPI int32_t
|
||||
uhash_hashLong(const void *key);
|
||||
|
||||
/********************************************************************
|
||||
* Key Comparators
|
||||
********************************************************************/
|
||||
|
||||
/**
|
||||
* Comparator for null-terminated UChar* strings. Use together with
|
||||
* uhash_hashUChars.
|
||||
@ -353,17 +384,6 @@ uhash_compareChars(const void *key1, const void *key2);
|
||||
U_CAPI bool_t
|
||||
uhash_compareIChars(const void *key1, const void *key2);
|
||||
|
||||
/********************************************************************
|
||||
* Object Deleters
|
||||
********************************************************************/
|
||||
|
||||
/**
|
||||
* Deleter for any key or value allocated using uprv_malloc. Calls
|
||||
* uprv_free.
|
||||
*/
|
||||
U_CAPI void
|
||||
uhash_freeBlock(void *obj);
|
||||
|
||||
/********************************************************************
|
||||
* UnicodeString Support Functions
|
||||
********************************************************************/
|
||||
@ -386,85 +406,31 @@ uhash_compareUnicodeString(const void *key1, const void *key2);
|
||||
U_CAPI void
|
||||
uhash_deleteUnicodeString(void *obj);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* BEGIN BACKWARD COMPATIBILITY
|
||||
* BEGIN BACKWARD COMPATIBILITY
|
||||
*
|
||||
* These functions will go away soon. Do not under any circumstances
|
||||
* use them. This means you.
|
||||
/********************************************************************
|
||||
* int32_t Support Functions
|
||||
********************************************************************/
|
||||
|
||||
/**
|
||||
* Put an item in a UHashtable.
|
||||
* @param hash The target UHashtable.
|
||||
* @param value The value to store.
|
||||
* @param status A pointer to an UErrorCode to receive any errors.
|
||||
* @return The hash code associated with value.
|
||||
* @see uhash_get
|
||||
* Hash function for 32-bit integer keys.
|
||||
*/
|
||||
U_CAPI int32_t
|
||||
uhash_OLD_put(UHashtable *hash,
|
||||
void *value,
|
||||
UErrorCode *status);
|
||||
|
||||
U_CAPI void*
|
||||
uhash_OLD_get(const UHashtable *hash,
|
||||
int32_t key);
|
||||
uhash_hashLong(const void *key);
|
||||
|
||||
/**
|
||||
* Put an item in a UHashtable.
|
||||
* @param hash The target UHashtable.
|
||||
* @param value The value to store.
|
||||
* @param status A pointer to an UErrorCode to receive any errors.
|
||||
* @return The hash code associated with value.
|
||||
* @see uhash_get
|
||||
* Comparator function for 32-bit integer keys.
|
||||
*/
|
||||
U_CAPI int32_t
|
||||
uhash_OLD_putKey(UHashtable *hash,
|
||||
int32_t valueKey,
|
||||
void *value,
|
||||
UErrorCode *status);
|
||||
|
||||
/**
|
||||
* Remove an item from a UHashtable.
|
||||
* @param hash The target UHashtable.
|
||||
* @param key The hash code of the value to be removed.
|
||||
* @param status A pointer to an UErrorCode to receive any errors.
|
||||
* @return The item removed, or 0 if not found.
|
||||
*/
|
||||
U_CAPI void*
|
||||
uhash_OLD_remove(UHashtable *hash,
|
||||
int32_t key,
|
||||
UErrorCode *status);
|
||||
|
||||
/**
|
||||
* Iterate through the elements of a UHashtable.
|
||||
* @param hash The target UHashtable.
|
||||
* @param pos A pointer to an integer. This should be set to -1 to retrieve
|
||||
* the first value, and should subsequently not be changed by the caller.
|
||||
* @return The next item in the hash table, or 0 if no items remain.
|
||||
*/
|
||||
U_CAPI void*
|
||||
uhash_OLD_nextElement(const UHashtable *hash,
|
||||
int32_t *pos);
|
||||
|
||||
U_CAPI int32_t
|
||||
uhash_OLD_hashUString(const void *key);
|
||||
|
||||
U_CAPI bool_t
|
||||
uhash_OLD_pointerComparator(const void* key1, const void* key2);
|
||||
uhash_compareLong(const void *key1, const void *key2);
|
||||
|
||||
/*********************************************************************
|
||||
* END BACKWARD COMPATIBILITY
|
||||
* END BACKWARD COMPATIBILITY
|
||||
/********************************************************************
|
||||
* Other Support Functions
|
||||
********************************************************************/
|
||||
|
||||
/**
|
||||
* Deleter for any key or value allocated using uprv_malloc. Calls
|
||||
* uprv_free.
|
||||
*/
|
||||
U_CAPI void
|
||||
uhash_freeBlock(void *obj);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user