diff options
Diffstat (limited to 'Zend/zend_hash.c')
| -rw-r--r-- | Zend/zend_hash.c | 108 |
1 files changed, 78 insertions, 30 deletions
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 2d2053670d..db53b4ab04 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -836,26 +836,82 @@ ZEND_API void zend_hash_clean(HashTable *ht) } +/* This function is used by the various apply() functions. + * It deletes the passed bucket, and returns the address of the + * next bucket. The hash *may* be altered during that time, the + * returned value will still be valid. + */ +static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p) +{ + Bucket *retval; + + HANDLE_BLOCK_INTERRUPTIONS(); + + if (!p->bIsPointer) { + if (ht->pDestructor) { + ht->pDestructor(p->pData); + } + if (!p->pDataPtr) { + pefree(p->pData, ht->persistent); + } + } + retval = p->pListNext; + + if (p->pListLast != NULL) { + p->pListLast->pListNext = p->pListNext; + } else { + /* Deleting the head of the list */ + ht->pListHead = p->pListNext; + } + if (p->pListNext != NULL) { + p->pListNext->pListLast = p->pListLast; + } else { + ht->pListTail = p->pListLast; + } + if (ht->pInternalPointer == p) { + ht->pInternalPointer = p->pListNext; + } + pefree(p,ht->persistent); + HANDLE_UNBLOCK_INTERRUPTIONS(); + ht->nNumOfElements--; + + return retval; +} + + +ZEND_API void zend_hash_graceful_destroy(HashTable *ht) +{ + Bucket *p; + + IS_CONSISTENT(ht); + + p = ht->pListHead; + while (p != NULL) { + p = zend_hash_apply_deleter(ht, p); + } + pefree(ht->arBuckets,ht->persistent); + + SET_INCONSISTENT(2); +} + /* This is used to selectively delete certain entries from a hashtable. * destruct() receives the data and decides if the entry should be deleted * or not */ + + ZEND_API void zend_hash_apply(HashTable *ht,int (*destruct) (void *)) { - Bucket *p, *q; + Bucket *p; IS_CONSISTENT(ht); p = ht->pListHead; while (p != NULL) { - q = p; - p = p->pListNext; - if (destruct(q->pData)) { - if (q->nKeyLength==0) { - zend_hash_index_del(ht, q->h); - } else { - zend_hash_del(ht,q->arKey,q->nKeyLength); - } + if (destruct(p->pData)) { + p = zend_hash_apply_deleter(ht, p); + } else { + p = p->pListNext; } } } @@ -863,20 +919,16 @@ ZEND_API void zend_hash_apply(HashTable *ht,int (*destruct) (void *)) ZEND_API void zend_hash_apply_with_argument(HashTable *ht,int (*destruct) (void *, void *), void *argument) { - Bucket *p, *q; + Bucket *p; IS_CONSISTENT(ht); p = ht->pListHead; while (p != NULL) { - q = p; - p = p->pListNext; - if (destruct(q->pData, argument)) { - if (q->nKeyLength == 0) { - zend_hash_index_del(ht, q->h); - } else { - zend_hash_del(ht,q->arKey,q->nKeyLength); - } + if (destruct(p->pData, argument)) { + p = zend_hash_apply_deleter(ht, p); + } else { + p = p->pListNext; } } } @@ -884,7 +936,7 @@ ZEND_API void zend_hash_apply_with_argument(HashTable *ht,int (*destruct) (void ZEND_API void zend_hash_apply_with_arguments(HashTable *ht,int (*destruct)(void *, int, va_list, zend_hash_key *), int num_args, ...) { - Bucket *p, *q; + Bucket *p; va_list args; zend_hash_key hash_key; @@ -894,17 +946,13 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht,int (*destruct)(void p = ht->pListHead; while (p != NULL) { - q = p; - p = p->pListNext; - hash_key.arKey = q->arKey; - hash_key.nKeyLength = q->nKeyLength; - hash_key.h = q->h; - if (destruct(q->pData, num_args, args, &hash_key)) { - if (q->nKeyLength == 0) { - zend_hash_index_del(ht, q->h); - } else { - zend_hash_del(ht,q->arKey,q->nKeyLength); - } + hash_key.arKey = p->arKey; + hash_key.nKeyLength = p->nKeyLength; + hash_key.h = p->h; + if (destruct(p->pData, num_args, args, &hash_key)) { + p = zend_hash_apply_deleter(ht, p); + } else { + p = p->pListNext; } } |
