Skip to content
Browse files

Add support for non-scalar Iterator keys in foreach

  • Loading branch information...
1 parent 8436342 commit fcc6611de9054327441786e52444b5f8eecdd525 @nikic nikic committed Feb 16, 2013
View
2 UPGRADING
@@ -81,6 +81,8 @@ PHP 5.5 UPGRADE NOTES
a string constant. (https://wiki.php.net/rfc/class_name_scalars)
- Support for changing the process's title in CLI/CLI-Server SAPIs. (Keyur)
(https://wiki.php.net/rfc/cli_process_title)
+- Added support for non-scalar Iterator keys in foreach.
+ (https://wiki.php.net/rfc/foreach-non-scalar-keys).
========================================
2. Changes in SAPI modules
View
8 UPGRADING.INTERNALS
@@ -64,6 +64,14 @@ void zend_qsort_r(void *base, size_t nmemb, size_t siz, compare_r_func_t compare
The extra argument it has (relatively to zend_qsort()) is passed to the
comparison function.
+ d. get_current_key
+
+The signature of the get_current_key iteration handler has been changed to:
+
+void (*get_current_key)(zend_object_iterator *iter, zval *key TSRMLS_DC);
+
+The key should be written into the zval* using the ZVAL_* macros.
+
========================
2. Build system changes
========================
View
52 Zend/tests/generators/generator_with_nonscalar_keys.phpt
@@ -0,0 +1,52 @@
+--TEST--
+Generators can return non-scalar keys
+--FILE--
+<?php
+
+function gen() {
+ yield [1, 2, 3] => [4, 5, 6];
+ yield (object) ['a' => 'b'] => (object) ['b' => 'a'];
+ yield 3.14 => 2.73;
+ yield false => true;
+ yield true => false;
+ yield null => null;
+}
+
+foreach (gen() as $k => $v) {
+ var_dump($k, $v);
+}
+
+?>
+--EXPECT--
+array(3) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+ [2]=>
+ int(3)
+}
+array(3) {
+ [0]=>
+ int(4)
+ [1]=>
+ int(5)
+ [2]=>
+ int(6)
+}
+object(stdClass)#3 (1) {
+ ["a"]=>
+ string(1) "b"
+}
+object(stdClass)#4 (1) {
+ ["b"]=>
+ string(1) "a"
+}
+float(3.14)
+float(2.73)
+bool(false)
+bool(true)
+bool(true)
+bool(false)
+NULL
+NULL
View
1 Zend/zend.h
@@ -299,7 +299,6 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore
/*
* zval
*/
-typedef struct _zval_struct zval;
typedef struct _zend_class_entry zend_class_entry;
typedef struct _zend_guard {
View
34 Zend/zend_API.c
@@ -1502,6 +1502,40 @@ ZEND_API int add_get_index_stringl(zval *arg, ulong index, const char *str, uint
}
/* }}} */
+ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
+{
+ int result;
+
+ switch (Z_TYPE_P(key)) {
+ case IS_STRING:
+ result = zend_symtable_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
+ break;
+ case IS_NULL:
+ result = zend_symtable_update(ht, "", 1, &value, sizeof(zval *), NULL);
+ break;
+ case IS_RESOURCE:
+ zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(key), Z_LVAL_P(key));
+ /* break missing intentionally */
+ case IS_BOOL:
+ case IS_LONG:
+ result = zend_hash_index_update(ht, Z_LVAL_P(key), &value, sizeof(zval *), NULL);
+ break;
+ case IS_DOUBLE:
+ result = zend_hash_index_update(ht, zend_dval_to_lval(Z_LVAL_P(key)), &value, sizeof(zval *), NULL);
@reeze
reeze added a note Mar 14, 2013

Hey, @nikic,

test ext/spl/tests/iterator_to_array_nonscalar_keys.phpt failed because of the wrong macro ;)

- result = zend_hash_index_update(ht, zend_dval_to_lval(Z_LVAL_P(key)), &value, sizeof(zval *), NULL);
+ result = zend_hash_index_update(ht, zend_dval_to_lval(Z_DVAL_P(key)), &value, sizeof(zval *), NULL);

and the test need to be updated too

@nikic
nikic added a note Mar 15, 2013

Good catch! Fixed in b7788c5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ break;
+ default:
+ zend_error(E_WARNING, "Illegal offset type");
+ result = FAILURE;
+ }
+
+ if (result == SUCCESS) {
+ Z_ADDREF_P(value);
+ }
+
+ return result;
+}
+/* }}} */
+
ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */
{
zval *tmp;
View
2 Zend/zend_API.h
@@ -426,6 +426,8 @@ ZEND_API int add_get_index_double(zval *arg, ulong idx, double d, void **dest);
ZEND_API int add_get_index_string(zval *arg, ulong idx, const char *str, void **dest, int duplicate);
ZEND_API int add_get_index_stringl(zval *arg, ulong idx, const char *str, uint length, void **dest, int duplicate);
+ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value);
+
ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long l TSRMLS_DC);
ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRMLS_DC);
ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, int b TSRMLS_DC);
View
24 Zend/zend_generators.c
@@ -755,31 +755,17 @@ static void zend_generator_iterator_get_data(zend_object_iterator *iterator, zva
}
/* }}} */
-static int zend_generator_iterator_get_key(zend_object_iterator *iterator, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
+static void zend_generator_iterator_get_key(zend_object_iterator *iterator, zval *key TSRMLS_DC) /* {{{ */
{
zend_generator *generator = (zend_generator *) iterator->data;
zend_generator_ensure_initialized(generator TSRMLS_CC);
- if (!generator->key) {
- return HASH_KEY_NON_EXISTANT;
- }
-
- if (Z_TYPE_P(generator->key) == IS_LONG) {
- *int_key = Z_LVAL_P(generator->key);
- return HASH_KEY_IS_LONG;
- }
-
- if (Z_TYPE_P(generator->key) == IS_STRING) {
- *str_key = estrndup(Z_STRVAL_P(generator->key), Z_STRLEN_P(generator->key));
- *str_key_len = Z_STRLEN_P(generator->key) + 1;
- return HASH_KEY_IS_STRING;
+ if (generator->key) {
+ ZVAL_ZVAL(key, generator->key, 1, 0);
+ } else {
+ ZVAL_NULL(key);
}
-
- /* Waiting for Etienne's patch to allow arbitrary zval keys. Until then
- * error out on non-int and non-string keys. */
- zend_error_noreturn(E_ERROR, "Currently only int and string keys can be yielded");
- return HASH_KEY_NON_EXISTANT; /* Nerver reached */
}
/* }}} */
View
18 Zend/zend_hash.c
@@ -1171,6 +1171,24 @@ ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, char **str_index,
return HASH_KEY_NON_EXISTANT;
}
+ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) {
+ Bucket *p;
+
+ IS_CONSISTENT(ht);
+
+ p = pos ? (*pos) : ht->pInternalPointer;
+
+ if (!p) {
+ Z_TYPE_P(key) = IS_NULL;
+ } else if (p->nKeyLength) {
+ Z_TYPE_P(key) = IS_STRING;
+ Z_STRVAL_P(key) = IS_INTERNED(p->arKey) ? (char *) p->arKey : estrndup(p->arKey, p->nKeyLength - 1);
+ Z_STRLEN_P(key) = p->nKeyLength - 1;
+ } else {
+ Z_TYPE_P(key) = IS_LONG;
+ Z_LVAL_P(key) = p->h;
+ }
+}
ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
{
View
4 Zend/zend_hash.h
@@ -170,13 +170,13 @@ ZEND_API int zend_hash_quick_exists(const HashTable *ht, const char *arKey, uint
ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h);
ZEND_API ulong zend_hash_next_free_element(const HashTable *ht);
-
/* traversing */
#define zend_hash_has_more_elements_ex(ht, pos) \
(zend_hash_get_current_key_type_ex(ht, pos) == HASH_KEY_NON_EXISTANT ? FAILURE : SUCCESS)
ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos);
ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos);
ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, char **str_index, uint *str_length, ulong *num_index, zend_bool duplicate, HashPosition *pos);
+ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos);
ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos);
ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosition *pos);
ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos);
@@ -199,6 +199,8 @@ ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr);
zend_hash_move_backwards_ex(ht, NULL)
#define zend_hash_get_current_key(ht, str_index, num_index, duplicate) \
zend_hash_get_current_key_ex(ht, str_index, NULL, num_index, duplicate, NULL)
+#define zend_hash_get_current_key_zval(ht, key) \
+ zend_hash_get_current_key_zval_ex(ht, key, NULL)
#define zend_hash_get_current_key_type(ht) \
zend_hash_get_current_key_type_ex(ht, NULL)
#define zend_hash_get_current_data(ht, pData) \
View
38 Zend/zend_interfaces.c
@@ -195,50 +195,24 @@ static int zend_user_it_get_current_key_default(zend_object_iterator *_iter, cha
/* }}} */
/* {{{ zend_user_it_get_current_key */
-ZEND_API int zend_user_it_get_current_key(zend_object_iterator *_iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
+ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *key TSRMLS_DC)
{
zend_user_iterator *iter = (zend_user_iterator*)_iter;
zval *object = (zval*)iter->it.data;
zval *retval;
zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_key, "key", &retval);
- if (!retval) {
- *int_key = 0;
- if (!EG(exception))
- {
+ if (retval) {
+ ZVAL_ZVAL(key, retval, 1, 1);
+ } else {
+ if (!EG(exception)) {
zend_error(E_WARNING, "Nothing returned from %s::key()", iter->ce->name);
}
- return HASH_KEY_IS_LONG;
- }
- switch (Z_TYPE_P(retval)) {
- default:
- zend_error(E_WARNING, "Illegal type returned from %s::key()", iter->ce->name);
- case IS_NULL:
- *int_key = 0;
- zval_ptr_dtor(&retval);
- return HASH_KEY_IS_LONG;
-
- case IS_STRING:
- *str_key = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
- *str_key_len = Z_STRLEN_P(retval)+1;
- zval_ptr_dtor(&retval);
- return HASH_KEY_IS_STRING;
-
- case IS_DOUBLE:
- *int_key = (long)Z_DVAL_P(retval);
- zval_ptr_dtor(&retval);
- return HASH_KEY_IS_LONG;
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- *int_key = (long)Z_LVAL_P(retval);
- zval_ptr_dtor(&retval);
- return HASH_KEY_IS_LONG;
+ ZVAL_LONG(key, 0);
}
}
-/* }}} */
/* {{{ zend_user_it_move_forward */
ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter TSRMLS_DC)
View
2 Zend/zend_interfaces.h
@@ -51,7 +51,7 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend
ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter TSRMLS_DC);
ZEND_API int zend_user_it_valid(zend_object_iterator *_iter TSRMLS_DC);
-ZEND_API int zend_user_it_get_current_key(zend_object_iterator *_iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC);
+ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *key TSRMLS_DC);
ZEND_API void zend_user_it_get_current_data(zend_object_iterator *_iter, zval ***data TSRMLS_DC);
ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter TSRMLS_DC);
ZEND_API void zend_user_it_invalidate_current(zend_object_iterator *_iter TSRMLS_DC);
View
7 Zend/zend_iterators.h
@@ -38,8 +38,11 @@ typedef struct _zend_object_iterator_funcs {
/* fetch the item data for the current element */
void (*get_current_data)(zend_object_iterator *iter, zval ***data TSRMLS_DC);
- /* fetch the key for the current element (return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG) (optional, may be NULL) */
- int (*get_current_key)(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC);
+ /* fetch the key for the current element (optional, may be NULL). The key
+ * should be written into the provided zval* using the ZVAL_* macros. If
+ * this handler is not provided auto-incrementing integer keys will be
+ * used. */
+ void (*get_current_key)(zend_object_iterator *iter, zval *key TSRMLS_DC);
/* step forwards to next element */
void (*move_forward)(zend_object_iterator *iter TSRMLS_DC);
View
1 Zend/zend_types.h
@@ -52,6 +52,7 @@ typedef unsigned long zend_uintptr_t;
typedef unsigned int zend_object_handle;
typedef struct _zend_object_handlers zend_object_handlers;
+typedef struct _zval_struct zval;
typedef struct _zend_object_value {
zend_object_handle handle;
View
70 Zend/zend_vm_def.h
@@ -4245,13 +4245,13 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
zend_free_op free_op1;
zval *array = EX_T(opline->op1.var).fe.ptr;
zval **value;
- char *str_key;
- uint str_key_len;
- ulong int_key;
HashTable *fe_ht;
zend_object_iterator *iter = NULL;
- int key_type = 0;
- zend_bool use_key = (zend_bool)(opline->extended_value & ZEND_FE_FETCH_WITH_KEY);
+
+ zval *key = NULL;
+ if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
+ key = &EX_T((opline+1)->result.var).tmp_var;
+ }
SAVE_OPLINE();
@@ -4262,8 +4262,11 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
case ZEND_ITER_PLAIN_OBJECT: {
- const char *class_name, *prop_name;
zend_object *zobj = zend_objects_get_address(array TSRMLS_CC);
+ int key_type;
+ char *str_key;
+ zend_uint str_key_len;
+ zend_ulong int_key;
fe_ht = Z_OBJPROP_P(array);
zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
@@ -4275,15 +4278,23 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
zend_hash_move_forward(fe_ht);
- } while (key_type == HASH_KEY_NON_EXISTANT ||
- (key_type != HASH_KEY_IS_LONG &&
- zend_check_property_access(zobj, str_key, str_key_len-1 TSRMLS_CC) != SUCCESS));
- zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
- if (use_key && key_type != HASH_KEY_IS_LONG) {
- zend_unmangle_property_name_ex(str_key, str_key_len-1, &class_name, &prop_name, &str_key_len);
- str_key = estrndup(prop_name, str_key_len);
- str_key_len++;
+ } while (key_type != HASH_KEY_IS_LONG &&
+ zend_check_property_access(zobj, str_key, str_key_len - 1 TSRMLS_CC) != SUCCESS);
+
+ if (key) {
+ if (key_type == HASH_KEY_IS_LONG) {
+ ZVAL_LONG(key, int_key);
+ } else {
+ const char *class_name, *prop_name;
+ int prop_name_len;
+ zend_unmangle_property_name_ex(
+ str_key, str_key_len - 1, &class_name, &prop_name, &prop_name_len
+ );
+ ZVAL_STRINGL(key, prop_name, prop_name_len, 1);
+ }
}
+
+ zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
break;
}
@@ -4294,8 +4305,8 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
/* reached end of iteration */
ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
- if (use_key) {
- key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL);
+ if (key) {
+ zend_hash_get_current_key_zval(fe_ht, key);
}
zend_hash_move_forward(fe_ht);
zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
@@ -4330,16 +4341,15 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
/* failure in get_current_data */
ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
- if (use_key) {
+ if (key) {
if (iter->funcs->get_current_key) {
- key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC);
+ iter->funcs->get_current_key(iter, key TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array);
HANDLE_EXCEPTION();
}
} else {
- key_type = HASH_KEY_IS_LONG;
- int_key = iter->index;
+ ZVAL_LONG(key, iter->index);
}
}
break;
@@ -4355,26 +4365,6 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
AI_SET_PTR(&EX_T(opline->result.var), *value);
}
- if (use_key) {
- zval *key = &EX_T((opline+1)->result.var).tmp_var;
-
- switch (key_type) {
- case HASH_KEY_IS_STRING:
- Z_STRVAL_P(key) = (char*)str_key;
- Z_STRLEN_P(key) = str_key_len-1;
- Z_TYPE_P(key) = IS_STRING;
- break;
- case HASH_KEY_IS_LONG:
- Z_LVAL_P(key) = int_key;
- Z_TYPE_P(key) = IS_LONG;
- break;
- default:
- case HASH_KEY_NON_EXISTANT:
- ZVAL_NULL(key);
- break;
- }
- }
-
CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
View
70 Zend/zend_vm_execute.h
@@ -13588,13 +13588,13 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
zval *array = EX_T(opline->op1.var).fe.ptr;
zval **value;
- char *str_key;
- uint str_key_len;
- ulong int_key;
HashTable *fe_ht;
zend_object_iterator *iter = NULL;
- int key_type = 0;
- zend_bool use_key = (zend_bool)(opline->extended_value & ZEND_FE_FETCH_WITH_KEY);
+
+ zval *key = NULL;
+ if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
+ key = &EX_T((opline+1)->result.var).tmp_var;
+ }
SAVE_OPLINE();
@@ -13605,8 +13605,11 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
case ZEND_ITER_PLAIN_OBJECT: {
- const char *class_name, *prop_name;
zend_object *zobj = zend_objects_get_address(array TSRMLS_CC);
+ int key_type;
+ char *str_key;
+ zend_uint str_key_len;
+ zend_ulong int_key;
fe_ht = Z_OBJPROP_P(array);
zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
@@ -13618,15 +13621,23 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
zend_hash_move_forward(fe_ht);
- } while (key_type == HASH_KEY_NON_EXISTANT ||
- (key_type != HASH_KEY_IS_LONG &&
- zend_check_property_access(zobj, str_key, str_key_len-1 TSRMLS_CC) != SUCCESS));
- zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
- if (use_key && key_type != HASH_KEY_IS_LONG) {
- zend_unmangle_property_name_ex(str_key, str_key_len-1, &class_name, &prop_name, &str_key_len);
- str_key = estrndup(prop_name, str_key_len);
- str_key_len++;
+ } while (key_type != HASH_KEY_IS_LONG &&
+ zend_check_property_access(zobj, str_key, str_key_len - 1 TSRMLS_CC) != SUCCESS);
+
+ if (key) {
+ if (key_type == HASH_KEY_IS_LONG) {
+ ZVAL_LONG(key, int_key);
+ } else {
+ const char *class_name, *prop_name;
+ int prop_name_len;
+ zend_unmangle_property_name_ex(
+ str_key, str_key_len - 1, &class_name, &prop_name, &prop_name_len
+ );
+ ZVAL_STRINGL(key, prop_name, prop_name_len, 1);
+ }
}
+
+ zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
break;
}
@@ -13637,8 +13648,8 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
/* reached end of iteration */
ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
- if (use_key) {
- key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL);
+ if (key) {
+ zend_hash_get_current_key_zval(fe_ht, key);
}
zend_hash_move_forward(fe_ht);
zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
@@ -13673,16 +13684,15 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
/* failure in get_current_data */
ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
- if (use_key) {
+ if (key) {
if (iter->funcs->get_current_key) {
- key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC);
+ iter->funcs->get_current_key(iter, key TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array);
HANDLE_EXCEPTION();
}
} else {
- key_type = HASH_KEY_IS_LONG;
- int_key = iter->index;
+ ZVAL_LONG(key, iter->index);
}
}
break;
@@ -13698,26 +13708,6 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
AI_SET_PTR(&EX_T(opline->result.var), *value);
}
- if (use_key) {
- zval *key = &EX_T((opline+1)->result.var).tmp_var;
-
- switch (key_type) {
- case HASH_KEY_IS_STRING:
- Z_STRVAL_P(key) = (char*)str_key;
- Z_STRLEN_P(key) = str_key_len-1;
- Z_TYPE_P(key) = IS_STRING;
- break;
- case HASH_KEY_IS_LONG:
- Z_LVAL_P(key) = int_key;
- Z_TYPE_P(key) = IS_LONG;
- break;
- default:
- case HASH_KEY_NON_EXISTANT:
- ZVAL_NULL(key);
- break;
- }
- }
-
CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
View
9 ext/com_dotnet/com_iterator.c
@@ -74,16 +74,15 @@ static void com_iter_get_data(zend_object_iterator *iter, zval ***data TSRMLS_DC
*data = &I->zdata;
}
-static int com_iter_get_key(zend_object_iterator *iter, char **str_key, uint *str_key_len,
- ulong *int_key TSRMLS_DC)
+static void com_iter_get_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
{
struct php_com_iterator *I = (struct php_com_iterator*)iter->data;
if (I->key == (ulong)-1) {
- return HASH_KEY_NON_EXISTANT;
+ ZVAL_NULL(key);
+ } else {
+ ZVAL_LONG(key, I->key);
}
- *int_key = I->key;
- return HASH_KEY_IS_LONG;
}
static int com_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
View
9 ext/com_dotnet/com_saproxy.c
@@ -519,16 +519,15 @@ static void saproxy_iter_get_data(zend_object_iterator *iter, zval ***data TSRML
*data = ptr_ptr;
}
-static int saproxy_iter_get_key(zend_object_iterator *iter, char **str_key, uint *str_key_len,
- ulong *int_key TSRMLS_DC)
+static void saproxy_iter_get_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
{
php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
if (I->key == -1) {
- return HASH_KEY_NON_EXISTANT;
+ ZVAL_NULL(key);
+ } else {
+ ZVAL_LONG(key, I->key);
}
- *int_key = (ulong)I->key;
- return HASH_KEY_IS_LONG;
}
static int saproxy_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
View
7 ext/date/php_date.c
@@ -1867,11 +1867,10 @@ static void date_period_it_current_data(zend_object_iterator *iter, zval ***data
/* {{{ date_period_it_current_key */
-static int date_period_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
+static void date_period_it_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
{
- date_period_it *iterator = (date_period_it *)iter;
- *int_key = iterator->current_index;
- return HASH_KEY_IS_LONG;
+ date_period_it *iterator = (date_period_it *)iter;
+ ZVAL_LONG(key, iterator->current_index);
}
/* }}} */
View
27 ext/dom/dom_iterators.c
@@ -157,35 +157,22 @@ static void php_dom_iterator_current_data(zend_object_iterator *iter, zval ***da
}
/* }}} */
-static int php_dom_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
+static void php_dom_iterator_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */
{
- zval *curobj;
- xmlNodePtr curnode = NULL;
- dom_object *intern;
- zval *object;
- int namelen;
-
php_dom_iterator *iterator = (php_dom_iterator *)iter;
-
- object = (zval *)iterator->intern.data;
+ zval *object = (zval *)iterator->intern.data;
if (instanceof_function(Z_OBJCE_P(object), dom_nodelist_class_entry TSRMLS_CC)) {
- *int_key = iter->index;
- return HASH_KEY_IS_LONG;
+ ZVAL_LONG(key, iter->index);
} else {
- curobj = iterator->curobj;
+ dom_object *intern = (dom_object *)zend_object_store_get_object(iterator->curobj TSRMLS_CC);
- intern = (dom_object *)zend_object_store_get_object(curobj TSRMLS_CC);
if (intern != NULL && intern->ptr != NULL) {
- curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node;
+ xmlNodePtr curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node;
+ ZVAL_STRINGL(key, (char *) curnode->name, xmlStrlen(curnode->name), 1);
} else {
- return HASH_KEY_NON_EXISTANT;
+ ZVAL_NULL(key);
}
-
- namelen = xmlStrlen(curnode->name);
- *str_key = estrndup(curnode->name, namelen);
- *str_key_len = namelen + 1;
- return HASH_KEY_IS_STRING;
}
}
/* }}} */
View
10 ext/intl/breakiterator/breakiterator_iterators.cpp
@@ -139,14 +139,10 @@ static void _breakiterator_parts_destroy_it(zend_object_iterator *iter TSRMLS_DC
zval_ptr_dtor(reinterpret_cast<zval**>(&iter->data));
}
-static int _breakiterator_parts_get_current_key(zend_object_iterator *iter,
- char **str_key,
- uint *str_key_len,
- ulong *int_key TSRMLS_DC)
+static void _breakiterator_parts_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
{
/* the actual work is done in move_forward and rewind */
- *int_key = iter->index;
- return HASH_KEY_IS_LONG;
+ ZVAL_LONG(key, iter->index);
}
static void _breakiterator_parts_move_forward(zend_object_iterator *iter TSRMLS_DC)
@@ -343,4 +339,4 @@ U_CFUNC void breakiterator_register_IntlPartsIterator_class(TSRMLS_D)
PARTSITER_DECL_LONG_CONST(KEY_RIGHT);
#undef PARTSITER_DECL_LONG_CONST
-}
+}
View
14 ext/intl/common/common_enum.cpp
@@ -251,19 +251,7 @@ static PHP_METHOD(IntlIterator, key)
INTLITERATOR_METHOD_FETCH_OBJECT;
if (ii->iterator->funcs->get_current_key) {
- char *str_key;
- uint str_key_len;
- ulong int_key;
-
- switch (ii->iterator->funcs->get_current_key(
- ii->iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) {
- case HASH_KEY_IS_LONG:
- RETURN_LONG(int_key);
- break;
- case HASH_KEY_IS_STRING:
- RETURN_STRINGL(str_key, str_key_len-1, 0);
- break;
- }
+ ii->iterator->funcs->get_current_key(ii->iterator, return_value TSRMLS_CC);
} else {
RETURN_LONG(ii->iterator->index);
}
View
13 ext/intl/resourcebundle/resourcebundle_iterator.c
@@ -101,21 +101,18 @@ static void resourcebundle_iterator_current( zend_object_iterator *iter, zval **
/* }}} */
/* {{{ resourcebundle_iterator_key */
-static int resourcebundle_iterator_key( zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC )
+static void resourcebundle_iterator_key( zend_object_iterator *iter, zval *key TSRMLS_DC )
{
ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
if (!iterator->current) {
resourcebundle_iterator_read( iterator TSRMLS_CC);
}
+
if (iterator->is_table) {
- *str_key = estrdup( iterator->currentkey );
- *str_key_len = strlen( iterator->currentkey ) + 1;
- return HASH_KEY_IS_STRING;
- }
- else {
- *int_key = iterator->i;
- return HASH_KEY_IS_LONG;
+ ZVAL_STRING(key, iterator->currentkey, 1);
+ } else {
+ ZVAL_LONG(key, iterator->i);
}
}
/* }}} */
View
5 ext/mysqli/mysqli_result_iterator.c
@@ -150,12 +150,11 @@ static void php_mysqli_result_iterator_rewind(zend_object_iterator *iter TSRMLS_
/* {{{ php_mysqli_result_iterator_current_key */
-static int php_mysqli_result_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
+static void php_mysqli_result_iterator_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
{
php_mysqli_result_iterator *iterator = (php_mysqli_result_iterator*) iter;
- *int_key = (ulong) iterator->row_num;
- return HASH_KEY_IS_LONG;
+ ZVAL_LONG(key, iterator->row_num);
}
/* }}} */
View
9 ext/pdo/pdo_stmt.c
@@ -2499,16 +2499,15 @@ static void pdo_stmt_iter_get_data(zend_object_iterator *iter, zval ***data TSRM
*data = &I->fetch_ahead;
}
-static int pdo_stmt_iter_get_key(zend_object_iterator *iter, char **str_key, uint *str_key_len,
- ulong *int_key TSRMLS_DC)
+static void pdo_stmt_iter_get_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
{
struct php_pdo_iterator *I = (struct php_pdo_iterator*)iter->data;
if (I->key == (ulong)-1) {
- return HASH_KEY_NON_EXISTANT;
+ ZVAL_NULL(key);
+ } else {
+ ZVAL_LONG(key, I->key);
}
- *int_key = I->key;
- return HASH_KEY_IS_LONG;
}
static void pdo_stmt_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
View
50 ext/phar/phar_object.c
@@ -1434,16 +1434,13 @@ struct _phar_t {
static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ */
{
zval **value;
- zend_uchar key_type;
zend_bool close_fp = 1;
- ulong int_key;
struct _phar_t *p_obj = (struct _phar_t*) puser;
uint str_key_len, base_len = p_obj->l, fname_len;
phar_entry_data *data;
php_stream *fp;
size_t contents_len;
char *fname, *error = NULL, *base = p_obj->b, *opened, *save = NULL, *temp = NULL;
- phar_zstr key;
char *str_key;
zend_class_entry *ce = p_obj->c;
phar_archive_object *phar_obj = p_obj->p;
@@ -1478,35 +1475,24 @@ static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{
}
if (iter->funcs->get_current_key) {
- key_type = iter->funcs->get_current_key(iter, &key, &str_key_len, &int_key TSRMLS_CC);
+ zval key;
+ iter->funcs->get_current_key(iter, &key TSRMLS_CC);
if (EG(exception)) {
return ZEND_HASH_APPLY_STOP;
}
- if (key_type == HASH_KEY_IS_LONG) {
+ if (Z_TYPE(key) != IS_STRING) {
+ zval_dtor(&key);
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
return ZEND_HASH_APPLY_STOP;
}
- if (key_type > 9) { /* IS_UNICODE == 10 */
-#if PHP_VERSION_ID < 60000
-/* this can never happen, but fixes a compile warning */
- spprintf(&str_key, 0, "%s", key);
-#else
- spprintf(&str_key, 0, "%v", key);
- ezfree(key);
-#endif
- } else {
- PHAR_STR(key, str_key);
- }
+ str_key_len = Z_STRLEN(key);
+ str_key = estrndup(Z_STRVAL(key), str_key_len);
save = str_key;
-
- if (str_key[str_key_len - 1] == '\0') {
- str_key_len--;
- }
-
+ zval_dtor(&key);
} else {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
return ZEND_HASH_APPLY_STOP;
@@ -1641,32 +1627,24 @@ static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{
}
} else {
if (iter->funcs->get_current_key) {
- key_type = iter->funcs->get_current_key(iter, &key, &str_key_len, &int_key TSRMLS_CC);
+ zval key;
+ iter->funcs->get_current_key(iter, &key TSRMLS_CC);
if (EG(exception)) {
return ZEND_HASH_APPLY_STOP;
}
- if (key_type == HASH_KEY_IS_LONG) {
+ if (Z_TYPE(key) != IS_STRING) {
+ zval_dtor(&key);
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
return ZEND_HASH_APPLY_STOP;
}
- if (key_type > 9) { /* IS_UNICODE == 10 */
-#if PHP_VERSION_ID < 60000
-/* this can never happen, but fixes a compile warning */
- spprintf(&str_key, 0, "%s", key);
-#else
- spprintf(&str_key, 0, "%v", key);
- ezfree(key);
-#endif
- } else {
- PHAR_STR(key, str_key);
- }
+ str_key_len = Z_STRLEN(key);
+ str_key = estrndup(Z_STRVAL(key), str_key_len);
save = str_key;
-
- if (str_key[str_key_len - 1] == '\0') str_key_len--;
+ zval_dtor(&key);
} else {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
return ZEND_HASH_APPLY_STOP;
View
27 ext/simplexml/simplexml.c
@@ -59,7 +59,7 @@ static zval *sxe_get_value(zval *z TSRMLS_DC);
static void php_sxe_iterator_dtor(zend_object_iterator *iter TSRMLS_DC);
static int php_sxe_iterator_valid(zend_object_iterator *iter TSRMLS_DC);
static void php_sxe_iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC);
-static int php_sxe_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC);
+static void php_sxe_iterator_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC);
static void php_sxe_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC);
static void php_sxe_iterator_rewind(zend_object_iterator *iter TSRMLS_DC);
@@ -2376,29 +2376,22 @@ static void php_sxe_iterator_current_data(zend_object_iterator *iter, zval ***da
}
/* }}} */
-static int php_sxe_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
+static void php_sxe_iterator_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */
{
- zval *curobj;
- xmlNodePtr curnode = NULL;
- php_sxe_object *intern;
- int namelen;
-
php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
- curobj = iterator->sxe->iter.data;
+ zval *curobj = iterator->sxe->iter.data;
+ php_sxe_object *intern = (php_sxe_object *)zend_object_store_get_object(curobj TSRMLS_CC);
- intern = (php_sxe_object *)zend_object_store_get_object(curobj TSRMLS_CC);
+ xmlNodePtr curnode = NULL;
if (intern != NULL && intern->node != NULL) {
curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->node)->node;
}
- if (!curnode) {
- return HASH_KEY_NON_EXISTANT;
- }
-
- namelen = xmlStrlen(curnode->name);
- *str_key = estrndup((char *)curnode->name, namelen);
- *str_key_len = namelen + 1;
- return HASH_KEY_IS_STRING;
+ if (curnode) {
+ ZVAL_STRINGL(key, (char *) curnode->name, xmlStrlen(curnode->name), 1);
+ } else {
+ ZVAL_NULL(key);
+ }
}
/* }}} */
View
19 ext/soap/php_encoding.c
@@ -2313,10 +2313,6 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod
zend_object_iterator *iter;
zend_class_entry *ce = Z_OBJCE_P(data);
zval **val;
- char *str_key;
- uint str_key_len;
- ulong int_key;
- int key_type;
ALLOC_ZVAL(array_copy);
INIT_PZVAL(array_copy);
@@ -2345,19 +2341,14 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod
goto iterator_done;
}
if (iter->funcs->get_current_key) {
- key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC);
+ zval key;
+ iter->funcs->get_current_key(iter, &key TSRMLS_CC);
if (EG(exception)) {
goto iterator_done;
}
- switch(key_type) {
- case HASH_KEY_IS_STRING:
- add_assoc_zval_ex(array_copy, str_key, str_key_len, *val);
- efree(str_key);
- break;
- case HASH_KEY_IS_LONG:
- add_index_zval(array_copy, int_key, *val);
- break;
- }
+ array_set_zval_key(Z_ARRVAL_P(array_copy), &key, *val);
+ zval_ptr_dtor(val);
+ zval_dtor(&key);
} else {
add_next_index_zval(array_copy, *val);
}
View
21 ext/spl/spl_array.c
@@ -1018,20 +1018,20 @@ static void spl_array_it_get_current_data(zend_object_iterator *iter, zval ***da
}
/* }}} */
-static int spl_array_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
+static void spl_array_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */
{
spl_array_it *iterator = (spl_array_it *)iter;
spl_array_object *object = iterator->object;
HashTable *aht = spl_array_get_hash_table(object, 0 TSRMLS_CC);
if (object->ar_flags & SPL_ARRAY_OVERLOADED_KEY) {
- return zend_user_it_get_current_key(iter, str_key, str_key_len, int_key TSRMLS_CC);
+ zend_user_it_get_current_key(iter, key TSRMLS_CC);
} else {
if (spl_array_object_verify_pos_ex(object, aht, "ArrayIterator::current(): " TSRMLS_CC) == FAILURE) {
- return HASH_KEY_NON_EXISTANT;
+ ZVAL_NULL(key);
+ } else {
+ zend_hash_get_current_key_zval_ex(aht, key, &object->pos);
}
-
- return zend_hash_get_current_key_ex(aht, str_key, str_key_len, int_key, 1, &object->pos);
}
}
/* }}} */
@@ -1556,16 +1556,7 @@ void spl_array_iterator_key(zval *object, zval *return_value TSRMLS_DC) /* {{{ *
return;
}
- switch (zend_hash_get_current_key_ex(aht, &string_key, &string_length, &num_key, 1, &intern->pos)) {
- case HASH_KEY_IS_STRING:
- RETVAL_STRINGL(string_key, string_length - 1, 0);
- break;
- case HASH_KEY_IS_LONG:
- RETVAL_LONG(num_key);
- break;
- case HASH_KEY_NON_EXISTANT:
- return;
- }
+ zend_hash_get_current_key_zval_ex(aht, return_value, &intern->pos);
}
/* }}} */
View
20 ext/spl/spl_directory.c
@@ -1621,7 +1621,7 @@ SPL_METHOD(GlobIterator, count)
static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC);
static int spl_filesystem_dir_it_valid(zend_object_iterator *iter TSRMLS_DC);
static void spl_filesystem_dir_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC);
-static int spl_filesystem_dir_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC);
+static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC);
static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter TSRMLS_DC);
static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC);
@@ -1698,12 +1698,11 @@ static void spl_filesystem_dir_it_current_data(zend_object_iterator *iter, zval
/* }}} */
/* {{{ spl_filesystem_dir_it_current_key */
-static int spl_filesystem_dir_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
+static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
{
spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
-
- *int_key = object->u.dir.index;
- return HASH_KEY_IS_LONG;
+
+ ZVAL_LONG(key, object->u.dir.index);
}
/* }}} */
@@ -1777,19 +1776,16 @@ static void spl_filesystem_tree_it_current_data(zend_object_iterator *iter, zval
/* }}} */
/* {{{ spl_filesystem_tree_it_current_key */
-static int spl_filesystem_tree_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
+static void spl_filesystem_tree_it_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
{
spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
-
+
if (SPL_FILE_DIR_KEY(object, SPL_FILE_DIR_KEY_AS_FILENAME)) {
- *str_key_len = strlen(object->u.dir.entry.d_name) + 1;
- *str_key = estrndup(object->u.dir.entry.d_name, *str_key_len - 1);
+ ZVAL_STRING(key, object->u.dir.entry.d_name, 1);
} else {
spl_filesystem_object_get_file_name(object TSRMLS_CC);
- *str_key_len = object->file_name_len + 1;
- *str_key = estrndup(object->file_name, object->file_name_len);
+ ZVAL_STRINGL(key, object->file_name, object->file_name_len, 1);
}
- return HASH_KEY_IS_STRING;
}
/* }}} */
View
5 ext/spl/spl_dllist.c
@@ -1023,12 +1023,11 @@ static void spl_dllist_it_get_current_data(zend_object_iterator *iter, zval ***d
}
/* }}} */
-static int spl_dllist_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
+static void spl_dllist_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */
{
spl_dllist_it *iterator = (spl_dllist_it *)iter;
- *int_key = (ulong) iterator->traverse_position;
- return HASH_KEY_IS_LONG;
+ ZVAL_LONG(key, iterator->traverse_position);
}
/* }}} */
View
8 ext/spl/spl_fixedarray.c
@@ -948,18 +948,16 @@ static void spl_fixedarray_it_get_current_data(zend_object_iterator *iter, zval
}
/* }}} */
-static int spl_fixedarray_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
+static void spl_fixedarray_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */
{
spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter;
spl_fixedarray_object *intern = iterator->object;
if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_KEY) {
- return zend_user_it_get_current_key(iter, str_key, str_key_len, int_key TSRMLS_CC);
+ zend_user_it_get_current_key(iter, key TSRMLS_CC);
} else {
- *int_key = (ulong) iterator->object->current;
- return HASH_KEY_IS_LONG;
+ ZVAL_LONG(key, iterator->object->current);
}
-
}
/* }}} */
View
5 ext/spl/spl_heap.c
@@ -949,12 +949,11 @@ static void spl_pqueue_it_get_current_data(zend_object_iterator *iter, zval ***d
}
/* }}} */
-static int spl_heap_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
+static void spl_heap_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */
{
spl_heap_it *iterator = (spl_heap_it *)iter;
- *int_key = (ulong) iterator->object->heap->count - 1;
- return HASH_KEY_IS_LONG;
+ ZVAL_LONG(key, iterator->object->heap->count - 1);
}
/* }}} */
View
171 ext/spl/spl_iterators.c
@@ -190,16 +190,15 @@ static void spl_recursive_it_get_current_data(zend_object_iterator *iter, zval *
sub_iter->funcs->get_current_data(sub_iter, data TSRMLS_CC);
}
-static int spl_recursive_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
+static void spl_recursive_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
{
spl_recursive_it_object *object = (spl_recursive_it_object*)iter->data;
zend_object_iterator *sub_iter = object->iterators[object->level].iterator;
if (sub_iter->funcs->get_current_key) {
- return sub_iter->funcs->get_current_key(sub_iter, str_key, str_key_len, int_key TSRMLS_CC);
+ sub_iter->funcs->get_current_key(sub_iter, key TSRMLS_CC);
} else {
- *int_key = iter->index;
- return HASH_KEY_IS_LONG;
+ ZVAL_LONG(key, iter->index);
}
}
@@ -617,20 +616,7 @@ SPL_METHOD(RecursiveIteratorIterator, key)
}
if (iterator->funcs->get_current_key) {
- char *str_key;
- uint str_key_len;
- ulong int_key;
-
- switch (iterator->funcs->get_current_key(iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) {
- case HASH_KEY_IS_LONG:
- RETURN_LONG(int_key);
- break;
- case HASH_KEY_IS_STRING:
- RETURN_STRINGL(str_key, str_key_len-1, 0);
- break;
- default:
- RETURN_NULL();
- }
+ iterator->funcs->get_current_key(iterator, return_value TSRMLS_CC);
} else {
RETURN_NULL();
}
@@ -1171,20 +1157,7 @@ SPL_METHOD(RecursiveTreeIterator, key)
}
if (iterator->funcs->get_current_key) {
- char *str_key;
- uint str_key_len;
- ulong int_key;
-
- switch (iterator->funcs->get_current_key(iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) {
- case HASH_KEY_IS_LONG:
- ZVAL_LONG(&key, int_key);
- break;
- case HASH_KEY_IS_STRING:
- ZVAL_STRINGL(&key, str_key, str_key_len-1, 0);
- break;
- default:
- ZVAL_NULL(&key);
- }
+ iterator->funcs->get_current_key(iterator, &key TSRMLS_CC);
} else {
ZVAL_NULL(&key);
}
@@ -1590,9 +1563,9 @@ static inline void spl_dual_it_free(spl_dual_it_object *intern TSRMLS_DC)
zval_ptr_dtor(&intern->current.data);
intern->current.data = NULL;
}
- if (intern->current.str_key) {
- efree(intern->current.str_key);
- intern->current.str_key = NULL;
+ if (intern->current.key) {
+ zval_ptr_dtor(&intern->current.key);
+ intern->current.key = NULL;
}
if (intern->dit_type == DIT_CachingIterator || intern->dit_type == DIT_RecursiveCachingIterator) {
if (intern->u.caching.zstr) {
@@ -1635,11 +1608,16 @@ static inline int spl_dual_it_fetch(spl_dual_it_object *intern, int check_more T
intern->current.data = *data;
Z_ADDREF_P(intern->current.data);
}
+
+ MAKE_STD_ZVAL(intern->current.key);
if (intern->inner.iterator->funcs->get_current_key) {
- intern->current.key_type = intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, &intern->current.str_key, &intern->current.str_key_len, &intern->current.int_key TSRMLS_CC);
+ intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, intern->current.key TSRMLS_CC);
+ if (EG(exception)) {
+ zval_ptr_dtor(&intern->current.key);
+ intern->current.key = NULL;
+ }
} else {
- intern->current.key_type = HASH_KEY_IS_LONG;
- intern->current.int_key = intern->current.pos;
+ ZVAL_LONG(intern->current.key, intern->current.pos);
}
return EG(exception) ? FAILURE : SUCCESS;
}
@@ -1711,12 +1689,8 @@ SPL_METHOD(dual_it, key)
SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
- if (intern->current.data) {
- if (intern->current.key_type == HASH_KEY_IS_STRING) {
- RETURN_STRINGL(intern->current.str_key, intern->current.str_key_len-1, 1);
- } else {
- RETURN_LONG(intern->current.int_key);
- }
+ if (intern->current.key) {
+ RETURN_ZVAL(intern->current.key, 1, 0);
}
RETURN_NULL();
} /* }}} */
@@ -1927,27 +1901,18 @@ SPL_METHOD(CallbackFilterIterator, accept)
zend_fcall_info *fci = &intern->u.cbfilter->fci;
zend_fcall_info_cache *fcc = &intern->u.cbfilter->fcc;
zval **params[3];
- zval zkey;
- zval *zkey_p = &zkey;
zval *result;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
- if (intern->current.data == NULL) {
+ if (intern->current.data == NULL || intern->current.key == NULL) {
RETURN_FALSE;
}
-
- INIT_PZVAL(&zkey);
- if (intern->current.key_type == HASH_KEY_IS_LONG) {
- ZVAL_LONG(&zkey, intern->current.int_key);
- } else {
- ZVAL_STRINGL(&zkey, intern->current.str_key, intern->current.str_key_len-1, 0);
- }
params[0] = &intern->current.data;
- params[1] = &zkey_p;
+ params[1] = &intern->current.key;
params[2] = &intern->inner.zobject;
fci->retval_ptr_ptr = &result;
@@ -1971,9 +1936,9 @@ SPL_METHOD(CallbackFilterIterator, accept)
SPL_METHOD(RegexIterator, accept)
{
spl_dual_it_object *intern;
- char *subject, tmp[32], *result;
+ char *subject, *result;
int subject_len, use_copy, count = 0, result_len;
- zval subject_copy, zcount, *replacement, tmp_replacement;
+ zval *subject_ptr, subject_copy, zcount, *replacement, tmp_replacement;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -1986,24 +1951,18 @@ SPL_METHOD(RegexIterator, accept)
}
if (intern->u.regex.flags & REGIT_USE_KEY) {
- if (intern->current.key_type == HASH_KEY_IS_LONG) {
- subject_len = slprintf(tmp, sizeof(tmp), "%ld", intern->current.int_key);
- subject = &tmp[0];
- use_copy = 0;
- } else {
- subject_len = intern->current.str_key_len - 1;
- subject = estrndup(intern->current.str_key, subject_len);
- use_copy = 1;
- }
+ subject_ptr = intern->current.key;
} else {
- zend_make_printable_zval(intern->current.data, &subject_copy, &use_copy);
- if (use_copy) {
- subject = Z_STRVAL(subject_copy);
- subject_len = Z_STRLEN(subject_copy);
- } else {
- subject = Z_STRVAL_P(intern->current.data);
- subject_len = Z_STRLEN_P(intern->current.data);
- }
+ subject_ptr = intern->current.data;
+ }
+
+ zend_make_printable_zval(subject_ptr, &subject_copy, &use_copy);
+ if (use_copy) {
+ subject = Z_STRVAL(subject_copy);
+ subject_len = Z_STRLEN(subject_copy);
+ } else {
+ subject = Z_STRVAL_P(subject_ptr);
+ subject_len = Z_STRLEN_P(subject_ptr);
}
switch (intern->u.regex.mode)
@@ -2051,12 +2010,9 @@ SPL_METHOD(RegexIterator, accept)
result = php_pcre_replace_impl(intern->u.regex.pce, subject, subject_len, replacement, 0, &result_len, -1, &count TSRMLS_CC);
if (intern->u.regex.flags & REGIT_USE_KEY) {
- if (intern->current.key_type != HASH_KEY_IS_LONG) {
- efree(intern->current.str_key);
- }
- intern->current.key_type = HASH_KEY_IS_STRING;
- intern->current.str_key = result;
- intern->current.str_key_len = result_len + 1;
+ zval_ptr_dtor(&intern->current.key);
+ MAKE_STD_ZVAL(intern->current.key);
+ ZVAL_STRINGL(intern->current.key, result, result_len, 0);
} else {
zval_ptr_dtor(&intern->current.data);
MAKE_STD_ZVAL(intern->current.data);
@@ -2590,14 +2546,14 @@ static inline void spl_caching_it_next(spl_dual_it_object *intern TSRMLS_DC)
/* Full cache ? */
if (intern->u.caching.flags & CIT_FULL_CACHE) {
zval *zcacheval;
+ zval *key = intern->current.key;
MAKE_STD_ZVAL(zcacheval);
ZVAL_ZVAL(zcacheval, intern->current.data, 1, 0);
- if (intern->current.key_type == HASH_KEY_IS_LONG) {
- add_index_zval(intern->u.caching.zcache, intern->current.int_key, zcacheval);
- } else {
- zend_symtable_update(HASH_OF(intern->u.caching.zcache), intern->current.str_key, intern->current.str_key_len, &zcacheval, sizeof(void*), NULL);
- }
+
+ array_set_zval_key(HASH_OF(intern->u.caching.zcache), key, zcacheval);
+
+ zval_ptr_dtor(&zcacheval);
}
/* Recursion ? */
if (intern->dit_type == DIT_RecursiveCachingIterator) {
@@ -2755,13 +2711,9 @@ SPL_METHOD(CachingIterator, __toString)
return;
}
if (intern->u.caching.flags & CIT_TOSTRING_USE_KEY) {
- if (intern->current.key_type == HASH_KEY_IS_STRING) {
- RETURN_STRINGL(intern->current.str_key, intern->current.str_key_len-1, 1);
- } else {
- RETVAL_LONG(intern->current.int_key);
- convert_to_string(return_value);
- return;
- }
+ MAKE_COPY_ZVAL(&intern->current.key, return_value);
+ convert_to_string(return_value);
+ return;
} else if (intern->u.caching.flags & CIT_TOSTRING_USE_CURRENT) {
MAKE_COPY_ZVAL(&intern->current.data, return_value);
convert_to_string(return_value);
@@ -3123,19 +3075,7 @@ SPL_METHOD(NoRewindIterator, key)
SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
if (intern->inner.iterator->funcs->get_current_key) {
- char *str_key;
- uint str_key_len;
- ulong int_key;
- switch (intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) {
- case HASH_KEY_IS_LONG:
- RETURN_LONG(int_key);
- break;
- case HASH_KEY_IS_STRING:
- RETURN_STRINGL(str_key, str_key_len-1, 0);
- break;
- default:
- RETURN_NULL();
- }
+ intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, return_value TSRMLS_CC);
} else {
RETURN_NULL();
}
@@ -3502,11 +3442,7 @@ PHPAPI int spl_iterator_apply(zval *obj, spl_iterator_apply_func_t apply_func, v
static int spl_iterator_to_array_apply(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ */
{
- zval **data, *return_value = (zval*)puser;
- char *str_key;
- uint str_key_len;
- ulong int_key;
- int key_type;
+ zval **data, *return_value = (zval*)puser;
iter->funcs->get_current_data(iter, &data TSRMLS_CC);
if (EG(exception)) {
@@ -3516,20 +3452,13 @@ static int spl_iterator_to_array_apply(zend_object_iterator *iter, void *puser T
return ZEND_HASH_APPLY_STOP;
}
if (iter->funcs->get_current_key) {
- key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC);
+ zval key;
+ iter->funcs->get_current_key(iter, &key TSRMLS_CC);
if (EG(exception)) {
return ZEND_HASH_APPLY_STOP;
}
- Z_ADDREF_PP(data);
- switch(key_type) {
- case HASH_KEY_IS_STRING:
- add_assoc_zval_ex(return_value, str_key, str_key_len, *data);
- efree(str_key);
- break;
- case HASH_KEY_IS_LONG:
- add_index_zval(return_value, int_key, *data);
- break;
- }
+ array_set_zval_key(Z_ARRVAL_P(return_value), &key, *data);
+ zval_dtor(&key);
} else {
Z_ADDREF_PP(data);
add_next_index_zval(return_value, *data);
View
5 ext/spl/spl_iterators.h
@@ -133,10 +133,7 @@ typedef struct _spl_dual_it_object {
} inner;
struct {
zval *data;
- char *str_key;
- uint str_key_len;
- ulong int_key;
- int key_type; /* HASH_KEY_IS_STRING or HASH_KEY_IS_LONG */
+ zval *key;
int pos;
} current;
dual_it_type dit_type;
View
31 ext/spl/tests/iterator_to_array_nonscalar_keys.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Tests iterator_to_array() with non-scalar keys
+--FILE--
+<?php
+
+function gen() {
+ yield "foo" => 0;
+ yield 1 => 1;
+ yield 2.5 => 2;
+ yield null => 3;
+ yield [] => 4;
+ yield new stdClass => 5;
+}
+
+var_dump(iterator_to_array(gen()));
+
+?>
+--EXPECTF--
+Warning: Illegal offset type in %s on line %d
+
+Warning: Illegal offset type in %s on line %d
+array(4) {
+ ["foo"]=>
+ int(0)
+ [1]=>
+ int(1)
+ [0]=>
+ int(2)
+ [""]=>
+ int(3)
+}
View
20 ext/spl/tests/multiple_iterator_001.phpt
@@ -23,8 +23,8 @@ echo "-- Default flags, MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_K
var_dump($m->getFlags() === (MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC));
-foreach($m as $value) {
- var_dump($m->key(), $value);
+foreach($m as $key => $value) {
+ var_dump($key, $value);
}
try {
$m->current();
@@ -42,17 +42,17 @@ echo "-- Flags = MultipleIterator::MIT_NEED_ANY | MultipleIterator::MIT_KEYS_NUM
$m->setFlags(MultipleIterator::MIT_NEED_ANY | MultipleIterator::MIT_KEYS_NUMERIC);
var_dump($m->getFlags() === (MultipleIterator::MIT_NEED_ANY | MultipleIterator::MIT_KEYS_NUMERIC));
-foreach($m as $value) {
- var_dump($m->key(), $value);
+foreach($m as $key => $value) {
+ var_dump($key, $value);
}
echo "-- Default flags, added element --\n";
$m->setFlags(MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC);
$iter2[] = 3;
-foreach($m as $value) {
- var_dump($m->key(), $value);
+foreach($m as $key => $value) {
+ var_dump($key, $value);
}
echo "-- Flags |= MultipleIterator::MIT_KEYS_ASSOC, with iterator associated with NULL --\n";
@@ -71,8 +71,8 @@ $m->attachIterator($iter1, "iter1");
$m->attachIterator($iter2, b"iter2");
$m->attachIterator($iter3, 3);
-foreach($m as $value) {
- var_dump($m->key(), $value);
+foreach($m as $key => $value) {
+ var_dump($key, $value);
}
echo "-- Associate with invalid value --\n";
@@ -98,8 +98,8 @@ var_dump($m->containsIterator($iter2));
var_dump($m->detachIterator($iter2));
var_dump($m->countIterators());
var_dump($m->containsIterator($iter2));
-foreach($m as $value) {
- var_dump($m->key(), $value);
+foreach($m as $key => $value) {
+ var_dump($key, $value);
}
?>
View
62 ext/standard/array.c
@@ -935,16 +935,7 @@ PHP_FUNCTION(key)
return;
}
- switch (zend_hash_get_current_key_ex(array, &string_key, &string_length, &num_key, 0, NULL)) {
- case HASH_KEY_IS_STRING:
- RETVAL_STRINGL(string_key, string_length - 1, 1);
- break;
- case HASH_KEY_IS_LONG:
- RETVAL_LONG(num_key);
- break;
- case HASH_KEY_NON_EXISTANT:
- return;
- }
+ zend_hash_get_current_key_zval(array, return_value);
}
/* }}} */
@@ -1055,9 +1046,6 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive
zval **args[3], /* Arguments to userland function */
*retval_ptr, /* Return value - unused */
*key=NULL; /* Entry key */
- char *string_key;
- uint string_key_len;
- ulong num_key;
/* Set up known arguments */
args[1] = &key;
@@ -1103,17 +1091,7 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive
} else {
/* Allocate space for key */
MAKE_STD_ZVAL(key);
-
- /* Set up the key */
- switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_key_len, &num_key, 0, NULL)) {
- case HASH_KEY_IS_LONG:
- Z_TYPE_P(key) = IS_LONG;
- Z_LVAL_P(key) = num_key;
- break;
- case HASH_KEY_IS_STRING:
- ZVAL_STRINGL(key, string_key, string_key_len - 1, 1);
- break;
- }
+ zend_hash_get_current_key_zval(target_hash, key);
/* Call the userland function */
if (zend_call_function(&BG(array_walk_fci), &BG(array_walk_fci_cache) TSRMLS_CC) == SUCCESS) {
@@ -1225,15 +1203,8 @@ static void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{
if (behavior == 0) {
RETURN_TRUE;
} else {
- /* Return current key */
- switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &str_key_len, &num_key, 0, &pos)) {
- case HASH_KEY_IS_STRING:
- RETURN_STRINGL(string_key, str_key_len - 1, 1);
- break;
- case HASH_KEY_IS_LONG:
- RETURN_LONG(num_key);
- break;
- }
+ zend_hash_get_current_key_zval_ex(Z_ARRVAL_P(array), return_value, &pos);
+ return;
}
}
zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos);
@@ -2480,19 +2451,8 @@ PHP_FUNCTION(array_keys)
if (add_key) {
MAKE_STD_ZVAL(new_val);
-
- switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 1, &pos)) {
- case HASH_KEY_IS_STRING:
- ZVAL_STRINGL(new_val, string_key, string_key_len - 1, 0);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL);
- break;
-
- case HASH_KEY_IS_LONG:
- Z_TYPE_P(new_val) = IS_LONG;
- Z_LVAL_P(new_val) = num_key;
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL);
- break;
- }
+ zend_hash_get_current_key_zval_ex(Z_ARRVAL_P(input), new_val, &pos);
+ zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL);
}
zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos);
@@ -2705,15 +2665,7 @@ PHP_FUNCTION(array_flip)
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) {
MAKE_STD_ZVAL(data);
- switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &str_key_len, &num_key, 1, &pos)) {
- case HASH_KEY_IS_STRING:
- ZVAL_STRINGL(data, string_key, str_key_len - 1, 0);
- break;
- case HASH_KEY_IS_LONG:
- Z_TYPE_P(data) = IS_LONG;
- Z_LVAL_P(data) = num_key;
- break;
- }
+ zend_hash_get_current_key_zval_ex(Z_ARRVAL_P(array), data, &pos);
if (Z_TYPE_PP(entry) == IS_LONG) {
zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_PP(entry), &data, sizeof(data), NULL);

0 comments on commit fcc6611

Please sign in to comment.
Something went wrong with that request. Please try again.