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