1: <?php
2:
3: /*
4: * This file is part of SwiftMailer.
5: * (c) 2004-2009 Chris Corbyn
6: *
7: * For the full copyright and license information, please view the LICENSE
8: * file that was distributed with this source code.
9: */
10:
11: /**
12: * Allows reading and writing of bytes to and from an array.
13: * @package Swift
14: * @subpackage ByteStream
15: * @author Chris Corbyn
16: */
17: class Swift_ByteStream_ArrayByteStream implements Swift_InputByteStream, Swift_OutputByteStream
18: {
19: /**
20: * The internal stack of bytes.
21: * @var string[]
22: * @access private
23: */
24: private $_array = array();
25:
26: /**
27: * The size of the stack
28: * @var int
29: * @access private
30: */
31: private $_arraySize = 0;
32:
33: /**
34: * The internal pointer offset.
35: * @var int
36: * @access private
37: */
38: private $_offset = 0;
39:
40: /** Bound streams */
41: private $_mirrors = array();
42:
43: /**
44: * Create a new ArrayByteStream.
45: * If $stack is given the stream will be populated with the bytes it contains.
46: * @param mixed $stack of bytes in string or array form, optional
47: */
48: public function __construct($stack = null)
49: {
50: if (is_array($stack)) {
51: $this->_array = $stack;
52: $this->_arraySize = count($stack);
53: } elseif (is_string($stack)) {
54: $this->write($stack);
55: } else {
56: $this->_array = array();
57: }
58: }
59:
60: /**
61: * Reads $length bytes from the stream into a string and moves the pointer
62: * through the stream by $length. 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: * @param int $length
66: * @return string
67: */
68: public function read($length)
69: {
70: if ($this->_offset == $this->_arraySize) {
71: return false;
72: }
73:
74: // Don't use array slice
75: $end = $length + $this->_offset;
76: $end = $this->_arraySize<$end
77: ?$this->_arraySize
78: :$end;
79: $ret = '';
80: for (; $this->_offset < $end; ++$this->_offset) {
81: $ret .= $this->_array[$this->_offset];
82: }
83:
84: return $ret;
85: }
86:
87: /**
88: * Writes $bytes to the end of the stream.
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:
99: foreach ($this->_mirrors as $stream) {
100: $stream->write($bytes);
101: }
102: }
103:
104: /**
105: * Not used.
106: */
107: public function commit()
108: {
109: }
110:
111: /**
112: * Attach $is to this stream.
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: /**
124: * Remove an already bound stream.
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: /**
141: * Move the internal read pointer to $byteOffset in the stream.
142: * @param int $byteOffset
143: * @return boolean
144: */
145: public function setReadPointer($byteOffset)
146: {
147: if ($byteOffset > $this->_arraySize) {
148: $byteOffset = $this->_arraySize;
149: } elseif ($byteOffset < 0) {
150: $byteOffset = 0;
151: }
152:
153: $this->_offset = $byteOffset;
154: }
155:
156: /**
157: * Flush the contents of the stream (empty it) and set the internal pointer
158: * to the beginning.
159: */
160: public function flushBuffers()
161: {
162: $this->_offset = 0;
163: $this->_array = array();
164: $this->_arraySize = 0;
165:
166: foreach ($this->_mirrors as $stream) {
167: $stream->flushBuffers();
168: }
169: }
170: }
171: