|
TYPO3 API
SVNRelease
|
00001 <?php 00002 00003 /* 00004 * This file is part of SwiftMailer. 00005 * (c) 2004-2009 Chris Corbyn 00006 * 00007 * For the full copyright and license information, please view the LICENSE 00008 * file that was distributed with this source code. 00009 */ 00010 00011 //@require 'Swift/CharacterStream.php'; 00012 //@require 'Swift/OutputByteStream.php'; 00013 00014 00015 /** 00016 * A CharacterStream implementation which stores characters in an internal array. 00017 * @package Swift 00018 * @subpackage CharacterStream 00019 * @author Chris Corbyn 00020 */ 00021 class Swift_CharacterStream_ArrayCharacterStream 00022 implements Swift_CharacterStream 00023 { 00024 00025 /** A map of byte values and their respective characters */ 00026 private static $_charMap; 00027 00028 /** A map of characters and their derivative byte values */ 00029 private static $_byteMap; 00030 00031 /** The char reader (lazy-loaded) for the current charset */ 00032 private $_charReader; 00033 00034 /** A factory for creatiing CharacterReader instances */ 00035 private $_charReaderFactory; 00036 00037 /** The character set this stream is using */ 00038 private $_charset; 00039 00040 /** Array of characters */ 00041 private $_array = array(); 00042 00043 /** Size of the array of character */ 00044 private $_array_size = array(); 00045 00046 /** The current character offset in the stream */ 00047 private $_offset = 0; 00048 00049 /** 00050 * Create a new CharacterStream with the given $chars, if set. 00051 * @param Swift_CharacterReaderFactory $factory for loading validators 00052 * @param string $charset used in the stream 00053 */ 00054 public function __construct(Swift_CharacterReaderFactory $factory, 00055 $charset) 00056 { 00057 self::_initializeMaps(); 00058 $this->setCharacterReaderFactory($factory); 00059 $this->setCharacterSet($charset); 00060 } 00061 00062 /** 00063 * Set the character set used in this CharacterStream. 00064 * @param string $charset 00065 */ 00066 public function setCharacterSet($charset) 00067 { 00068 $this->_charset = $charset; 00069 $this->_charReader = null; 00070 } 00071 00072 /** 00073 * Set the CharacterReaderFactory for multi charset support. 00074 * @param Swift_CharacterReaderFactory $factory 00075 */ 00076 public function setCharacterReaderFactory( 00077 Swift_CharacterReaderFactory $factory) 00078 { 00079 $this->_charReaderFactory = $factory; 00080 } 00081 00082 /** 00083 * Overwrite this character stream using the byte sequence in the byte stream. 00084 * @param Swift_OutputByteStream $os output stream to read from 00085 */ 00086 public function importByteStream(Swift_OutputByteStream $os) 00087 { 00088 if (!isset($this->_charReader)) 00089 { 00090 $this->_charReader = $this->_charReaderFactory 00091 ->getReaderFor($this->_charset); 00092 } 00093 00094 $startLength = $this->_charReader->getInitialByteSize(); 00095 while (false !== $bytes = $os->read($startLength)) 00096 { 00097 $c = array(); 00098 for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) 00099 { 00100 $c[] = self::$_byteMap[$bytes[$i]]; 00101 } 00102 $size = count($c); 00103 $need = $this->_charReader 00104 ->validateByteSequence($c, $size); 00105 if ($need > 0 && 00106 false !== $bytes = $os->read($need)) 00107 { 00108 for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) 00109 { 00110 $c[] = self::$_byteMap[$bytes[$i]]; 00111 } 00112 } 00113 $this->_array[] = $c; 00114 ++$this->_array_size; 00115 } 00116 } 00117 00118 /** 00119 * Import a string a bytes into this CharacterStream, overwriting any existing 00120 * data in the stream. 00121 * @param string $string 00122 */ 00123 public function importString($string) 00124 { 00125 $this->flushContents(); 00126 $this->write($string); 00127 } 00128 00129 /** 00130 * Read $length characters from the stream and move the internal pointer 00131 * $length further into the stream. 00132 * @param int $length 00133 * @return string 00134 */ 00135 public function read($length) 00136 { 00137 if ($this->_offset == $this->_array_size) 00138 { 00139 return false; 00140 } 00141 00142 // Don't use array slice 00143 $arrays = array(); 00144 $end = $length + $this->_offset; 00145 for ($i = $this->_offset; $i < $end; ++$i) 00146 { 00147 if (!isset($this->_array[$i])) 00148 { 00149 break; 00150 } 00151 $arrays[] = $this->_array[$i]; 00152 } 00153 $this->_offset += $i - $this->_offset; // Limit function calls 00154 $chars = false; 00155 foreach ($arrays as $array) 00156 { 00157 $chars .= implode('', array_map('chr', $array)); 00158 } 00159 return $chars; 00160 } 00161 00162 /** 00163 * Read $length characters from the stream and return a 1-dimensional array 00164 * containing there octet values. 00165 * @param int $length 00166 * @return int[] 00167 */ 00168 public function readBytes($length) 00169 { 00170 if ($this->_offset == $this->_array_size) 00171 { 00172 return false; 00173 } 00174 $arrays = array(); 00175 $end = $length + $this->_offset; 00176 for ($i = $this->_offset; $i < $end; ++$i) 00177 { 00178 if (!isset($this->_array[$i])) 00179 { 00180 break; 00181 } 00182 $arrays[] = $this->_array[$i]; 00183 } 00184 $this->_offset += ($i - $this->_offset); // Limit function calls 00185 return call_user_func_array('array_merge', $arrays); 00186 } 00187 00188 /** 00189 * Write $chars to the end of the stream. 00190 * @param string $chars 00191 */ 00192 public function write($chars) 00193 { 00194 if (!isset($this->_charReader)) 00195 { 00196 $this->_charReader = $this->_charReaderFactory->getReaderFor( 00197 $this->_charset); 00198 } 00199 00200 $startLength = $this->_charReader->getInitialByteSize(); 00201 00202 $fp = fopen('php://memory', 'w+b'); 00203 fwrite($fp, $chars); 00204 unset($chars); 00205 fseek($fp, 0, SEEK_SET); 00206 00207 $buffer = array(0); 00208 $buf_pos = 1; 00209 $buf_len = 1; 00210 $has_datas = true; 00211 do 00212 { 00213 $bytes = array(); 00214 // Buffer Filing 00215 if ($buf_len - $buf_pos < $startLength) 00216 { 00217 $buf = array_splice($buffer, $buf_pos); 00218 $new = $this->_reloadBuffer($fp, 100); 00219 if ($new) 00220 { 00221 $buffer = array_merge($buf, $new); 00222 $buf_len = count($buffer); 00223 $buf_pos = 0; 00224 } 00225 else 00226 { 00227 $has_datas = false; 00228 } 00229 } 00230 if ($buf_len - $buf_pos > 0) 00231 { 00232 $size = 0; 00233 for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i) 00234 { 00235 ++$size; 00236 $bytes[] = $buffer[$buf_pos++]; 00237 } 00238 $need = $this->_charReader->validateByteSequence( 00239 $bytes, $size); 00240 if ($need > 0) 00241 { 00242 if ($buf_len - $buf_pos < $need) 00243 { 00244 $new = $this->_reloadBuffer($fp, $need); 00245 00246 if ($new) 00247 { 00248 $buffer = array_merge($buffer, $new); 00249 $buf_len = count($buffer); 00250 } 00251 } 00252 for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i) 00253 { 00254 $bytes[] = $buffer[$buf_pos++]; 00255 } 00256 } 00257 $this->_array[] = $bytes; 00258 ++$this->_array_size; 00259 } 00260 } 00261 while ($has_datas); 00262 00263 fclose($fp); 00264 } 00265 00266 /** 00267 * Move the internal pointer to $charOffset in the stream. 00268 * @param int $charOffset 00269 */ 00270 public function setPointer($charOffset) 00271 { 00272 if ($charOffset > $this->_array_size) 00273 { 00274 $charOffset = $this->_array_size; 00275 } 00276 elseif ($charOffset < 0) 00277 { 00278 $charOffset = 0; 00279 } 00280 $this->_offset = $charOffset; 00281 } 00282 00283 /** 00284 * Empty the stream and reset the internal pointer. 00285 */ 00286 public function flushContents() 00287 { 00288 $this->_offset = 0; 00289 $this->_array = array(); 00290 $this->_array_size = 0; 00291 } 00292 00293 private function _reloadBuffer($fp, $len) 00294 { 00295 if (!feof($fp) && ($bytes = fread($fp, $len)) !== false) 00296 { 00297 $buf = array(); 00298 for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) 00299 { 00300 $buf[] = self::$_byteMap[$bytes[$i]]; 00301 } 00302 return $buf; 00303 } 00304 return false; 00305 } 00306 00307 private static function _initializeMaps() 00308 { 00309 if (!isset(self::$_charMap)) 00310 { 00311 self::$_charMap = array(); 00312 for ($byte = 0; $byte < 256; ++$byte) 00313 { 00314 self::$_charMap[$byte] = chr($byte); 00315 } 00316 self::$_byteMap = array_flip(self::$_charMap); 00317 } 00318 } 00319 }
1.8.0