Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php/** This file is part of SwiftMailer.* (c) 2004-2009 Chris Corbyn** For the full copyright and license information, please view the LICENSE* file that was distributed with this source code.*///@require 'Swift/CharacterStream.php';//@require 'Swift/OutputByteStream.php';/*** A CharacterStream implementation which stores characters in an internal array.* @package Swift* @subpackage CharacterStream* @author Chris Corbyn*/class Swift_CharacterStream_ArrayCharacterStreamimplements Swift_CharacterStream{/** A map of byte values and their respective characters */private static $_charMap;/** A map of characters and their derivative byte values */private static $_byteMap;/** The char reader (lazy-loaded) for the current charset */private $_charReader;/** A factory for creatiing CharacterReader instances */private $_charReaderFactory;/** The character set this stream is using */private $_charset;/** Array of characters */private $_array = array();/** Size of the array of character */private $_array_size = array();/** The current character offset in the stream */private $_offset = 0;/*** Create a new CharacterStream with the given $chars, if set.* @param Swift_CharacterReaderFactory $factory for loading validators* @param string $charset used in the stream*/public function __construct(Swift_CharacterReaderFactory $factory,$charset){self::_initializeMaps();$this->setCharacterReaderFactory($factory);$this->setCharacterSet($charset);}/*** Set the character set used in this CharacterStream.* @param string $charset*/public function setCharacterSet($charset){$this->_charset = $charset;$this->_charReader = null;}/*** Set the CharacterReaderFactory for multi charset support.* @param Swift_CharacterReaderFactory $factory*/public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory){$this->_charReaderFactory = $factory;}/*** Overwrite this character stream using the byte sequence in the byte stream.* @param Swift_OutputByteStream $os output stream to read from*/public function importByteStream(Swift_OutputByteStream $os){if (!isset($this->_charReader)){$this->_charReader = $this->_charReaderFactory->getReaderFor($this->_charset);}$startLength = $this->_charReader->getInitialByteSize();while (false !== $bytes = $os->read($startLength)){$c = array();for ($i = 0, $len = strlen($bytes); $i < $len; ++$i){$c[] = self::$_byteMap[$bytes[$i]];}$size = count($c);$need = $this->_charReader->validateByteSequence($c, $size);if ($need > 0 &&false !== $bytes = $os->read($need)){for ($i = 0, $len = strlen($bytes); $i < $len; ++$i){$c[] = self::$_byteMap[$bytes[$i]];}}$this->_array[] = $c;++$this->_array_size;}}/*** Import a string a bytes into this CharacterStream, overwriting any existing* data in the stream.* @param string $string*/public function importString($string){$this->flushContents();$this->write($string);}/*** Read $length characters from the stream and move the internal pointer* $length further into the stream.* @param int $length* @return string*/public function read($length){if ($this->_offset == $this->_array_size){return false;}// Don't use array slice$arrays = array();$end = $length + $this->_offset;for ($i = $this->_offset; $i < $end; ++$i){if (!isset($this->_array[$i])){break;}$arrays[] = $this->_array[$i];}$this->_offset += $i - $this->_offset; // Limit function calls$chars = false;foreach ($arrays as $array){$chars .= implode('', array_map('chr', $array));}return $chars;}/*** Read $length characters from the stream and return a 1-dimensional array* containing there octet values.* @param int $length* @return int[]*/public function readBytes($length){if ($this->_offset == $this->_array_size){return false;}$arrays = array();$end = $length + $this->_offset;for ($i = $this->_offset; $i < $end; ++$i){if (!isset($this->_array[$i])){break;}$arrays[] = $this->_array[$i];}$this->_offset += ($i - $this->_offset); // Limit function callsreturn call_user_func_array('array_merge', $arrays);}/*** Write $chars to the end of the stream.* @param string $chars*/public function write($chars){if (!isset($this->_charReader)){$this->_charReader = $this->_charReaderFactory->getReaderFor($this->_charset);}$startLength = $this->_charReader->getInitialByteSize();$fp = fopen('php://memory', 'w+b');fwrite($fp, $chars);unset($chars);fseek($fp, 0, SEEK_SET);$buffer = array(0);$buf_pos = 1;$buf_len = 1;$has_datas = true;do{$bytes = array();// Buffer Filingif ($buf_len - $buf_pos < $startLength){$buf = array_splice($buffer, $buf_pos);$new = $this->_reloadBuffer($fp, 100);if ($new){$buffer = array_merge($buf, $new);$buf_len = count($buffer);$buf_pos = 0;}else{$has_datas = false;}}if ($buf_len - $buf_pos > 0){$size = 0;for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i){++$size;$bytes[] = $buffer[$buf_pos++];}$need = $this->_charReader->validateByteSequence($bytes, $size);if ($need > 0){if ($buf_len - $buf_pos < $need){$new = $this->_reloadBuffer($fp, $need);if ($new){$buffer = array_merge($buffer, $new);$buf_len = count($buffer);}}for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i){$bytes[] = $buffer[$buf_pos++];}}$this->_array[] = $bytes;++$this->_array_size;}}while ($has_datas);fclose($fp);}/*** Move the internal pointer to $charOffset in the stream.* @param int $charOffset*/public function setPointer($charOffset){if ($charOffset > $this->_array_size){$charOffset = $this->_array_size;}elseif ($charOffset < 0){$charOffset = 0;}$this->_offset = $charOffset;}/*** Empty the stream and reset the internal pointer.*/public function flushContents(){$this->_offset = 0;$this->_array = array();$this->_array_size = 0;}private function _reloadBuffer($fp, $len){if (!feof($fp) && ($bytes = fread($fp, $len)) !== false){$buf = array();for ($i = 0, $len = strlen($bytes); $i < $len; ++$i){$buf[] = self::$_byteMap[$bytes[$i]];}return $buf;}return false;}private static function _initializeMaps(){if (!isset(self::$_charMap)){self::$_charMap = array();for ($byte = 0; $byte < 256; ++$byte){self::$_charMap[$byte] = chr($byte);}self::$_byteMap = array_flip(self::$_charMap);}}}