/framework/vendor/swift/lib/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php

http://zoop.googlecode.com/ · PHP · 188 lines · 127 code · 17 blank · 44 comment · 18 complexity · 02ff52ee82e189189a8371460584c513 MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of SwiftMailer.
  4. * (c) 2004-2009 Chris Corbyn
  5. *
  6. * For the full copyright and license information, please view the LICENSE
  7. * file that was distributed with this source code.
  8. */
  9. //@require 'Swift/StreamFilter.php';
  10. /**
  11. * Processes bytes as they pass through a buffer and replaces sequences in it.
  12. * This stream filter deals with Byte arrays rather than simple strings.
  13. * @package Swift
  14. * @author Chris Corbyn
  15. */
  16. class Swift_StreamFilters_ByteArrayReplacementFilter
  17. implements Swift_StreamFilter
  18. {
  19. /** The needle(s) to search for */
  20. private $_search;
  21. /** The replacement(s) to make */
  22. private $_replace;
  23. /** The Index for searching */
  24. private $_index;
  25. /** The Search Tree */
  26. private $_tree = array();
  27. /** Gives the size of the largest search */
  28. private $_treeMaxLen = 0;
  29. private $_repSize;
  30. /**
  31. * Create a new ByteArrayReplacementFilter with $search and $replace.
  32. * @param array $search
  33. * @param array $replace
  34. */
  35. public function __construct($search, $replace)
  36. {
  37. $this->_search = $search;
  38. $this->_index = array();
  39. $this->_tree = array();
  40. $this->_replace = array();
  41. $this->_repSize = array();
  42. $tree = null;
  43. $i = null;
  44. $last_size = $size = 0;
  45. foreach ($search as $i => $search_element)
  46. {
  47. if ($tree !== null)
  48. {
  49. $tree[-1] = min (count($replace) - 1, $i - 1);
  50. $tree[-2] = $last_size;
  51. }
  52. $tree = &$this->_tree;
  53. if (is_array ($search_element))
  54. {
  55. foreach ($search_element as $k => $char)
  56. {
  57. $this->_index[$char] = true;
  58. if (!isset($tree[$char]))
  59. {
  60. $tree[$char] = array();
  61. }
  62. $tree = &$tree[$char];
  63. }
  64. $last_size = $k+1;
  65. $size = max($size, $last_size);
  66. }
  67. else
  68. {
  69. $last_size = 1;
  70. if (!isset($tree[$search_element]))
  71. {
  72. $tree[$search_element] = array();
  73. }
  74. $tree = &$tree[$search_element];
  75. $size = max($last_size, $size);
  76. $this->_index[$search_element] = true;
  77. }
  78. }
  79. if ($i !== null)
  80. {
  81. $tree[-1] = min (count ($replace) - 1, $i);
  82. $tree[-2] = $last_size;
  83. $this->_treeMaxLen = $size;
  84. }
  85. foreach ($replace as $rep)
  86. {
  87. if (!is_array($rep))
  88. {
  89. $rep = array ($rep);
  90. }
  91. $this->_replace[] = $rep;
  92. }
  93. for ($i = count($this->_replace) - 1; $i >= 0; --$i)
  94. {
  95. $this->_replace[$i] = $rep = $this->filter($this->_replace[$i], $i);
  96. $this->_repSize[$i] = count($rep);
  97. }
  98. }
  99. /**
  100. * Returns true if based on the buffer passed more bytes should be buffered.
  101. * @param array $buffer
  102. * @return boolean
  103. */
  104. public function shouldBuffer($buffer)
  105. {
  106. $endOfBuffer = end($buffer);
  107. return isset ($this->_index[$endOfBuffer]);
  108. }
  109. /**
  110. * Perform the actual replacements on $buffer and return the result.
  111. * @param array $buffer
  112. * @return array
  113. */
  114. public function filter($buffer, $_minReplaces = -1)
  115. {
  116. if ($this->_treeMaxLen == 0)
  117. {
  118. return $buffer;
  119. }
  120. $newBuffer = array();
  121. $buf_size = count($buffer);
  122. for ($i = 0; $i < $buf_size; ++$i)
  123. {
  124. $search_pos = $this->_tree;
  125. $last_found = PHP_INT_MAX;
  126. // We try to find if the next byte is part of a search pattern
  127. for ($j = 0; $j <= $this->_treeMaxLen; ++$j)
  128. {
  129. // We have a new byte for a search pattern
  130. if (isset ($buffer [$p = $i + $j]) && isset($search_pos[$buffer[$p]]))
  131. {
  132. $search_pos = $search_pos[$buffer[$p]];
  133. // We have a complete pattern, save, in case we don't find a better match later
  134. if (isset($search_pos[- 1]) && $search_pos[-1] < $last_found
  135. && $search_pos[-1] > $_minReplaces)
  136. {
  137. $last_found = $search_pos[-1];
  138. $last_size = $search_pos[-2];
  139. }
  140. }
  141. // We got a complete pattern
  142. elseif ($last_found !== PHP_INT_MAX)
  143. {
  144. // Adding replacement datas to output buffer
  145. $rep_size = $this->_repSize[$last_found];
  146. for ($j = 0; $j < $rep_size; ++$j)
  147. {
  148. $newBuffer[] = $this->_replace[$last_found][$j];
  149. }
  150. // We Move cursor forward
  151. $i += $last_size - 1;
  152. // Edge Case, last position in buffer
  153. if ($i >= $buf_size)
  154. {
  155. $newBuffer[] = $buffer[$i];
  156. }
  157. // We start the next loop
  158. continue 2;
  159. }
  160. else
  161. {
  162. // this byte is not in a pattern and we haven't found another pattern
  163. break;
  164. }
  165. }
  166. // Normal byte, move it to output buffer
  167. $newBuffer[] = $buffer[$i];
  168. }
  169. return $newBuffer;
  170. }
  171. }