[ Index ] |
MailPress 7.2 |
[ Index ] [ Classes ] [ Functions ] [ Variables ] [ Constants ] [ Statistics ] |
[Summary view] [Print] [Text view]
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 /** 12 * A CharacterStream implementation which stores characters in an internal array. 13 * 14 * @author Chris Corbyn 15 */ 16 class Swift_CharacterStream_ArrayCharacterStream implements Swift_CharacterStream 17 { 18 /** A map of byte values and their respective characters */ 19 private static $charMap; 20 21 /** A map of characters and their derivative byte values */ 22 private static $byteMap; 23 24 /** The char reader (lazy-loaded) for the current charset */ 25 private $charReader; 26 27 /** A factory for creating CharacterReader instances */ 28 private $charReaderFactory; 29 30 /** The character set this stream is using */ 31 private $charset; 32 33 /** Array of characters */ 34 private $array = []; 35 36 /** Size of the array of character */ 37 private $array_size = []; 38 39 /** The current character offset in the stream */ 40 private $offset = 0; 41 42 /** 43 * Create a new CharacterStream with the given $chars, if set. 44 * 45 * @param Swift_CharacterReaderFactory $factory for loading validators 46 * @param string $charset used in the stream 47 */ 48 public function __construct(Swift_CharacterReaderFactory $factory, $charset) 49 { 50 self::initializeMaps(); 51 $this->setCharacterReaderFactory($factory); 52 $this->setCharacterSet($charset); 53 } 54 55 /** 56 * Set the character set used in this CharacterStream. 57 * 58 * @param string $charset 59 */ 60 public function setCharacterSet($charset) 61 { 62 $this->charset = $charset; 63 $this->charReader = null; 64 } 65 66 /** 67 * Set the CharacterReaderFactory for multi charset support. 68 */ 69 public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory) 70 { 71 $this->charReaderFactory = $factory; 72 } 73 74 /** 75 * Overwrite this character stream using the byte sequence in the byte stream. 76 * 77 * @param Swift_OutputByteStream $os output stream to read from 78 */ 79 public function importByteStream(Swift_OutputByteStream $os) 80 { 81 if (!isset($this->charReader)) { 82 $this->charReader = $this->charReaderFactory 83 ->getReaderFor($this->charset); 84 } 85 86 $startLength = $this->charReader->getInitialByteSize(); 87 while (false !== $bytes = $os->read($startLength)) { 88 $c = []; 89 for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) { 90 $c[] = self::$byteMap[$bytes[$i]]; 91 } 92 $size = count($c); 93 $need = $this->charReader 94 ->validateByteSequence($c, $size); 95 if ($need > 0 && 96 false !== $bytes = $os->read($need)) { 97 for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) { 98 $c[] = self::$byteMap[$bytes[$i]]; 99 } 100 } 101 $this->array[] = $c; 102 ++$this->array_size; 103 } 104 } 105 106 /** 107 * Import a string a bytes into this CharacterStream, overwriting any existing 108 * data in the stream. 109 * 110 * @param string $string 111 */ 112 public function importString($string) 113 { 114 $this->flushContents(); 115 $this->write($string); 116 } 117 118 /** 119 * Read $length characters from the stream and move the internal pointer 120 * $length further into the stream. 121 * 122 * @param int $length 123 * 124 * @return string 125 */ 126 public function read($length) 127 { 128 if ($this->offset == $this->array_size) { 129 return false; 130 } 131 132 // Don't use array slice 133 $arrays = []; 134 $end = $length + $this->offset; 135 for ($i = $this->offset; $i < $end; ++$i) { 136 if (!isset($this->array[$i])) { 137 break; 138 } 139 $arrays[] = $this->array[$i]; 140 } 141 $this->offset += $i - $this->offset; // Limit function calls 142 $chars = false; 143 foreach ($arrays as $array) { 144 $chars .= implode('', array_map('chr', $array)); 145 } 146 147 return $chars; 148 } 149 150 /** 151 * Read $length characters from the stream and return a 1-dimensional array 152 * containing there octet values. 153 * 154 * @param int $length 155 * 156 * @return int[] 157 */ 158 public function readBytes($length) 159 { 160 if ($this->offset == $this->array_size) { 161 return false; 162 } 163 $arrays = []; 164 $end = $length + $this->offset; 165 for ($i = $this->offset; $i < $end; ++$i) { 166 if (!isset($this->array[$i])) { 167 break; 168 } 169 $arrays[] = $this->array[$i]; 170 } 171 $this->offset += ($i - $this->offset); // Limit function calls 172 173 return array_merge(...$arrays); 174 } 175 176 /** 177 * Write $chars to the end of the stream. 178 * 179 * @param string $chars 180 */ 181 public function write($chars) 182 { 183 if (!isset($this->charReader)) { 184 $this->charReader = $this->charReaderFactory->getReaderFor( 185 $this->charset); 186 } 187 188 $startLength = $this->charReader->getInitialByteSize(); 189 190 $fp = fopen('php://memory', 'w+b'); 191 fwrite($fp, $chars); 192 unset($chars); 193 fseek($fp, 0, SEEK_SET); 194 195 $buffer = [0]; 196 $buf_pos = 1; 197 $buf_len = 1; 198 $has_datas = true; 199 do { 200 $bytes = []; 201 // Buffer Filing 202 if ($buf_len - $buf_pos < $startLength) { 203 $buf = array_splice($buffer, $buf_pos); 204 $new = $this->reloadBuffer($fp, 100); 205 if ($new) { 206 $buffer = array_merge($buf, $new); 207 $buf_len = count($buffer); 208 $buf_pos = 0; 209 } else { 210 $has_datas = false; 211 } 212 } 213 if ($buf_len - $buf_pos > 0) { 214 $size = 0; 215 for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i) { 216 ++$size; 217 $bytes[] = $buffer[$buf_pos++]; 218 } 219 $need = $this->charReader->validateByteSequence( 220 $bytes, $size); 221 if ($need > 0) { 222 if ($buf_len - $buf_pos < $need) { 223 $new = $this->reloadBuffer($fp, $need); 224 225 if ($new) { 226 $buffer = array_merge($buffer, $new); 227 $buf_len = count($buffer); 228 } 229 } 230 for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i) { 231 $bytes[] = $buffer[$buf_pos++]; 232 } 233 } 234 $this->array[] = $bytes; 235 ++$this->array_size; 236 } 237 } while ($has_datas); 238 239 fclose($fp); 240 } 241 242 /** 243 * Move the internal pointer to $charOffset in the stream. 244 * 245 * @param int $charOffset 246 */ 247 public function setPointer($charOffset) 248 { 249 if ($charOffset > $this->array_size) { 250 $charOffset = $this->array_size; 251 } elseif ($charOffset < 0) { 252 $charOffset = 0; 253 } 254 $this->offset = $charOffset; 255 } 256 257 /** 258 * Empty the stream and reset the internal pointer. 259 */ 260 public function flushContents() 261 { 262 $this->offset = 0; 263 $this->array = []; 264 $this->array_size = 0; 265 } 266 267 private function reloadBuffer($fp, $len) 268 { 269 if (!feof($fp) && false !== ($bytes = fread($fp, $len))) { 270 $buf = []; 271 for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) { 272 $buf[] = self::$byteMap[$bytes[$i]]; 273 } 274 275 return $buf; 276 } 277 278 return false; 279 } 280 281 private static function initializeMaps() 282 { 283 if (!isset(self::$charMap)) { 284 self::$charMap = []; 285 for ($byte = 0; $byte < 256; ++$byte) { 286 self::$charMap[$byte] = chr($byte); 287 } 288 self::$byteMap = array_flip(self::$charMap); 289 } 290 } 291 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue May 19 15:55:14 2020 | Cross-referenced by PHPXref 0.7.1 |