| 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 // Utility class which can deliver bytes one by one from a number of | 5 // Utility class which can deliver bytes one by one from a number of |
| 6 // buffers added. | 6 // buffers added. |
| 7 class _BufferList { | 7 class _BufferList { |
| 8 _BufferList() : _index = 0, _length = 0, _buffers = new Queue(); | 8 _BufferList() : _index = 0, _length = 0, _buffers = new Queue(); |
| 9 | 9 |
| 10 void add(List<int> buffer) { | 10 void add(List<int> buffer) { |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 // If there is buffered data return that first. | 191 // If there is buffered data return that first. |
| 192 var decodedString = _decoder.decoded; | 192 var decodedString = _decoder.decoded; |
| 193 if (_buffer !== null) { | 193 if (_buffer !== null) { |
| 194 var result = _buffer; | 194 var result = _buffer; |
| 195 _resetBuffer(); | 195 _resetBuffer(); |
| 196 if (decodedString !== null) result += decodedString; | 196 if (decodedString !== null) result += decodedString; |
| 197 return result; | 197 return result; |
| 198 } else { | 198 } else { |
| 199 if (decodedString !== null) { | 199 if (decodedString !== null) { |
| 200 return decodedString; | 200 return decodedString; |
| 201 } else if (_inputClosed) { |
| 202 _streamClosed(); |
| 203 return null; |
| 201 } else { | 204 } else { |
| 202 _readData(); | 205 _readData(); |
| 203 return _decoder.decoded; | 206 return _decoder.decoded; |
| 204 } | 207 } |
| 205 } | 208 } |
| 206 } | 209 } |
| 207 | 210 |
| 208 String readLine() { | 211 String readLine() { |
| 212 if (_closed) return null; |
| 209 // Get line from the buffer if possible. | 213 // Get line from the buffer if possible. |
| 210 if (_buffer !== null) { | 214 if (_buffer !== null) { |
| 211 var result = _readLineFromBuffer(); | 215 var result = _readLineFromBuffer(); |
| 212 if (result !== null) return result; | 216 if (result !== null) return result; |
| 213 } | 217 } |
| 214 // Try to fill more data into the buffer and read a line. | 218 // Try to fill more data into the buffer and read a line. |
| 215 if (_fillBuffer()) { | 219 if (_fillBuffer()) { |
| 216 if (_eof && _buffer === null) return null; | 220 if (_eof && _buffer === null) { |
| 221 _streamClosed(); |
| 222 return null; |
| 223 } |
| 217 return _readLineFromBuffer(); | 224 return _readLineFromBuffer(); |
| 218 } | 225 } |
| 219 return null; | 226 return null; |
| 220 } | 227 } |
| 221 | 228 |
| 222 String get encoding() => _encoding; | 229 String get encoding() => _encoding; |
| 223 | 230 |
| 224 bool get closed() => _closed; | 231 bool get closed() => _closed; |
| 225 | 232 |
| 226 void set dataHandler(void callback()) { | 233 void set dataHandler(void callback()) { |
| 227 _clientDataHandler = callback; | 234 _clientDataHandler = callback; |
| 228 } | 235 } |
| 229 | 236 |
| 230 void set closeHandler(void callback()) { | 237 void set closeHandler(void callback()) { |
| 231 _clientCloseHandler = callback; | 238 _clientCloseHandler = callback; |
| 232 } | 239 } |
| 233 | 240 |
| 234 void _dataHandler() { | 241 void _dataHandler() { |
| 235 _readData(); | 242 _readData(); |
| 236 if (!_decoder.isEmpty() && _clientDataHandler !== null) { | 243 if (!_decoder.isEmpty() && _clientDataHandler !== null) { |
| 237 _clientDataHandler(); | 244 _clientDataHandler(); |
| 238 } | 245 } |
| 239 } | 246 } |
| 240 | 247 |
| 241 void _closeHandler() { | 248 void _closeHandler() { |
| 242 _closed = true; | 249 _inputClosed = true; |
| 243 if (_clientDataHandler !== null) _clientDataHandler(); | 250 if (_buffer !== null || !_decoder.isEmpty()) { |
| 244 if (_clientCloseHandler !== null) _clientCloseHandler(); | 251 // If there is still data buffered in either the buffer or the |
| 252 // decoder call the data handler. |
| 253 if (_clientDataHandler !== null) _clientDataHandler(); |
| 254 } else { |
| 255 closed_ = true; |
| 256 if (_clientCloseHandler !== null) _clientCloseHandler(); |
| 257 } |
| 245 } | 258 } |
| 246 | 259 |
| 247 void _readData() { | 260 void _readData() { |
| 248 List<int> data = _input.read(); | 261 List<int> data = _input.read(); |
| 249 if (data !== null) { | 262 if (data !== null) { |
| 250 _decoder.write(data); | 263 _decoder.write(data); |
| 251 } | 264 } |
| 252 } | 265 } |
| 253 | 266 |
| 254 String _readLineFromBuffer() { | 267 String _readLineFromBuffer() { |
| 255 // Both \n or \r indicates a new line. If \r is followed by \n the | 268 // Both \n or \r indicates a new line. If \r is followed by \n the |
| 256 // \n is part of the line breaking character. | 269 // \n is part of the line breaking character. |
| 257 for (int i = _bufferLineStart; i < _buffer.length; i++) { | 270 for (int i = _bufferLineStart; i < _buffer.length; i++) { |
| 258 String char = _buffer[i]; | 271 String char = _buffer[i]; |
| 259 if (char == '\r') { | 272 if (char == '\r') { |
| 260 if (i == _buffer.length - 1) { | 273 if (i == _buffer.length - 1) { |
| 261 if (_eof) { | 274 if (_eof) { |
| 262 var result = _buffer.substring(_bufferLineStart, i); | 275 var result = _buffer.substring(_bufferLineStart, i); |
| 263 _resetBuffer(); | 276 _resetBuffer(); |
| 277 _streamClosed(); |
| 264 return result; | 278 return result; |
| 265 } else { | 279 } else { |
| 266 return null; | 280 return null; |
| 267 } | 281 } |
| 268 } | 282 } |
| 269 var result = _buffer.substring(_bufferLineStart, i); | 283 var result = _buffer.substring(_bufferLineStart, i); |
| 270 _bufferLineStart = i + 1; | 284 _bufferLineStart = i + 1; |
| 271 if (_buffer[_bufferLineStart] == '\n') _bufferLineStart++; | 285 if (_buffer[_bufferLineStart] == '\n') _bufferLineStart++; |
| 286 if (_bufferLineStart == _buffer.length) _resetBuffer(); |
| 272 return result; | 287 return result; |
| 273 } else if (char == '\n') { | 288 } else if (char == '\n') { |
| 274 var result = _buffer.substring(_bufferLineStart, i); | 289 var result = _buffer.substring(_bufferLineStart, i); |
| 275 _bufferLineStart = i + 1; | 290 _bufferLineStart = i + 1; |
| 291 if (_bufferLineStart == _buffer.length) _resetBuffer(); |
| 276 return result; | 292 return result; |
| 277 } | 293 } |
| 278 } | 294 } |
| 279 if (_eof) { | 295 if (_eof) { |
| 280 var result = _buffer; | 296 var result = _buffer; |
| 281 _resetBuffer(); | 297 _resetBuffer(); |
| 298 _streamClosed(); |
| 282 return result; | 299 return result; |
| 283 } | 300 } |
| 284 return null; | 301 return null; |
| 285 } | 302 } |
| 286 | 303 |
| 287 void _resetBuffer() { | 304 void _resetBuffer() { |
| 288 _buffer = null; | 305 _buffer = null; |
| 289 _bufferLineStart = null; | 306 _bufferLineStart = null; |
| 290 } | 307 } |
| 291 | 308 |
| 292 // Fill decoded data into the buffer. Returns true if more data was | 309 // Fill decoded data into the buffer. Returns true if more data was |
| 293 // added or end of file was reached. | 310 // added or end of file was reached. |
| 294 bool _fillBuffer() { | 311 bool _fillBuffer() { |
| 295 if (_eof) return false; | 312 if (_eof) return false; |
| 296 if (_buffer !== null && _bufferLineStart == _buffer.length) { | 313 if (!_inputClosed) _readData(); |
| 297 _buffer = null; | |
| 298 _bufferLineStart = null; | |
| 299 } | |
| 300 _readData(); | |
| 301 var decodedString = _decoder.decoded; | 314 var decodedString = _decoder.decoded; |
| 302 if (decodedString === null && _closed) { | 315 if (decodedString === null && _inputClosed) { |
| 303 _eof = true; | 316 _eof = true; |
| 304 return true; | 317 return true; |
| 305 } | 318 } |
| 306 if (_buffer === null) { | 319 if (_buffer === null) { |
| 307 _buffer = decodedString; | 320 _buffer = decodedString; |
| 308 if (_buffer !== null) { | 321 if (_buffer !== null) { |
| 309 _bufferLineStart = 0; | 322 _bufferLineStart = 0; |
| 310 return true; | 323 return true; |
| 311 } | 324 } |
| 312 } else if (decodedString !== null) { | 325 } else if (decodedString !== null) { |
| 313 _buffer = _buffer.substring(_bufferLineStart) + decodedString; | 326 _buffer = _buffer.substring(_bufferLineStart) + decodedString; |
| 314 _bufferLineStart = 0; | 327 _bufferLineStart = 0; |
| 315 return true; | 328 return true; |
| 316 } | 329 } |
| 317 return false; | 330 return false; |
| 318 } | 331 } |
| 319 | 332 |
| 333 void _streamClosed() { |
| 334 _closed = true; |
| 335 |
| 336 // TODO(sgjesse): Find a better way of scheduling callbacks from |
| 337 // the event loop. |
| 338 void issueCloseCallback(Timer timer) { |
| 339 if (_clientCloseHandler !== null) _clientCloseHandler(); |
| 340 } |
| 341 new Timer(issueCloseCallback, 0, false); |
| 342 } |
| 343 |
| 320 InputStream _input; | 344 InputStream _input; |
| 321 String _encoding; | 345 String _encoding; |
| 322 _Decoder _decoder; | 346 _Decoder _decoder; |
| 323 String _buffer; // String can be buffered here if readLine is used. | 347 String _buffer; // String can be buffered here if readLine is used. |
| 324 int _bufferLineStart; // Current offset into _buffer if any. | 348 int _bufferLineStart; // Current offset into _buffer if any. |
| 325 bool _closed = false; | 349 bool _inputClosed = false; // Is the underlying input stream closed? |
| 350 bool _closed = false; // Is this stream closed. |
| 326 bool _eof = false; // Has all data been read from the decoder? | 351 bool _eof = false; // Has all data been read from the decoder? |
| 327 var _clientDataHandler; | 352 var _clientDataHandler; |
| 328 var _clientCloseHandler; | 353 var _clientCloseHandler; |
| 329 } | 354 } |
| OLD | NEW |