ArrayByteStream.php 4.3KB

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