| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 part of dart.io; | 5 part of dart.io; |
| 6 | 6 |
| 7 // Read the file in blocks of size 64k. | 7 // Read the file in blocks of size 64k. |
| 8 const int _BLOCK_SIZE = 64 * 1024; | 8 const int _BLOCK_SIZE = 64 * 1024; |
| 9 | 9 |
| 10 | 10 |
| 11 class _FileStream extends Stream<List<int>> { | 11 class _FileStream extends Stream<List<int>> { |
| 12 // Stream controller. | 12 // Stream controller. |
| 13 StreamController<List<int>> _controller; | 13 StreamController<List<int>> _controller; |
| 14 | 14 |
| 15 // Information about the underlying file. | 15 // Information about the underlying file. |
| 16 String _path; | 16 String _path; |
| 17 RandomAccessFile _openedFile; | 17 RandomAccessFile _openedFile; |
| 18 int _position; | 18 int _position; |
| 19 int _end; | 19 int _end; |
| 20 final Completer _closeCompleter = new Completer(); | 20 final Completer _closeCompleter = new Completer(); |
| 21 | 21 |
| 22 // Has the stream been paused or unsubscribed? | 22 // Has the stream been paused or unsubscribed? |
| 23 bool _paused = false; | 23 bool _paused = false; |
| 24 bool _unsubscribed = false; | 24 bool _unsubscribed = false; |
| 25 | 25 |
| 26 // Is there a read currently in progress? | 26 // Is there a read currently in progress? |
| 27 bool _readInProgress = false; | 27 bool _readInProgress = false; |
| 28 bool _closed = false; |
| 28 | 29 |
| 29 // Block read but not yet send because stream is paused. | 30 // Block read but not yet send because stream is paused. |
| 30 List<int> _currentBlock; | 31 List<int> _currentBlock; |
| 31 | 32 |
| 32 _FileStream(String this._path, this._position, this._end) { | 33 _FileStream(String this._path, this._position, this._end) { |
| 33 _setupController(); | 34 _setupController(); |
| 34 } | 35 } |
| 35 | 36 |
| 36 _FileStream.forStdin() : _position = 0 { | 37 _FileStream.forStdin() : _position = 0 { |
| 37 _setupController(); | 38 _setupController(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 52 onListen: _start, | 53 onListen: _start, |
| 53 onPause: () => _paused = true, | 54 onPause: () => _paused = true, |
| 54 onResume: _resume, | 55 onResume: _resume, |
| 55 onCancel: () { | 56 onCancel: () { |
| 56 _unsubscribed = true; | 57 _unsubscribed = true; |
| 57 return _closeFile(); | 58 return _closeFile(); |
| 58 }); | 59 }); |
| 59 } | 60 } |
| 60 | 61 |
| 61 Future _closeFile() { | 62 Future _closeFile() { |
| 62 if (_readInProgress) { | 63 if (_readInProgress || _closed) { |
| 63 return _closeCompleter.future; | 64 return _closeCompleter.future; |
| 64 } | 65 } |
| 66 _closed = true; |
| 67 void done() { |
| 68 _closeCompleter.complete(); |
| 69 _controller.close(); |
| 70 } |
| 65 if (_openedFile != null) { | 71 if (_openedFile != null) { |
| 66 _openedFile.close() | 72 _openedFile.close() |
| 67 .then(_closeCompleter.complete, | 73 .catchError(_controller.addError) |
| 68 onError: _closeCompleter.completeError); | 74 .whenComplete(done); |
| 69 _openedFile = null; | 75 _openedFile = null; |
| 76 } else { |
| 77 done(); |
| 70 } | 78 } |
| 71 return _closeCompleter.future; | 79 return _closeCompleter.future; |
| 72 } | 80 } |
| 73 | 81 |
| 74 void _readBlock() { | 82 void _readBlock() { |
| 75 // Don't start a new read if one is already in progress. | 83 // Don't start a new read if one is already in progress. |
| 76 if (_readInProgress) return; | 84 if (_readInProgress) return; |
| 77 _readInProgress = true; | 85 _readInProgress = true; |
| 78 int readBytes = _BLOCK_SIZE; | 86 int readBytes = _BLOCK_SIZE; |
| 79 if (_end != null) { | 87 if (_end != null) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 92 .whenComplete(() { | 100 .whenComplete(() { |
| 93 _readInProgress = false; | 101 _readInProgress = false; |
| 94 }) | 102 }) |
| 95 .then((block) { | 103 .then((block) { |
| 96 if (_unsubscribed) { | 104 if (_unsubscribed) { |
| 97 _closeFile(); | 105 _closeFile(); |
| 98 return; | 106 return; |
| 99 } | 107 } |
| 100 if (block.length == 0) { | 108 if (block.length == 0) { |
| 101 if (!_unsubscribed) { | 109 if (!_unsubscribed) { |
| 102 _closeFile().then((_) { _controller.close(); }); | 110 _closeFile(); |
| 103 _unsubscribed = true; | 111 _unsubscribed = true; |
| 104 } | 112 } |
| 105 return; | 113 return; |
| 106 } | 114 } |
| 107 _position += block.length; | 115 _position += block.length; |
| 108 if (_paused) { | 116 if (_paused) { |
| 109 _currentBlock = block; | 117 _currentBlock = block; |
| 110 } else { | 118 } else { |
| 111 _controller.add(block); | 119 _controller.add(block); |
| 112 _readBlock(); | 120 _readBlock(); |
| 113 } | 121 } |
| 114 }) | 122 }) |
| 115 .catchError((e) { | 123 .catchError((e) { |
| 116 if (!_unsubscribed) { | 124 if (!_unsubscribed) { |
| 117 _controller.addError(e); | 125 _controller.addError(e); |
| 118 _closeFile().then((_) { _controller.close(); }); | 126 _closeFile(); |
| 119 _unsubscribed = true; | 127 _unsubscribed = true; |
| 120 } | 128 } |
| 121 }); | 129 }); |
| 122 } | 130 } |
| 123 | 131 |
| 124 void _start() { | 132 void _start() { |
| 125 if (_position == null) { | 133 if (_position == null) { |
| 126 _position = 0; | 134 _position = 0; |
| 127 } else if (_position < 0) { | 135 } else if (_position < 0) { |
| 128 _controller.addError(new RangeError("Bad start position: $_position")); | 136 _controller.addError(new RangeError("Bad start position: $_position")); |
| (...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 861 | 869 |
| 862 void _checkAvailable() { | 870 void _checkAvailable() { |
| 863 if (_asyncDispatched) { | 871 if (_asyncDispatched) { |
| 864 throw new FileSystemException("An async operation is currently pending", p
ath); | 872 throw new FileSystemException("An async operation is currently pending", p
ath); |
| 865 } | 873 } |
| 866 if (closed) { | 874 if (closed) { |
| 867 throw new FileSystemException("File closed", path); | 875 throw new FileSystemException("File closed", path); |
| 868 } | 876 } |
| 869 } | 877 } |
| 870 } | 878 } |
| OLD | NEW |