U_CAPI void U_EXPORT2 uhash_close(UHashtable *hash) { U_ASSERT(hash != NULL); if (hash->elements != NULL) { if (hash->keyDeleter != NULL || hash->valueDeleter != NULL) { int32_t pos=-1; UHashElement *e; while ((e = (UHashElement*) uhash_nextElement(hash, &pos)) != NULL) { HASH_DELETE_KEY_VALUE(hash, e->key.pointer, e->value.pointer); } } uprv_free(hash->elements); hash->elements = NULL; } uprv_free(hash); }
U_CAPI void U_EXPORT2 uhash_close(UHashtable *hash) { if (hash == NULL) { return; } if (hash->elements != NULL) { if (hash->keyDeleter != NULL || hash->valueDeleter != NULL) { int32_t pos=UHASH_FIRST; UHashElement *e; while ((e = (UHashElement*) uhash_nextElement(hash, &pos)) != NULL) { HASH_DELETE_KEY_VALUE(hash, e->key.pointer, e->value.pointer); } } uprv_free(hash->elements); hash->elements = NULL; } if (hash->allocated) { uprv_free(hash); } }
static UHashTok _uhash_put(UHashtable *hash, UHashTok key, UHashTok value, int8_t hint, UErrorCode *status) { /* 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; UHashTok emptytok; if (U_FAILURE(*status)) { goto err; } U_ASSERT(hash != NULL); /* Cannot always check pointer here or iSeries sees NULL every time. */ if ((hint & HINT_VALUE_POINTER) && value.pointer == 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); U_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, hint); 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.pointer); emptytok.pointer = NULL; emptytok.integer = 0; return emptytok; }