| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 class _ChunkedInputStream implements ChunkedInputStream { | |
| 6 _ChunkedInputStream(InputStream this._input, int this._chunkSize) | |
| 7 : _bufferList = new _BufferList() { | |
| 8 _input.onClosed = _onClosed; | |
| 9 } | |
| 10 | |
| 11 List<int> read() { | |
| 12 if (_closed) return null; | |
| 13 var result = _bufferList.readBytes(_chunkSize); | |
| 14 if (result == null) { | |
| 15 _readData(); | |
| 16 result = _bufferList.readBytes(_chunkSize); | |
| 17 } | |
| 18 if (result == null && _inputClosed) { | |
| 19 if (_bufferList.length == 0) { | |
| 20 result = null; | |
| 21 } else { | |
| 22 result = _bufferList.readBytes(_bufferList.length); | |
| 23 } | |
| 24 } | |
| 25 _checkInstallDataHandler(); | |
| 26 return result; | |
| 27 } | |
| 28 | |
| 29 int get chunkSize => _chunkSize; | |
| 30 | |
| 31 void set chunkSize(int chunkSize) { | |
| 32 _chunkSize = chunkSize; | |
| 33 _checkInstallDataHandler(); | |
| 34 _checkScheduleCallback(); | |
| 35 } | |
| 36 | |
| 37 bool get closed => _closed; | |
| 38 | |
| 39 void set onData(void callback()) { | |
| 40 _clientDataHandler = callback; | |
| 41 _checkInstallDataHandler(); | |
| 42 } | |
| 43 | |
| 44 void set onClosed(void callback()) { | |
| 45 _clientCloseHandler = callback; | |
| 46 } | |
| 47 | |
| 48 void set onError(void callback(e)) { | |
| 49 _input.onError = callback; | |
| 50 } | |
| 51 | |
| 52 void _onData() { | |
| 53 _readData(); | |
| 54 if (_bufferList.length >= _chunkSize && _clientDataHandler !== null) { | |
| 55 _clientDataHandler(); | |
| 56 } | |
| 57 _checkScheduleCallback(); | |
| 58 _checkInstallDataHandler(); | |
| 59 } | |
| 60 | |
| 61 void _readData() { | |
| 62 List<int> data = _input.read(); | |
| 63 if (data !== null) { | |
| 64 _bufferList.add(data); | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 void _onClosed() { | |
| 69 _inputClosed = true; | |
| 70 if (_bufferList.length == 0 && _clientCloseHandler !== null) { | |
| 71 _clientCloseHandler(); | |
| 72 _closed = true; | |
| 73 } else { | |
| 74 _checkScheduleCallback(); | |
| 75 } | |
| 76 } | |
| 77 | |
| 78 void _checkInstallDataHandler() { | |
| 79 if (_clientDataHandler === null) { | |
| 80 _input.onData = null; | |
| 81 } else { | |
| 82 if (_bufferList.length < _chunkSize && !_inputClosed) { | |
| 83 _input.onData = _onData; | |
| 84 } else { | |
| 85 _input.onData = null; | |
| 86 } | |
| 87 } | |
| 88 } | |
| 89 | |
| 90 void _checkScheduleCallback() { | |
| 91 // TODO(sgjesse): Find a better way of scheduling callbacks from | |
| 92 // the event loop. | |
| 93 void issueDataCallback(Timer timer) { | |
| 94 _scheduledDataCallback = null; | |
| 95 if (_clientDataHandler !== null) { | |
| 96 _clientDataHandler(); | |
| 97 _checkScheduleCallback(); | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 void issueCloseCallback(Timer timer) { | |
| 102 _scheduledCloseCallback = null; | |
| 103 if (!_closed) { | |
| 104 if (_clientCloseHandler !== null) _clientCloseHandler(); | |
| 105 _closed = true; | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 // Schedule data callback if enough data in buffer. | |
| 110 if ((_bufferList.length >= _chunkSize || | |
| 111 (_bufferList.length > 0 && _inputClosed)) && | |
| 112 _clientDataHandler !== null && | |
| 113 _scheduledDataCallback == null) { | |
| 114 _scheduledDataCallback = new Timer(0, issueDataCallback); | |
| 115 } | |
| 116 | |
| 117 // Schedule close callback if no more data and input is closed. | |
| 118 if (_bufferList.length == 0 && | |
| 119 _inputClosed && | |
| 120 !_closed && | |
| 121 _scheduledCloseCallback == null) { | |
| 122 if (_scheduledDataCallback != null) { | |
| 123 _scheduledDataCallback.cancel(); | |
| 124 } | |
| 125 _scheduledCloseCallback = new Timer(0, issueCloseCallback); | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 InputStream _input; | |
| 130 _BufferList _bufferList; | |
| 131 int _chunkSize; | |
| 132 bool _inputClosed = false; // Is the underlying input stream closed? | |
| 133 bool _closed = false; // Has the close handler been called?. | |
| 134 Timer _scheduledDataCallback; | |
| 135 Timer _scheduledCloseCallback; | |
| 136 Function _clientDataHandler; | |
| 137 Function _clientCloseHandler; | |
| 138 } | |
| OLD | NEW |