summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_hash.h151
-rw-r--r--Zend/zend_vm_def.h17
-rw-r--r--Zend/zend_vm_execute.h17
-rw-r--r--ext/standard/array.c35
4 files changed, 103 insertions, 117 deletions
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);