helly Wed Jul 27 18:19:02 2005 EDT
Modified files:
/php-src/ext/spl spl_iterators.c
/php-src/ext/spl/internal recursiveiteratoriterator.inc
Log:
- Fix issues with iterators and excpetions
# update documentation
#
# In 5.2 we need to implement an event handler onException() to be invoked
# on exceptions during getChildren() calls. Its default implementation
# would simply rethrow the exception if the flag is not set and delete if
# if it was set. To do so the exceptions refcount needs to be increased
# before calling zend_clear_exception() to keep the exception alive but
# clear the control information.
#
# As a side note this is alos the easy solution to allow multi exception
# handling: Simply clear the engine's exception info and add a property
# called $previousException to the base exception and assign it from the
# already pending one.
http://cvs.php.net/diff.php/php-src/ext/spl/spl_iterators.c?r1=1.70&r2=1.71&ty=u
Index: php-src/ext/spl/spl_iterators.c
diff -u php-src/ext/spl/spl_iterators.c:1.70
php-src/ext/spl/spl_iterators.c:1.71
--- php-src/ext/spl/spl_iterators.c:1.70 Thu Jun 16 10:56:13 2005
+++ php-src/ext/spl/spl_iterators.c Wed Jul 27 18:19:00 2005
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: spl_iterators.c,v 1.70 2005/06/16 14:56:13 dmitry Exp $ */
+/* $Id: spl_iterators.c,v 1.71 2005/07/27 22:19:00 helly Exp $ */
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -65,6 +65,9 @@
RIT_CHILD_FIRST = 2
} RecursiveIteratorMode;
+#define RIT_MODE_MASK 0x000000FF
+#define RIT_CATCH_GET_CHILD 0x00000100
+
typedef enum {
RS_NEXT = 0,
RS_TEST = 1,
@@ -85,6 +88,7 @@
spl_sub_iterator *iterators;
int level;
RecursiveIteratorMode mode;
+ int flags;
zend_function *callHasChildren;
zend_function *callGetChildren;
zend_function *beginChildren;
@@ -222,6 +226,20 @@
} else {
zend_call_method_with_0_params(&zobject, ce, NULL, "getchildren", &child);
}
+
+ if (EG(exception)) {
+ if (!(object->flags &
RIT_CATCH_GET_CHILD)) {
+ return;
+ } else {
+
zend_clear_exception(TSRMLS_C);
+ if (child) {
+ zval_ptr_dtor(&child);
+ }
+
object->iterators[object->level].state = RS_NEXT;
+ goto next_step;
+ }
+ }
+
ce = child && Z_TYPE_P(child) ==
IS_OBJECT ? Z_OBJCE_P(child) : NULL;
if (!ce || !instanceof_function(ce,
spl_ce_RecursiveIterator TSRMLS_CC)) {
if (child) {
@@ -344,7 +362,8 @@
intern =
(spl_recursive_it_object*)zend_object_store_get_object(object TSRMLS_CC);
intern->iterators = emalloc(sizeof(spl_sub_iterator));
intern->level = 0;
- intern->mode = mode;
+ intern->mode = mode & RIT_MODE_MASK;
+ intern->flags = mode & ~RIT_MODE_MASK;
intern->ce = Z_OBJCE_P(object);
zend_hash_find(&intern->ce->function_table, "callhaschildren",
sizeof("callHasChildren"), (void **) &intern->callHasChildren);
if (intern->callHasChildren->common.scope ==
spl_ce_RecursiveIteratorIterator) {
@@ -1308,8 +1327,7 @@
if (zend_is_true(retval)) {
zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce,
NULL, "getchildren", &zchildren);
if (EG(exception) &&
intern->u.caching.flags & CIT_CATCH_GET_CHILD) {
- zval_ptr_dtor(&EG(exception));
- EG(exception) = NULL;
+ zend_clear_exception(TSRMLS_C);
if (zchildren) {
zval_ptr_dtor(&zchildren);
}
@@ -1914,9 +1932,10 @@
spl_ce_RecursiveIteratorIterator->get_iterator =
spl_recursive_it_get_iterator;
spl_ce_RecursiveIteratorIterator->iterator_funcs.funcs =
&spl_recursive_it_iterator_funcs;
- REGISTER_LONG_CONSTANT("RIT_LEAVES_ONLY", (long)RIT_LEAVES_ONLY,
CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("RIT_SELF_FIRST", (long)RIT_SELF_FIRST,
CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("RIT_CHILD_FIRST", (long)RIT_CHILD_FIRST,
CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("RIT_LEAVES_ONLY",
(long)RIT_LEAVES_ONLY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("RIT_SELF_FIRST",
(long)RIT_SELF_FIRST, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("RIT_CHILD_FIRST",
(long)RIT_CHILD_FIRST, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("RIT_CATCH_GET_CHILD",
(long)RIT_CATCH_GET_CHILD, CONST_CS | CONST_PERSISTENT);
REGISTER_SPL_STD_CLASS_EX(FilterIterator, spl_dual_it_new,
spl_funcs_FilterIterator);
REGISTER_SPL_ITERATOR(FilterIterator);
http://cvs.php.net/diff.php/php-src/ext/spl/internal/recursiveiteratoriterator.inc?r1=1.11&r2=1.12&ty=u
Index: php-src/ext/spl/internal/recursiveiteratoriterator.inc
diff -u php-src/ext/spl/internal/recursiveiteratoriterator.inc:1.11
php-src/ext/spl/internal/recursiveiteratoriterator.inc:1.12
--- php-src/ext/spl/internal/recursiveiteratoriterator.inc:1.11 Sat May 14
12:40:58 2005
+++ php-src/ext/spl/internal/recursiveiteratoriterator.inc Wed Jul 27
18:19:01 2005
@@ -12,6 +12,7 @@
define('RIT_LEAVES_ONLY', 0);
define('RIT_SELF_FIRST', 1);
define('RIT_CHILD_FIRST', 2);
+define('RIT_CATCH_GET_CHILD', 256);
/**
* @brief Iterates through recursive iterators
@@ -27,18 +28,26 @@
{
private $ait = array();
private $count = 0;
+ private $mode = RIT_LEAVES_ONLY;
+ private $flags = 0;
/** Construct from RecursiveIterator
*
* @param it RecursiveIterator to iterate
- * @param flags Operation mode:
+ * @param flags Operation mode (one of):
* - RIT_LEAVES_ONLY only show leaves
* - RIT_SELF_FIRST show parents prior to their childs
* - RIT_CHILD_FIRST show all childs prior to their
parent
+ * or'ed with the following flags:
+ * - RIT_CATCH_GET_CHILD which catches exceptions during
+ * getChildren() calls and simply jumps to the next
+ * element.
*/
function __construct(RecursiveIterator $it, $flags)
{
$this->ait[0] = $it;
+ $this->mode = $flags & 0xFF;
+ $this->flags = $flags & ~0xFF;
}
/** Rewind to top iterator as set in constructor
@@ -94,7 +103,19 @@
if ($it->valid()) {
if (!$it->recursed && callHasChildren()) {
$it->recursed = true;
- $sub = callGetChildren();
+ try
+ {
+ $sub = callGetChildren();
+ }
+ catch (Exception $e)
+ {
+ if (!($this->flags &
RIT_CATCH_GET_CHILD))
+ {
+ throw $e;
+ }
+ $it->next();
+ continue;
+ }
$sub->recursed = false;
$sub->rewind();
if ($sub->valid()) {
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php