XOOPS RMCommon Utilities  2.1.8.91RC
 All Classes Namespaces Files Functions Variables
ByteArrayReplacementFilter.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of SwiftMailer.
5  * (c) 2004-2009 Chris Corbyn
6  *
7  * For the full copyright and license information, please view the LICENSE
8  * file that was distributed with this source code.
9  */
10 
11 //@require 'Swift/StreamFilter.php';
12 
20  implements Swift_StreamFilter
21 {
22 
24  private $_search;
25 
27  private $_replace;
28 
30  private $_index;
31 
33  private $_tree = array();
34 
36  private $_treeMaxLen = 0;
37 
38  private $_repSize;
39 
45  public function __construct($search, $replace)
46  {
47  $this->_search = $search;
48  $this->_index = array();
49  $this->_tree = array();
50  $this->_replace = array();
51  $this->_repSize = array();
52 
53  $tree = null;
54  $i = null;
55  $last_size = $size = 0;
56  foreach ($search as $i => $search_element)
57  {
58  if ($tree !== null)
59  {
60  $tree[-1] = min (count($replace) - 1, $i - 1);
61  $tree[-2] = $last_size;
62  }
63  $tree = &$this->_tree;
64  if (is_array ($search_element))
65  {
66  foreach ($search_element as $k => $char)
67  {
68  $this->_index[$char] = true;
69  if (!isset($tree[$char]))
70  {
71  $tree[$char] = array();
72  }
73  $tree = &$tree[$char];
74  }
75  $last_size = $k+1;
76  $size = max($size, $last_size);
77  }
78  else
79  {
80  $last_size = 1;
81  if (!isset($tree[$search_element]))
82  {
83  $tree[$search_element] = array();
84  }
85  $tree = &$tree[$search_element];
86  $size = max($last_size, $size);
87  $this->_index[$search_element] = true;
88  }
89  }
90  if ($i !== null)
91  {
92  $tree[-1] = min (count ($replace) - 1, $i);
93  $tree[-2] = $last_size;
94  $this->_treeMaxLen = $size;
95  }
96  foreach ($replace as $rep)
97  {
98  if (!is_array($rep))
99  {
100  $rep = array ($rep);
101  }
102  $this->_replace[] = $rep;
103  }
104  for ($i = count($this->_replace) - 1; $i >= 0; --$i)
105  {
106  $this->_replace[$i] = $rep = $this->filter($this->_replace[$i], $i);
107  $this->_repSize[$i] = count($rep);
108  }
109  }
110 
116  public function shouldBuffer($buffer)
117  {
118  $endOfBuffer = end($buffer);
119  return isset ($this->_index[$endOfBuffer]);
120  }
121 
127  public function filter($buffer, $_minReplaces = -1)
128  {
129  if ($this->_treeMaxLen == 0)
130  {
131  return $buffer;
132  }
133 
134  $newBuffer = array();
135  $buf_size = count($buffer);
136  for ($i = 0; $i < $buf_size; ++$i)
137  {
138  $search_pos = $this->_tree;
139  $last_found = PHP_INT_MAX;
140  // We try to find if the next byte is part of a search pattern
141  for ($j = 0; $j <= $this->_treeMaxLen; ++$j)
142  {
143  // We have a new byte for a search pattern
144  if (isset ($buffer [$p = $i + $j]) && isset($search_pos[$buffer[$p]]))
145  {
146  $search_pos = $search_pos[$buffer[$p]];
147  // We have a complete pattern, save, in case we don't find a better match later
148  if (isset($search_pos[- 1]) && $search_pos[-1] < $last_found
149  && $search_pos[-1] > $_minReplaces)
150  {
151  $last_found = $search_pos[-1];
152  $last_size = $search_pos[-2];
153  }
154  }
155  // We got a complete pattern
156  elseif ($last_found !== PHP_INT_MAX)
157  {
158  // Adding replacement datas to output buffer
159  $rep_size = $this->_repSize[$last_found];
160  for ($j = 0; $j < $rep_size; ++$j)
161  {
162  $newBuffer[] = $this->_replace[$last_found][$j];
163  }
164  // We Move cursor forward
165  $i += $last_size - 1;
166  // Edge Case, last position in buffer
167  if ($i >= $buf_size)
168  {
169  $newBuffer[] = $buffer[$i];
170  }
171 
172  // We start the next loop
173  continue 2;
174  }
175  else
176  {
177  // this byte is not in a pattern and we haven't found another pattern
178  break;
179  }
180  }
181  // Normal byte, move it to output buffer
182  $newBuffer[] = $buffer[$i];
183  }
184 
185  return $newBuffer;
186  }
187 
188 }