ArrayByteStream.php 4.2 KB

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