diff options
-rwxr-xr-x | ext/simplexml/php_simplexml_exports.h | 5 | ||||
-rw-r--r-- | ext/simplexml/simplexml.c | 6 | ||||
-rwxr-xr-x | ext/spl/internal/cachingiterator.inc | 24 | ||||
-rwxr-xr-x | ext/spl/spl_iterators.c | 27 | ||||
-rwxr-xr-x | ext/spl/spl_sxe.c | 16 |
5 files changed, 60 insertions, 18 deletions
diff --git a/ext/simplexml/php_simplexml_exports.h b/ext/simplexml/php_simplexml_exports.h index 0b296df..db97da0 100755 --- a/ext/simplexml/php_simplexml_exports.h +++ b/ext/simplexml/php_simplexml_exports.h @@ -52,6 +52,11 @@ php_sxe_fetch_object(zval *object TSRMLS_DC) ZEND_API void php_sxe_reset_iterator(php_sxe_object *sxe TSRMLS_DC); ZEND_API void php_sxe_move_forward_iterator(php_sxe_object *sxe TSRMLS_DC); +typedef struct { + zend_object_iterator intern; + php_sxe_object *sxe; +} php_sxe_iterator; + #endif /* PHP_SIMPLEXML_EXPORTS_H */ /** diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 8fbb01f..e42ab24 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -1383,11 +1383,6 @@ SXE_METHOD(__construct) /* }}} */ -typedef struct { - zend_object_iterator intern; - php_sxe_object *sxe; -} php_sxe_iterator; - 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); @@ -1704,6 +1699,7 @@ PHP_MINIT_FUNCTION(simplexml) sxe.create_object = sxe_object_new; sxe_class_entry = zend_register_internal_class(&sxe TSRMLS_CC); sxe_class_entry->get_iterator = php_sxe_get_iterator; + sxe_class_entry->iterator_funcs.funcs = &php_sxe_iterator_funcs; zend_class_implements(sxe_class_entry TSRMLS_CC, 1, zend_ce_traversable); sxe_object_handlers.get_method = zend_get_std_object_handlers()->get_method; sxe_object_handlers.get_constructor = zend_get_std_object_handlers()->get_constructor; diff --git a/ext/spl/internal/cachingiterator.inc b/ext/spl/internal/cachingiterator.inc index f5ca2c3..6391322 100755 --- a/ext/spl/internal/cachingiterator.inc +++ b/ext/spl/internal/cachingiterator.inc @@ -27,8 +27,10 @@ */ class CachingIterator implements OuterIterator { - const CALL_TOSTRING = 1; - const CATCH_GET_CHILD = 2; + const CALL_TOSTRING = 1; + const CATCH_GET_CHILD = 2; + const TOSTRING_USE_KEY = 4; + const TOSTRING_USE_CURRENT = 8; private $it; private $current; @@ -44,8 +46,13 @@ class CachingIterator implements OuterIterator */ function __construct(Iterator $it, $flags = self::CALL_TOSTRING) { + if ((($flags & self::CALL_TOSTRING) && ($flags & (self::TOSTRING_USE_KEY|self::TOSTRING_USE_CURRENT))) + || ((flags & (self::CIT_TOSTRING_USE_KEY|self::CIT_TOSTRING_USE_CURRENT)) == (self::CIT_TOSTRING_USE_KEY|self::CIT_TOSTRING_USE_CURRENT))) + { + throw new InvalidArgumentException('Flags must contain only one of CIT_CALL_TOSTRING, CIT_TOSTRING_USE_KEY, CIT_TOSTRING_USE_CURRENT'); + } $this->it = $it; - $this->flags = $flags & (self::CALL_TOSTRING|self::CATCH_GET_CHILD); + $this->flags = $flags & (0x0000FFFF); $this->next(); } @@ -123,7 +130,16 @@ class CachingIterator implements OuterIterator */ function __toString() { - if (!$this->flags & self::CALL_TOSTRING) { + if ($this->flags & self::TOSTRING_USE_KEY) + { + return $this->key; + } + else if ($this->flags & self::TOSTRING_USE_CURRENT) + { + return $this->current; + } + if (!$this->flags & self::CALL_TOSTRING) + { throw new exception('CachingIterator does not fetch string value (see CachingIterator::__construct)'); } return $this->strValue; diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index c89b1eb..99e2641 100755 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -764,6 +764,12 @@ static INLINE spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAME php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); return NULL; } + if (((flags & CIT_CALL_TOSTRING) && (flags & (CIT_TOSTRING_USE_KEY|CIT_TOSTRING_USE_CURRENT))) + || ((flags & (CIT_TOSTRING_USE_KEY|CIT_TOSTRING_USE_CURRENT)) == (CIT_TOSTRING_USE_KEY|CIT_TOSTRING_USE_CURRENT))) { + php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); + zend_throw_exception(spl_ce_InvalidArgumentException, "Flags must contain only one of CIT_CALL_TOSTRING, CIT_TOSTRING_USE_KEY, CIT_TOSTRING_USE_CURRENT", 0 TSRMLS_CC); + return NULL; + } intern->u.caching.flags |= flags & CIT_PUBLIC; break; } @@ -1517,9 +1523,22 @@ SPL_METHOD(CachingIterator, __toString) intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - if (!(intern->u.caching.flags & CIT_CALL_TOSTRING)) { + if (!(intern->u.caching.flags & (CIT_CALL_TOSTRING|CIT_TOSTRING_USE_KEY|CIT_TOSTRING_USE_CURRENT))) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s does not fetch string value (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name); } + 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); + } else { + RETVAL_LONG(intern->current.int_key); + convert_to_string(return_value); + return; + } + } else if (intern->u.caching.flags & CIT_TOSTRING_USE_CURRENT) { + RETVAL_ZVAL(intern->current.data, 1, 0); + + return; + } if (intern->u.caching.zstr) { RETURN_STRINGL(Z_STRVAL_P(intern->u.caching.zstr), Z_STRLEN_P(intern->u.caching.zstr), 1); } else { @@ -2018,8 +2037,10 @@ PHP_MINIT_FUNCTION(spl_iterators) REGISTER_SPL_STD_CLASS_EX(CachingIterator, spl_dual_it_new, spl_funcs_CachingIterator); REGISTER_SPL_ITERATOR(CachingIterator); - REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CALL_TOSTRING", CIT_CALL_TOSTRING); - REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CATCH_GET_CHILD", CIT_CATCH_GET_CHILD); + REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CALL_TOSTRING", CIT_CALL_TOSTRING); + REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CATCH_GET_CHILD", CIT_CATCH_GET_CHILD); + REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "TOSTRING_USE_KEY", CIT_TOSTRING_USE_KEY); + REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "TOSTRING_USE_CURRENT", CIT_TOSTRING_USE_CURRENT); REGISTER_SPL_SUB_CLASS_EX(RecursiveCachingIterator, CachingIterator, spl_dual_it_new, spl_funcs_RecursiveCachingIterator); REGISTER_SPL_IMPLEMENTS(RecursiveCachingIterator, RecursiveIterator); diff --git a/ext/spl/spl_sxe.c b/ext/spl/spl_sxe.c index 5a2cd7e..5cf7c22 100755 --- a/ext/spl/spl_sxe.c +++ b/ext/spl/spl_sxe.c @@ -34,6 +34,7 @@ #include "spl_sxe.h" zend_class_entry *spl_ce_SimpleXMLIterator = NULL; +zend_class_entry *spl_ce_SimpleXMLElement; #if HAVE_LIBXML && HAVE_SIMPLEXML @@ -41,9 +42,10 @@ zend_class_entry *spl_ce_SimpleXMLIterator = NULL; SPL_METHOD(SimpleXMLIterator, rewind) /* {{{ */ { - php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + php_sxe_iterator iter; - php_sxe_reset_iterator(sxe TSRMLS_CC); + iter.sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + spl_ce_SimpleXMLElement->iterator_funcs.funcs->rewind((zend_object_iterator*)&iter TSRMLS_CC); } /* }}} */ @@ -89,9 +91,10 @@ SPL_METHOD(SimpleXMLIterator, key) /* {{{ */ SPL_METHOD(SimpleXMLIterator, next) /* {{{ */ { - php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + php_sxe_iterator iter; - php_sxe_move_forward_iterator(sxe TSRMLS_CC); + iter.sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + spl_ce_SimpleXMLElement->iterator_funcs.funcs->move_forward((zend_object_iterator*)&iter TSRMLS_CC); } /* }}} */ @@ -146,16 +149,17 @@ static zend_function_entry spl_funcs_SimpleXMLIterator[] = { SPL_API PHP_MINIT_FUNCTION(spl_sxe) /* {{{ */ { - zend_class_entry **pce, *spl_ce_SimpleXMLElement; + zend_class_entry **pce; if (zend_hash_find(CG(class_table), "simplexmlelement", sizeof("SimpleXMLElement"), (void **) &pce) == FAILURE) { + spl_ce_SimpleXMLElement = NULL; spl_ce_SimpleXMLIterator = NULL; return SUCCESS; /* SimpleXML must be initialized before */ } spl_ce_SimpleXMLElement = *pce; - REGISTER_SPL_SUB_CLASS_EX(SimpleXMLIterator, SimpleXMLElement, sxe_object_new, spl_funcs_SimpleXMLIterator); + REGISTER_SPL_SUB_CLASS_EX(SimpleXMLIterator, SimpleXMLElement, spl_ce_SimpleXMLElement->create_object, spl_funcs_SimpleXMLIterator); REGISTER_SPL_IMPLEMENTS(SimpleXMLIterator, RecursiveIterator); return SUCCESS; |