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 |