static int clean_non_persistent_constant(zend_constant *c TSRMLS_DC)
{
if (c->flags & CONST_PERSISTENT) {
- return 0;
+ return ZEND_HASH_APPLY_STOP;
} else {
- return 1;
+ return ZEND_HASH_APPLY_REMOVE;
}
}
void clean_non_persistent_constants(TSRMLS_D)
{
- zend_hash_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant TSRMLS_CC);
+ zend_hash_reverse_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant TSRMLS_CC);
}
static int is_not_internal_function(zend_function *function TSRMLS_DC)
{
- return(function->type != ZEND_INTERNAL_FUNCTION);
+ if (function->type == ZEND_INTERNAL_FUNCTION) {
+ return ZEND_HASH_APPLY_STOP;
+ } else {
+ return ZEND_HASH_APPLY_REMOVE;
+ }
}
static int is_not_internal_class(zend_class_entry *ce TSRMLS_DC)
{
- return(ce->type != ZEND_INTERNAL_CLASS);
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ return ZEND_HASH_APPLY_STOP;
+ } else {
+ return ZEND_HASH_APPLY_REMOVE;
+ }
}
zend_ptr_stack_destroy(&EG(argument_stack));
/* Destroy all op arrays */
- zend_hash_apply(EG(function_table), (apply_func_t) is_not_internal_function TSRMLS_CC);
- zend_hash_apply(EG(class_table), (apply_func_t) is_not_internal_class TSRMLS_CC);
+ zend_hash_reverse_apply(EG(function_table), (apply_func_t) is_not_internal_function TSRMLS_CC);
+ zend_hash_reverse_apply(EG(class_table), (apply_func_t) is_not_internal_class TSRMLS_CC);
} zend_end_try();
/* The regular list must be destroyed after the main symbol table and
}
+ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
+{
+ Bucket *p, *q;
+
+ IS_CONSISTENT(ht);
+
+ HASH_PROTECT_RECURSION(ht);
+ p = ht->pListTail;
+ while (p != NULL) {
+ int result = apply_func(p->pData TSRMLS_CC);
+
+ q = p;
+ p = p->pListLast;
+ if (result & ZEND_HASH_APPLY_REMOVE) {
+ if (q->nKeyLength>0) {
+ zend_hash_del(ht, q->arKey, q->nKeyLength);
+ } else {
+ zend_hash_index_del(ht, q->h);
+ }
+ }
+ if (result & ZEND_HASH_APPLY_STOP) {
+ break;
+ }
+ }
+ HASH_UNPROTECT_RECURSION(ht);
+}
+
ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size)
{
ZEND_API int zend_hash_add_empty_element(HashTable *ht, char *arKey, uint nKeyLength);
+
+#define ZEND_HASH_APPLY_KEEP 0
+#define ZEND_HASH_APPLY_REMOVE 1<<0
+#define ZEND_HASH_APPLY_STOP 1<<1
+
typedef struct _zend_hash_key {
char *arKey;
uint nKeyLength;
ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void * TSRMLS_DC);
ZEND_API void zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t apply_func, int, ...);
-
+/* This function should be used with special care (in other words,
+ * it should usually not be used). When used with the ZEND_HASH_APPLY_STOP
+ * return value, it assumes things about the order of the elements in the hash.
+ * Also, it does not provide the same kind of reentrancy protection that
+ * the standard apply functions do.
+ */
+ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC);
/* Deletes */