-<pre>
This is an extension that aims to implement some efficient data access
interfaces and classes.
be the best case. And 4) also enables the foreach trick.
To implement 3) and 4) with other db extensions ask me and wait for LT to pass.
-
-</pre>
\ No newline at end of file
/* {{{ spl_array_writer_default_set */
void spl_array_writer_default_set(zval *object, zval *newval, zval **retval TSRMLS_DC)
{
- zval *obj, *idx;
spl_array_writer_object *writer;
writer = (spl_array_writer_object *) zend_object_store_get_object(object TSRMLS_CC);
- obj = writer->obj;
- idx = writer->idx;
- spl_begin_method_call_arg_ex2(&obj, "set", retval, &idx, &newval, 0, NULL TSRMLS_CC);
+ spl_begin_method_call_arg_ex2(&writer->obj, NULL, "set", sizeof("set")-1, retval, writer->idx, newval TSRMLS_CC);
}
/* }}} */
zval *exists;
/*ALLOC_ZVAL(exists); not needed */
- spl_begin_method_call_arg_ex1(container_ptr, "exists", &exists, &dim, 0, NULL TSRMLS_CC);
+ spl_begin_method_call_arg_ex1(container_ptr, NULL, "exists", sizeof("exists")-1, &exists, dim TSRMLS_CC);
if (!i_zend_is_true(exists)) {
if (type == BP_VAR_R || type == BP_VAR_RW) {
SEPARATE_ZVAL(&dim);
}
DELETE_RET_ZVAL(exists);
if (type == BP_VAR_R || type == BP_VAR_IS) {
- spl_begin_method_call_arg_ex1(container_ptr, "get", retval, &dim, 0, NULL TSRMLS_CC);
+ spl_begin_method_call_arg_ex1(container_ptr, NULL, "get", sizeof("get")-1, retval, dim TSRMLS_CC);
(*retval)->refcount--;
} else
#ifdef SPL_ARRAY_WRITE
if (spl_is_instance_of(container_ptr, spl_ce_array_access_ex TSRMLS_CC)) {
/* array_access_ex instaces have their own way of creating an access_writer */
- spl_begin_method_call_arg_ex1(container_ptr, "new_writer", retval, &dim, 0, NULL TSRMLS_CC);
+ spl_begin_method_call_arg_ex1(container_ptr, NULL, "new_writer", sizeof("new_writer")-1, retval, dim TSRMLS_CC);
T(result->u.var).var.ptr = *retval;
AI_PTR_2_PTR_PTR(T(result->u.var).var);
SELECTIVE_PZVAL_LOCK(*retval, result);
}
SELECTIVE_PZVAL_LOCK(*retval, result);
#else
- zend_error(E_ERROR, "SPL compiled withut array write hook");
+ zend_error(E_ERROR, "SPL compiled without array write hook");
#endif
FREE_OP(Ts, op2, EG(free_op2));
return 0;
spl_array_writer_default_set(*writer, newval, &retval TSRMLS_CC);
} else if (spl_is_instance_of(writer, spl_ce_array_writer TSRMLS_CC)) {
newval = spl_get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2) TSRMLS_CC);
- spl_begin_method_call_arg_ex1(writer, "set", &retval, &newval, 0, NULL TSRMLS_CC);
+ spl_begin_method_call_arg_ex1(writer, NULL, "set", sizeof("set")-1, &retval, newval TSRMLS_CC);
} else {
ZEND_EXECUTE_HOOK_ORIGINAL(ZEND_ASSIGN);
}
#include "spl_functions.h"
#include "spl_engine.h"
-/* {{{ spl_begin_method_call_arg */
-int spl_begin_method_call_arg(zval **ce, char *function_name, zval *retval, zval *arg1 TSRMLS_DC)
-{
- zval *args[1];
- zval fn_name;
-
- ZVAL_STRING(&fn_name, function_name, 0);
-
- args[0] = arg1;
- return call_user_function(&Z_OBJCE_PP(ce)->function_table, ce, &fn_name, retval, 1, args TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ spl_begin_method_call_this */
-int spl_begin_method_call_this(zval **ce, char *function_name, zval *retval TSRMLS_DC)
-{
- zval fn_name;
-
- ZVAL_STRING(&fn_name, function_name, 0);
-
- return call_user_function(&Z_OBJCE_PP(ce)->function_table, ce, &fn_name, retval, 0, NULL TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ spl_begin_method_call_arg_ex1 */
-int spl_begin_method_call_arg_ex1(zval **ce, char *function_name, zval **retval, zval **arg1, int no_separation, HashTable *symbol_table TSRMLS_DC)
-{
- zval **args[1];
- zval fn_name;
-
- ZVAL_STRING(&fn_name, function_name, 0);
-
- args[0] = arg1;
- return call_user_function_ex(&Z_OBJCE_PP(ce)->function_table, ce, &fn_name, retval, 1, args, no_separation, symbol_table TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ spl_begin_method_call_arg_ex2 */
-int spl_begin_method_call_arg_ex2(zval **ce, char *function_name, zval **retval, zval **arg1, zval **arg2, int no_separation, HashTable *symbol_table TSRMLS_DC)
-{
- zval **args[2];
- zval fn_name;
-
- ZVAL_STRING(&fn_name, function_name, 0);
-
- args[0] = arg1;
- args[1] = arg2;
- return call_user_function_ex(&Z_OBJCE_PP(ce)->function_table, ce, &fn_name, retval, 2, args, no_separation, symbol_table TSRMLS_CC);
-}
-/* }}} */
-
/* {{{ spl_instanciate */
void spl_instanciate(zend_class_entry *pce, zval **object TSRMLS_DC)
{
/* }}} */
/* {{{ spl_instanciate_arg_ex2 */
-int spl_instanciate_arg_ex2(zend_class_entry *pce, zval **retval, zval **arg1, zval **arg2, int no_separation, HashTable *symbol_table TSRMLS_DC)
+int spl_instanciate_arg_ex2(zend_class_entry *pce, zval **retval, zval *arg1, zval *arg2, HashTable *symbol_table TSRMLS_DC)
{
- zval **args[2];
- zval fn_name;
zval *object;
spl_instanciate(pce, &object TSRMLS_CC);
retval = &EG(uninitialized_zval_ptr);
- ZVAL_STRING(&fn_name, pce->constructor->common.function_name, 0);
-
- args[0] = arg1;
- args[1] = arg2;
- call_user_function_ex(&pce->function_table, &object, &fn_name, retval, 2, args, no_separation, symbol_table TSRMLS_CC);
+ spl_call_method(&object, NULL, pce->constructor->common.function_name, strlen(pce->constructor->common.function_name), retval, NULL TSRMLS_CC, 2, arg1, arg2);
*retval = object;
return 0;
}
}
/* }}} */
+#undef EX
+#define EX(element) execute_data.element
+
+/* {{{ spl_call_method */
+int spl_call_method(zval **object_pp, zend_function **fn_proxy, char *function_name, int fname_len, zval **retval, HashTable *symbol_table TSRMLS_DC, int param_count, ...)
+{
+ int i;
+ zval **original_return_value;
+ HashTable *calling_symbol_table;
+ zend_function_state *original_function_state_ptr;
+ zend_op_array *original_op_array;
+ zend_op **original_opline_ptr;
+ zval *orig_free_op1, *orig_free_op2;
+ int (*orig_unary_op)(zval *result, zval *op1);
+ int (*orig_binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC);
+ zend_class_entry *current_scope;
+ zend_class_entry *calling_scope = NULL;
+ zval *current_this;
+ zend_namespace *current_namespace = EG(active_namespace);
+ zend_execute_data execute_data;
+ zend_class_entry *obj_ce;
+ va_list args;
+
+ if (!object_pp || (obj_ce = spl_get_class_entry(*object_pp TSRMLS_CC)) == NULL) {
+ return FAILURE;
+ }
+
+ /* Initialize execute_data */
+ EX(fbc) = NULL;
+ EX(Ts) = NULL;
+ EX(op_array) = NULL;
+ EX(opline) = NULL;
+
+ EX(object) = *object_pp;
+ calling_scope = Z_OBJCE_PP(object_pp);
+
+ original_function_state_ptr = EG(function_state_ptr);
+ if (fn_proxy && *fn_proxy) {
+ EX(function_state).function = *fn_proxy;
+ } else {
+ if (zend_hash_find(&obj_ce->function_table, function_name, fname_len+1, (void **) &EX(function_state).function)==FAILURE) {
+ return FAILURE;
+ }
+ if (fn_proxy) {
+ *fn_proxy = EX(function_state).function;
+ }
+ }
+
+ va_start(args, param_count);
+ for (i=0; i<param_count; i++) {
+ zval *arg;
+ zval *param;
+
+ arg = va_arg(args, zval*);
+
+ if (EX(function_state).function->common.arg_types
+ && i<EX(function_state).function->common.arg_types[0]
+ && EX(function_state).function->common.arg_types[i+1]==BYREF_FORCE
+ && !PZVAL_IS_REF(arg)) {
+ if (arg->refcount > 1) {
+ zval *new_zval;
+
+ ALLOC_ZVAL(new_zval);
+ *new_zval = *arg;
+ zval_copy_ctor(new_zval);
+ new_zval->refcount = 1;
+ arg->refcount--;
+ arg = new_zval;
+ }
+ arg->refcount++;
+ arg->is_ref = 1;
+ param = arg;
+ } else if (arg != &EG(uninitialized_zval)) {
+ arg->refcount++;
+ param = arg;
+ } else {
+ ALLOC_ZVAL(param);
+ *param = *arg;
+ INIT_PZVAL(param);
+ }
+ zend_ptr_stack_push(&EG(argument_stack), param);
+ }
+ va_end(args);
+
+ zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) (long) param_count, NULL);
+
+ EG(function_state_ptr) = &EX(function_state);
+
+ current_scope = EG(scope);
+ EG(scope) = calling_scope;
+
+ current_this = EG(This);
+
+ EG(This) = *object_pp;
+
+ if (!PZVAL_IS_REF(EG(This))) {
+ EG(This)->refcount++; /* For $this pointer */
+ } else {
+ zval *this_ptr;
+
+ ALLOC_ZVAL(this_ptr);
+ *this_ptr = *EG(This);
+ INIT_PZVAL(this_ptr);
+ zval_copy_ctor(this_ptr);
+ EG(This) = this_ptr;
+ }
+
+ EX(prev_execute_data) = EG(current_execute_data);
+ EG(current_execute_data) = &execute_data;
+
+ if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
+ calling_symbol_table = EG(active_symbol_table);
+ if (symbol_table) {
+ EG(active_symbol_table) = symbol_table;
+ } else {
+ ALLOC_HASHTABLE(EG(active_symbol_table));
+ zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
+ }
+
+ original_return_value = EG(return_value_ptr_ptr);
+ original_op_array = EG(active_op_array);
+ EG(return_value_ptr_ptr) = retval;
+ EG(active_op_array) = (zend_op_array *) EX(function_state).function;
+ original_opline_ptr = EG(opline_ptr);
+ orig_free_op1 = EG(free_op1);
+ orig_free_op2 = EG(free_op2);
+ orig_unary_op = EG(unary_op);
+ orig_binary_op = EG(binary_op);
+ zend_execute(EG(active_op_array) TSRMLS_CC);
+ if (!symbol_table) {
+ zend_hash_destroy(EG(active_symbol_table));
+ FREE_HASHTABLE(EG(active_symbol_table));
+ }
+ EG(active_symbol_table) = calling_symbol_table;
+ EG(active_op_array) = original_op_array;
+ EG(return_value_ptr_ptr)=original_return_value;
+ EG(opline_ptr) = original_opline_ptr;
+ EG(free_op1) = orig_free_op1;
+ EG(free_op2) = orig_free_op2;
+ EG(unary_op) = orig_unary_op;
+ EG(binary_op) = orig_binary_op;
+ } else {
+ ALLOC_INIT_ZVAL(*retval);
+ ((zend_internal_function *) EX(function_state).function)->handler(param_count, *retval, (object_pp?*object_pp:NULL), 1 TSRMLS_CC);
+ INIT_PZVAL(*retval);
+ }
+ zend_ptr_stack_clear_multiple(TSRMLS_C);
+ EG(function_state_ptr) = original_function_state_ptr;
+ EG(active_namespace) = current_namespace;
+
+ if (EG(This)) {
+ zval_ptr_dtor(&EG(This));
+ }
+ EG(scope) = current_scope;
+ EG(This) = current_this;
+ EG(current_execute_data) = EX(prev_execute_data); \
+
+ return SUCCESS;
+}
+/* }}} */
+
/*
* Local variables:
* tab-width: 4
int zend_do_fcall_common_helper(ZEND_OPCODE_HANDLER_ARGS);
-int spl_begin_method_call_arg(zval **ce, char *function_name, zval *retval, zval *arg1 TSRMLS_DC);
-int spl_begin_method_call_this(zval **ce, char *function_name, zval *retval TSRMLS_DC);
-int spl_begin_method_call_arg_ex1(zval **ce, char *function_name, zval **retval, zval **arg1, int no_separation, HashTable *symbol_table TSRMLS_DC);
-int spl_begin_method_call_arg_ex2(zval **ce, char *function_name, zval **retval, zval **arg1, zval **arg2, int no_separation, HashTable *symbol_table TSRMLS_DC);
+int spl_call_method(zval **object_pp, zend_function **fn_proxy, char *function_name, int function_name_len, zval **retval_ptr, HashTable *symbol_table TSRMLS_DC, int param_count, ...);
+
+/* {{{ spl_begin_method_call_arg */
+static inline int spl_begin_method_call_arg(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval *retval, zval *arg1 TSRMLS_DC)
+{
+ zval *local_retval;
+ int ret = spl_call_method(ce, fn_proxy, function_name, fname_len, &local_retval, NULL TSRMLS_CC, 1, arg1);
+ if (local_retval) {
+ COPY_PZVAL_TO_ZVAL(*retval, local_retval);
+ } else {
+ INIT_ZVAL(*retval);
+ }
+ return ret;
+}
+/* }}} */
+
+/* {{{ spl_begin_method_call_this */
+static inline int spl_begin_method_call_this(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval *retval TSRMLS_DC)
+{
+ zval *local_retval;
+ int ret = spl_call_method(ce, fn_proxy, function_name, fname_len, &local_retval, NULL TSRMLS_CC, 0);
+ if (local_retval) {
+ COPY_PZVAL_TO_ZVAL(*retval, local_retval);
+ } else {
+ INIT_ZVAL(*retval);
+ }
+ return ret;
+}
+/* }}} */
+
+/* {{{ spl_begin_method_call_ex */
+static inline int spl_begin_method_call_ex(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval **retval TSRMLS_DC)
+{
+ return spl_call_method(ce, fn_proxy, function_name, fname_len, retval, NULL TSRMLS_CC, 0);
+}
+/* }}} */
+
+/* {{{ spl_begin_method_call_arg_ex1 */
+static inline int spl_begin_method_call_arg_ex1(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval **retval, zval *arg1 TSRMLS_DC)
+{
+ return spl_call_method(ce, fn_proxy, function_name, fname_len, retval, NULL TSRMLS_CC, 1, arg1);
+}
+/* }}} */
+
+/* {{{ spl_begin_method_call_arg_ex2 */
+static inline int spl_begin_method_call_arg_ex2(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval **retval, zval *arg1, zval *arg2 TSRMLS_DC)
+{
+ return spl_call_method(ce, fn_proxy, function_name, fname_len, retval, NULL TSRMLS_CC, 2, arg1, arg2);
+}
+/* }}} */
void spl_instanciate(zend_class_entry *pce, zval **object TSRMLS_DC);
-int spl_instanciate_arg_ex2(zend_class_entry *pce, zval **retval, zval **arg1, zval **arg2, int no_separation, HashTable *symbol_table TSRMLS_DC);
+int spl_instanciate_arg_ex2(zend_class_entry *pce, zval **retval, zval *arg1, zval *arg2, HashTable *symbol_table TSRMLS_DC);
zval ** spl_get_zval_ptr_ptr(znode *node, temp_variable *Ts TSRMLS_DC);
void spl_unlock_zval_ptr_ptr(znode *node, temp_variable *Ts TSRMLS_DC);
#include "spl_engine.h"
#include "spl_foreach.h"
+#define ezalloc(size) \
+ memset(emalloc(size), 0, size)
+
+typedef struct {
+ zend_uint index;
+ zend_function *f_next;
+ zend_function *f_rewind;
+ zend_function *f_more;
+ zend_function *f_current;
+ zend_function *f_key;
+} spl_foreach_proxy;
+
/* {{{ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET) */
ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET)
{
if (spl_implements(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);
+ spl_begin_method_call_this(obj, NULL, "new_iterator", sizeof("new_iterator")-1, 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 */
+ /* EX(opline)->result.u.EA.type = 0; */
PZVAL_LOCK(retval);
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 */
+ /* EX(opline)->result.u.EA.type = 0; */
(*obj)->refcount++;
PZVAL_LOCK(*obj);
{
zval **obj = spl_get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC);
zval more, tmp, *value, *key, *result;
+ spl_foreach_proxy *proxy;
if (spl_implements(obj, spl_ce_forward TSRMLS_CC)) {
- zend_uint index = EX(opline)->op2.u.EA.type++;
+ proxy = (spl_foreach_proxy*)EX(opline)->op1.u.EA.type;
+
+ if (!proxy) {
+ (spl_foreach_proxy*)EX(opline)->op1.u.EA.type = proxy = ezalloc(sizeof(spl_foreach_proxy));
+ }
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);
+ if (proxy->index++) {
+ spl_begin_method_call_this(obj, &proxy->f_next, "next", sizeof("next")-1, &tmp TSRMLS_CC);
} else if (spl_implements(obj, spl_ce_sequence TSRMLS_CC)) {
- spl_begin_method_call_this(obj, "rewind", &more TSRMLS_CC);
+ spl_begin_method_call_this(obj, &proxy->f_rewind, "rewind", sizeof("rewind")-1, &tmp TSRMLS_CC);
}
- spl_begin_method_call_this(obj, "has_more", &more TSRMLS_CC);
+ spl_begin_method_call_this(obj, &proxy->f_more, "has_more", sizeof("has_more")-1, &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);
+ spl_begin_method_call_this(obj, &proxy->f_current, "current", sizeof("current")-1, value TSRMLS_CC);
zend_hash_index_update(result->value.ht, 0, &value, sizeof(zval *), NULL);
if (spl_implements(obj, spl_ce_assoc TSRMLS_CC)) {
ALLOC_ZVAL(key);
- spl_begin_method_call_this(obj, "key", key TSRMLS_CC);
+ spl_begin_method_call_this(obj, &proxy->f_key, "key", sizeof("key")-1, 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.value.lval = proxy->index;
tmp.type = IS_LONG;
tmp.refcount = 0;
tmp.is_ref = 0;
zend_hash_index_update(result->value.ht, 1, &key, sizeof(zval *), NULL);
NEXT_OPCODE();
+ } else {
+ efree(proxy);
+ EX(opline)->op1.u.EA.type = 0;
}
EX(opline) = op_array->opcodes+EX(opline)->op2.u.opline_num;
return 0;
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, class_name, NULL);
- ce.num_interfaces = 0;
*ppce = zend_register_internal_ns_class(&ce, NULL, namespace_entry, NULL TSRMLS_CC);
/* entries changed by initialize */
(*ppce)->ce_flags = ZEND_ACC_ABSTRACT | ZEND_ACC_INTERFACE;
- (*ppce)->ns = namespace_entry;
}
/* }}} */
memset(&ce, 0, sizeof(zend_class_entry));
INIT_CLASS_ENTRY(ce, class_name, NULL);
-
- ce.num_interfaces = 0;
-
*ppce = zend_register_internal_ns_class(&ce, NULL, namespace_entry, NULL TSRMLS_CC);
/* entries changed by initialize */
(*ppce)->ce_flags = ZEND_ACC_ABSTRACT | ZEND_ACC_INTERFACE;
(*ppce)->create_object = obj_ctor;
- (*ppce)->ns = namespace_entry;
}
/* }}} */
$this->num++;
}
function has_more() {
- echo __CLASS__ . '::' . __FUNCTION__ . "\n";
- return $this->num < $this->obj->max;
+ $more = $this->num < $this->obj->max;
+ echo __CLASS__ . '::' . __FUNCTION__ . ' = ' .($more ? 'true' : 'false') . "\n";
+ return $more;
}
function key() {
echo __CLASS__ . '::' . __FUNCTION__ . "\n";
?>
--EXPECT--
c::new_iterator
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
0
c_iter::next
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
1
c_iter::next
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
2
c_iter::next
-c_iter::has_more
+c_iter::has_more = false
array:0
array:1
array:2
c::new_iterator
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
object:0
c_iter::next
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
object:1
c_iter::next
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
object:2
c_iter::next
-c_iter::has_more
+c_iter::has_more = false
c::new_iterator
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
c::new_iterator
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
double:0:0
c_iter::next
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
double:0:1
c_iter::next
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
double:0:2
c_iter::next
-c_iter::has_more
+c_iter::has_more = false
c_iter::next
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
c::new_iterator
+c_iter::has_more = true
+c_iter::current
+c_iter::key
+double:1:0
c_iter::next
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
double:1:1
c_iter::next
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
double:1:2
c_iter::next
-c_iter::has_more
+c_iter::has_more = false
c_iter::next
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
c::new_iterator
+c_iter::has_more = true
+c_iter::current
+c_iter::key
+double:2:0
c_iter::next
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
double:2:1
c_iter::next
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
double:2:2
c_iter::next
-c_iter::has_more
+c_iter::has_more = false
c_iter::next
-c_iter::has_more
+c_iter::has_more = false
c::new_iterator
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
object:1st=>0
c_iter::next
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
object:2nd=>1
c_iter::next
-c_iter::has_more
+c_iter::has_more = true
c_iter::current
c_iter::key
object:3rd=>2
c_iter::next
-c_iter::has_more
+c_iter::has_more = false
Done
\ No newline at end of file