summaryrefslogtreecommitdiff
path: root/ext/spl/spl_foreach.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/spl/spl_foreach.c')
-rwxr-xr-xext/spl/spl_foreach.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/ext/spl/spl_foreach.c b/ext/spl/spl_foreach.c
new file mode 100755
index 0000000000..8474639bcd
--- /dev/null
+++ b/ext/spl/spl_foreach.c
@@ -0,0 +1,130 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP version 4.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.02 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/2_02.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "zend_compile.h"
+#include "zend_execute_locks.h"
+
+#include "php_spl.h"
+#include "spl_functions.h"
+#include "spl_engine.h"
+#include "spl_foreach.h"
+
+/* {{{ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET) */
+ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET)
+{
+ zval **obj, *retval;
+
+ if (EX(opline)->extended_value) {
+ obj = spl_get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC);
+ if (spl_is_instance_of(obj, spl_ce_iterator TSRMLS_CC)) {
+ spl_unlock_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC);
+ MAKE_STD_ZVAL(retval);
+ spl_begin_method_call_this(obj, "new_iterator", retval TSRMLS_CC);
+ EX_T(EX(opline)->result.u.var).var.ptr = retval;
+ EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr;
+ EX(opline)->op2.u.EA.type = 0; /* missuse as index */
+
+ PZVAL_LOCK(retval);
+
+ NEXT_OPCODE();
+ } else if (spl_is_instance_of(obj, spl_ce_forward TSRMLS_CC)) {
+ spl_unlock_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC);
+
+ EX_T(EX(opline)->result.u.var).var.ptr = *obj;
+ EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr;
+ EX(opline)->op2.u.EA.type = 0; /* missuse as index */
+
+ (*obj)->refcount++;
+ PZVAL_LOCK(*obj);
+
+ NEXT_OPCODE();
+ }
+ }
+ ZEND_EXECUTE_HOOK_ORIGINAL(ZEND_FE_RESET);
+}
+/* }}} */
+
+/* {{{ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_FETCH) */
+ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_FETCH)
+{
+ zval **obj = spl_get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC);
+ zval more, tmp, *value, *key, *result;
+
+ if (spl_is_instance_of(obj, spl_ce_forward TSRMLS_CC)) {
+ zend_uint index = EX(opline)->op2.u.EA.type++;
+
+ spl_unlock_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC);
+ PZVAL_LOCK(*obj);
+
+ if (index) {
+ spl_begin_method_call_this(obj, "next", &more TSRMLS_CC);
+ } else if (spl_is_instance_of(obj, spl_ce_sequence TSRMLS_CC)) {
+ spl_begin_method_call_this(obj, "rewind", &more TSRMLS_CC);
+ }
+
+ spl_begin_method_call_this(obj, "has_more", &more TSRMLS_CC);
+ if (zend_is_true(&more)) {
+ result = &EX_T(EX(opline)->result.u.var).tmp_var;
+ array_init(result);
+ ALLOC_ZVAL(value);
+
+ spl_begin_method_call_this(obj, "current", value TSRMLS_CC);
+
+ zend_hash_index_update(result->value.ht, 0, &value, sizeof(zval *), NULL);
+
+ if (spl_is_instance_of(obj, spl_ce_assoc TSRMLS_CC)) {
+ ALLOC_ZVAL(key);
+ spl_begin_method_call_this(obj, "key", key TSRMLS_CC);
+ } else {
+ /* If someone makes a reference to this value then there is
+ * a real problem. And the only way to avoid it is to alloc
+ * dealloc this temporary zval then.
+ */
+ tmp.value.lval = index;
+ tmp.type = IS_LONG;
+ tmp.refcount = 0;
+ tmp.is_ref = 0;
+ key = &tmp;
+ }
+ zend_hash_index_update(result->value.ht, 1, &key, sizeof(zval *), NULL);
+
+ NEXT_OPCODE();
+ }
+ else
+ EX(opline) = op_array->opcodes+EX(opline)->op2.u.opline_num;
+ return 0;
+ }
+ ZEND_EXECUTE_HOOK_ORIGINAL(ZEND_FE_FETCH);
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: fdm=marker
+ * vim: noet sw=4 ts=4
+ */