From: Dmitry Stogov Date: Fri, 18 Apr 2014 20:08:14 +0000 (+0400) Subject: More ZEND_HASH_FOREACH_* related changes X-Git-Tag: POST_PHPNG_MERGE~412^2~82^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=54d9ad53f4797733b41bf2c65bd2c2cb5a1938b6;p=php More ZEND_HASH_FOREACH_* related changes --- diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index ba0b28bd7b..c770539dd1 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -533,105 +533,84 @@ static inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, HashPositio #define zend_hash_get_current_data_ptr(ht) \ zend_hash_get_current_data_ptr_ex(ht, &(ht)->nInternalPointer) -#define ZEND_HASH_FOREACH_VAL(_ht, _val) do { \ +#define ZEND_HASH_FOREACH(_ht, indirect) do { \ uint _idx; \ - Bucket *_p; \ for (_idx = 0; _idx < (_ht)->nNumUsed; _idx++) { \ - _p = (_ht)->arData + _idx; \ - if (Z_TYPE(_p->val) == IS_UNDEF) continue; \ - _val = &_p->val; - -#define ZEND_HASH_FOREACH_VAL_IND(_ht, _val) do { \ - uint _idx; \ - Bucket *_p; \ - zval *_z; \ - for (_idx = 0; _idx < (_ht)->nNumUsed; _idx++) { \ - _p = (_ht)->arData + _idx; \ - _z = &_p->val; \ - if (Z_TYPE_P(_z) == IS_INDIRECT) { \ + Bucket *_p = (_ht)->arData + _idx; \ + zval *_z = &_p->val; \ + if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \ _z = Z_INDIRECT_P(_z); \ } \ - if (Z_TYPE_P(_z) == IS_UNDEF) continue; \ - _val = _z; - -#define ZEND_HASH_FOREACH_PTR(_ht, _ptr) do { \ - uint _idx; \ - Bucket *_p; \ - for (_idx = 0; _idx < (_ht)->nNumUsed; _idx++) { \ - _p = (_ht)->arData + _idx; \ - if (Z_TYPE(_p->val) == IS_UNDEF) continue; \ - _ptr = Z_PTR(_p->val); - -#define ZEND_HASH_FOREACH_KEY(_ht, _h, _key) do { \ - uint _idx; \ - Bucket *_p; \ - for (_idx = 0; _idx < (_ht)->nNumUsed; _idx++) { \ - _p = (_ht)->arData + _idx; \ - if (Z_TYPE(_p->val) == IS_UNDEF) continue; \ - _h = _p->h; \ - _key = _p->key; \ - -#define ZEND_HASH_FOREACH_KEY_VAL(_ht, _h, _key, _val) do { \ - uint _idx; \ - Bucket *_p; \ - for (_idx = 0; _idx < (_ht)->nNumUsed; _idx++) { \ - _p = (_ht)->arData + _idx; \ - if (Z_TYPE(_p->val) == IS_UNDEF) continue; \ - _h = _p->h; \ - _key = _p->key; \ - _val = &_p->val; - -#define ZEND_HASH_FOREACH_KEY_VAL(_ht, _h, _key, _val) do { \ - uint _idx; \ - Bucket *_p; \ - for (_idx = 0; _idx < (_ht)->nNumUsed; _idx++) { \ - _p = (_ht)->arData + _idx; \ - if (Z_TYPE(_p->val) == IS_UNDEF) continue; \ - _h = _p->h; \ - _key = _p->key; \ - _val = &_p->val; + if (Z_TYPE_P(_z) == IS_UNDEF) continue; -#define ZEND_HASH_FOREACH_KEY_VAL_IND(_ht, _h, _key, _val) do { \ +#define ZEND_HASH_REVERSE_FOREACH(_ht, indirect) do { \ uint _idx; \ - Bucket *_p; \ - zval *_z; \ - for (_idx = 0; _idx < (_ht)->nNumUsed; _idx++) { \ - _p = (_ht)->arData + _idx; \ - _z = &_p->val; \ - if (Z_TYPE_P(_z) == IS_INDIRECT) { \ + for (_idx = (_ht)->nNumUsed; _idx > 0; _idx--) { \ + Bucket *_p = (_ht)->arData + _idx - 1; \ + zval *_z = &_p->val; \ + if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \ _z = Z_INDIRECT_P(_z); \ } \ - if (Z_TYPE_P(_z) == IS_UNDEF) continue; \ - _h = _p->h; \ - _key = _p->key; \ - _val = _z; - -#define ZEND_HASH_FOREACH_KEY_PTR(_ht, _h, _key, _ptr) do { \ - uint _idx; \ - Bucket *_p; \ - for (_idx = 0; _idx < (_ht)->nNumUsed; _idx++) { \ - _p = (_ht)->arData + _idx; \ - if (Z_TYPE(_p->val) == IS_UNDEF) continue; \ - _h = _p->h; \ - _key = _p->key; \ - _ptr = Z_PTR(_p->val); - - -#define ZEND_HASH_REVERSE_FOREACH_KEY_VAL(_ht, _h, _key, _val) do { \ - uint _idx; \ - Bucket *_p; \ - for (_idx = (_ht)->nNumUsed; _idx > 0; _idx--) { \ - _p = (_ht)->arData + _idx - 1; \ - if (Z_TYPE(_p->val) == IS_UNDEF) continue; \ - _h = _p->h; \ - _key = _p->key; \ - _val = &_p->val; + if (Z_TYPE_P(_z) == IS_UNDEF) continue; #define ZEND_HASH_FOREACH_END() \ } \ } while (0) - +#define ZEND_HASH_FOREACH_VAL(ht, _val) \ + ZEND_HASH_FOREACH(ht, 0); \ + _val = _z; + +#define ZEND_HASH_FOREACH_VAL_IND(ht, _val) \ + ZEND_HASH_FOREACH(ht, 1); \ + _val = _z; + +#define ZEND_HASH_FOREACH_PTR(ht, _ptr) \ + ZEND_HASH_FOREACH(ht, 0); \ + _ptr = Z_PTR_P(_z); + +#define ZEND_HASH_FOREACH_KEY(ht, _h, _key) \ + ZEND_HASH_FOREACH(ht, 0); \ + _h = _p->h; \ + _key = _p->key; + +#define ZEND_HASH_FOREACH_KEY_VAL(ht, _h, _key, _val) \ + ZEND_HASH_FOREACH(ht, 0); \ + _h = _p->h; \ + _key = _p->key; \ + _val = _z; + +#define ZEND_HASH_FOREACH_KEY_VAL_IND(ht, _h, _key, _val) \ + ZEND_HASH_FOREACH(ht, 1); \ + _h = _p->h; \ + _key = _p->key; \ + _val = _z; + +#define ZEND_HASH_FOREACH_KEY_PTR(ht, _h, _key, _ptr) \ + ZEND_HASH_FOREACH(ht, 0); \ + _h = _p->h; \ + _key = _p->key; \ + _ptr = Z_PTR_P(_z); + +#define ZEND_HASH_REVERSE_FOREACH_VAL(ht, _val) \ + ZEND_HASH_REVERSE_FOREACH(ht, 0); \ + _val = _z; + +#define ZEND_HASH_REVERSE_FOREACH_VAL_IND(ht, _val) \ + ZEND_HASH_REVERSE_FOREACH(ht, 1); \ + _val = _z; + +#define ZEND_HASH_REVERSE_FOREACH_KEY_VAL(ht, _h, _key, _val) \ + ZEND_HASH_REVERSE_FOREACH(ht, 0); \ + _h = _p->h; \ + _key = _p->key; \ + _val = _z; + +#define ZEND_HASH_REVERSE_FOREACH_KEY_VAL_IND(ht, _h, _key, _val) \ + ZEND_HASH_REVERSE_FOREACH(ht, 1); \ + _h = _p->h; \ + _key = _p->key; \ + _val = _z; #endif /* ZEND_HASH_H */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index d6723fbd5a..e3b58bcea8 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3112,19 +3112,14 @@ ZEND_VM_C_LABEL(send_again): switch (Z_TYPE_P(args)) { case IS_ARRAY: { HashTable *ht = Z_ARRVAL_P(args); - HashPosition pos; zval *arg; + zend_string *name; + zend_ulong index; ZEND_VM_STACK_GROW_IF_NEEDED(zend_hash_num_elements(ht)); - for (zend_hash_internal_pointer_reset_ex(ht, &pos); - (arg = zend_hash_get_current_data_ex(ht, &pos)) != NULL; - zend_hash_move_forward_ex(ht, &pos), ++arg_num - ) { - zend_string *name; - zend_ulong index; - - if (zend_hash_get_current_key_ex(ht, &name, &index, 0, &pos) == HASH_KEY_IS_STRING) { + ZEND_HASH_FOREACH_KEY_VAL(ht, index, name, arg) { + if (name) { zend_error(E_RECOVERABLE_ERROR, "Cannot unpack array with string keys"); FREE_OP1(); CHECK_EXCEPTION(); @@ -3142,7 +3137,9 @@ ZEND_VM_C_LABEL(send_again): zend_vm_stack_push(arg TSRMLS_CC); EX(call)->num_additional_args++; - } + arg_num++; + } ZEND_HASH_FOREACH_END(); + break; } case IS_OBJECT: { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 9217e1113b..482ea3109d 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -720,19 +720,14 @@ send_again: switch (Z_TYPE_P(args)) { case IS_ARRAY: { HashTable *ht = Z_ARRVAL_P(args); - HashPosition pos; zval *arg; + zend_string *name; + zend_ulong index; ZEND_VM_STACK_GROW_IF_NEEDED(zend_hash_num_elements(ht)); - for (zend_hash_internal_pointer_reset_ex(ht, &pos); - (arg = zend_hash_get_current_data_ex(ht, &pos)) != NULL; - zend_hash_move_forward_ex(ht, &pos), ++arg_num - ) { - zend_string *name; - zend_ulong index; - - if (zend_hash_get_current_key_ex(ht, &name, &index, 0, &pos) == HASH_KEY_IS_STRING) { + ZEND_HASH_FOREACH_KEY_VAL(ht, index, name, arg) { + if (name) { zend_error(E_RECOVERABLE_ERROR, "Cannot unpack array with string keys"); FREE_OP(free_op1); CHECK_EXCEPTION(); @@ -750,7 +745,9 @@ send_again: zend_vm_stack_push(arg TSRMLS_CC); EX(call)->num_additional_args++; - } + arg_num++; + } ZEND_HASH_FOREACH_END(); + break; } case IS_OBJECT: { diff --git a/ext/standard/array.c b/ext/standard/array.c index d5799196d2..03c77fea80 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1975,21 +1975,34 @@ static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end) /* Get the first or last value and copy it into the return value */ if (off_the_end) { zend_hash_internal_pointer_end(Z_ARRVAL_P(stack)); + while (1) { + val = zend_hash_get_current_data(Z_ARRVAL_P(stack)); + if (!val) { + return; + } else if (Z_TYPE_P(val) == IS_INDIRECT) { + val = Z_INDIRECT_P(val); + if (Z_TYPE_P(val) == IS_UNDEF) { + zend_hash_move_backwards(Z_ARRVAL_P(stack)); + continue; + } + } + break; + } } else { zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack)); - } - while (1) { - val = zend_hash_get_current_data(Z_ARRVAL_P(stack)); - if (!val) { - return; - } else if (Z_TYPE_P(val) == IS_INDIRECT) { - val = Z_INDIRECT_P(val); - if (Z_TYPE_P(val) == IS_UNDEF) { - zend_hash_move_forward(Z_ARRVAL_P(stack)); - continue; + while (1) { + val = zend_hash_get_current_data(Z_ARRVAL_P(stack)); + if (!val) { + return; + } else if (Z_TYPE_P(val) == IS_INDIRECT) { + val = Z_INDIRECT_P(val); + if (Z_TYPE_P(val) == IS_UNDEF) { + zend_hash_move_forward(Z_ARRVAL_P(stack)); + continue; + } } + break; } - break; } RETVAL_ZVAL_FAST(val);