NgCharacterStream.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <?php
  2. /*
  3. * This file is part of SwiftMailer.
  4. * (c) 2004-2009 Chris Corbyn
  5. *
  6. * For the full copyright and license information, please view the LICENSE
  7. * file that was distributed with this source code.
  8. */
  9. /**
  10. * A CharacterStream implementation which stores characters in an internal array.
  11. *
  12. * @author Xavier De Cock <xdecock@gmail.com>
  13. */
  14. class Swift_CharacterStream_NgCharacterStream implements Swift_CharacterStream
  15. {
  16. /**
  17. * The char reader (lazy-loaded) for the current charset.
  18. *
  19. * @var Swift_CharacterReader
  20. */
  21. private $_charReader;
  22. /**
  23. * A factory for creating CharacterReader instances.
  24. *
  25. * @var Swift_CharacterReaderFactory
  26. */
  27. private $_charReaderFactory;
  28. /**
  29. * The character set this stream is using.
  30. *
  31. * @var string
  32. */
  33. private $_charset;
  34. /**
  35. * The data's stored as-is.
  36. *
  37. * @var string
  38. */
  39. private $_datas = '';
  40. /**
  41. * Number of bytes in the stream
  42. *
  43. * @var int
  44. */
  45. private $_datasSize = 0;
  46. /**
  47. * Map.
  48. *
  49. * @var mixed
  50. */
  51. private $_map;
  52. /**
  53. * Map Type.
  54. *
  55. * @var int
  56. */
  57. private $_mapType = 0;
  58. /**
  59. * Number of characters in the stream.
  60. *
  61. * @var int
  62. */
  63. private $_charCount = 0;
  64. /**
  65. * Position in the stream.
  66. *
  67. * @var int
  68. */
  69. private $_currentPos = 0;
  70. /**
  71. * Constructor.
  72. *
  73. * @param Swift_CharacterReaderFactory $factory
  74. * @param string $charset
  75. */
  76. public function __construct(Swift_CharacterReaderFactory $factory, $charset)
  77. {
  78. $this->setCharacterReaderFactory($factory);
  79. $this->setCharacterSet($charset);
  80. }
  81. /* -- Changing parameters of the stream -- */
  82. /**
  83. * Set the character set used in this CharacterStream.
  84. *
  85. * @param string $charset
  86. */
  87. public function setCharacterSet($charset)
  88. {
  89. $this->_charset = $charset;
  90. $this->_charReader = null;
  91. $this->_mapType = 0;
  92. }
  93. /**
  94. * Set the CharacterReaderFactory for multi charset support.
  95. *
  96. * @param Swift_CharacterReaderFactory $factory
  97. */
  98. public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory)
  99. {
  100. $this->_charReaderFactory = $factory;
  101. }
  102. /**
  103. * @see Swift_CharacterStream::flushContents()
  104. */
  105. public function flushContents()
  106. {
  107. $this->_datas = null;
  108. $this->_map = null;
  109. $this->_charCount = 0;
  110. $this->_currentPos = 0;
  111. $this->_datasSize = 0;
  112. }
  113. /**
  114. * @see Swift_CharacterStream::importByteStream()
  115. *
  116. * @param Swift_OutputByteStream $os
  117. */
  118. public function importByteStream(Swift_OutputByteStream $os)
  119. {
  120. $this->flushContents();
  121. $blocks=512;
  122. $os->setReadPointer(0);
  123. while(false!==($read = $os->read($blocks)))
  124. $this->write($read);
  125. }
  126. /**
  127. * @see Swift_CharacterStream::importString()
  128. *
  129. * @param string $string
  130. */
  131. public function importString($string)
  132. {
  133. $this->flushContents();
  134. $this->write($string);
  135. }
  136. /**
  137. * @see Swift_CharacterStream::read()
  138. *
  139. * @param int $length
  140. *
  141. * @return string
  142. */
  143. public function read($length)
  144. {
  145. if ($this->_currentPos>=$this->_charCount) {
  146. return false;
  147. }
  148. $ret=false;
  149. $length = ($this->_currentPos+$length > $this->_charCount)
  150. ? $this->_charCount - $this->_currentPos
  151. : $length;
  152. switch ($this->_mapType) {
  153. case Swift_CharacterReader::MAP_TYPE_FIXED_LEN:
  154. $len = $length*$this->_map;
  155. $ret = substr($this->_datas,
  156. $this->_currentPos * $this->_map,
  157. $len);
  158. $this->_currentPos += $length;
  159. break;
  160. case Swift_CharacterReader::MAP_TYPE_INVALID:
  161. $end = $this->_currentPos + $length;
  162. $end = $end > $this->_charCount
  163. ?$this->_charCount
  164. :$end;
  165. $ret = '';
  166. for (; $this->_currentPos < $length; ++$this->_currentPos) {
  167. if (isset ($this->_map[$this->_currentPos])) {
  168. $ret .= '?';
  169. } else {
  170. $ret .= $this->_datas[$this->_currentPos];
  171. }
  172. }
  173. break;
  174. case Swift_CharacterReader::MAP_TYPE_POSITIONS:
  175. $end = $this->_currentPos + $length;
  176. $end = $end > $this->_charCount
  177. ?$this->_charCount
  178. :$end;
  179. $ret = '';
  180. $start = 0;
  181. if ($this->_currentPos>0) {
  182. $start = $this->_map['p'][$this->_currentPos-1];
  183. }
  184. $to = $start;
  185. for (; $this->_currentPos < $end; ++$this->_currentPos) {
  186. if (isset($this->_map['i'][$this->_currentPos])) {
  187. $ret .= substr($this->_datas, $start, $to - $start).'?';
  188. $start = $this->_map['p'][$this->_currentPos];
  189. } else {
  190. $to = $this->_map['p'][$this->_currentPos];
  191. }
  192. }
  193. $ret .= substr($this->_datas, $start, $to - $start);
  194. break;
  195. }
  196. return $ret;
  197. }
  198. /**
  199. * @see Swift_CharacterStream::readBytes()
  200. *
  201. * @param int $length
  202. *
  203. * @return integer[]
  204. */
  205. public function readBytes($length)
  206. {
  207. $read=$this->read($length);
  208. if ($read!==false) {
  209. $ret = array_map('ord', str_split($read, 1));
  210. return $ret;
  211. }
  212. return false;
  213. }
  214. /**
  215. * @see Swift_CharacterStream::setPointer()
  216. *
  217. * @param int $charOffset
  218. */
  219. public function setPointer($charOffset)
  220. {
  221. if ($this->_charCount<$charOffset) {
  222. $charOffset=$this->_charCount;
  223. }
  224. $this->_currentPos = $charOffset;
  225. }
  226. /**
  227. * @see Swift_CharacterStream::write()
  228. *
  229. * @param string $chars
  230. */
  231. public function write($chars)
  232. {
  233. if (!isset($this->_charReader)) {
  234. $this->_charReader = $this->_charReaderFactory->getReaderFor(
  235. $this->_charset);
  236. $this->_map = array();
  237. $this->_mapType = $this->_charReader->getMapType();
  238. }
  239. $ignored='';
  240. $this->_datas .= $chars;
  241. $this->_charCount += $this->_charReader->getCharPositions(substr($this->_datas, $this->_datasSize), $this->_datasSize, $this->_map, $ignored);
  242. if ($ignored!==false) {
  243. $this->_datasSize=strlen($this->_datas)-strlen($ignored);
  244. } else {
  245. $this->_datasSize=strlen($this->_datas);
  246. }
  247. }
  248. }