cachingiterator.inc 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. <?php
  2. /** @file cachingiterator.inc
  3. * @ingroup SPL
  4. * @brief class CachingIterator
  5. * @author Marcus Boerger
  6. * @date 2003 - 2009
  7. *
  8. * SPL - Standard PHP Library
  9. */
  10. /**
  11. * @brief Cached iteration over another Iterator
  12. * @author Marcus Boerger
  13. * @version 1.2
  14. * @since PHP 5.0
  15. *
  16. * This iterator wrapper does a one ahead iteration. This way it knows whether
  17. * the inner iterator has one more element.
  18. *
  19. * @note If you want to convert the elements into strings and the inner
  20. * Iterator is an internal Iterator then you need to provide the
  21. * flag CALL_TOSTRING to do the conversion when the actual element
  22. * is being fetched. Otherwise the conversion would happen with the
  23. * already changed iterator. If you do not need this then it you should
  24. * omit this flag because it costs unnecessary work and time.
  25. */
  26. class CachingIterator implements OuterIterator
  27. {
  28. const CALL_TOSTRING = 0x00000001;
  29. const CATCH_GET_CHILD = 0x00000002;
  30. const TOSTRING_USE_KEY = 0x00000010;
  31. const TOSTRING_USE_CURRENT = 0x00000020;
  32. private $it;
  33. private $current;
  34. private $key;
  35. private $valid;
  36. private $strValue;
  37. /** Construct from another iterator
  38. *
  39. * @param it Iterator to cache
  40. * @param flags Bitmask:
  41. * - CALL_TOSTRING (whether to call __toString() for every element)
  42. */
  43. function __construct(Iterator $it, $flags = self::CALL_TOSTRING)
  44. {
  45. if ((($flags & self::CALL_TOSTRING) && ($flags & (self::TOSTRING_USE_KEY|self::TOSTRING_USE_CURRENT)))
  46. || ((flags & (self::CIT_TOSTRING_USE_KEY|self::CIT_TOSTRING_USE_CURRENT)) == (self::CIT_TOSTRING_USE_KEY|self::CIT_TOSTRING_USE_CURRENT)))
  47. {
  48. throw new InvalidArgumentException('Flags must contain only one of CIT_CALL_TOSTRING, CIT_TOSTRING_USE_KEY, CIT_TOSTRING_USE_CURRENT');
  49. }
  50. $this->it = $it;
  51. $this->flags = $flags & (0x0000FFFF);
  52. $this->next();
  53. }
  54. /** Rewind the Iterator
  55. */
  56. function rewind()
  57. {
  58. $this->it->rewind();
  59. $this->next();
  60. }
  61. /** Forward to the next element
  62. */
  63. function next()
  64. {
  65. if ($this->valid = $this->it->valid()) {
  66. $this->current = $this->it->current();
  67. $this->key = $this->it->key();
  68. if ($this->flags & self::CALL_TOSTRING) {
  69. if (is_object($this->current)) {
  70. $this->strValue = $this->current->__toString();
  71. } else {
  72. $this->strValue = (string)$this->current;
  73. }
  74. }
  75. } else {
  76. $this->current = NULL;
  77. $this->key = NULL;
  78. $this->strValue = NULL;
  79. }
  80. $this->it->next();
  81. }
  82. /** @return whether the iterator is valid
  83. */
  84. function valid()
  85. {
  86. return $this->valid;
  87. }
  88. /** @return whether there is one more element
  89. */
  90. function hasNext()
  91. {
  92. return $this->it->valid();
  93. }
  94. /** @return the current element
  95. */
  96. function current()
  97. {
  98. return $this->current;
  99. }
  100. /** @return the current key
  101. */
  102. function key()
  103. {
  104. return $this->key;
  105. }
  106. /** Aggregate the inner iterator
  107. *
  108. * @param func Name of method to invoke
  109. * @param params Array of parameters to pass to method
  110. */
  111. function __call($func, $params)
  112. {
  113. return call_user_func_array(array($this->it, $func), $params);
  114. }
  115. /** @return the string represenatation that was generated for the current
  116. * element
  117. * @throw exception when CALL_TOSTRING was not specified in constructor
  118. */
  119. function __toString()
  120. {
  121. if ($this->flags & self::TOSTRING_USE_KEY)
  122. {
  123. return $this->key;
  124. }
  125. else if ($this->flags & self::TOSTRING_USE_CURRENT)
  126. {
  127. return $this->current;
  128. }
  129. if (!$this->flags & self::CALL_TOSTRING)
  130. {
  131. throw new exception('CachingIterator does not fetch string value (see CachingIterator::__construct)');
  132. }
  133. return $this->strValue;
  134. }
  135. /**
  136. * @return The inner iterator
  137. */
  138. function getInnerIterator()
  139. {
  140. return $this->it;
  141. }
  142. }
  143. ?>