XOOPS RMCommon Utilities  2.1.8.91RC
 All Classes Namespaces Files Functions Variables
ArrayCharacterStream.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/CharacterStream.php';
12 //@require 'Swift/OutputByteStream.php';
13 
14 
22  implements Swift_CharacterStream
23 {
24 
26  private static $_charMap;
27 
29  private static $_byteMap;
30 
32  private $_charReader;
33 
36 
38  private $_charset;
39 
41  private $_array = array();
42 
44  private $_array_size = array();
45 
47  private $_offset = 0;
48 
54  public function __construct(Swift_CharacterReaderFactory $factory,
55  $charset)
56  {
57  self::_initializeMaps();
58  $this->setCharacterReaderFactory($factory);
59  $this->setCharacterSet($charset);
60  }
61 
66  public function setCharacterSet($charset)
67  {
68  $this->_charset = $charset;
69  $this->_charReader = null;
70  }
71 
76  public function setCharacterReaderFactory(
78  {
79  $this->_charReaderFactory = $factory;
80  }
81 
87  {
88  if (!isset($this->_charReader))
89  {
90  $this->_charReader = $this->_charReaderFactory
91  ->getReaderFor($this->_charset);
92  }
93 
94  $startLength = $this->_charReader->getInitialByteSize();
95  while (false !== $bytes = $os->read($startLength))
96  {
97  $c = array();
98  for ($i = 0, $len = strlen($bytes); $i < $len; ++$i)
99  {
100  $c[] = self::$_byteMap[$bytes[$i]];
101  }
102  $size = count($c);
103  $need = $this->_charReader
104  ->validateByteSequence($c, $size);
105  if ($need > 0 &&
106  false !== $bytes = $os->read($need))
107  {
108  for ($i = 0, $len = strlen($bytes); $i < $len; ++$i)
109  {
110  $c[] = self::$_byteMap[$bytes[$i]];
111  }
112  }
113  $this->_array[] = $c;
115  }
116  }
117 
123  public function importString($string)
124  {
125  $this->flushContents();
126  $this->write($string);
127  }
128 
135  public function read($length)
136  {
137  if ($this->_offset == $this->_array_size)
138  {
139  return false;
140  }
141 
142  // Don't use array slice
143  $arrays = array();
144  $end = $length + $this->_offset;
145  for ($i = $this->_offset; $i < $end; ++$i)
146  {
147  if (!isset($this->_array[$i]))
148  {
149  break;
150  }
151  $arrays[] = $this->_array[$i];
152  }
153  $this->_offset += $i - $this->_offset; // Limit function calls
154  $chars = false;
155  foreach ($arrays as $array)
156  {
157  $chars .= implode('', array_map('chr', $array));
158  }
159  return $chars;
160  }
161 
168  public function readBytes($length)
169  {
170  if ($this->_offset == $this->_array_size)
171  {
172  return false;
173  }
174  $arrays = array();
175  $end = $length + $this->_offset;
176  for ($i = $this->_offset; $i < $end; ++$i)
177  {
178  if (!isset($this->_array[$i]))
179  {
180  break;
181  }
182  $arrays[] = $this->_array[$i];
183  }
184  $this->_offset += ($i - $this->_offset); // Limit function calls
185  return call_user_func_array('array_merge', $arrays);
186  }
187 
192  public function write($chars)
193  {
194  if (!isset($this->_charReader))
195  {
196  $this->_charReader = $this->_charReaderFactory->getReaderFor(
197  $this->_charset);
198  }
199 
200  $startLength = $this->_charReader->getInitialByteSize();
201 
202  $fp = fopen('php://memory', 'w+b');
203  fwrite($fp, $chars);
204  unset($chars);
205  fseek($fp, 0, SEEK_SET);
206 
207  $buffer = array(0);
208  $buf_pos = 1;
209  $buf_len = 1;
210  $has_datas = true;
211  do
212  {
213  $bytes = array();
214  // Buffer Filing
215  if ($buf_len - $buf_pos < $startLength)
216  {
217  $buf = array_splice($buffer, $buf_pos);
218  $new = $this->_reloadBuffer($fp, 100);
219  if ($new)
220  {
221  $buffer = array_merge($buf, $new);
222  $buf_len = count($buffer);
223  $buf_pos = 0;
224  }
225  else
226  {
227  $has_datas = false;
228  }
229  }
230  if ($buf_len - $buf_pos > 0)
231  {
232  $size = 0;
233  for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i)
234  {
235  ++$size;
236  $bytes[] = $buffer[$buf_pos++];
237  }
238  $need = $this->_charReader->validateByteSequence(
239  $bytes, $size);
240  if ($need > 0)
241  {
242  if ($buf_len - $buf_pos < $need)
243  {
244  $new = $this->_reloadBuffer($fp, $need);
245 
246  if ($new)
247  {
248  $buffer = array_merge($buffer, $new);
249  $buf_len = count($buffer);
250  }
251  }
252  for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i)
253  {
254  $bytes[] = $buffer[$buf_pos++];
255  }
256  }
257  $this->_array[] = $bytes;
259  }
260  }
261  while ($has_datas);
262 
263  fclose($fp);
264  }
265 
270  public function setPointer($charOffset)
271  {
272  if ($charOffset > $this->_array_size)
273  {
274  $charOffset = $this->_array_size;
275  }
276  elseif ($charOffset < 0)
277  {
278  $charOffset = 0;
279  }
280  $this->_offset = $charOffset;
281  }
282 
286  public function flushContents()
287  {
288  $this->_offset = 0;
289  $this->_array = array();
290  $this->_array_size = 0;
291  }
292 
293  private function _reloadBuffer($fp, $len)
294  {
295  if (!feof($fp) && ($bytes = fread($fp, $len)) !== false)
296  {
297  $buf = array();
298  for ($i = 0, $len = strlen($bytes); $i < $len; ++$i)
299  {
300  $buf[] = self::$_byteMap[$bytes[$i]];
301  }
302  return $buf;
303  }
304  return false;
305  }
306 
307  private static function _initializeMaps()
308  {
309  if (!isset(self::$_charMap))
310  {
311  self::$_charMap = array();
312  for ($byte = 0; $byte < 256; ++$byte)
313  {
314  self::$_charMap[$byte] = chr($byte);
315  }
316  self::$_byteMap = array_flip(self::$_charMap);
317  }
318  }
319 }