ArrayByteStream.php 4.2KB

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