OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 class SocketInputStream implements InputStream { | 5 class SocketInputStream implements InputStream { |
6 SocketInputStream(Socket socket) { | 6 SocketInputStream(Socket socket) { |
7 _socket = socket; | 7 _socket = socket; |
8 _buffer = null; | |
9 } | 8 } |
10 | 9 |
11 bool read(List<int> buffer, int offset, int len, void callback()) { | 10 List<int> read([int len]) { |
12 // Read data just out of the buffer. | 11 int bytesToRead = available(); |
13 if (_buffer !== null && len <= _buffer.length) { | 12 if (bytesToRead == 0) return null; |
14 buffer.copyFrom(_buffer, 0, offset, len); | 13 if (len != null) { |
15 int remainder = _buffer.length - len; | 14 if (len <= 0) { |
16 if (remainder > 0) { | 15 throw new StreamException("Illegal length $len"); |
17 List<int> newBuffer = new List<int>(remainder); | 16 } else if (bytesToRead > len) { |
18 newBuffer.copyFrom(_buffer, 0, len, remainder); | 17 bytesToRead = len; |
19 _buffer = newBuffer; | |
20 } else { | |
21 _buffer = null; | |
22 } | 18 } |
23 return true; | |
24 } | 19 } |
25 // Read data out of the buffer if available and from the socket. | 20 List<int> buffer = new List<int>(bytesToRead); |
26 else { | 21 int bytesRead = _socket.readList(buffer, 0, bytesToRead); |
27 int bytesRead = 0; | 22 if (bytesRead < bytesToRead) { |
28 if (_buffer !== null) { | 23 List<int> newBuffer = new List<int>(bytesRead); |
29 buffer.copyFrom(_buffer, offset, 0, _buffer.length); | 24 newBuffer.copyFrom(buffer, 0, 0, bytesRead); |
30 bytesRead = _buffer.length; | 25 return newBuffer; |
31 _buffer = null; | 26 } else { |
32 } | 27 return buffer; |
33 | |
34 bytesRead += | |
35 _socket.readList(buffer, offset + bytesRead, len - bytesRead); | |
36 | |
37 if (bytesRead == len) { | |
38 return true; | |
39 } | |
40 | |
41 void doRead() { | |
42 bytesRead += | |
43 _socket.readList(buffer, offset + bytesRead, len - bytesRead); | |
44 if (bytesRead < len) { | |
45 _socket.setDataHandler(doRead); | |
46 } else { | |
47 assert(bytesRead == len); | |
48 _socket.setDataHandler(null); | |
49 if (callback !== null) { | |
50 callback(); | |
51 } | |
52 } | |
53 } | |
54 | |
55 _socket.setDataHandler(doRead); | |
56 return false; | |
57 } | 28 } |
58 } | 29 } |
59 | 30 |
60 int _matchPattern(List<int> buffer, List<int> pattern, int start) { | 31 int readInto(List<int> buffer, int offset, int len) { |
61 int j; | 32 if (offset == null) offset = 0; |
62 if (pattern.length > buffer.length) { | 33 if (len == null) len = buffer.length; |
63 return -1; | 34 if (offset < 0) throw new StreamException("Illegal offset $offset"); |
64 } | 35 if (len < 0) throw new StreamException("Illegal length $len"); |
65 for (int i = start; i < (buffer.length - pattern.length + 1); i++) { | 36 return _socket.readList(buffer, offset, len); |
66 for (j = 0; j < pattern.length; j++) { | |
67 if (buffer[i + j] != pattern[j]) { | |
68 break; | |
69 } | |
70 } | |
71 if (j == pattern.length) { | |
72 return i; | |
73 } | |
74 } | |
75 return -1; | |
76 } | 37 } |
77 | 38 |
78 /* | 39 int available() { |
79 * Appends the newBuffer to the buffer (if available), sets the buffer to | 40 return _socket.available(); |
80 * null, and returns the merged buffer. | |
81 */ | |
82 List<int> _getBufferedData(List<int> newBuffer, int appendingBufferSpace) { | |
83 List<int> buffer; | |
84 int newDataStart = 0; | |
85 if (_buffer !== null) { | |
86 buffer = new List<int>(_buffer.length + appendingBufferSpace); | |
87 buffer.copyFrom(_buffer, 0, 0, _buffer.length); | |
88 newDataStart = _buffer.length; | |
89 _buffer = null; | |
90 } else { | |
91 buffer = new List<int>(appendingBufferSpace); | |
92 } | |
93 buffer.copyFrom(newBuffer, 0, newDataStart, appendingBufferSpace); | |
94 return buffer; | |
95 } | 41 } |
96 | 42 |
97 void readUntil(List<int> pattern, void callback(List<int> resultBuffer)) { | 43 void set dataHandler(void callback()) { |
98 void doRead() { | 44 _socket.setDataHandler(callback); |
99 List<int> newBuffer; | 45 } |
100 int available = _socket.available(); | |
101 if (available > 0) { | |
102 List<int> buffer = new List<int>(available); | |
103 int result = _socket.readList(buffer, 0, buffer.length); | |
104 if (result > 0) { | |
105 // TODO(hpayer): Avoid copying of data before pattern matching. | |
106 newBuffer = _getBufferedData(buffer, result); | |
107 } | |
108 } else if (_buffer != null) { | |
109 newBuffer = _buffer; | |
110 } else { | |
111 _socket.setDataHandler(doRead); | |
112 return; | |
113 } | |
114 | 46 |
115 int index = _matchPattern(newBuffer, pattern, 0); | 47 void set closeHandler(void callback()) { |
116 // If pattern was found return the data including pattern and store the | 48 _socket.setCloseHandler(callback); |
117 // remainder in the buffer. | 49 } |
118 if (index != -1) { | |
119 int finalBufferSize = index + pattern.length; | |
120 List<int> finalBuffer = new List<int>(finalBufferSize); | |
121 finalBuffer.copyFrom(newBuffer, 0, 0, finalBufferSize); | |
122 if (finalBufferSize < newBuffer.length) { | |
123 List<int> remainder = | |
124 new List<int>(newBuffer.length - finalBufferSize); | |
125 remainder.copyFrom(newBuffer, finalBufferSize, 0, remainder.length); | |
126 _buffer = remainder; | |
127 } else { | |
128 _buffer = null; | |
129 } | |
130 _socket.setDataHandler(null); | |
131 callback(finalBuffer); | |
132 } else { | |
133 _buffer = newBuffer; | |
134 _socket.setDataHandler(doRead); | |
135 } | |
136 } | |
137 | 50 |
138 // Register callback for data available. | 51 void set errorHandler(void callback()) { |
139 _socket.setDataHandler(doRead); | 52 _socket.setErrorHandler(callback); |
140 | |
141 // If data is already buffered schedule a data available callback. | |
142 if (_buffer != null) { | |
143 _socket._scheduleEvent(_SocketBase._IN_EVENT); | |
144 } | |
145 } | 53 } |
146 | 54 |
147 Socket _socket; | 55 Socket _socket; |
148 | |
149 /* | |
150 * Read and readUntil read data out of that buffer first before reading new | |
151 * data out of the socket. | |
152 */ | |
153 List<int> _buffer; | |
154 } | 56 } |
155 | 57 |
| 58 |
156 class SocketOutputStream implements OutputStream { | 59 class SocketOutputStream implements OutputStream { |
157 SocketOutputStream(Socket socket) { | 60 SocketOutputStream(Socket socket) : _socket = socket; |
158 _socket = socket; | |
159 } | |
160 | 61 |
161 bool write(List<int> buffer, int offset, int len, void callback()) { | 62 bool write(List<int> buffer, int offset, int len, void callback()) { |
162 int bytesWritten = _socket.writeList(buffer, offset, len); | 63 int bytesWritten = _socket.writeList(buffer, offset, len); |
163 | 64 |
164 void finishWrite() { | 65 void finishWrite() { |
165 bytesWritten += _socket.writeList( | 66 bytesWritten += _socket.writeList( |
166 buffer, offset + bytesWritten, len - bytesWritten); | 67 buffer, offset + bytesWritten, len - bytesWritten); |
167 if (bytesWritten < len) { | 68 if (bytesWritten < len) { |
168 _socket.setWriteHandler(finishWrite); | 69 _socket.setWriteHandler(finishWrite); |
169 } else { | 70 } else { |
170 assert(bytesWritten == len); | 71 assert(bytesWritten == len); |
171 if (callback !== null) { | 72 if (callback !== null) { |
172 callback(); | 73 callback(); |
173 } | 74 } |
174 } | 75 } |
175 } | 76 } |
176 | 77 |
177 if (bytesWritten == len) { | 78 if (bytesWritten == len) { |
178 return true; | 79 return true; |
179 } | 80 } |
180 _socket.setWriteHandler(finishWrite); | 81 _socket.setWriteHandler(finishWrite); |
181 return false; | 82 return false; |
182 } | 83 } |
183 | 84 |
184 Socket _socket; | 85 Socket _socket; |
185 } | 86 } |
OLD | NEW |