mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
No OOM in hash_may_resize() and hash_add_item()
hash_add() can still return FAIL if the key already exists.
This commit is contained in:
parent
6f29364632
commit
48fc1602be
@ -5781,7 +5781,7 @@ static dict_T *dict_copy(dict_T *orig, int deep, int copyID)
|
||||
|
||||
/*
|
||||
* Add item "item" to Dictionary "d".
|
||||
* Returns FAIL when out of memory and when key already exists.
|
||||
* Returns FAIL when key already exists.
|
||||
*/
|
||||
int dict_add(dict_T *d, dictitem_T *item)
|
||||
{
|
||||
@ -5815,7 +5815,7 @@ int dict_add_nr_str(dict_T *d, char *key, long nr, char_u *str)
|
||||
|
||||
/*
|
||||
* Add a list entry to dictionary "d".
|
||||
* Returns FAIL when out of memory and when key already exists.
|
||||
* Returns FAIL when key already exists.
|
||||
*/
|
||||
int dict_add_list(dict_T *d, char *key, list_T *list)
|
||||
{
|
||||
|
@ -171,7 +171,7 @@ void hash_debug_results(void)
|
||||
/// in the new item (@see hashitem_T). Must not be NULL.
|
||||
///
|
||||
/// @return OK if success.
|
||||
/// FAIL if key already present, or out of memory.
|
||||
/// FAIL if key already present
|
||||
int hash_add(hashtab_T *ht, char_u *key)
|
||||
{
|
||||
hash_T hash = hash_hash(key);
|
||||
@ -180,7 +180,8 @@ int hash_add(hashtab_T *ht, char_u *key)
|
||||
EMSG2(_(e_intern2), "hash_add()");
|
||||
return FAIL;
|
||||
}
|
||||
return hash_add_item(ht, hi, key, hash);
|
||||
hash_add_item(ht, hi, key, hash);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/// Add item "hi" for key "key" to hashtable "ht".
|
||||
@ -190,16 +191,8 @@ int hash_add(hashtab_T *ht, char_u *key)
|
||||
/// @param key Pointer to the key for the new item. The key has to be contained
|
||||
/// in the new item (@see hashitem_T). Must not be NULL.
|
||||
/// @param hash The precomputed hash value for the key.
|
||||
///
|
||||
/// @return OK if success.
|
||||
/// FAIL if out of memory.
|
||||
int hash_add_item(hashtab_T *ht, hashitem_T *hi, char_u *key, hash_T hash)
|
||||
void hash_add_item(hashtab_T *ht, hashitem_T *hi, char_u *key, hash_T hash)
|
||||
{
|
||||
// If resizing failed before and it fails again we can't add an item.
|
||||
if (ht->ht_error && (hash_may_resize(ht, 0) == FAIL)) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
ht->ht_used++;
|
||||
if (hi->hi_key == NULL) {
|
||||
ht->ht_filled++;
|
||||
@ -208,7 +201,7 @@ int hash_add_item(hashtab_T *ht, hashitem_T *hi, char_u *key, hash_T hash)
|
||||
hi->hi_hash = hash;
|
||||
|
||||
// When the space gets low may resize the array.
|
||||
return hash_may_resize(ht, 0);
|
||||
hash_may_resize(ht, 0);
|
||||
}
|
||||
|
||||
/// Remove item "hi" from hashtable "ht".
|
||||
@ -250,14 +243,11 @@ void hash_unlock(hashtab_T *ht)
|
||||
/// - Shrink when too much empty space.
|
||||
/// - Grow when not enough empty space.
|
||||
/// If non-zero, passed minitems will be used.
|
||||
///
|
||||
/// @return OK if success.
|
||||
/// FAIL if out of memory.
|
||||
static int hash_may_resize(hashtab_T *ht, size_t minitems)
|
||||
static void hash_may_resize(hashtab_T *ht, size_t minitems)
|
||||
{
|
||||
// Don't resize a locked table.
|
||||
if (ht->ht_locked > 0) {
|
||||
return OK;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HT_DEBUG
|
||||
@ -276,7 +266,7 @@ static int hash_may_resize(hashtab_T *ht, size_t minitems)
|
||||
// items are required for the lookup to decide a key isn't there.
|
||||
if ((ht->ht_filled < HT_INIT_SIZE - 1)
|
||||
&& (ht->ht_array == ht->ht_smallarray)) {
|
||||
return OK;
|
||||
return;
|
||||
}
|
||||
|
||||
// Grow or refill the array when it's more than 2/3 full (including
|
||||
@ -285,7 +275,7 @@ static int hash_may_resize(hashtab_T *ht, size_t minitems)
|
||||
// at least 1/4 full (avoids repeated grow-shrink operations)
|
||||
size_t oldsize = ht->ht_mask + 1;
|
||||
if ((ht->ht_filled * 3 < oldsize * 2) && (ht->ht_used > oldsize / 5)) {
|
||||
return OK;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ht->ht_used > 1000) {
|
||||
@ -309,10 +299,8 @@ static int hash_may_resize(hashtab_T *ht, size_t minitems)
|
||||
while (newsize < minsize) {
|
||||
// make sure it's always a power of 2
|
||||
newsize <<= 1;
|
||||
if (newsize == 0) {
|
||||
// overflow
|
||||
return FAIL;
|
||||
}
|
||||
// assert newsize didn't overflow
|
||||
assert(newsize != 0);
|
||||
}
|
||||
|
||||
bool newarray_is_small = newsize == HT_INIT_SIZE;
|
||||
@ -364,9 +352,6 @@ static int hash_may_resize(hashtab_T *ht, size_t minitems)
|
||||
ht->ht_array = newarray;
|
||||
ht->ht_mask = newmask;
|
||||
ht->ht_filled = ht->ht_used;
|
||||
ht->ht_error = false;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/// Get the hash number for a key.
|
||||
|
@ -59,8 +59,6 @@ typedef struct hashtable_S {
|
||||
size_t ht_used; /// number of items used
|
||||
size_t ht_filled; /// number of items used or removed
|
||||
int ht_locked; /// counter for hash_lock()
|
||||
bool ht_error; /// when set growing failed, can't add more
|
||||
/// items before growing works
|
||||
hashitem_T *ht_array; /// points to the array, allocated when it's
|
||||
/// not "ht_smallarray"
|
||||
hashitem_T ht_smallarray[HT_INIT_SIZE]; /// initial array
|
||||
@ -69,4 +67,5 @@ typedef struct hashtable_S {
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "hashtab.h.generated.h"
|
||||
#endif
|
||||
|
||||
#endif // NVIM_HASHTAB_H
|
||||
|
Loading…
Reference in New Issue
Block a user