ICU-1023 upgrade uhash to support int32_t keys on platforms with sizeof(void*) < 32
X-SVN-Rev: 5196
This commit is contained in:
parent
ac95eb8654
commit
1c40f7aebd
@ -50,6 +50,8 @@ public:
|
|||||||
|
|
||||||
void* remove(const UnicodeString& key);
|
void* remove(const UnicodeString& key);
|
||||||
|
|
||||||
|
const UHashElement* find(const UnicodeString& key) const;
|
||||||
|
|
||||||
const UHashElement* nextElement(int32_t& pos) const;
|
const UHashElement* nextElement(int32_t& pos) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -111,6 +113,10 @@ inline void* Hashtable::remove(const UnicodeString& key) {
|
|||||||
return uhash_remove(hash, &key);
|
return uhash_remove(hash, &key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const UHashElement* Hashtable::find(const UnicodeString& key) const {
|
||||||
|
return uhash_find(hash, &key);
|
||||||
|
}
|
||||||
|
|
||||||
inline const UHashElement* Hashtable::nextElement(int32_t& pos) const {
|
inline const UHashElement* Hashtable::nextElement(int32_t& pos) const {
|
||||||
return uhash_nextElement(hash, &pos);
|
return uhash_nextElement(hash, &pos);
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ UBool TaggedList::nextElement(const UnicodeString*& key,
|
|||||||
int32_t& pos) const {
|
int32_t& pos) const {
|
||||||
const UHashElement *e = hash->nextElement(pos);
|
const UHashElement *e = hash->nextElement(pos);
|
||||||
if (e != NULL) {
|
if (e != NULL) {
|
||||||
key = (const UnicodeString*) e->key;
|
key = (const UnicodeString*) e->key.pointer;
|
||||||
value = (const UnicodeString*) e->value;
|
value = (const UnicodeString*) e->value;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -318,12 +318,12 @@ ResourceBundle::~ResourceBundle()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ICU_RESBUND_USE_DEPRECATES
|
||||||
void
|
void
|
||||||
ResourceBundle::deleteValue(void *value) {
|
ResourceBundle::deleteValue(UHashKey value) {
|
||||||
delete (ResourceBundleData *)value;
|
delete (ResourceBundleData *)value.pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ICU_RESBUND_USE_DEPRECATES
|
|
||||||
void ResourceBundle::initItemCache(UErrorCode& error) {
|
void ResourceBundle::initItemCache(UErrorCode& error) {
|
||||||
if(fItemCache == 0) {
|
if(fItemCache == 0) {
|
||||||
fItemCache = uhash_open(uhash_hashChars, uhash_compareChars, &error);
|
fItemCache = uhash_open(uhash_hashChars, uhash_compareChars, &error);
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Date Name Description
|
* Date Name Description
|
||||||
* 03/22/00 aliu Adapted from original C++ ICU Hashtable.
|
* 03/22/00 aliu Adapted from original C++ ICU Hashtable.
|
||||||
|
* 07/06/01 aliu Modified to support int32_t keys on
|
||||||
|
* platforms with sizeof(void*) < 32.
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -107,9 +109,10 @@ static const float RESIZE_POLICY_RATIO_TABLE[6] = {
|
|||||||
|
|
||||||
#define IS_EMPTY_OR_DELETED(x) ((x) < 0)
|
#define IS_EMPTY_OR_DELETED(x) ((x) < 0)
|
||||||
|
|
||||||
#define HASH_DELETE_KEY_VALUE(hash, key, value) \
|
/* This macro expects a UHashKey.pointer as its keypointer parameter */
|
||||||
if (hash->keyDeleter != NULL && key != NULL) { \
|
#define HASH_DELETE_KEY_VALUE(hash, keypointer, value) \
|
||||||
(*hash->keyDeleter)(key); \
|
if (hash->keyDeleter != NULL && keypointer != NULL) { \
|
||||||
|
(*hash->keyDeleter)(keypointer); \
|
||||||
} \
|
} \
|
||||||
if (hash->valueDeleter != NULL && value != NULL) { \
|
if (hash->valueDeleter != NULL && value != NULL) { \
|
||||||
(*hash->valueDeleter)(value); \
|
(*hash->valueDeleter)(value); \
|
||||||
@ -151,13 +154,21 @@ static void _uhash_allocate(UHashtable *hash, int32_t primeIndex,
|
|||||||
|
|
||||||
static void _uhash_rehash(UHashtable *hash);
|
static void _uhash_rehash(UHashtable *hash);
|
||||||
|
|
||||||
static UHashElement* _uhash_find(const UHashtable *hash, const void* key,
|
static UHashElement* _uhash_find(const UHashtable *hash, UHashKey key,
|
||||||
int32_t hashcode);
|
int32_t hashcode);
|
||||||
|
|
||||||
|
static void* _uhash_put(UHashtable *hash,
|
||||||
|
UHashKey key,
|
||||||
|
void* value,
|
||||||
|
UErrorCode *status);
|
||||||
|
|
||||||
|
static void* _uhash_remove(UHashtable *hash,
|
||||||
|
UHashKey key);
|
||||||
|
|
||||||
static void* _uhash_internalRemoveElement(UHashtable *hash, UHashElement* e);
|
static void* _uhash_internalRemoveElement(UHashtable *hash, UHashElement* e);
|
||||||
|
|
||||||
static void* _uhash_setElement(UHashtable* hash, UHashElement* e,
|
static void* _uhash_setElement(UHashtable* hash, UHashElement* e,
|
||||||
int32_t hashcode, void* key, void* value);
|
int32_t hashcode, UHashKey key, void* value);
|
||||||
|
|
||||||
static void _uhash_internalSetResizePolicy(UHashtable *hash, enum UHashResizePolicy policy);
|
static void _uhash_internalSetResizePolicy(UHashtable *hash, enum UHashResizePolicy policy);
|
||||||
|
|
||||||
@ -194,7 +205,7 @@ uhash_close(UHashtable *hash) {
|
|||||||
int32_t pos=-1;
|
int32_t pos=-1;
|
||||||
UHashElement *e;
|
UHashElement *e;
|
||||||
while ((e = (UHashElement*) uhash_nextElement(hash, &pos)) != NULL) {
|
while ((e = (UHashElement*) uhash_nextElement(hash, &pos)) != NULL) {
|
||||||
HASH_DELETE_KEY_VALUE(hash, e->key, e->value);
|
HASH_DELETE_KEY_VALUE(hash, e->key.pointer, e->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uprv_free(hash->elements);
|
uprv_free(hash->elements);
|
||||||
@ -247,7 +258,17 @@ uhash_count(const UHashtable *hash) {
|
|||||||
U_CAPI void*
|
U_CAPI void*
|
||||||
uhash_get(const UHashtable *hash,
|
uhash_get(const UHashtable *hash,
|
||||||
const void* key) {
|
const void* key) {
|
||||||
return _uhash_find(hash, key, hash->keyHasher(key))->value;
|
UHashKey keyholder;
|
||||||
|
keyholder.pointer = (void*) key;
|
||||||
|
return _uhash_find(hash, keyholder, hash->keyHasher(keyholder))->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
U_CAPI void*
|
||||||
|
uhash_geti(const UHashtable *hash,
|
||||||
|
int32_t key) {
|
||||||
|
UHashKey keyholder;
|
||||||
|
keyholder.integer = key;
|
||||||
|
return _uhash_find(hash, keyholder, hash->keyHasher(keyholder))->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
U_CAPI void*
|
U_CAPI void*
|
||||||
@ -255,85 +276,35 @@ uhash_put(UHashtable *hash,
|
|||||||
void* key,
|
void* key,
|
||||||
void* value,
|
void* value,
|
||||||
UErrorCode *status) {
|
UErrorCode *status) {
|
||||||
|
UHashKey keyholder;
|
||||||
|
keyholder.pointer = key;
|
||||||
|
return _uhash_put(hash, keyholder, value, status);
|
||||||
|
}
|
||||||
|
|
||||||
/* Put finds the position in the table for the new value. If the
|
void*
|
||||||
* key is already in the table, it is deleted, if there is a
|
uhash_puti(UHashtable *hash,
|
||||||
* non-NULL keyDeleter. Then the key, the hash and the value are
|
int32_t key,
|
||||||
* all put at the position in their respective arrays.
|
void* value,
|
||||||
*/
|
UErrorCode *status) {
|
||||||
int32_t hashcode;
|
UHashKey keyholder;
|
||||||
UHashElement* e;
|
keyholder.integer = key;
|
||||||
|
return _uhash_put(hash, keyholder, value, status);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
hashcode = (*hash->keyHasher)(key);
|
|
||||||
e = _uhash_find(hash, key, hashcode);
|
|
||||||
assert(e != NULL);
|
|
||||||
|
|
||||||
if (IS_EMPTY_OR_DELETED(e->hashcode)) {
|
|
||||||
/* Important: We must never actually fill the table up. If we
|
|
||||||
* do so, then _uhash_find() will return NULL, and we'll have
|
|
||||||
* to check for NULL after every call to _uhash_find(). To
|
|
||||||
* avoid this we make sure there is always at least one empty
|
|
||||||
* or deleted slot in the table. This only is a problem if we
|
|
||||||
* are out of memory and rehash isn't working.
|
|
||||||
*/
|
|
||||||
++hash->count;
|
|
||||||
if (hash->count == hash->length) {
|
|
||||||
/* Don't allow count to reach length */
|
|
||||||
--hash->count;
|
|
||||||
*status = U_MEMORY_ALLOCATION_ERROR;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We must in all cases handle storage properly. If there was an
|
|
||||||
* old key, then it must be deleted (if the deleter != NULL).
|
|
||||||
* Make hashcodes stored in table positive.
|
|
||||||
*/
|
|
||||||
return _uhash_setElement(hash, e, hashcode & 0x7FFFFFFF, key, value);
|
|
||||||
|
|
||||||
err:
|
|
||||||
/* If the deleters are non-NULL, this method adopts its key and/or
|
|
||||||
* value arguments, and we must be sure to delete the key and/or
|
|
||||||
* value in all cases, even upon failure.
|
|
||||||
*/
|
|
||||||
HASH_DELETE_KEY_VALUE(hash, key, value);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
U_CAPI void*
|
U_CAPI void*
|
||||||
uhash_remove(UHashtable *hash,
|
uhash_remove(UHashtable *hash,
|
||||||
const void* key) {
|
const void* key) {
|
||||||
/* First find the position of the key in the table. If the object
|
UHashKey keyholder;
|
||||||
* has not been removed already, remove it. If the user wanted
|
keyholder.pointer = (void*) key;
|
||||||
* keys deleted, then delete it also. We have to put a special
|
return _uhash_remove(hash, keyholder);
|
||||||
* hashcode in that position that means that something has been
|
}
|
||||||
* deleted, since when we do a find, we have to continue PAST any
|
|
||||||
* deleted values.
|
U_CAPI void*
|
||||||
*/
|
uhash_removei(UHashtable *hash,
|
||||||
void* result = NULL;
|
int32_t key) {
|
||||||
UHashElement* e = _uhash_find(hash, key, hash->keyHasher(key));
|
UHashKey keyholder;
|
||||||
assert(e != NULL);
|
keyholder.integer = key;
|
||||||
if (!IS_EMPTY_OR_DELETED(e->hashcode)) {
|
return _uhash_remove(hash, keyholder);
|
||||||
result = _uhash_internalRemoveElement(hash, e);
|
|
||||||
if (hash->count < hash->lowWaterMark) {
|
|
||||||
_uhash_rehash(hash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
U_CAPI void
|
U_CAPI void
|
||||||
@ -349,6 +320,15 @@ uhash_removeAll(UHashtable *hash) {
|
|||||||
assert(hash->count == 0);
|
assert(hash->count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
U_CAPI const UHashElement*
|
||||||
|
uhash_find(const UHashtable *hash, const void* key) {
|
||||||
|
UHashKey keyholder;
|
||||||
|
const UHashElement *e;
|
||||||
|
keyholder.pointer = (void*) key;
|
||||||
|
e = _uhash_find(hash, keyholder, hash->keyHasher(keyholder));
|
||||||
|
return IS_EMPTY_OR_DELETED(e->hashcode) ? NULL : e;
|
||||||
|
}
|
||||||
|
|
||||||
U_CAPI const UHashElement*
|
U_CAPI const UHashElement*
|
||||||
uhash_nextElement(const UHashtable *hash, int32_t *pos) {
|
uhash_nextElement(const UHashtable *hash, int32_t *pos) {
|
||||||
/* Walk through the array until we find an element that is not
|
/* Walk through the array until we find an element that is not
|
||||||
@ -390,10 +370,10 @@ uhash_removeElement(UHashtable *hash, const UHashElement* e) {
|
|||||||
the output range. [LIU]
|
the output range. [LIU]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define STRING_HASH(TYPE, STRLEN, DEREF) \
|
#define STRING_HASH(TYPE, STR, STRLEN, DEREF) \
|
||||||
int32_t hash = 0; \
|
int32_t hash = 0; \
|
||||||
if (key != NULL) { \
|
const TYPE *p = (const TYPE*) STR; \
|
||||||
const TYPE *p = (const TYPE*) key; \
|
if (p != NULL) { \
|
||||||
int32_t len = STRLEN; \
|
int32_t len = STRLEN; \
|
||||||
int32_t inc = ((len - 32) / 32) + 1; \
|
int32_t inc = ((len - 32) / 32) + 1; \
|
||||||
const TYPE *limit = p + len; \
|
const TYPE *limit = p + len; \
|
||||||
@ -405,24 +385,24 @@ uhash_removeElement(UHashtable *hash, const UHashElement* e) {
|
|||||||
return hash
|
return hash
|
||||||
|
|
||||||
U_CAPI int32_t
|
U_CAPI int32_t
|
||||||
uhash_hashUChars(const void *key) {
|
uhash_hashUChars(const UHashKey key) {
|
||||||
STRING_HASH(UChar, u_strlen(p), *p);
|
STRING_HASH(UChar, key.pointer, u_strlen(p), *p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used by UnicodeString to compute its hashcode - Not public API. */
|
/* Used by UnicodeString to compute its hashcode - Not public API. */
|
||||||
U_CAPI int32_t
|
U_CAPI int32_t
|
||||||
uhash_hashUCharsN(const UChar *key, int32_t length) {
|
uhash_hashUCharsN(const UChar *str, int32_t length) {
|
||||||
STRING_HASH(UChar, length, *p);
|
STRING_HASH(UChar, str, length, *p);
|
||||||
}
|
}
|
||||||
|
|
||||||
U_CAPI int32_t
|
U_CAPI int32_t
|
||||||
uhash_hashChars(const void *key) {
|
uhash_hashChars(const UHashKey key) {
|
||||||
STRING_HASH(uint8_t, uprv_strlen((char*)p), *p);
|
STRING_HASH(uint8_t, key.pointer, uprv_strlen((char*)p), *p);
|
||||||
}
|
}
|
||||||
|
|
||||||
U_CAPI int32_t
|
U_CAPI int32_t
|
||||||
uhash_hashIChars(const void *key) {
|
uhash_hashIChars(const UHashKey key) {
|
||||||
STRING_HASH(uint8_t, uprv_strlen((char*)p), uprv_tolower(*p));
|
STRING_HASH(uint8_t, key.pointer, uprv_strlen((char*)p), uprv_tolower(*p));
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
@ -430,9 +410,9 @@ uhash_hashIChars(const void *key) {
|
|||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
U_CAPI UBool
|
U_CAPI UBool
|
||||||
uhash_compareUChars(const void *key1, const void *key2) {
|
uhash_compareUChars(const UHashKey key1, const UHashKey key2) {
|
||||||
const UChar *p1 = (const UChar*) key1;
|
const UChar *p1 = (const UChar*) key1.pointer;
|
||||||
const UChar *p2 = (const UChar*) key2;
|
const UChar *p2 = (const UChar*) key2.pointer;
|
||||||
if (p1 == p2) {
|
if (p1 == p2) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -447,9 +427,9 @@ uhash_compareUChars(const void *key1, const void *key2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
U_CAPI UBool
|
U_CAPI UBool
|
||||||
uhash_compareChars(const void *key1, const void *key2) {
|
uhash_compareChars(const UHashKey key1, const UHashKey key2) {
|
||||||
const char *p1 = (const char*) key1;
|
const char *p1 = (const char*) key1.pointer;
|
||||||
const char *p2 = (const char*) key2;
|
const char *p2 = (const char*) key2.pointer;
|
||||||
if (p1 == p2) {
|
if (p1 == p2) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -464,9 +444,9 @@ uhash_compareChars(const void *key1, const void *key2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
U_CAPI UBool
|
U_CAPI UBool
|
||||||
uhash_compareIChars(const void *key1, const void *key2) {
|
uhash_compareIChars(const UHashKey key1, const UHashKey key2) {
|
||||||
const char *p1 = (const char*) key1;
|
const char *p1 = (const char*) key1.pointer;
|
||||||
const char *p2 = (const char*) key2;
|
const char *p2 = (const char*) key2.pointer;
|
||||||
if (p1 == p2) {
|
if (p1 == p2) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -485,13 +465,13 @@ uhash_compareIChars(const void *key1, const void *key2) {
|
|||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
U_CAPI int32_t
|
U_CAPI int32_t
|
||||||
uhash_hashLong(const void *key) {
|
uhash_hashLong(const UHashKey key) {
|
||||||
return (int32_t) key;
|
return key.integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
U_CAPI UBool
|
U_CAPI UBool
|
||||||
uhash_compareLong(const void *key1, const void *key2) {
|
uhash_compareLong(const UHashKey key1, const UHashKey key2) {
|
||||||
return (UBool)(key1 == key2);
|
return (UBool)(key1.integer == key2.integer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
@ -554,6 +534,7 @@ _uhash_allocate(UHashtable *hash,
|
|||||||
UErrorCode *status) {
|
UErrorCode *status) {
|
||||||
|
|
||||||
UHashElement *p, *limit;
|
UHashElement *p, *limit;
|
||||||
|
UHashKey emptykey;
|
||||||
|
|
||||||
if (U_FAILURE(*status)) return;
|
if (U_FAILURE(*status)) return;
|
||||||
|
|
||||||
@ -570,9 +551,12 @@ _uhash_allocate(UHashtable *hash,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emptykey.pointer = NULL; /* Only one of these two is needed */
|
||||||
|
emptykey.integer = 0; /* but we don't know which one. */
|
||||||
|
|
||||||
limit = p + hash->length;
|
limit = p + hash->length;
|
||||||
while (p < limit) {
|
while (p < limit) {
|
||||||
p->key = NULL;
|
p->key = emptykey;
|
||||||
p->value = NULL;
|
p->value = NULL;
|
||||||
p->hashcode = HASH_EMPTY;
|
p->hashcode = HASH_EMPTY;
|
||||||
++p;
|
++p;
|
||||||
@ -665,7 +649,7 @@ _uhash_rehash(UHashtable *hash) {
|
|||||||
* hash) is relatively prime to the table length.
|
* hash) is relatively prime to the table length.
|
||||||
*/
|
*/
|
||||||
static UHashElement*
|
static UHashElement*
|
||||||
_uhash_find(const UHashtable *hash, const void* key,
|
_uhash_find(const UHashtable *hash, UHashKey key,
|
||||||
int32_t hashcode) {
|
int32_t hashcode) {
|
||||||
|
|
||||||
int32_t firstDeleted = -1; /* assume invalid index */
|
int32_t firstDeleted = -1; /* assume invalid index */
|
||||||
@ -717,13 +701,99 @@ _uhash_find(const UHashtable *hash, const void* key,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void*
|
static void*
|
||||||
_uhash_setElement(UHashtable *hash, UHashElement* e,
|
_uhash_put(UHashtable *hash,
|
||||||
int32_t hashcode, void* key, void* value) {
|
UHashKey key,
|
||||||
|
void* value,
|
||||||
|
UErrorCode *status) {
|
||||||
|
|
||||||
void* oldKey = e->key;
|
/* Put finds the position in the table for the new value. If the
|
||||||
|
* key is already in the table, it is deleted, if there is a
|
||||||
|
* non-NULL keyDeleter. Then the key, the hash and the value are
|
||||||
|
* all put at the position in their respective arrays.
|
||||||
|
*/
|
||||||
|
int32_t hashcode;
|
||||||
|
UHashElement* e;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
hashcode = (*hash->keyHasher)(key);
|
||||||
|
e = _uhash_find(hash, key, hashcode);
|
||||||
|
assert(e != NULL);
|
||||||
|
|
||||||
|
if (IS_EMPTY_OR_DELETED(e->hashcode)) {
|
||||||
|
/* Important: We must never actually fill the table up. If we
|
||||||
|
* do so, then _uhash_find() will return NULL, and we'll have
|
||||||
|
* to check for NULL after every call to _uhash_find(). To
|
||||||
|
* avoid this we make sure there is always at least one empty
|
||||||
|
* or deleted slot in the table. This only is a problem if we
|
||||||
|
* are out of memory and rehash isn't working.
|
||||||
|
*/
|
||||||
|
++hash->count;
|
||||||
|
if (hash->count == hash->length) {
|
||||||
|
/* Don't allow count to reach length */
|
||||||
|
--hash->count;
|
||||||
|
*status = U_MEMORY_ALLOCATION_ERROR;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We must in all cases handle storage properly. If there was an
|
||||||
|
* old key, then it must be deleted (if the deleter != NULL).
|
||||||
|
* Make hashcodes stored in table positive.
|
||||||
|
*/
|
||||||
|
return _uhash_setElement(hash, e, hashcode & 0x7FFFFFFF, key, value);
|
||||||
|
|
||||||
|
err:
|
||||||
|
/* If the deleters are non-NULL, this method adopts its key and/or
|
||||||
|
* value arguments, and we must be sure to delete the key and/or
|
||||||
|
* value in all cases, even upon failure.
|
||||||
|
*/
|
||||||
|
HASH_DELETE_KEY_VALUE(hash, key.pointer, value);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void*
|
||||||
|
_uhash_remove(UHashtable *hash,
|
||||||
|
UHashKey key) {
|
||||||
|
/* First find the position of the key in the table. If the object
|
||||||
|
* has not been removed already, remove it. If the user wanted
|
||||||
|
* keys deleted, then delete it also. We have to put a special
|
||||||
|
* hashcode in that position that means that something has been
|
||||||
|
* deleted, since when we do a find, we have to continue PAST any
|
||||||
|
* deleted values.
|
||||||
|
*/
|
||||||
|
void* result = NULL;
|
||||||
|
UHashElement* e = _uhash_find(hash, key, hash->keyHasher(key));
|
||||||
|
assert(e != NULL);
|
||||||
|
if (!IS_EMPTY_OR_DELETED(e->hashcode)) {
|
||||||
|
result = _uhash_internalRemoveElement(hash, e);
|
||||||
|
if (hash->count < hash->lowWaterMark) {
|
||||||
|
_uhash_rehash(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void*
|
||||||
|
_uhash_setElement(UHashtable *hash, UHashElement* e,
|
||||||
|
int32_t hashcode, UHashKey key, void* value) {
|
||||||
|
|
||||||
|
void* oldKey = e->key.pointer;
|
||||||
void* oldValue = e->value;
|
void* oldValue = e->value;
|
||||||
if (hash->keyDeleter != NULL && oldKey != NULL &&
|
if (hash->keyDeleter != NULL && oldKey != NULL &&
|
||||||
oldKey != key) { /* Avoid double deletion */
|
oldKey != key.pointer) { /* Avoid double deletion */
|
||||||
(*hash->keyDeleter)(oldKey);
|
(*hash->keyDeleter)(oldKey);
|
||||||
}
|
}
|
||||||
if (oldValue == value) { /* Avoid double deletion */
|
if (oldValue == value) { /* Avoid double deletion */
|
||||||
@ -733,6 +803,10 @@ _uhash_setElement(UHashtable *hash, UHashElement* e,
|
|||||||
(*hash->valueDeleter)(oldValue);
|
(*hash->valueDeleter)(oldValue);
|
||||||
oldValue = NULL;
|
oldValue = NULL;
|
||||||
}
|
}
|
||||||
|
/* Compilers should copy the UHashKey union correctly. If they do
|
||||||
|
* not, replace this line with e->key.pointer = key.pointer for
|
||||||
|
* platforms with sizeof(void*) >= sizeof(int32_t), e->key.integer
|
||||||
|
* = key.integer otherwise. */
|
||||||
e->key = key;
|
e->key = key;
|
||||||
e->value = value;
|
e->value = value;
|
||||||
e->hashcode = hashcode;
|
e->hashcode = hashcode;
|
||||||
@ -744,9 +818,11 @@ _uhash_setElement(UHashtable *hash, UHashElement* e,
|
|||||||
*/
|
*/
|
||||||
static void*
|
static void*
|
||||||
_uhash_internalRemoveElement(UHashtable *hash, UHashElement* e) {
|
_uhash_internalRemoveElement(UHashtable *hash, UHashElement* e) {
|
||||||
|
UHashKey emptykey;
|
||||||
assert(!IS_EMPTY_OR_DELETED(e->hashcode));
|
assert(!IS_EMPTY_OR_DELETED(e->hashcode));
|
||||||
--hash->count;
|
--hash->count;
|
||||||
return _uhash_setElement(hash, e, HASH_DELETED, NULL, NULL);
|
emptykey.pointer = NULL; emptykey.integer = 0;
|
||||||
|
return _uhash_setElement(hash, e, HASH_DELETED, emptykey, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Date Name Description
|
* Date Name Description
|
||||||
* 03/22/00 aliu Adapted from original C++ ICU Hashtable.
|
* 03/22/00 aliu Adapted from original C++ ICU Hashtable.
|
||||||
|
* 07/06/01 aliu Modified to support int32_t keys on
|
||||||
|
* platforms with sizeof(void*) < 32.
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -73,12 +75,39 @@
|
|||||||
|
|
||||||
U_CDECL_BEGIN
|
U_CDECL_BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A key within the hashtable. The key may be either a 32-bit
|
||||||
|
* integral value or an opaque void* pointer. The void* pointer may
|
||||||
|
* be smaller than 32 bits (e.g. 24 bits) or may be larger (e.g. 64
|
||||||
|
* bits). The hashing and comparison functions take a pointer to a
|
||||||
|
* UHashKey, but the deleter receives the void* pointer within it.
|
||||||
|
*
|
||||||
|
* Because a UHashKey is the size of a native pointer or a 32-bit
|
||||||
|
* integer, we pass it around by value.
|
||||||
|
*/
|
||||||
|
union UHashKey {
|
||||||
|
void* pointer;
|
||||||
|
int32_t integer;
|
||||||
|
};
|
||||||
|
typedef union UHashKey UHashKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a single hash element.
|
||||||
|
*/
|
||||||
|
struct UHashElement {
|
||||||
|
/* Reorder these elements to pack nicely if necessary */
|
||||||
|
int32_t hashcode;
|
||||||
|
void* value;
|
||||||
|
UHashKey key;
|
||||||
|
};
|
||||||
|
typedef struct UHashElement UHashElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A hashing function.
|
* A hashing function.
|
||||||
* @param key A key stored in a hashtable
|
* @param key A key stored in a hashtable
|
||||||
* @return A NON-NEGATIVE hash code for parm.
|
* @return A NON-NEGATIVE hash code for parm.
|
||||||
*/
|
*/
|
||||||
typedef int32_t (* U_CALLCONV UHashFunction)(const void* key);
|
typedef int32_t (* U_CALLCONV UHashFunction)(const UHashKey key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A key comparison function.
|
* A key comparison function.
|
||||||
@ -86,8 +115,8 @@ typedef int32_t (* U_CALLCONV UHashFunction)(const void* key);
|
|||||||
* @param key2 A key stored in a hashtable
|
* @param key2 A key stored in a hashtable
|
||||||
* @return TRUE if the two keys are equal.
|
* @return TRUE if the two keys are equal.
|
||||||
*/
|
*/
|
||||||
typedef UBool (* U_CALLCONV UKeyComparator)(const void* key1,
|
typedef UBool (* U_CALLCONV UKeyComparator)(const UHashKey key1,
|
||||||
const void* key2);
|
const UHashKey key2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function called by <TT>uhash_remove</TT>,
|
* A function called by <TT>uhash_remove</TT>,
|
||||||
@ -97,19 +126,6 @@ typedef UBool (* U_CALLCONV UKeyComparator)(const void* key1,
|
|||||||
*/
|
*/
|
||||||
typedef void (* U_CALLCONV UObjectDeleter)(void* obj);
|
typedef void (* U_CALLCONV UObjectDeleter)(void* obj);
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a single hash element. These should pack nicely
|
|
||||||
* into exactly 24 bytes. If this is not true, then split
|
|
||||||
* the elements array into 3 separate arrays for the hash,
|
|
||||||
* key, and value.
|
|
||||||
*/
|
|
||||||
struct UHashElement {
|
|
||||||
int32_t hashcode;
|
|
||||||
void* key;
|
|
||||||
void* value;
|
|
||||||
};
|
|
||||||
typedef struct UHashElement UHashElement;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This specifies whether or not, and how, the hastable resizes itself.
|
* This specifies whether or not, and how, the hastable resizes itself.
|
||||||
* See uhash_setResizePolicy().
|
* See uhash_setResizePolicy().
|
||||||
@ -282,26 +298,43 @@ uhash_put(UHashtable *hash,
|
|||||||
void *value,
|
void *value,
|
||||||
UErrorCode *status);
|
UErrorCode *status);
|
||||||
|
|
||||||
|
/* NEW */
|
||||||
|
U_CAPI void*
|
||||||
|
uhash_puti(UHashtable *hash,
|
||||||
|
int32_t key,
|
||||||
|
void* value,
|
||||||
|
UErrorCode *status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an item from a UHashtable.
|
* Get an item from a UHashtable.
|
||||||
* @param hash The target UHashtable.
|
* @param hash The target UHashtable.
|
||||||
* @param key The hash code of the desired value.
|
* @param key A key stored in a hashtable
|
||||||
* @return The requested item, or 0 if not found.
|
* @return The requested item, or 0 if not found.
|
||||||
*/
|
*/
|
||||||
U_CAPI void*
|
U_CAPI void*
|
||||||
uhash_get(const UHashtable *hash,
|
uhash_get(const UHashtable *hash,
|
||||||
const void *key);
|
const void *key);
|
||||||
|
|
||||||
|
/* NEW */
|
||||||
|
U_CAPI void*
|
||||||
|
uhash_geti(const UHashtable *hash,
|
||||||
|
int32_t key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove an item from a UHashtable.
|
* Remove an item from a UHashtable.
|
||||||
* @param hash The target UHashtable.
|
* @param hash The target UHashtable.
|
||||||
* @param key The hash code of the value to be removed.
|
* @param key A key stored in a hashtable
|
||||||
* @return The item removed, or 0 if not found.
|
* @return The item removed, or 0 if not found.
|
||||||
*/
|
*/
|
||||||
U_CAPI void*
|
U_CAPI void*
|
||||||
uhash_remove(UHashtable *hash,
|
uhash_remove(UHashtable *hash,
|
||||||
const void *key);
|
const void *key);
|
||||||
|
|
||||||
|
/* NEW */
|
||||||
|
U_CAPI void*
|
||||||
|
uhash_removei(UHashtable *hash,
|
||||||
|
int32_t key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all items from a UHashtable.
|
* Remove all items from a UHashtable.
|
||||||
* @param hash The target UHashtable.
|
* @param hash The target UHashtable.
|
||||||
@ -309,6 +342,20 @@ uhash_remove(UHashtable *hash,
|
|||||||
U_CAPI void
|
U_CAPI void
|
||||||
uhash_removeAll(UHashtable *hash);
|
uhash_removeAll(UHashtable *hash);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locate an element of a UHashtable. The caller must not modify the
|
||||||
|
* returned object. The primary use of this function is to obtain the
|
||||||
|
* stored key when it may not be identical to the search key. For
|
||||||
|
* example, if the compare function is a case-insensitive string
|
||||||
|
* compare, then the hash key may be desired in order to obtain the
|
||||||
|
* canonical case corresponding to a search key.
|
||||||
|
* @param hash The target UHashtable.
|
||||||
|
* @param key A key stored in a hashtable
|
||||||
|
* @return a hash element, or NULL if the key is not found.
|
||||||
|
*/
|
||||||
|
U_CAPI const UHashElement*
|
||||||
|
uhash_find(const UHashtable *hash, const void* key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterate through the elements of a UHashtable. The caller must not
|
* Iterate through the elements of a UHashtable. The caller must not
|
||||||
* modify the returned object. However, uhash_removeElement() may be
|
* modify the returned object. However, uhash_removeElement() may be
|
||||||
@ -352,7 +399,7 @@ uhash_removeElement(UHashtable *hash, const UHashElement* e);
|
|||||||
* @return A hash code for the key.
|
* @return A hash code for the key.
|
||||||
*/
|
*/
|
||||||
U_CAPI int32_t
|
U_CAPI int32_t
|
||||||
uhash_hashUChars(const void *key);
|
uhash_hashUChars(const UHashKey key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a hash code for a null-terminated char* string. If the
|
* Generate a hash code for a null-terminated char* string. If the
|
||||||
@ -362,7 +409,7 @@ uhash_hashUChars(const void *key);
|
|||||||
* @return A hash code for the key.
|
* @return A hash code for the key.
|
||||||
*/
|
*/
|
||||||
U_CAPI int32_t
|
U_CAPI int32_t
|
||||||
uhash_hashChars(const void *key);
|
uhash_hashChars(const UHashKey key);
|
||||||
|
|
||||||
/* Used by UnicodeString to compute its hashcode - Not public API. */
|
/* Used by UnicodeString to compute its hashcode - Not public API. */
|
||||||
U_CAPI int32_t
|
U_CAPI int32_t
|
||||||
@ -376,28 +423,28 @@ uhash_hashUCharsN(const UChar *key, int32_t length);
|
|||||||
* @return A hash code for the key.
|
* @return A hash code for the key.
|
||||||
*/
|
*/
|
||||||
U_CAPI int32_t
|
U_CAPI int32_t
|
||||||
uhash_hashIChars(const void *key);
|
uhash_hashIChars(const UHashKey key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comparator for null-terminated UChar* strings. Use together with
|
* Comparator for null-terminated UChar* strings. Use together with
|
||||||
* uhash_hashUChars.
|
* uhash_hashUChars.
|
||||||
*/
|
*/
|
||||||
U_CAPI UBool
|
U_CAPI UBool
|
||||||
uhash_compareUChars(const void *key1, const void *key2);
|
uhash_compareUChars(const UHashKey key1, const UHashKey key2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comparator for null-terminated char* strings. Use together with
|
* Comparator for null-terminated char* strings. Use together with
|
||||||
* uhash_hashChars.
|
* uhash_hashChars.
|
||||||
*/
|
*/
|
||||||
U_CAPI UBool
|
U_CAPI UBool
|
||||||
uhash_compareChars(const void *key1, const void *key2);
|
uhash_compareChars(const UHashKey key1, const UHashKey key2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Case-insensitive comparator for null-terminated char* strings. Use
|
* Case-insensitive comparator for null-terminated char* strings. Use
|
||||||
* together with uhash_hashIChars.
|
* together with uhash_hashIChars.
|
||||||
*/
|
*/
|
||||||
U_CAPI UBool
|
U_CAPI UBool
|
||||||
uhash_compareIChars(const void *key1, const void *key2);
|
uhash_compareIChars(const UHashKey key1, const UHashKey key2);
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* UnicodeString Support Functions
|
* UnicodeString Support Functions
|
||||||
@ -407,27 +454,27 @@ uhash_compareIChars(const void *key1, const void *key2);
|
|||||||
* Hash function for UnicodeString* keys.
|
* Hash function for UnicodeString* keys.
|
||||||
*/
|
*/
|
||||||
U_CAPI int32_t
|
U_CAPI int32_t
|
||||||
uhash_hashUnicodeString(const void *key);
|
uhash_hashUnicodeString(const UHashKey key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash function for UnicodeString* keys (case insensitive).
|
* Hash function for UnicodeString* keys (case insensitive).
|
||||||
* Make sure to use together with uhash_compareCaselessUnicodeString.
|
* Make sure to use together with uhash_compareCaselessUnicodeString.
|
||||||
*/
|
*/
|
||||||
U_CAPI int32_t
|
U_CAPI int32_t
|
||||||
uhash_hashCaselessUnicodeString(const void *key);
|
uhash_hashCaselessUnicodeString(const UHashKey key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comparator function for UnicodeString* keys.
|
* Comparator function for UnicodeString* keys.
|
||||||
*/
|
*/
|
||||||
U_CAPI UBool
|
U_CAPI UBool
|
||||||
uhash_compareUnicodeString(const void *key1, const void *key2);
|
uhash_compareUnicodeString(const UHashKey key1, const UHashKey key2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comparator function for UnicodeString* keys (case insensitive).
|
* Comparator function for UnicodeString* keys (case insensitive).
|
||||||
* Make sure to use together with uhash_hashCaselessUnicodeString.
|
* Make sure to use together with uhash_hashCaselessUnicodeString.
|
||||||
*/
|
*/
|
||||||
U_CAPI UBool
|
U_CAPI UBool
|
||||||
uhash_compareCaselessUnicodeString(const void *key1, const void *key2);
|
uhash_compareCaselessUnicodeString(const UHashKey key1, const UHashKey key2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deleter function for UnicodeString* keys or values.
|
* Deleter function for UnicodeString* keys or values.
|
||||||
@ -443,13 +490,13 @@ uhash_deleteUnicodeString(void *obj);
|
|||||||
* Hash function for 32-bit integer keys.
|
* Hash function for 32-bit integer keys.
|
||||||
*/
|
*/
|
||||||
U_CAPI int32_t
|
U_CAPI int32_t
|
||||||
uhash_hashLong(const void *key);
|
uhash_hashLong(const UHashKey key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comparator function for 32-bit integer keys.
|
* Comparator function for 32-bit integer keys.
|
||||||
*/
|
*/
|
||||||
U_CAPI UBool
|
U_CAPI UBool
|
||||||
uhash_compareLong(const void *key1, const void *key2);
|
uhash_compareLong(const UHashKey key1, const UHashKey key2);
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Other Support Functions
|
* Other Support Functions
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Date Name Description
|
* Date Name Description
|
||||||
* 03/22/00 aliu Creation.
|
* 03/22/00 aliu Creation.
|
||||||
|
* 07/06/01 aliu Modified to support int32_t keys on
|
||||||
|
* platforms with sizeof(void*) < 32.
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -16,18 +18,20 @@
|
|||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
U_CAPI int32_t
|
U_CAPI int32_t
|
||||||
uhash_hashUnicodeString(const void *key) {
|
uhash_hashUnicodeString(const UHashKey key) {
|
||||||
return (key == NULL) ? 0 : ((UnicodeString*)key)->hashCode();
|
const UnicodeString *str = (const UnicodeString*) key.pointer;
|
||||||
|
return (str == NULL) ? 0 : str->hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
U_CAPI int32_t
|
U_CAPI int32_t
|
||||||
uhash_hashCaselessUnicodeString(const void *key) {
|
uhash_hashCaselessUnicodeString(const UHashKey key) {
|
||||||
if (key == NULL) {
|
const UnicodeString *str = (const UnicodeString*) key.pointer;
|
||||||
|
if (str == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// Inefficient; a better way would be to have a hash function in
|
// Inefficient; a better way would be to have a hash function in
|
||||||
// UnicodeString that does case folding on the fly.
|
// UnicodeString that does case folding on the fly.
|
||||||
UnicodeString copy(*(UnicodeString*) key);
|
UnicodeString copy(*str);
|
||||||
return copy.foldCase().hashCode();
|
return copy.foldCase().hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,24 +41,27 @@ uhash_deleteUnicodeString(void *obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
U_CAPI UBool
|
U_CAPI UBool
|
||||||
uhash_compareUnicodeString(const void *key1, const void *key2) {
|
uhash_compareUnicodeString(const UHashKey key1, const UHashKey key2) {
|
||||||
if (key1 == key2) {
|
const UnicodeString *str1 = (const UnicodeString*) key1.pointer;
|
||||||
|
const UnicodeString *str2 = (const UnicodeString*) key2.pointer;
|
||||||
|
if (str1 == str2) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
if (key1 == NULL || key2 == NULL) {
|
if (str1 == NULL || str2 == NULL) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return *((UnicodeString*) key1) == *((UnicodeString*) key2);
|
return *str1 == *str2;
|
||||||
}
|
}
|
||||||
|
|
||||||
U_CAPI UBool
|
U_CAPI UBool
|
||||||
uhash_compareCaselessUnicodeString(const void *key1, const void *key2) {
|
uhash_compareCaselessUnicodeString(const UHashKey key1, const UHashKey key2) {
|
||||||
if (key1 == key2) {
|
const UnicodeString *str1 = (const UnicodeString*) key1.pointer;
|
||||||
|
const UnicodeString *str2 = (const UnicodeString*) key2.pointer;
|
||||||
|
if (str1 == str2) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
if (key1 == NULL || key2 == NULL) {
|
if (str1 == NULL || str2 == NULL) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return ((UnicodeString*) key1)->caseCompare(*(UnicodeString*)key2,
|
return str1->caseCompare(*str2, U_FOLD_CASE_DEFAULT) == 0;
|
||||||
U_FOLD_CASE_DEFAULT) == 0;
|
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,7 @@ class ResourceBundle;
|
|||||||
|
|
||||||
#ifdef ICU_RESBUND_USE_DEPRECATES
|
#ifdef ICU_RESBUND_USE_DEPRECATES
|
||||||
struct UHashtable;
|
struct UHashtable;
|
||||||
|
union UHashKey;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -563,10 +564,10 @@ private:
|
|||||||
UErrorCode& status);
|
UErrorCode& status);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void U_CALLCONV deleteValue(void* value);
|
|
||||||
Locale fRealLocale;
|
Locale fRealLocale;
|
||||||
|
|
||||||
#ifdef ICU_RESBUND_USE_DEPRECATES
|
#ifdef ICU_RESBUND_USE_DEPRECATES
|
||||||
|
static void U_CALLCONV deleteValue(UHashKey value);
|
||||||
UHashtable* fItemCache;
|
UHashtable* fItemCache;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -37,18 +37,25 @@ static UBool isMutexInited = FALSE;
|
|||||||
static UMTX resbMutex = NULL;
|
static UMTX resbMutex = NULL;
|
||||||
|
|
||||||
/* INTERNAL: hashes an entry */
|
/* INTERNAL: hashes an entry */
|
||||||
static int32_t hashEntry(const void *parm) {
|
static int32_t hashEntry(const UHashKey parm) {
|
||||||
UResourceDataEntry *b = (UResourceDataEntry *)parm;
|
UResourceDataEntry *b = (UResourceDataEntry *)parm.pointer;
|
||||||
return uhash_hashChars(b->fName)+37*uhash_hashChars(b->fPath);
|
UHashKey namekey, pathkey;
|
||||||
|
namekey.pointer = b->fName;
|
||||||
|
pathkey.pointer = b->fPath;
|
||||||
|
return uhash_hashChars(namekey)+37*uhash_hashChars(pathkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* INTERNAL: compares two entries */
|
/* INTERNAL: compares two entries */
|
||||||
static UBool compareEntries(const void *p1, const void *p2) {
|
static UBool compareEntries(const UHashKey p1, const UHashKey p2) {
|
||||||
UResourceDataEntry *b1 = (UResourceDataEntry *)p1;
|
UResourceDataEntry *b1 = (UResourceDataEntry *)p1.pointer;
|
||||||
UResourceDataEntry *b2 = (UResourceDataEntry *)p2;
|
UResourceDataEntry *b2 = (UResourceDataEntry *)p2.pointer;
|
||||||
|
UHashKey name1, name2, path1, path2;
|
||||||
return (UBool)(uhash_compareChars(b1->fName, b2->fName) &
|
name1.pointer = b1->fName;
|
||||||
uhash_compareChars(b1->fPath, b2->fPath));
|
name2.pointer = b2->fName;
|
||||||
|
path1.pointer = b1->fPath;
|
||||||
|
path2.pointer = b2->fPath;
|
||||||
|
return (UBool)(uhash_compareChars(name1, name2) &
|
||||||
|
uhash_compareChars(path1, path2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -177,7 +184,7 @@ static UResourceDataEntry *init_entry(const char *localeID, const char *path, UE
|
|||||||
char aliasName[100] = { 0 };
|
char aliasName[100] = { 0 };
|
||||||
int32_t aliasLen = 0;
|
int32_t aliasLen = 0;
|
||||||
UBool isAlias = FALSE;
|
UBool isAlias = FALSE;
|
||||||
|
UHashKey hashkey;
|
||||||
|
|
||||||
if(U_FAILURE(*status)) {
|
if(U_FAILURE(*status)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -202,7 +209,8 @@ static UResourceDataEntry *init_entry(const char *localeID, const char *path, UE
|
|||||||
find.fPath = (char *)myPath;
|
find.fPath = (char *)myPath;
|
||||||
|
|
||||||
/* calculate the hash value of the entry */
|
/* calculate the hash value of the entry */
|
||||||
hashValue = hashEntry((const void *)&find);
|
hashkey.pointer = (void *)&find;
|
||||||
|
hashValue = hashEntry(hashkey);
|
||||||
|
|
||||||
/* check to see if we already have this entry */
|
/* check to see if we already have this entry */
|
||||||
r = (UResourceDataEntry *)uhash_get(cache, &find);
|
r = (UResourceDataEntry *)uhash_get(cache, &find);
|
||||||
|
@ -40,7 +40,7 @@ TransliterationRuleData::TransliterationRuleData(const TransliterationRuleData&
|
|||||||
while ((e = other.variableNames->nextElement(pos)) != 0) {
|
while ((e = other.variableNames->nextElement(pos)) != 0) {
|
||||||
UnicodeString* value =
|
UnicodeString* value =
|
||||||
new UnicodeString(*(const UnicodeString*)e->value);
|
new UnicodeString(*(const UnicodeString*)e->value);
|
||||||
variableNames->put(*(UnicodeString*)e->key, value, status);
|
variableNames->put(*(UnicodeString*)e->key.pointer, value, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +305,9 @@ CollationKey::hashCode() const
|
|||||||
|
|
||||||
if (fHashCode == kInvalidHashCode)
|
if (fHashCode == kInvalidHashCode)
|
||||||
{
|
{
|
||||||
((CollationKey *)this)->fHashCode = uhash_hashChars(fBytes);
|
UHashKey key;
|
||||||
|
key.pointer = fBytes;
|
||||||
|
((CollationKey *)this)->fHashCode = uhash_hashChars(key);
|
||||||
#if 0
|
#if 0
|
||||||
// We compute the hash by iterating sparsely over 64 (at most) characters
|
// We compute the hash by iterating sparsely over 64 (at most) characters
|
||||||
// spaced evenly through the string. For each character, we multiply the
|
// spaced evenly through the string. For each character, we multiply the
|
||||||
|
@ -907,6 +907,18 @@ UChar Transliterator::filteredCharAt(const Replaceable& text, int32_t i) const {
|
|||||||
(localFilter->contains(c = text.charAt(i)) ? c : (UChar)0xFFFE);
|
(localFilter->contains(c = text.charAt(i)) ? c : (UChar)0xFFFE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Move this into the class
|
||||||
|
/**
|
||||||
|
* Comparison function for UVector.
|
||||||
|
*/
|
||||||
|
static UBool
|
||||||
|
_compareCaselessUnicodeString(const void* a, const void* b) {
|
||||||
|
UHashKey s, t;
|
||||||
|
s.pointer = (void*) a;
|
||||||
|
t.pointer = (void*) b;
|
||||||
|
return uhash_compareCaselessUnicodeString(s, t);
|
||||||
|
}
|
||||||
|
|
||||||
void Transliterator::initializeCache(void) {
|
void Transliterator::initializeCache(void) {
|
||||||
// Lock first, check init boolean second
|
// Lock first, check init boolean second
|
||||||
Mutex lock(&cacheMutex);
|
Mutex lock(&cacheMutex);
|
||||||
@ -920,7 +932,7 @@ void Transliterator::initializeCache(void) {
|
|||||||
// That way if the resource is absent, we will at least
|
// That way if the resource is absent, we will at least
|
||||||
// have a valid cache object.
|
// have a valid cache object.
|
||||||
cacheIDs.setDeleter(uhash_deleteUnicodeString);
|
cacheIDs.setDeleter(uhash_deleteUnicodeString);
|
||||||
cacheIDs.setComparer(uhash_compareCaselessUnicodeString);
|
cacheIDs.setComparer(_compareCaselessUnicodeString);
|
||||||
|
|
||||||
/* The following code parses the index table located in
|
/* The following code parses the index table located in
|
||||||
* icu/data/translit_index.txt. The index is an n x 4 table
|
* icu/data/translit_index.txt. The index is an n x 4 table
|
||||||
|
@ -24,10 +24,10 @@
|
|||||||
const UChar *rulesToParse = 0;
|
const UChar *rulesToParse = 0;
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
uhash_hashTokens(const void *k) {
|
uhash_hashTokens(const UHashKey k) {
|
||||||
int32_t hash = 0;
|
int32_t hash = 0;
|
||||||
if (k != NULL) {
|
uint32_t key = (uint32_t)k.integer;
|
||||||
uint32_t key = (uint32_t)k;
|
if (key != 0) {
|
||||||
int32_t len = (key & 0xFF000000)>>24;
|
int32_t len = (key & 0xFF000000)>>24;
|
||||||
int32_t inc = ((len - 32) / 32) + 1;
|
int32_t inc = ((len - 32) / 32) + 1;
|
||||||
|
|
||||||
@ -42,9 +42,9 @@ uhash_hashTokens(const void *k) {
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
UBool uhash_compareTokens(const void *key1, const void *key2) {
|
UBool uhash_compareTokens(const UHashKey key1, const UHashKey key2) {
|
||||||
uint32_t p1 = (uint32_t) key1;
|
uint32_t p1 = (uint32_t) key1.integer;
|
||||||
uint32_t p2 = (uint32_t) key2;
|
uint32_t p2 = (uint32_t) key2.integer;
|
||||||
const UChar *s1 = (p1 & 0x00FFFFFF) + rulesToParse;
|
const UChar *s1 = (p1 & 0x00FFFFFF) + rulesToParse;
|
||||||
const UChar *s2 = (p2 & 0x00FFFFFF) + rulesToParse;
|
const UChar *s2 = (p2 & 0x00FFFFFF) + rulesToParse;
|
||||||
uint32_t s1L = ((p1 & 0xFF000000) >> 24);
|
uint32_t s1L = ((p1 & 0xFF000000) >> 24);
|
||||||
|
@ -21,9 +21,10 @@
|
|||||||
#define UCOL_SOL_H
|
#define UCOL_SOL_H
|
||||||
|
|
||||||
#include "unicode/utypes.h"
|
#include "unicode/utypes.h"
|
||||||
|
#include "uhash.h"
|
||||||
|
|
||||||
U_CFUNC int32_t uhash_hashTokens(const void *k);
|
U_CFUNC int32_t uhash_hashTokens(const UHashKey k);
|
||||||
U_CFUNC UBool uhash_compareTokens(const void *key1, const void *key2);
|
U_CFUNC UBool uhash_compareTokens(const UHashKey key1, const UHashKey key2);
|
||||||
U_CFUNC void deleteToken(void *token);
|
U_CFUNC void deleteToken(void *token);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -650,7 +650,7 @@ uint32_t ucol_tok_assembleTokenList(UColTokenParser *src, UErrorCode *status) {
|
|||||||
key = newCharsLen << 24 | charsOffset;
|
key = newCharsLen << 24 | charsOffset;
|
||||||
|
|
||||||
/* 4 Lookup each source in the CharsToToken map, and find a sourceToken */
|
/* 4 Lookup each source in the CharsToToken map, and find a sourceToken */
|
||||||
sourceToken = (UColToken *)uhash_get(uchars2tokens, (void *)key);
|
sourceToken = (UColToken *)uhash_geti(uchars2tokens, (int32_t)key);
|
||||||
|
|
||||||
if(newStrength != UCOL_TOK_RESET) {
|
if(newStrength != UCOL_TOK_RESET) {
|
||||||
if(lastToken == NULL) { /* this means that rules haven't started properly */
|
if(lastToken == NULL) { /* this means that rules haven't started properly */
|
||||||
@ -670,7 +670,7 @@ uint32_t ucol_tok_assembleTokenList(UColTokenParser *src, UErrorCode *status) {
|
|||||||
sourceToken->previous = NULL;
|
sourceToken->previous = NULL;
|
||||||
sourceToken->noOfCEs = 0;
|
sourceToken->noOfCEs = 0;
|
||||||
sourceToken->noOfExpCEs = 0;
|
sourceToken->noOfExpCEs = 0;
|
||||||
uhash_put(uchars2tokens, (void *)sourceToken->source, sourceToken, status);
|
uhash_puti(uchars2tokens, (int32_t)sourceToken->source, sourceToken, status);
|
||||||
} else {
|
} else {
|
||||||
/* we could have fished out a reset here */
|
/* we could have fished out a reset here */
|
||||||
if(sourceToken->strength != UCOL_TOK_RESET && lastToken != sourceToken) {
|
if(sourceToken->strength != UCOL_TOK_RESET && lastToken != sourceToken) {
|
||||||
@ -808,7 +808,7 @@ uint32_t ucol_tok_assembleTokenList(UColTokenParser *src, UErrorCode *status) {
|
|||||||
while(searchCharsLen > 1 && sourceToken == NULL) {
|
while(searchCharsLen > 1 && sourceToken == NULL) {
|
||||||
searchCharsLen--;
|
searchCharsLen--;
|
||||||
key = searchCharsLen << 24 | charsOffset;
|
key = searchCharsLen << 24 | charsOffset;
|
||||||
sourceToken = (UColToken *)uhash_get(uchars2tokens, (void *)key);
|
sourceToken = (UColToken *)uhash_geti(uchars2tokens, (int32_t)key);
|
||||||
}
|
}
|
||||||
if(sourceToken != NULL) {
|
if(sourceToken != NULL) {
|
||||||
expandNext = (newCharsLen - searchCharsLen) << 24 | (charsOffset + searchCharsLen);
|
expandNext = (newCharsLen - searchCharsLen) << 24 | (charsOffset + searchCharsLen);
|
||||||
@ -920,7 +920,7 @@ uint32_t ucol_tok_assembleTokenList(UColTokenParser *src, UErrorCode *status) {
|
|||||||
ListList[src->resultLen].reset = sourceToken;
|
ListList[src->resultLen].reset = sourceToken;
|
||||||
|
|
||||||
src->resultLen++;
|
src->resultLen++;
|
||||||
uhash_put(uchars2tokens, (void *)sourceToken->source, sourceToken, status);
|
uhash_puti(uchars2tokens, (int32_t)sourceToken->source, sourceToken, status);
|
||||||
} else { /* reset to something already in rules */
|
} else { /* reset to something already in rules */
|
||||||
top = FALSE;
|
top = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,9 @@
|
|||||||
static void TestBasic(void);
|
static void TestBasic(void);
|
||||||
static void TestOtherAPI(void);
|
static void TestOtherAPI(void);
|
||||||
|
|
||||||
static int32_t hashChars(const void* key);
|
static int32_t hashChars(const UHashKey key);
|
||||||
|
|
||||||
static UBool isEqualChars(const void* key1, const void* key2);
|
static UBool isEqualChars(const UHashKey key1, const UHashKey key2);
|
||||||
|
|
||||||
static void _put(UHashtable* hash,
|
static void _put(UHashtable* hash,
|
||||||
const char* key,
|
const char* key,
|
||||||
@ -41,6 +41,42 @@ static void _remove(UHashtable* hash,
|
|||||||
|
|
||||||
void addHashtableTest(TestNode** root);
|
void addHashtableTest(TestNode** root);
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* UHashKey wrapper functions
|
||||||
|
*********************************************************************/
|
||||||
|
|
||||||
|
static UBool
|
||||||
|
_compareChars(void* a, void* b) {
|
||||||
|
UHashKey s, t;
|
||||||
|
s.pointer = a;
|
||||||
|
t.pointer = b;
|
||||||
|
return uhash_compareChars(s, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static UBool
|
||||||
|
_compareIChars(void* a, void* b) {
|
||||||
|
UHashKey s, t;
|
||||||
|
s.pointer = a;
|
||||||
|
t.pointer = b;
|
||||||
|
return uhash_compareIChars(s, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static UBool
|
||||||
|
_compareUChars(void* a, void* b) {
|
||||||
|
UHashKey s, t;
|
||||||
|
s.pointer = a;
|
||||||
|
t.pointer = b;
|
||||||
|
return uhash_compareUChars(s, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static UBool
|
||||||
|
_compareLong(int32_t a, int32_t b) {
|
||||||
|
UHashKey s, t;
|
||||||
|
s.integer = a;
|
||||||
|
t.integer = b;
|
||||||
|
return uhash_compareLong(s, t);
|
||||||
|
}
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* FW Registration
|
* FW Registration
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
@ -93,16 +129,16 @@ static void TestBasic(void) {
|
|||||||
_get(hash, omega, 48);
|
_get(hash, omega, 48);
|
||||||
_get(hash, two, 200);
|
_get(hash, two, 200);
|
||||||
|
|
||||||
if(uhash_compareChars((void*)one, (void*)three) == TRUE ||
|
if(_compareChars((void*)one, (void*)three) == TRUE ||
|
||||||
uhash_compareChars((void*)one, (void*)one2) != TRUE ||
|
_compareChars((void*)one, (void*)one2) != TRUE ||
|
||||||
uhash_compareChars((void*)one, (void*)one) != TRUE ||
|
_compareChars((void*)one, (void*)one) != TRUE ||
|
||||||
uhash_compareChars((void*)one, NULL) == TRUE ) {
|
_compareChars((void*)one, NULL) == TRUE ) {
|
||||||
log_err("FAIL: compareChars failed\n");
|
log_err("FAIL: compareChars failed\n");
|
||||||
}
|
}
|
||||||
if(uhash_compareIChars((void*)one, (void*)three) == TRUE ||
|
if(_compareIChars((void*)one, (void*)three) == TRUE ||
|
||||||
uhash_compareIChars((void*)one, (void*)one) != TRUE ||
|
_compareIChars((void*)one, (void*)one) != TRUE ||
|
||||||
uhash_compareIChars((void*)one, (void*)one2) != TRUE ||
|
_compareIChars((void*)one, (void*)one2) != TRUE ||
|
||||||
uhash_compareIChars((void*)one, NULL) == TRUE ) {
|
_compareIChars((void*)one, NULL) == TRUE ) {
|
||||||
log_err("FAIL: compareIChars failed\n");
|
log_err("FAIL: compareIChars failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,10 +213,10 @@ static void TestOtherAPI(void){
|
|||||||
log_err("FAIL: uhash_put() with value!=NULL didn't replace the key value pair\n");
|
log_err("FAIL: uhash_put() with value!=NULL didn't replace the key value pair\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(uhash_compareUChars((void*)one, (void*)two) == TRUE ||
|
if(_compareUChars((void*)one, (void*)two) == TRUE ||
|
||||||
uhash_compareUChars((void*)one, (void*)one) != TRUE ||
|
_compareUChars((void*)one, (void*)one) != TRUE ||
|
||||||
uhash_compareUChars((void*)one, (void*)one2) != TRUE ||
|
_compareUChars((void*)one, (void*)one2) != TRUE ||
|
||||||
uhash_compareUChars((void*)one, NULL) == TRUE ) {
|
_compareUChars((void*)one, NULL) == TRUE ) {
|
||||||
log_err("FAIL: compareUChars failed\n");
|
log_err("FAIL: compareUChars failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,27 +227,27 @@ static void TestOtherAPI(void){
|
|||||||
|
|
||||||
uhash_setKeyComparator(hash, uhash_compareLong);
|
uhash_setKeyComparator(hash, uhash_compareLong);
|
||||||
uhash_setKeyHasher(hash, uhash_hashLong);
|
uhash_setKeyHasher(hash, uhash_hashLong);
|
||||||
uhash_put(hash, (void*)1001, (void*)1, &status);
|
uhash_puti(hash, 1001, (void*)1, &status);
|
||||||
uhash_put(hash, (void*)1002, (void*)2, &status);
|
uhash_puti(hash, 1002, (void*)2, &status);
|
||||||
uhash_put(hash, (void*)1003, (void*)3, &status);
|
uhash_puti(hash, 1003, (void*)3, &status);
|
||||||
if(uhash_compareLong((void*)1001, (void*)1002) == TRUE ||
|
if(_compareLong(1001, 1002) == TRUE ||
|
||||||
uhash_compareLong((void*)1001, (void*)1001) != TRUE ||
|
_compareLong(1001, 1001) != TRUE ||
|
||||||
uhash_compareLong((void*)1001, NULL) == TRUE ) {
|
_compareLong(1001, 0) == TRUE ) {
|
||||||
log_err("FAIL: compareLong failed\n");
|
log_err("FAIL: compareLong failed\n");
|
||||||
}
|
}
|
||||||
/*set the resize policy to just GROW and SHRINK*/
|
/*set the resize policy to just GROW and SHRINK*/
|
||||||
/*how to test this??*/
|
/*how to test this??*/
|
||||||
uhash_setResizePolicy(hash, U_GROW_AND_SHRINK);
|
uhash_setResizePolicy(hash, U_GROW_AND_SHRINK);
|
||||||
uhash_put(hash, (void*)1004, (void*)4, &status);
|
uhash_puti(hash, 1004, (void*)4, &status);
|
||||||
uhash_put(hash, (void*)1005, (void*)5, &status);
|
uhash_puti(hash, 1005, (void*)5, &status);
|
||||||
uhash_put(hash, (void*)1006, (void*)6, &status);
|
uhash_puti(hash, 1006, (void*)6, &status);
|
||||||
if(uhash_count(hash) != 6){
|
if(uhash_count(hash) != 6){
|
||||||
log_err("FAIL: uhash_count() failed. Expected: 6, Got: %d\n", uhash_count(hash));
|
log_err("FAIL: uhash_count() failed. Expected: 6, Got: %d\n", uhash_count(hash));
|
||||||
}
|
}
|
||||||
if((int32_t)uhash_remove(hash, (void*)1004) != 4){
|
if((int32_t)uhash_removei(hash, 1004) != 4){
|
||||||
log_err("FAIL: uhash_remove failed\n");
|
log_err("FAIL: uhash_remove failed\n");
|
||||||
}
|
}
|
||||||
if((int32_t)uhash_remove(hash, (void*)1004) != 0){
|
if((int32_t)uhash_removei(hash, 1004) != 0){
|
||||||
log_err("FAIL: uhash_remove failed\n");
|
log_err("FAIL: uhash_remove failed\n");
|
||||||
}
|
}
|
||||||
uhash_close(hash);
|
uhash_close(hash);
|
||||||
@ -225,14 +261,14 @@ static void TestOtherAPI(void){
|
|||||||
* This hash function is designed to collide a lot to test key equality
|
* This hash function is designed to collide a lot to test key equality
|
||||||
* resolution. It only uses the first char.
|
* resolution. It only uses the first char.
|
||||||
*/
|
*/
|
||||||
static int32_t hashChars(const void* key) {
|
static int32_t hashChars(const UHashKey key) {
|
||||||
return *(const char*) key;
|
return *(const char*) key.pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UBool isEqualChars(const void* key1, const void* key2) {
|
static UBool isEqualChars(const UHashKey key1, const UHashKey key2) {
|
||||||
return (UBool)((key1 != NULL) &&
|
return (UBool)((key1.pointer != NULL) &&
|
||||||
(key2 != NULL) &&
|
(key2.pointer != NULL) &&
|
||||||
(uprv_strcmp((const char*)key1, (const char*)key2) == 0));
|
(uprv_strcmp((const char*)key1.pointer, (const char*)key2.pointer) == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
|
@ -88,7 +88,9 @@ UBool SimpleFwdCharIterator::operator==(const ForwardCharacterIterator& that) co
|
|||||||
int32_t SimpleFwdCharIterator::hashCode(void) const {
|
int32_t SimpleFwdCharIterator::hashCode(void) const {
|
||||||
if (fHashCode == kInvalidHashCode)
|
if (fHashCode == kInvalidHashCode)
|
||||||
{
|
{
|
||||||
((SimpleFwdCharIterator *)this)->fHashCode = uhash_hashUChars(fStart);
|
UHashKey key;
|
||||||
|
key.pointer = fStart;
|
||||||
|
((SimpleFwdCharIterator *)this)->fHashCode = uhash_hashUChars(key);
|
||||||
}
|
}
|
||||||
return fHashCode;
|
return fHashCode;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user