$value) { $this->_array[] = &$array[$key]; $this->_size++; } $this->reset(); } function ¤t() { if (!isset($this->_array[$this->_index])) { trigger_error("Array out of bounds", E_USER_ERROR); } return $this->_array[$this->key()]; } function hasNext() { return ($this->_size > $this->_index + 1); } function key() { return $this->_index; } function next() { if ($ret = $this->hasNext()) { $this->_index++; } return $ret; } function push(&$array) { $this->_array[] = &$array; $this->_size++; } function reset() { $this->_index = -1; return TRUE; } } class FAAssocArrayIterator extends FAIterator { var $_array; var $_index; function FAAssocArrayIterator(&$array) { assert(is_array($array)); $this->_array = &$array; $this->reset(); } function _valid() { return ($this->_index >= 0 && $this->_index < sizeof($this->_array)); } function ¤t() { if (!$this->_valid()) { trigger_error("Iterator out of bounds", E_USER_ERROR); } return $this->_array[$this->key()]; } function hasNext() { return (sizeof($this->_array) > $this->_index + 1); } function key() { if (!$this->_valid()) { trigger_error("Iterator out of bounds", E_USER_ERROR); } return key($this->_array); } function next() { if ($ret = $this->hasNext()) { if ($this->_index >= 0) { next($this->_array); } $this->_index++; } return $ret; } function reset() { $this->_index = -1; return reset($this->_array); } } class FAKeyedArrayIterator extends FAArrayIterator { var $_key; function FAKeyedArrayIterator(&$array, $key) { parent::FAArrayIterator($array); $this->_key = $key; } function ¤t() { $current = array(); $current[$this->_key] = &parent::current(); return $current; } } class FAProxyIterator extends FAIterator { var $_it; function FAProxyIterator(&$it) { assert(is_a($it, 'FAIterator')); $this->_it = &$it; } function ¤t() { return $this->_it->current(); } function hasNext() { return $this->_it->hasNext(); } function key() { return $this->_it->key(); } function next() { return $this->_it->next(); } function reset() { return $this->_it->reset(); } } class FAChainedIterator extends FAIterator { var $_index; var $_it; var $_chain; function FAChainedIterator(&$it) { assert(is_a($it, 'FAIterator')); $this->_chain = array(&$it); } function addIterator(&$it) { assert(is_a($it, 'FAIterator')); $this->_chain[] = &$it; } function ¤t() { if (!isset($this->_chain[$this->_it])) { trigger_error("Array out of bounds", E_USER_ERROR); } return $this->_chain[$this->_it]->current(); } function hasNext() { $i = $this->_it; $ret = FALSE; while (isset($this->_chain[$i])) { if ($this->_chain[$i]->hasNext()) { $ret = TRUE; break; } $i++; } return $ret; } function key() { if (!isset($this->_chain[$this->_it]) || $this->_index < 0) { trigger_error("Array out of bounds", E_USER_ERROR); } return $this->_index; } function next() { $ret = FALSE; while (isset($this->_chain[$this->_it])) { if ($this->_chain[$this->_it]->hasNext()) { $ret = $this->_chain[$this->_it]->next(); $this->_index++; } $this->_it++; } return $ret; } function reset() { $this->_index = -1; $this->_it = 0; return TRUE; } } class FABufferedIterator extends FAIterator { var $_current; var $_has_next; var $_key; var $_next; var $_it; function FABufferedIterator(&$it) { assert(is_a($it, 'FAIterator')); $this->_it = &$it; if ($this->_it->next()) { $this->_has_next = TRUE; $this->_next = &$this->_it->current(); $this->_key = $this->_it->key(); } } function ¤t() { return $this->_current; } function &getNext() { $ret = NULL; if ($this->hasNext()) { $ret = &$this->_next; } return $ret; } function hasNext() { return $this->_has_next; } function key() { return $this->_key; } function next() { $ret = FALSE; if ($this->hasNext()) { $this->_current = &$this->_next; $this->_has_next = FALSE; if ($ret = $this->_it->next()) { $this->_has_next = TRUE; $this->_next = &$this->_it->current(); $this->_key = $this->_it->key(); } $ret = TRUE; } return $ret; } function reset() { if ($ret = $this->_it->reset()) { $this->_has_next = TRUE; $this->_next = &$this->_it->current(); $this->_key = $this->_it->key(); } return $ret; } } // // Utility Functions // function it_map($callback, &$it) { assert(is_a($it, 'FAIterator')); if ($it->reset()) { while ($it->next()) { $value = &$it->current(); $value = call_user_func($callback, $value); } } } function print_it(&$it, $level = 0) { assert(is_a($it, 'FAIterator')); if ($it->reset()) { $padding = str_repeat(" ", $level * 4); echo get_class($it) . "\n$padding(\n"; while ($it->next()) { $key = $it->key(); $value = &$it->current(); $offset = str_repeat(" ", ($level + 1) * 4); echo "{$offset}[$key] => "; if (is_scalar($value)) { echo $value; } elseif (is_array($value) || is_object($value)) { ob_start(); print_r($value); $buffer = preg_replace('~^(.*)$~m', $offset.' $1', ob_get_contents()); ob_end_clean(); echo ltrim($buffer); } elseif (is_a($value, 'FAIterator')) { print_it($value, $level + 2); } elseif (is_object($value)) { print_r($value); } if ($it->hasNext()) { echo "\n"; } } echo "\n$padding)\n"; } } ?>