ArrayByteStream.php 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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. * Allows reading and writing of bytes to and from an array.
  11. * @package Swift
  12. * @subpackage ByteStream
  13. * @author Chris Corbyn
  14. */
  15. class Swift_ByteStream_ArrayByteStream
  16. implements Swift_InputByteStream, Swift_OutputByteStream
  17. {
  18. /**
  19. * The internal stack of bytes.
  20. * @var string[]
  21. * @access private
  22. */
  23. private $_array = array();
  24. /**
  25. * The size of the stack
  26. * @var int
  27. * @access private
  28. */
  29. private $_arraySize = 0;
  30. /**
  31. * The internal pointer offset.
  32. * @var int
  33. * @access private
  34. */
  35. private $_offset = 0;
  36. /** Bound streams */
  37. private $_mirrors = array();
  38. /**
  39. * Create a new ArrayByteStream.
  40. * If $stack is given the stream will be populated with the bytes it contains.
  41. * @param mixed $stack of bytes in string or array form, optional
  42. */
  43. public function __construct($stack = null)
  44. {
  45. if (is_array($stack))
  46. {
  47. $this->_array = $stack;
  48. $this->_arraySize = count($stack);
  49. }
  50. elseif (is_string($stack))
  51. {
  52. $this->write($stack);
  53. }
  54. else
  55. {
  56. $this->_array = array();
  57. }
  58. }
  59. /**
  60. * Reads $length bytes from the stream into a string and moves the pointer
  61. * through the stream by $length. If less bytes exist than are requested the
  62. * remaining bytes are given instead. If no bytes are remaining at all, boolean
  63. * false is returned.
  64. * @param int $length
  65. * @return string
  66. */
  67. public function read($length)
  68. {
  69. if ($this->_offset == $this->_arraySize)
  70. {
  71. return false;
  72. }
  73. // Don't use array slice
  74. $end = $length + $this->_offset;
  75. $end = $this->_arraySize<$end
  76. ?$this->_arraySize
  77. :$end;
  78. $ret = '';
  79. for (; $this->_offset < $end; ++$this->_offset)
  80. {
  81. $ret .= $this->_array[$this->_offset];
  82. }
  83. return $ret;
  84. }
  85. /**
  86. * Writes $bytes to the end of the stream.
  87. * @param string $bytes
  88. */
  89. public function write($bytes)
  90. {
  91. $to_add = str_split($bytes);
  92. foreach ($to_add as $value)
  93. {
  94. $this->_array[] = $value;
  95. }
  96. $this->_arraySize = count($this->_array);
  97. foreach ($this->_mirrors as $stream)
  98. {
  99. $stream->write($bytes);
  100. }
  101. }
  102. /**
  103. * Not used.
  104. */
  105. public function commit()
  106. {
  107. }
  108. /**
  109. * Attach $is to this stream.
  110. * The stream acts as an observer, receiving all data that is written.
  111. * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
  112. *
  113. * @param Swift_InputByteStream $is
  114. */
  115. public function bind(Swift_InputByteStream $is)
  116. {
  117. $this->_mirrors[] = $is;
  118. }
  119. /**
  120. * Remove an already bound stream.
  121. * If $is is not bound, no errors will be raised.
  122. * If the stream currently has any buffered data it will be written to $is
  123. * before unbinding occurs.
  124. *
  125. * @param Swift_InputByteStream $is
  126. */
  127. public function unbind(Swift_InputByteStream $is)
  128. {
  129. foreach ($this->_mirrors as $k => $stream)
  130. {
  131. if ($is === $stream)
  132. {
  133. unset($this->_mirrors[$k]);
  134. }
  135. }
  136. }
  137. /**
  138. * Move the internal read pointer to $byteOffset in the stream.
  139. * @param int $byteOffset
  140. * @return boolean
  141. */
  142. public function setReadPointer($byteOffset)
  143. {
  144. if ($byteOffset > $this->_arraySize)
  145. {
  146. $byteOffset = $this->_arraySize;
  147. }
  148. elseif ($byteOffset < 0)
  149. {
  150. $byteOffset = 0;
  151. }
  152. $this->_offset = $byteOffset;
  153. }
  154. /**
  155. * Flush the contents of the stream (empty it) and set the internal pointer
  156. * to the beginning.
  157. */
  158. public function flushBuffers()
  159. {
  160. $this->_offset = 0;
  161. $this->_array = array();
  162. $this->_arraySize = 0;
  163. foreach ($this->_mirrors as $stream)
  164. {
  165. $stream->flushBuffers();
  166. }
  167. }
  168. }