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 |