1: <?php
2:
3: 4: 5: 6: 7: 8: 9:
10:
11: 12: 13: 14: 15: 16:
17: class Swift_CharacterStream_ArrayCharacterStream implements Swift_CharacterStream
18: {
19:
20: private static $_charMap;
21:
22:
23: private static $_byteMap;
24:
25:
26: private $_charReader;
27:
28:
29: private $_charReaderFactory;
30:
31:
32: private $_charset;
33:
34:
35: private $_array = array();
36:
37:
38: private $_array_size = array();
39:
40:
41: private $_offset = 0;
42:
43: 44: 45: 46: 47:
48: public function __construct(Swift_CharacterReaderFactory $factory, $charset)
49: {
50: self::_initializeMaps();
51: $this->setCharacterReaderFactory($factory);
52: $this->setCharacterSet($charset);
53: }
54:
55: 56: 57: 58:
59: public function setCharacterSet($charset)
60: {
61: $this->_charset = $charset;
62: $this->_charReader = null;
63: }
64:
65: 66: 67: 68:
69: public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory)
70: {
71: $this->_charReaderFactory = $factory;
72: }
73:
74: 75: 76: 77:
78: public function importByteStream(Swift_OutputByteStream $os)
79: {
80: if (!isset($this->_charReader)) {
81: $this->_charReader = $this->_charReaderFactory
82: ->getReaderFor($this->_charset);
83: }
84:
85: $startLength = $this->_charReader->getInitialByteSize();
86: while (false !== $bytes = $os->read($startLength)) {
87: $c = array();
88: for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) {
89: $c[] = self::$_byteMap[$bytes[$i]];
90: }
91: $size = count($c);
92: $need = $this->_charReader
93: ->validateByteSequence($c, $size);
94: if ($need > 0 &&
95: false !== $bytes = $os->read($need))
96: {
97: for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) {
98: $c[] = self::$_byteMap[$bytes[$i]];
99: }
100: }
101: $this->_array[] = $c;
102: ++$this->_array_size;
103: }
104: }
105:
106: 107: 108: 109: 110:
111: public function importString($string)
112: {
113: $this->flushContents();
114: $this->write($string);
115: }
116:
117: 118: 119: 120: 121: 122:
123: public function read($length)
124: {
125: if ($this->_offset == $this->_array_size) {
126: return false;
127: }
128:
129:
130: $arrays = array();
131: $end = $length + $this->_offset;
132: for ($i = $this->_offset; $i < $end; ++$i) {
133: if (!isset($this->_array[$i])) {
134: break;
135: }
136: $arrays[] = $this->_array[$i];
137: }
138: $this->_offset += $i - $this->_offset;
139: $chars = false;
140: foreach ($arrays as $array) {
141: $chars .= implode('', array_map('chr', $array));
142: }
143:
144: return $chars;
145: }
146:
147: 148: 149: 150: 151: 152:
153: public function readBytes($length)
154: {
155: if ($this->_offset == $this->_array_size) {
156: return false;
157: }
158: $arrays = array();
159: $end = $length + $this->_offset;
160: for ($i = $this->_offset; $i < $end; ++$i) {
161: if (!isset($this->_array[$i])) {
162: break;
163: }
164: $arrays[] = $this->_array[$i];
165: }
166: $this->_offset += ($i - $this->_offset);
167:
168: return call_user_func_array('array_merge', $arrays);
169: }
170:
171: 172: 173: 174:
175: public function write($chars)
176: {
177: if (!isset($this->_charReader)) {
178: $this->_charReader = $this->_charReaderFactory->getReaderFor(
179: $this->_charset);
180: }
181:
182: $startLength = $this->_charReader->getInitialByteSize();
183:
184: $fp = fopen('php://memory', 'w+b');
185: fwrite($fp, $chars);
186: unset($chars);
187: fseek($fp, 0, SEEK_SET);
188:
189: $buffer = array(0);
190: $buf_pos = 1;
191: $buf_len = 1;
192: $has_datas = true;
193: do {
194: $bytes = array();
195:
196: if ($buf_len - $buf_pos < $startLength) {
197: $buf = array_splice($buffer, $buf_pos);
198: $new = $this->_reloadBuffer($fp, 100);
199: if ($new) {
200: $buffer = array_merge($buf, $new);
201: $buf_len = count($buffer);
202: $buf_pos = 0;
203: } else {
204: $has_datas = false;
205: }
206: }
207: if ($buf_len - $buf_pos > 0) {
208: $size = 0;
209: for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i) {
210: ++$size;
211: $bytes[] = $buffer[$buf_pos++];
212: }
213: $need = $this->_charReader->validateByteSequence(
214: $bytes, $size);
215: if ($need > 0) {
216: if ($buf_len - $buf_pos < $need) {
217: $new = $this->_reloadBuffer($fp, $need);
218:
219: if ($new) {
220: $buffer = array_merge($buffer, $new);
221: $buf_len = count($buffer);
222: }
223: }
224: for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i) {
225: $bytes[] = $buffer[$buf_pos++];
226: }
227: }
228: $this->_array[] = $bytes;
229: ++$this->_array_size;
230: }
231: } while ($has_datas);
232:
233: fclose($fp);
234: }
235:
236: 237: 238: 239:
240: public function setPointer($charOffset)
241: {
242: if ($charOffset > $this->_array_size) {
243: $charOffset = $this->_array_size;
244: } elseif ($charOffset < 0) {
245: $charOffset = 0;
246: }
247: $this->_offset = $charOffset;
248: }
249:
250: 251: 252:
253: public function flushContents()
254: {
255: $this->_offset = 0;
256: $this->_array = array();
257: $this->_array_size = 0;
258: }
259:
260: private function _reloadBuffer($fp, $len)
261: {
262: if (!feof($fp) && ($bytes = fread($fp, $len)) !== false) {
263: $buf = array();
264: for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) {
265: $buf[] = self::$_byteMap[$bytes[$i]];
266: }
267:
268: return $buf;
269: }
270:
271: return false;
272: }
273:
274: private static function _initializeMaps()
275: {
276: if (!isset(self::$_charMap)) {
277: self::$_charMap = array();
278: for ($byte = 0; $byte < 256; ++$byte) {
279: self::$_charMap[$byte] = chr($byte);
280: }
281: self::$_byteMap = array_flip(self::$_charMap);
282: }
283: }
284: }
285: