Search and remove an element. This is an helper function for * dictDelete() and dictUnlink(), please check the top comment * of those functions. */
| 703 | * dictDelete() and dictUnlink(), please check the top comment |
| 704 | * of those functions. */ |
| 705 | static dictEntry *dictGenericDelete(dict *d, const void *key, int nofree) { |
| 706 | uint64_t h, idx; |
| 707 | dictEntry *he, *prevHe; |
| 708 | int table; |
| 709 | |
| 710 | // if we are deleting elements we probably aren't mass inserting anymore and it is safe to shrink |
| 711 | d->noshrink = false; |
| 712 | |
| 713 | if (d->ht[0].used == 0 && d->ht[1].used == 0) return NULL; |
| 714 | |
| 715 | if (dictIsRehashing(d)) _dictRehashStep(d); |
| 716 | h = dictHashKey(d, key); |
| 717 | |
| 718 | for (table = 0; table <= 1; table++) { |
| 719 | idx = h & d->ht[table].sizemask; |
| 720 | he = d->ht[table].table[idx]; |
| 721 | prevHe = NULL; |
| 722 | while(he) { |
| 723 | if (key==he->key || dictCompareKeys(d, key, he->key)) { |
| 724 | /* Unlink the element from the list */ |
| 725 | if (prevHe) |
| 726 | prevHe->next = he->next; |
| 727 | else |
| 728 | d->ht[table].table[idx] = he->next; |
| 729 | if (!nofree) { |
| 730 | if (table == 0 && d->asyncdata != nullptr && (ssize_t)idx < d->rehashidx) { |
| 731 | dictFreeVal(d, he); |
| 732 | he->v.val = nullptr; |
| 733 | he->next = d->asyncdata->deGCList; |
| 734 | d->asyncdata->deGCList = he; |
| 735 | } else { |
| 736 | dictFreeKey(d, he); |
| 737 | dictFreeVal(d, he); |
| 738 | zfree(he); |
| 739 | } |
| 740 | } |
| 741 | d->ht[table].used--; |
| 742 | _dictExpandIfNeeded(d); |
| 743 | return he; |
| 744 | } |
| 745 | prevHe = he; |
| 746 | he = he->next; |
| 747 | } |
| 748 | if (!dictIsRehashing(d)) break; |
| 749 | } |
| 750 | _dictExpandIfNeeded(d); |
| 751 | return NULL; /* not found */ |
| 752 | } |
| 753 | |
| 754 | /* Remove an element, returning DICT_OK on success or DICT_ERR if the |
| 755 | * element was not found. */ |
no test coverage detected