Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Side by Side Diff: runtime/bin/string_stream.dart

Issue 8885032: Improve the event handling for string input stream (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: rebased Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/chunked_stream.dart ('k') | tests/standalone/src/FileInputStreamTest.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 // Interface for decoders decoding binary data into string data. The 5 // Interface for decoders decoding binary data into string data. The
6 // decoder keeps track of line breaks during decoding. 6 // decoder keeps track of line breaks during decoding.
7 interface _StringDecoder { 7 interface _StringDecoder {
8 // Add more binary data to be decoded. The ownership of the buffer 8 // Add more binary data to be decoded. The ownership of the buffer
9 // is transfered to the decoder and the caller most not modify it any more. 9 // is transfered to the decoder and the caller most not modify it any more.
10 int write(List<int> buffer); 10 int write(List<int> buffer);
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 } else if (_encoding == "ASCII") { 225 } else if (_encoding == "ASCII") {
226 _decoder = new _AsciiDecoder(); 226 _decoder = new _AsciiDecoder();
227 } else { 227 } else {
228 throw new StreamException("Unsupported encoding $_encoding"); 228 throw new StreamException("Unsupported encoding $_encoding");
229 } 229 }
230 _input.dataHandler = _dataHandler; 230 _input.dataHandler = _dataHandler;
231 _input.closeHandler = _closeHandler; 231 _input.closeHandler = _closeHandler;
232 } 232 }
233 233
234 String read() { 234 String read() {
235 // If there is buffered data return that first. 235 String result = _decoder.decoded;
236 var decodedString = _decoder.decoded; 236 _checkInstallDataHandler();
237 if (decodedString !== null) { 237 return result;
238 if (_inputClosed && _decoder.isEmpty()) {
239 _streamClosed();
240 }
241 return decodedString;
242 } else if (_inputClosed) {
243 _streamClosed();
244 return null;
245 } else {
246 _readData();
247 return _decoder.decoded;
248 }
249 } 238 }
250 239
251 String readLine() { 240 String readLine() {
252 if (_closed) return null; 241 String decodedLine = _decoder.decodedLine;
253 242 if (decodedLine == null) {
254 if (_decoder.lineBreaks == 0) { 243 if (_inputClosed) {
255 _readData(); 244 // Last line might not have a line separator.
245 decodedLine = _decoder.decoded;
246 if (decodedLine != null &&
247 decodedLine[decodedLine.length - 1] == '\r') {
248 decodedLine = decodedLine.substring(0, decodedLine.length - 1);
249 }
250 }
256 } 251 }
257 var decodedLine = _decoder.decodedLine; 252 _checkInstallDataHandler();
258 if (decodedLine !== null) { 253 return decodedLine;
259 if (_inputClosed && _decoder.isEmpty()) {
260 _streamClosed();
261 }
262 return decodedLine;
263 }
264 if (_inputClosed) {
265 decodedLine = _decoder.decoded;
266 if (decodedLine[decodedLine.length - 1] == '\r') {
267 decodedLine = decodedLine.substring(0, decodedLine.length - 1);
268 }
269 _streamClosed();
270 return decodedLine;
271 }
272 return null;
273 } 254 }
274 255
275 String get encoding() => _encoding; 256 String get encoding() => _encoding;
276 257
277 bool get closed() => _closed; 258 bool get closed() => _inputClosed && _decoder.isEmpty();
278 259
279 void set dataHandler(void callback()) { 260 void set dataHandler(void callback()) {
280 _clientDataHandler = callback; 261 _clientDataHandler = callback;
281 _clientLineHandler = null; 262 _clientLineHandler = null;
263 _checkInstallDataHandler();
264 _checkScheduleCallback();
282 } 265 }
283 266
284 void set lineHandler(void callback()) { 267 void set lineHandler(void callback()) {
285 _clientLineHandler = callback; 268 _clientLineHandler = callback;
286 _clientDataHandler = null; 269 _clientDataHandler = null;
270 _checkInstallDataHandler();
271 _checkScheduleCallback();
287 } 272 }
288 273
289 void set closeHandler(void callback()) { 274 void set closeHandler(void callback()) {
290 _clientCloseHandler = callback; 275 _clientCloseHandler = callback;
291 } 276 }
292 277
293 void _dataHandler() { 278 void _dataHandler() {
294 _readData(); 279 _readData();
295 if (!_decoder.isEmpty() && _clientDataHandler !== null) { 280 if (!_decoder.isEmpty() && _clientDataHandler !== null) {
296 _clientDataHandler(); 281 _clientDataHandler();
297 } 282 }
298 if (_decoder.lineBreaks > 0 && _clientLineHandler !== null) { 283 if (_decoder.lineBreaks > 0 && _clientLineHandler !== null) {
299 _clientLineHandler(); 284 _clientLineHandler();
300 } 285 }
286 _checkScheduleCallback();
287 _checkInstallDataHandler();
301 } 288 }
302 289
303 void _closeHandler() { 290 void _closeHandler() {
304 _inputClosed = true; 291 _inputClosed = true;
305 if (!_decoder.isEmpty()) { 292 if (_decoder.isEmpty() && _clientCloseHandler != null) {
306 // If there is still data buffered call the data handler. 293 _clientCloseHandler();
307 if (_clientDataHandler !== null) _clientDataHandler(); 294 _closed = true;
308 if (_clientLineHandler !== null) _clientLineHandler();
309 } else { 295 } else {
310 _closed = true; 296 _checkScheduleCallback();
311 if (_clientCloseHandler !== null) _clientCloseHandler();
312 } 297 }
313 } 298 }
314 299
315 void _readData() { 300 void _readData() {
316 List<int> data = _input.read(); 301 List<int> data = _input.read();
317 if (data !== null) { 302 if (data !== null) {
318 _decoder.write(data); 303 _decoder.write(data);
319 } 304 }
320 } 305 }
321 306
322 void _streamClosed() { 307 void _checkInstallDataHandler() {
323 _closed = true; 308 if (_inputClosed ||
309 (_clientDataHandler === null && _clientLineHandler === null)) {
310 _input.dataHandler = null;
311 } else if (_clientDataHandler !== null) {
312 if (_decoder.isEmpty()) {
313 _input.dataHandler = _dataHandler;
314 } else {
315 _input.dataHandler = null;
316 }
317 } else {
318 assert(_clientLineHandler !== null);
319 if (_decoder.lineBreaks == 0) {
320 _input.dataHandler = _dataHandler;
321 } else {
322 _input.dataHandler = null;
323 }
324 }
325 }
324 326
325 // TODO(sgjesse): Find a better way of scheduling callbacks from 327 // TODO(sgjesse): Find a better way of scheduling callbacks from
326 // the event loop. 328 // the event loop.
329 void _checkScheduleCallback() {
330 void issueDataCallback(Timer timer) {
331 _scheduledDataCallback = null;
332 if (_clientDataHandler !== null) {
333 _clientDataHandler();
334 _checkScheduleCallback();
335 }
336 }
337
338 void issueLineCallback(Timer timer) {
339 _scheduledLineCallback = null;
340 if (_clientLineHandler !== null) {
341 _clientLineHandler();
342 _checkScheduleCallback();
343 }
344 }
345
327 void issueCloseCallback(Timer timer) { 346 void issueCloseCallback(Timer timer) {
328 if (_clientCloseHandler !== null) _clientCloseHandler(); 347 _scheduledCloseCallback = null;
348 if (!_closed) {
349 if (_clientCloseHandler !== null) _clientCloseHandler();
350 _closed = true;
351 }
329 } 352 }
330 new Timer(issueCloseCallback, 0, false); 353
354 if (!_closed) {
355 // Schedule data callback if string data available.
356 if (_clientDataHandler != null &&
357 !_decoder.isEmpty() &&
358 _scheduledDataCallback == null) {
359 if (_scheduledLineCallback != null) _scheduledLineCallback.cancel();
360 _scheduledDataCallback = new Timer(issueDataCallback, 0, false);
361 }
362
363 // Schedule line callback if a line is available.
364 if (_clientLineHandler != null &&
365 (_decoder.lineBreaks > 0 || (!_decoder.isEmpty() && _inputClosed)) &&
366 _scheduledLineCallback == null) {
367 if (_scheduledDataCallback != null) _scheduledDataCallback.cancel();
368 _scheduledLineCallback = new Timer(issueLineCallback, 0, false);
369 }
370
371 // Schedule close callback if no more data and input is closed.
372 if (_decoder.isEmpty() &&
373 _inputClosed &&
374 _scheduledCloseCallback == null) {
375 _scheduledCloseCallback = new Timer(issueCloseCallback, 0, false);
376 }
377 }
331 } 378 }
332 379
333 InputStream _input; 380 InputStream _input;
334 String _encoding; 381 String _encoding;
335 _StringDecoder _decoder; 382 _StringDecoder _decoder;
336 bool _inputClosed = false; // Is the underlying input stream closed? 383 bool _inputClosed = false; // Is the underlying input stream closed?
337 bool _closed = false; // Is this stream closed. 384 bool _closed = false; // Is this stream closed.
338 bool _eof = false; // Has all data been read from the decoder? 385 bool _eof = false; // Has all data been read from the decoder?
339 var _clientDataHandler; 386 Timer _scheduledDataCallback;
340 var _clientLineHandler; 387 Timer _scheduledLineCallback;
341 var _clientCloseHandler; 388 Timer _scheduledCloseCallback;
389 Function _clientDataHandler;
390 Function _clientLineHandler;
391 Function _clientCloseHandler;
342 } 392 }
OLDNEW
« no previous file with comments | « runtime/bin/chunked_stream.dart ('k') | tests/standalone/src/FileInputStreamTest.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698