}
+/* 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;
}
}
}
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;
}
}
}
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;
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;
}
}
zend_hash_pointer_index_update_or_next_insert(ht,h,pData,HASH_UPDATE)
#define zend_hash_next_index_pointer_insert(ht,pData) \
zend_hash_pointer_index_update_or_next_insert(ht,0,pData,HASH_NEXT_INSERT)
+ZEND_API void zend_hash_graceful_destroy(HashTable *ht);
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 *);
ZEND_API void zend_hash_apply_with_arguments(HashTable *ht, ZEND_STD_HASH_APPLIER, int, ...);