- Consistency of apply funcs, #39320

This commit is contained in:
Marcus Boerger 2006-10-31 22:05:56 +00:00
parent ee741531aa
commit d675326a22

View File

@ -872,12 +872,15 @@ ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht)
SET_INCONSISTENT(HT_DESTROYED); SET_INCONSISTENT(HT_DESTROYED);
} }
/* This is used to selectively delete certain entries from a hashtable. /* This is used to recurse elements and selectively delete certain entries
* destruct() receives the data and decides if the entry should be deleted * from a hashtable. apply_func() receives the data and decides if the entry
* or not * should be deleted or recursion should be stopped. The following three
* return codes are possible:
* ZEND_HASH_APPLY_KEEP - continue
* ZEND_HASH_APPLY_STOP - stop iteration
* ZEND_HASH_APPLY_REMOVE - delete the element, combineable with the former
*/ */
ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC) ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
{ {
Bucket *p; Bucket *p;
@ -887,11 +890,16 @@ ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
HASH_PROTECT_RECURSION(ht); HASH_PROTECT_RECURSION(ht);
p = ht->pListHead; p = ht->pListHead;
while (p != NULL) { while (p != NULL) {
if (apply_func(p->pData TSRMLS_CC)) { int result = apply_func(p->pData TSRMLS_CC);
if (result & ZEND_HASH_APPLY_REMOVE) {
p = zend_hash_apply_deleter(ht, p); p = zend_hash_apply_deleter(ht, p);
} else { } else {
p = p->pListNext; p = p->pListNext;
} }
if (result & ZEND_HASH_APPLY_STOP) {
break;
}
} }
HASH_UNPROTECT_RECURSION(ht); HASH_UNPROTECT_RECURSION(ht);
} }
@ -906,17 +914,22 @@ ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t appl
HASH_PROTECT_RECURSION(ht); HASH_PROTECT_RECURSION(ht);
p = ht->pListHead; p = ht->pListHead;
while (p != NULL) { while (p != NULL) {
if (apply_func(p->pData, argument TSRMLS_CC)) { int result = apply_func(p->pData, argument TSRMLS_CC);
if (result & ZEND_HASH_APPLY_REMOVE) {
p = zend_hash_apply_deleter(ht, p); p = zend_hash_apply_deleter(ht, p);
} else { } else {
p = p->pListNext; p = p->pListNext;
} }
if (result & ZEND_HASH_APPLY_STOP) {
break;
}
} }
HASH_UNPROTECT_RECURSION(ht); HASH_UNPROTECT_RECURSION(ht);
} }
ZEND_API void zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t destruct, int num_args, ...) ZEND_API void zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t apply_func, int num_args, ...)
{ {
Bucket *p; Bucket *p;
va_list args; va_list args;
@ -928,16 +941,20 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t de
p = ht->pListHead; p = ht->pListHead;
while (p != NULL) { while (p != NULL) {
int result;
va_start(args, num_args); va_start(args, num_args);
hash_key.nKeyLength = p->nKeyLength; hash_key.nKeyLength = p->nKeyLength;
hash_key.h = p->h; hash_key.h = p->h;
hash_key.type = p->key.type; result = apply_func(p->pData, num_args, args, &hash_key);
hash_key.arKey.s = p->key.arKey.s;
if (destruct(p->pData, num_args, args, &hash_key)) { if (result & ZEND_HASH_APPLY_REMOVE) {
p = zend_hash_apply_deleter(ht, p); p = zend_hash_apply_deleter(ht, p);
} else { } else {
p = p->pListNext; p = p->pListNext;
} }
if (result & ZEND_HASH_APPLY_STOP) {
break;
}
va_end(args); va_end(args);
} }