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

Side by Side Diff: sdk/lib/io/file_impl.dart

Issue 2754013002: Format all dart: library files (Closed)
Patch Set: Created 3 years, 9 months 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
OLDNEW
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
11 class _FileStream extends Stream<List<int>> { 10 class _FileStream extends Stream<List<int>> {
12 // Stream controller. 11 // Stream controller.
13 StreamController<List<int>> _controller; 12 StreamController<List<int>> _controller;
14 13
15 // Information about the underlying file. 14 // Information about the underlying file.
16 String _path; 15 String _path;
17 RandomAccessFile _openedFile; 16 RandomAccessFile _openedFile;
18 int _position; 17 int _position;
19 int _end; 18 int _end;
20 final Completer _closeCompleter = new Completer(); 19 final Completer _closeCompleter = new Completer();
21 20
22 // Has the stream been paused or unsubscribed? 21 // Has the stream been paused or unsubscribed?
23 bool _unsubscribed = false; 22 bool _unsubscribed = false;
24 23
25 // Is there a read currently in progress? 24 // Is there a read currently in progress?
26 bool _readInProgress = true; 25 bool _readInProgress = true;
27 bool _closed = false; 26 bool _closed = false;
28 27
29 bool _atEnd = false; 28 bool _atEnd = false;
30 29
31 _FileStream(this._path, this._position, this._end) { 30 _FileStream(this._path, this._position, this._end) {
32 if (_position == null) _position = 0; 31 if (_position == null) _position = 0;
33 } 32 }
34 33
35 _FileStream.forStdin() : _position = 0; 34 _FileStream.forStdin() : _position = 0;
36 35
37 StreamSubscription<List<int>> listen(void onData(List<int> event), 36 StreamSubscription<List<int>> listen(void onData(List<int> event),
38 {Function onError, 37 {Function onError, void onDone(), bool cancelOnError}) {
39 void onDone(),
40 bool cancelOnError}) {
41 _setupController(); 38 _setupController();
42 return _controller.stream.listen(onData, 39 return _controller.stream.listen(onData,
43 onError: onError, 40 onError: onError, onDone: onDone, cancelOnError: cancelOnError);
44 onDone: onDone,
45 cancelOnError: cancelOnError);
46 } 41 }
47 42
48 void _setupController() { 43 void _setupController() {
49 _controller = new StreamController<List<int>>(sync: true, 44 _controller = new StreamController<List<int>>(
45 sync: true,
50 onListen: _start, 46 onListen: _start,
51 onResume: _readBlock, 47 onResume: _readBlock,
52 onCancel: () { 48 onCancel: () {
53 _unsubscribed = true; 49 _unsubscribed = true;
54 return _closeFile(); 50 return _closeFile();
55 }); 51 });
56 } 52 }
57 53
58 Future _closeFile() { 54 Future _closeFile() {
59 if (_readInProgress || _closed) { 55 if (_readInProgress || _closed) {
60 return _closeCompleter.future; 56 return _closeCompleter.future;
61 } 57 }
62 _closed = true; 58 _closed = true;
63 59
64 void done() { 60 void done() {
65 _closeCompleter.complete(); 61 _closeCompleter.complete();
66 _controller.close(); 62 _controller.close();
67 } 63 }
68 64
69 _openedFile.close() 65 _openedFile.close().catchError(_controller.addError).whenComplete(done);
70 .catchError(_controller.addError)
71 .whenComplete(done);
72 return _closeCompleter.future; 66 return _closeCompleter.future;
73 } 67 }
74 68
75 void _readBlock() { 69 void _readBlock() {
76 // Don't start a new read if one is already in progress. 70 // Don't start a new read if one is already in progress.
77 if (_readInProgress) return; 71 if (_readInProgress) return;
78 if (_atEnd) { 72 if (_atEnd) {
79 _closeFile(); 73 _closeFile();
80 return; 74 return;
81 } 75 }
82 _readInProgress = true; 76 _readInProgress = true;
83 int readBytes = _BLOCK_SIZE; 77 int readBytes = _BLOCK_SIZE;
84 if (_end != null) { 78 if (_end != null) {
85 readBytes = min(readBytes, _end - _position); 79 readBytes = min(readBytes, _end - _position);
86 if (readBytes < 0) { 80 if (readBytes < 0) {
87 _readInProgress = false; 81 _readInProgress = false;
88 if (!_unsubscribed) { 82 if (!_unsubscribed) {
89 _controller.addError(new RangeError("Bad end position: $_end")); 83 _controller.addError(new RangeError("Bad end position: $_end"));
90 _closeFile(); 84 _closeFile();
91 _unsubscribed = true; 85 _unsubscribed = true;
92 } 86 }
93 return; 87 return;
94 } 88 }
95 } 89 }
96 _openedFile.read(readBytes) 90 _openedFile.read(readBytes).then((block) {
97 .then((block) { 91 _readInProgress = false;
98 _readInProgress = false; 92 if (_unsubscribed) {
99 if (_unsubscribed) { 93 _closeFile();
100 _closeFile(); 94 return;
101 return; 95 }
102 } 96 _position += block.length;
103 _position += block.length; 97 if (block.length < readBytes || (_end != null && _position == _end)) {
104 if (block.length < readBytes || 98 _atEnd = true;
105 (_end != null && _position == _end)) { 99 }
106 _atEnd = true; 100 if (!_atEnd && !_controller.isPaused) {
107 } 101 _readBlock();
108 if (!_atEnd && !_controller.isPaused) { 102 }
109 _readBlock(); 103 _controller.add(block);
110 } 104 if (_atEnd) {
111 _controller.add(block); 105 _closeFile();
112 if (_atEnd) { 106 }
113 _closeFile(); 107 }).catchError((e, s) {
114 } 108 if (!_unsubscribed) {
115 }) 109 _controller.addError(e, s);
116 .catchError((e, s) { 110 _closeFile();
117 if (!_unsubscribed) { 111 _unsubscribed = true;
118 _controller.addError(e, s); 112 }
119 _closeFile(); 113 });
120 _unsubscribed = true;
121 }
122 });
123 } 114 }
124 115
125 void _start() { 116 void _start() {
126 if (_position < 0) { 117 if (_position < 0) {
127 _controller.addError(new RangeError("Bad start position: $_position")); 118 _controller.addError(new RangeError("Bad start position: $_position"));
128 _controller.close(); 119 _controller.close();
129 _closeCompleter.complete(); 120 _closeCompleter.complete();
130 return; 121 return;
131 } 122 }
132 123
133 void onReady(RandomAccessFile file) { 124 void onReady(RandomAccessFile file) {
134 _openedFile = file; 125 _openedFile = file;
135 _readInProgress = false; 126 _readInProgress = false;
136 _readBlock(); 127 _readBlock();
137 } 128 }
138 129
139 void onOpenFile(RandomAccessFile file) { 130 void onOpenFile(RandomAccessFile file) {
140 if (_position > 0) { 131 if (_position > 0) {
141 file.setPosition(_position) 132 file.setPosition(_position).then(onReady, onError: (e, s) {
142 .then(onReady, onError: (e, s) { 133 _controller.addError(e, s);
143 _controller.addError(e, s); 134 _readInProgress = false;
144 _readInProgress = false; 135 _closeFile();
145 _closeFile(); 136 });
146 });
147 } else { 137 } else {
148 onReady(file); 138 onReady(file);
149 } 139 }
150 } 140 }
151 141
152 void openFailed(error, stackTrace) { 142 void openFailed(error, stackTrace) {
153 _controller.addError(error, stackTrace); 143 _controller.addError(error, stackTrace);
154 _controller.close(); 144 _controller.close();
155 _closeCompleter.complete(); 145 _closeCompleter.complete();
156 } 146 }
157 147
158 if (_path != null) { 148 if (_path != null) {
159 new File(_path).open(mode: FileMode.READ) 149 new File(_path)
150 .open(mode: FileMode.READ)
160 .then(onOpenFile, onError: openFailed); 151 .then(onOpenFile, onError: openFailed);
161 } else { 152 } else {
162 try { 153 try {
163 onOpenFile(_File._openStdioSync(0)); 154 onOpenFile(_File._openStdioSync(0));
164 } catch (e, s) { 155 } catch (e, s) {
165 openFailed(e, s); 156 openFailed(e, s);
166 } 157 }
167 } 158 }
168 } 159 }
169 } 160 }
170 161
171 class _FileStreamConsumer extends StreamConsumer<List<int>> { 162 class _FileStreamConsumer extends StreamConsumer<List<int>> {
172 File _file; 163 File _file;
173 Future<RandomAccessFile> _openFuture; 164 Future<RandomAccessFile> _openFuture;
174 165
175 _FileStreamConsumer(this._file, FileMode mode) { 166 _FileStreamConsumer(this._file, FileMode mode) {
176 _openFuture = _file.open(mode: mode); 167 _openFuture = _file.open(mode: mode);
177 } 168 }
178 169
179 _FileStreamConsumer.fromStdio(int fd) { 170 _FileStreamConsumer.fromStdio(int fd) {
180 assert(1 <= fd && fd <= 2); 171 assert(1 <= fd && fd <= 2);
181 _openFuture = new Future.value(_File._openStdioSync(fd)); 172 _openFuture = new Future.value(_File._openStdioSync(fd));
182 } 173 }
183 174
184 Future<File> addStream(Stream<List<int>> stream) { 175 Future<File> addStream(Stream<List<int>> stream) {
185 Completer<File> completer = new Completer<File>.sync(); 176 Completer<File> completer = new Completer<File>.sync();
186 _openFuture 177 _openFuture.then((openedFile) {
187 .then((openedFile) { 178 var _subscription;
188 var _subscription; 179 void error(e, [StackTrace stackTrace]) {
189 void error(e, [StackTrace stackTrace]) { 180 _subscription.cancel();
190 _subscription.cancel(); 181 openedFile.close();
191 openedFile.close(); 182 completer.completeError(e, stackTrace);
192 completer.completeError(e, stackTrace); 183 }
184
185 _subscription = stream.listen((d) {
186 _subscription.pause();
187 try {
188 openedFile
189 .writeFrom(d, 0, d.length)
190 .then((_) => _subscription.resume(), onError: error);
191 } catch (e, stackTrace) {
192 error(e, stackTrace);
193 } 193 }
194 _subscription = stream.listen( 194 }, onDone: () {
195 (d) { 195 completer.complete(_file);
196 _subscription.pause(); 196 }, onError: error, cancelOnError: true);
197 try { 197 }).catchError(completer.completeError);
198 openedFile.writeFrom(d, 0, d.length)
199 .then((_) => _subscription.resume(),
200 onError: error);
201 } catch (e, stackTrace) {
202 error(e, stackTrace);
203 }
204 },
205 onDone: () {
206 completer.complete(_file);
207 },
208 onError: error,
209 cancelOnError: true);
210 })
211 .catchError(completer.completeError);
212 return completer.future; 198 return completer.future;
213 } 199 }
214 200
215 Future<File> close() => 201 Future<File> close() =>
216 _openFuture.then<File>((openedFile) => openedFile.close()); 202 _openFuture.then<File>((openedFile) => openedFile.close());
217 } 203 }
218 204
219
220 // Class for encapsulating the native implementation of files. 205 // Class for encapsulating the native implementation of files.
221 class _File extends FileSystemEntity implements File { 206 class _File extends FileSystemEntity implements File {
222 final String path; 207 final String path;
223 208
224 // Constructor for file. 209 // Constructor for file.
225 _File(this.path) { 210 _File(this.path) {
226 if (path is! String) { 211 if (path is! String) {
227 throw new ArgumentError('${Error.safeToString(path)} ' 212 throw new ArgumentError('${Error.safeToString(path)} '
228 'is not a String'); 213 'is not a String');
229 } 214 }
230 } 215 }
231 216
232 Future<bool> exists() { 217 Future<bool> exists() {
233 return _IOService._dispatch(_FILE_EXISTS, [path]).then((response) { 218 return _IOService._dispatch(_FILE_EXISTS, [path]).then((response) {
234 if (_isErrorResponse(response)) { 219 if (_isErrorResponse(response)) {
235 throw _exceptionFromResponse(response, "Cannot check existence", path); 220 throw _exceptionFromResponse(response, "Cannot check existence", path);
236 } 221 }
237 return response; 222 return response;
238 }); 223 });
239 } 224 }
240 225
241 external static _exists(String path); 226 external static _exists(String path);
242 227
243 bool existsSync() { 228 bool existsSync() {
244 var result = _exists(path); 229 var result = _exists(path);
245 throwIfError(result, "Cannot check existence of file", path); 230 throwIfError(result, "Cannot check existence of file", path);
246 return result; 231 return result;
247 } 232 }
248 233
249 File get absolute => new File(_absolutePath); 234 File get absolute => new File(_absolutePath);
250 235
251 Future<File> create({bool recursive: false}) { 236 Future<File> create({bool recursive: false}) {
252 var result = recursive ? parent.create(recursive: true) 237 var result =
253 : new Future.value(null); 238 recursive ? parent.create(recursive: true) : new Future.value(null);
254 return result 239 return result
255 .then((_) => _IOService._dispatch(_FILE_CREATE, [path])) 240 .then((_) => _IOService._dispatch(_FILE_CREATE, [path]))
256 .then((response) { 241 .then((response) {
257 if (_isErrorResponse(response)) { 242 if (_isErrorResponse(response)) {
258 throw _exceptionFromResponse(response, "Cannot create file", path); 243 throw _exceptionFromResponse(response, "Cannot create file", path);
259 } 244 }
260 return this; 245 return this;
261 }); 246 });
262 } 247 }
263 248
264 external static _create(String path); 249 external static _create(String path);
265 250
266 external static _createLink(String path, String target); 251 external static _createLink(String path, String target);
267 252
268 external static _linkTarget(String path); 253 external static _linkTarget(String path);
269 254
270 void createSync({bool recursive: false}) { 255 void createSync({bool recursive: false}) {
271 if (recursive) { 256 if (recursive) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 324
340 Future<RandomAccessFile> open({FileMode mode: FileMode.READ}) { 325 Future<RandomAccessFile> open({FileMode mode: FileMode.READ}) {
341 if (mode != FileMode.READ && 326 if (mode != FileMode.READ &&
342 mode != FileMode.WRITE && 327 mode != FileMode.WRITE &&
343 mode != FileMode.APPEND && 328 mode != FileMode.APPEND &&
344 mode != FileMode.WRITE_ONLY && 329 mode != FileMode.WRITE_ONLY &&
345 mode != FileMode.WRITE_ONLY_APPEND) { 330 mode != FileMode.WRITE_ONLY_APPEND) {
346 return new Future.error( 331 return new Future.error(
347 new ArgumentError('Invalid file mode for this operation')); 332 new ArgumentError('Invalid file mode for this operation'));
348 } 333 }
349 return _IOService._dispatch(_FILE_OPEN, [path, mode._mode]) 334 return _IOService
350 .then((response) { 335 ._dispatch(_FILE_OPEN, [path, mode._mode]).then((response) {
351 if (_isErrorResponse(response)) { 336 if (_isErrorResponse(response)) {
352 throw _exceptionFromResponse(response, "Cannot open file", path); 337 throw _exceptionFromResponse(response, "Cannot open file", path);
353 } 338 }
354 return new _RandomAccessFile(response, path); 339 return new _RandomAccessFile(response, path);
355 }); 340 });
356 } 341 }
357 342
358 Future<int> length() { 343 Future<int> length() {
359 return _IOService._dispatch(_FILE_LENGTH_FROM_PATH, [path]) 344 return _IOService
360 .then((response) { 345 ._dispatch(_FILE_LENGTH_FROM_PATH, [path]).then((response) {
361 if (_isErrorResponse(response)) { 346 if (_isErrorResponse(response)) {
362 throw _exceptionFromResponse(response, 347 throw _exceptionFromResponse(
363 "Cannot retrieve length of file", 348 response, "Cannot retrieve length of file", path);
364 path); 349 }
365 } 350 return response;
366 return response; 351 });
367 });
368 } 352 }
369 353
370
371 external static _lengthFromPath(String path); 354 external static _lengthFromPath(String path);
372 355
373 int lengthSync() { 356 int lengthSync() {
374 var result = _lengthFromPath(path); 357 var result = _lengthFromPath(path);
375 throwIfError(result, "Cannot retrieve length of file", path); 358 throwIfError(result, "Cannot retrieve length of file", path);
376 return result; 359 return result;
377 } 360 }
378 361
379 Future<DateTime> lastAccessed() { 362 Future<DateTime> lastAccessed() {
380 return _IOService._dispatch(_FILE_LAST_ACCESSED, [path]).then((response) { 363 return _IOService._dispatch(_FILE_LAST_ACCESSED, [path]).then((response) {
381 if (_isErrorResponse(response)) { 364 if (_isErrorResponse(response)) {
382 throw _exceptionFromResponse(response, 365 throw _exceptionFromResponse(
383 "Cannot retrieve access time", 366 response, "Cannot retrieve access time", path);
384 path);
385 } 367 }
386 return new DateTime.fromMillisecondsSinceEpoch(response); 368 return new DateTime.fromMillisecondsSinceEpoch(response);
387 }); 369 });
388 } 370 }
389 371
390 external static _lastAccessed(String path); 372 external static _lastAccessed(String path);
391 373
392 DateTime lastAccessedSync() { 374 DateTime lastAccessedSync() {
393 var ms = _lastAccessed(path); 375 var ms = _lastAccessed(path);
394 throwIfError(ms, "Cannot retrieve access time", path); 376 throwIfError(ms, "Cannot retrieve access time", path);
395 return new DateTime.fromMillisecondsSinceEpoch(ms); 377 return new DateTime.fromMillisecondsSinceEpoch(ms);
396 } 378 }
397 379
398 Future setLastAccessed(DateTime time) { 380 Future setLastAccessed(DateTime time) {
399 int millis = time.millisecondsSinceEpoch; 381 int millis = time.millisecondsSinceEpoch;
400 return _IOService._dispatch(_FILE_SET_LAST_ACCESSED, [path, millis]) 382 return _IOService
401 .then((response) { 383 ._dispatch(_FILE_SET_LAST_ACCESSED, [path, millis]).then((response) {
402 if (_isErrorResponse(response)) { 384 if (_isErrorResponse(response)) {
403 throw _exceptionFromResponse(response, 385 throw _exceptionFromResponse(response, "Cannot set access time", path);
404 "Cannot set access time",
405 path);
406 } 386 }
407 return null; 387 return null;
408 }); 388 });
409 } 389 }
410 390
411 external static _setLastAccessed(String path, int millis); 391 external static _setLastAccessed(String path, int millis);
412 392
413 void setLastAccessedSync(DateTime time) { 393 void setLastAccessedSync(DateTime time) {
414 int millis = time.millisecondsSinceEpoch; 394 int millis = time.millisecondsSinceEpoch;
415 var result = _setLastAccessed(path, millis); 395 var result = _setLastAccessed(path, millis);
416 if (result is OSError) { 396 if (result is OSError) {
417 throw new FileSystemException("Failed to set file access time", 397 throw new FileSystemException(
418 path, result); 398 "Failed to set file access time", path, result);
419 } 399 }
420 } 400 }
421 401
422 Future<DateTime> lastModified() { 402 Future<DateTime> lastModified() {
423 return _IOService._dispatch(_FILE_LAST_MODIFIED, [path]).then((response) { 403 return _IOService._dispatch(_FILE_LAST_MODIFIED, [path]).then((response) {
424 if (_isErrorResponse(response)) { 404 if (_isErrorResponse(response)) {
425 throw _exceptionFromResponse(response, 405 throw _exceptionFromResponse(
426 "Cannot retrieve modification time", 406 response, "Cannot retrieve modification time", path);
427 path);
428 } 407 }
429 return new DateTime.fromMillisecondsSinceEpoch(response); 408 return new DateTime.fromMillisecondsSinceEpoch(response);
430 }); 409 });
431 } 410 }
432 411
433 external static _lastModified(String path); 412 external static _lastModified(String path);
434 413
435 DateTime lastModifiedSync() { 414 DateTime lastModifiedSync() {
436 var ms = _lastModified(path); 415 var ms = _lastModified(path);
437 throwIfError(ms, "Cannot retrieve modification time", path); 416 throwIfError(ms, "Cannot retrieve modification time", path);
438 return new DateTime.fromMillisecondsSinceEpoch(ms); 417 return new DateTime.fromMillisecondsSinceEpoch(ms);
439 } 418 }
440 419
441 Future setLastModified(DateTime time) { 420 Future setLastModified(DateTime time) {
442 int millis = time.millisecondsSinceEpoch; 421 int millis = time.millisecondsSinceEpoch;
443 return _IOService._dispatch(_FILE_SET_LAST_MODIFIED, [path, millis]) 422 return _IOService
444 .then((response) { 423 ._dispatch(_FILE_SET_LAST_MODIFIED, [path, millis]).then((response) {
445 if (_isErrorResponse(response)) { 424 if (_isErrorResponse(response)) {
446 throw _exceptionFromResponse(response, 425 throw _exceptionFromResponse(
447 "Cannot set modification time", 426 response, "Cannot set modification time", path);
448 path);
449 } 427 }
450 return null; 428 return null;
451 }); 429 });
452 } 430 }
453 431
454 external static _setLastModified(String path, int millis); 432 external static _setLastModified(String path, int millis);
455 433
456 void setLastModifiedSync(DateTime time) { 434 void setLastModifiedSync(DateTime time) {
457 int millis = time.millisecondsSinceEpoch; 435 int millis = time.millisecondsSinceEpoch;
458 var result = _setLastModified(path, millis); 436 var result = _setLastModified(path, millis);
459 if (result is OSError) { 437 if (result is OSError) {
460 throw new FileSystemException("Failed to set file modification time", 438 throw new FileSystemException(
461 path, result); 439 "Failed to set file modification time", path, result);
462 } 440 }
463 } 441 }
464 442
465 external static _open(String path, int mode); 443 external static _open(String path, int mode);
466 444
467 RandomAccessFile openSync({FileMode mode: FileMode.READ}) { 445 RandomAccessFile openSync({FileMode mode: FileMode.READ}) {
468 if (mode != FileMode.READ && 446 if (mode != FileMode.READ &&
469 mode != FileMode.WRITE && 447 mode != FileMode.WRITE &&
470 mode != FileMode.APPEND && 448 mode != FileMode.APPEND &&
471 mode != FileMode.WRITE_ONLY && 449 mode != FileMode.WRITE_ONLY &&
(...skipping 12 matching lines...) Expand all
484 if (id == 0) { 462 if (id == 0) {
485 throw new FileSystemException("Cannot open stdio file for: $fd"); 463 throw new FileSystemException("Cannot open stdio file for: $fd");
486 } 464 }
487 return new _RandomAccessFile(id, ""); 465 return new _RandomAccessFile(id, "");
488 } 466 }
489 467
490 Stream<List<int>> openRead([int start, int end]) { 468 Stream<List<int>> openRead([int start, int end]) {
491 return new _FileStream(path, start, end); 469 return new _FileStream(path, start, end);
492 } 470 }
493 471
494 IOSink openWrite({FileMode mode: FileMode.WRITE, 472 IOSink openWrite({FileMode mode: FileMode.WRITE, Encoding encoding: UTF8}) {
495 Encoding encoding: UTF8}) {
496 if (mode != FileMode.WRITE && 473 if (mode != FileMode.WRITE &&
497 mode != FileMode.APPEND && 474 mode != FileMode.APPEND &&
498 mode != FileMode.WRITE_ONLY && 475 mode != FileMode.WRITE_ONLY &&
499 mode != FileMode.WRITE_ONLY_APPEND) { 476 mode != FileMode.WRITE_ONLY_APPEND) {
500 throw new ArgumentError('Invalid file mode for this operation'); 477 throw new ArgumentError('Invalid file mode for this operation');
501 } 478 }
502 var consumer = new _FileStreamConsumer(this, mode); 479 var consumer = new _FileStreamConsumer(this, mode);
503 return new IOSink(consumer, encoding: encoding); 480 return new IOSink(consumer, encoding: encoding);
504 } 481 }
505 482
506 Future<List<int>> readAsBytes() { 483 Future<List<int>> readAsBytes() {
507 Future<List<int>> readDataChunked(RandomAccessFile file) { 484 Future<List<int>> readDataChunked(RandomAccessFile file) {
508 var builder = new BytesBuilder(copy: false); 485 var builder = new BytesBuilder(copy: false);
509 var completer = new Completer<List<int>>(); 486 var completer = new Completer<List<int>>();
510 void read() { 487 void read() {
511 file.read(_BLOCK_SIZE).then((data) { 488 file.read(_BLOCK_SIZE).then((data) {
512 if (data.length > 0) { 489 if (data.length > 0) {
513 builder.add(data); 490 builder.add(data);
514 read(); 491 read();
515 } else { 492 } else {
516 completer.complete(builder.takeBytes()); 493 completer.complete(builder.takeBytes());
517 } 494 }
518 }, onError: completer.completeError); 495 }, onError: completer.completeError);
519 } 496 }
497
520 read(); 498 read();
521 return completer.future; 499 return completer.future;
522 } 500 }
523 501
524 return open().then((file) { 502 return open().then((file) {
525 return file.length().then((length) { 503 return file.length().then((length) {
526 if (length == 0) { 504 if (length == 0) {
527 // May be character device, try to read it in chunks. 505 // May be character device, try to read it in chunks.
528 return readDataChunked(file); 506 return readDataChunked(file);
529 } 507 }
(...skipping 27 matching lines...) Expand all
557 String _tryDecode(List<int> bytes, Encoding encoding) { 535 String _tryDecode(List<int> bytes, Encoding encoding) {
558 try { 536 try {
559 return encoding.decode(bytes); 537 return encoding.decode(bytes);
560 } catch (_) { 538 } catch (_) {
561 throw new FileSystemException( 539 throw new FileSystemException(
562 "Failed to decode data using encoding '${encoding.name}'", path); 540 "Failed to decode data using encoding '${encoding.name}'", path);
563 } 541 }
564 } 542 }
565 543
566 Future<String> readAsString({Encoding encoding: UTF8}) => 544 Future<String> readAsString({Encoding encoding: UTF8}) =>
567 readAsBytes().then((bytes) => _tryDecode(bytes, encoding)); 545 readAsBytes().then((bytes) => _tryDecode(bytes, encoding));
568 546
569 String readAsStringSync({Encoding encoding: UTF8}) => 547 String readAsStringSync({Encoding encoding: UTF8}) =>
570 _tryDecode(readAsBytesSync(), encoding); 548 _tryDecode(readAsBytesSync(), encoding);
571 549
572 Future<List<String>> readAsLines({Encoding encoding: UTF8}) => 550 Future<List<String>> readAsLines({Encoding encoding: UTF8}) =>
573 readAsString(encoding: encoding).then(const LineSplitter().convert); 551 readAsString(encoding: encoding).then(const LineSplitter().convert);
574 552
575 List<String> readAsLinesSync({Encoding encoding: UTF8}) => 553 List<String> readAsLinesSync({Encoding encoding: UTF8}) =>
576 const LineSplitter().convert(readAsStringSync(encoding: encoding)); 554 const LineSplitter().convert(readAsStringSync(encoding: encoding));
577 555
578 Future<File> writeAsBytes(List<int> bytes, 556 Future<File> writeAsBytes(List<int> bytes,
579 {FileMode mode: FileMode.WRITE, 557 {FileMode mode: FileMode.WRITE, bool flush: false}) {
580 bool flush: false}) {
581 return open(mode: mode).then((file) { 558 return open(mode: mode).then((file) {
582 return file.writeFrom(bytes, 0, bytes.length) 559 return file.writeFrom(bytes, 0, bytes.length).then((_) {
583 .then((_) { 560 if (flush) return file.flush().then((_) => this);
584 if (flush) return file.flush().then((_) => this); 561 return this;
585 return this; 562 }).whenComplete(file.close);
586 })
587 .whenComplete(file.close);
588 }); 563 });
589 } 564 }
590 565
591 void writeAsBytesSync(List<int> bytes, 566 void writeAsBytesSync(List<int> bytes,
592 {FileMode mode: FileMode.WRITE, 567 {FileMode mode: FileMode.WRITE, bool flush: false}) {
593 bool flush: false}) {
594 RandomAccessFile opened = openSync(mode: mode); 568 RandomAccessFile opened = openSync(mode: mode);
595 try { 569 try {
596 opened.writeFromSync(bytes, 0, bytes.length); 570 opened.writeFromSync(bytes, 0, bytes.length);
597 if (flush) opened.flushSync(); 571 if (flush) opened.flushSync();
598 } finally { 572 } finally {
599 opened.closeSync(); 573 opened.closeSync();
600 } 574 }
601 } 575 }
602 576
603 Future<File> writeAsString(String contents, 577 Future<File> writeAsString(String contents,
604 {FileMode mode: FileMode.WRITE, 578 {FileMode mode: FileMode.WRITE,
605 Encoding encoding: UTF8, 579 Encoding encoding: UTF8,
606 bool flush: false}) { 580 bool flush: false}) {
607 try { 581 try {
608 return writeAsBytes(encoding.encode(contents), mode: mode, flush: flush); 582 return writeAsBytes(encoding.encode(contents), mode: mode, flush: flush);
609 } catch (e) { 583 } catch (e) {
610 return new Future.error(e); 584 return new Future.error(e);
611 } 585 }
612 } 586 }
613 587
614 void writeAsStringSync(String contents, 588 void writeAsStringSync(String contents,
615 {FileMode mode: FileMode.WRITE, 589 {FileMode mode: FileMode.WRITE,
616 Encoding encoding: UTF8, 590 Encoding encoding: UTF8,
617 bool flush: false}) { 591 bool flush: false}) {
618 writeAsBytesSync(encoding.encode(contents), mode: mode, flush: flush); 592 writeAsBytesSync(encoding.encode(contents), mode: mode, flush: flush);
619 } 593 }
620 594
621 String toString() => "File: '$path'"; 595 String toString() => "File: '$path'";
622 596
623 static throwIfError(Object result, String msg, String path) { 597 static throwIfError(Object result, String msg, String path) {
624 if (result is OSError) { 598 if (result is OSError) {
625 throw new FileSystemException(msg, path, result); 599 throw new FileSystemException(msg, path, result);
626 } 600 }
627 } 601 }
(...skipping 11 matching lines...) Expand all
639 writeFrom(List<int> buffer, int start, int end); 613 writeFrom(List<int> buffer, int start, int end);
640 position(); 614 position();
641 setPosition(int position); 615 setPosition(int position);
642 truncate(int length); 616 truncate(int length);
643 length(); 617 length();
644 flush(); 618 flush();
645 lock(int lock, int start, int end); 619 lock(int lock, int start, int end);
646 setTranslation(int translation); 620 setTranslation(int translation);
647 } 621 }
648 622
649
650 /** 623 /**
651 * The translation mode of a File. 624 * The translation mode of a File.
652 * 625 *
653 * Whether the data written to a file should be interpreted as text 626 * Whether the data written to a file should be interpreted as text
654 * or binary data. This distinction is only meaningful on platforms that 627 * or binary data. This distinction is only meaningful on platforms that
655 * recognize a difference, in particular on Windows. 628 * recognize a difference, in particular on Windows.
656 */ 629 */
657 enum _FileTranslation { 630 enum _FileTranslation {
658 /// Data should be interpreted as text. 631 /// Data should be interpreted as text.
659 text, 632 text,
633
660 /// Data should be interpreted as binary data. 634 /// Data should be interpreted as binary data.
661 binary, 635 binary,
662 } 636 }
663 637
664
665 class _RandomAccessFile implements RandomAccessFile { 638 class _RandomAccessFile implements RandomAccessFile {
666 static bool _connectedResourceHandler = false; 639 static bool _connectedResourceHandler = false;
667 640
668 final String path; 641 final String path;
669 642
670 bool _asyncDispatched = false; 643 bool _asyncDispatched = false;
671 SendPort _fileService; 644 SendPort _fileService;
672 645
673 _FileResourceInfo _resourceInfo; 646 _FileResourceInfo _resourceInfo;
674 _RandomAccessFileOps _ops; 647 _RandomAccessFileOps _ops;
(...skipping 12 matching lines...) Expand all
687 _FileResourceInfo.FileClosed(_resourceInfo); 660 _FileResourceInfo.FileClosed(_resourceInfo);
688 } 661 }
689 } 662 }
690 663
691 _maybeConnectHandler() { 664 _maybeConnectHandler() {
692 if (!_connectedResourceHandler) { 665 if (!_connectedResourceHandler) {
693 // TODO(ricow): We probably need to set these in some initialization code. 666 // TODO(ricow): We probably need to set these in some initialization code.
694 // We need to make sure that these are always available from the 667 // We need to make sure that these are always available from the
695 // observatory even if no files (or sockets for the socket ones) are 668 // observatory even if no files (or sockets for the socket ones) are
696 // open. 669 // open.
697 registerExtension('ext.dart.io.getOpenFiles', 670 registerExtension(
698 _FileResourceInfo.getOpenFiles); 671 'ext.dart.io.getOpenFiles', _FileResourceInfo.getOpenFiles);
699 registerExtension('ext.dart.io.getFileByID', 672 registerExtension(
700 _FileResourceInfo.getFileInfoMapByID); 673 'ext.dart.io.getFileByID', _FileResourceInfo.getFileInfoMapByID);
701 _connectedResourceHandler = true; 674 _connectedResourceHandler = true;
702 } 675 }
703 } 676 }
704 677
705 Future<RandomAccessFile> close() { 678 Future<RandomAccessFile> close() {
706 return _dispatch(_FILE_CLOSE, [null], markClosed: true).then((result) { 679 return _dispatch(_FILE_CLOSE, [null], markClosed: true).then((result) {
707 if (result != -1) { 680 if (result != -1) {
708 closed = closed || (result == 0); 681 closed = closed || (result == 0);
709 _maybePerformCleanup(); 682 _maybePerformCleanup();
710 return this; 683 return this;
(...skipping 27 matching lines...) Expand all
738 _checkAvailable(); 711 _checkAvailable();
739 var result = _ops.readByte(); 712 var result = _ops.readByte();
740 if (result is OSError) { 713 if (result is OSError) {
741 throw new FileSystemException("readByte failed", path, result); 714 throw new FileSystemException("readByte failed", path, result);
742 } 715 }
743 _resourceInfo.addRead(1); 716 _resourceInfo.addRead(1);
744 return result; 717 return result;
745 } 718 }
746 719
747 Future<List<int>> read(int bytes) { 720 Future<List<int>> read(int bytes) {
748 if (bytes is !int) { 721 if (bytes is! int) {
749 throw new ArgumentError(bytes); 722 throw new ArgumentError(bytes);
750 } 723 }
751 return _dispatch(_FILE_READ, [null, bytes]).then((response) { 724 return _dispatch(_FILE_READ, [null, bytes]).then((response) {
752 if (_isErrorResponse(response)) { 725 if (_isErrorResponse(response)) {
753 throw _exceptionFromResponse(response, "read failed", path); 726 throw _exceptionFromResponse(response, "read failed", path);
754 } 727 }
755 _resourceInfo.addRead(response[1].length); 728 _resourceInfo.addRead(response[1].length);
756 return response[1] as Object/*=List<int>*/; 729 return response[1] as Object/*=List<int>*/;
757 }); 730 });
758 } 731 }
759 732
760 List<int> readSync(int bytes) { 733 List<int> readSync(int bytes) {
761 _checkAvailable(); 734 _checkAvailable();
762 if (bytes is !int) { 735 if (bytes is! int) {
763 throw new ArgumentError(bytes); 736 throw new ArgumentError(bytes);
764 } 737 }
765 var result = _ops.read(bytes); 738 var result = _ops.read(bytes);
766 if (result is OSError) { 739 if (result is OSError) {
767 throw new FileSystemException("readSync failed", path, result); 740 throw new FileSystemException("readSync failed", path, result);
768 } 741 }
769 _resourceInfo.addRead(result.length); 742 _resourceInfo.addRead(result.length);
770 return result as Object/*=List<int>*/; 743 return result as Object/*=List<int>*/;
771 } 744 }
772 745
773 Future<int> readInto(List<int> buffer, [int start = 0, int end]) { 746 Future<int> readInto(List<int> buffer, [int start = 0, int end]) {
774 if ((buffer is !List) || 747 if ((buffer is! List) ||
775 ((start != null) && (start is !int)) || 748 ((start != null) && (start is! int)) ||
776 ((end != null) && (end is !int))) { 749 ((end != null) && (end is! int))) {
777 throw new ArgumentError(); 750 throw new ArgumentError();
778 } 751 }
779 end = RangeError.checkValidRange(start, end, buffer.length); 752 end = RangeError.checkValidRange(start, end, buffer.length);
780 if (end == start) { 753 if (end == start) {
781 return new Future.value(0); 754 return new Future.value(0);
782 } 755 }
783 int length = end - start; 756 int length = end - start;
784 return _dispatch(_FILE_READ_INTO, [null, length]).then((response) { 757 return _dispatch(_FILE_READ_INTO, [null, length]).then((response) {
785 if (_isErrorResponse(response)) { 758 if (_isErrorResponse(response)) {
786 throw _exceptionFromResponse(response, "readInto failed", path); 759 throw _exceptionFromResponse(response, "readInto failed", path);
787 } 760 }
788 var read = response[1]; 761 var read = response[1];
789 var data = response[2] as Object/*=List<int>*/; 762 var data = response[2] as Object/*=List<int>*/;
790 buffer.setRange(start, start + read, data); 763 buffer.setRange(start, start + read, data);
791 _resourceInfo.addRead(read); 764 _resourceInfo.addRead(read);
792 return read; 765 return read;
793 }); 766 });
794 } 767 }
795 768
796 int readIntoSync(List<int> buffer, [int start = 0, int end]) { 769 int readIntoSync(List<int> buffer, [int start = 0, int end]) {
797 _checkAvailable(); 770 _checkAvailable();
798 if ((buffer is !List) || 771 if ((buffer is! List) ||
799 ((start != null) && (start is !int)) || 772 ((start != null) && (start is! int)) ||
800 ((end != null) && (end is !int))) { 773 ((end != null) && (end is! int))) {
801 throw new ArgumentError(); 774 throw new ArgumentError();
802 } 775 }
803 end = RangeError.checkValidRange(start, end, buffer.length); 776 end = RangeError.checkValidRange(start, end, buffer.length);
804 if (end == start) { 777 if (end == start) {
805 return 0; 778 return 0;
806 } 779 }
807 var result = _ops.readInto(buffer, start, end); 780 var result = _ops.readInto(buffer, start, end);
808 if (result is OSError) { 781 if (result is OSError) {
809 throw new FileSystemException("readInto failed", path, result); 782 throw new FileSystemException("readInto failed", path, result);
810 } 783 }
811 _resourceInfo.addRead(result); 784 _resourceInfo.addRead(result);
812 return result; 785 return result;
813 } 786 }
814 787
815 Future<RandomAccessFile> writeByte(int value) { 788 Future<RandomAccessFile> writeByte(int value) {
816 if (value is !int) { 789 if (value is! int) {
817 throw new ArgumentError(value); 790 throw new ArgumentError(value);
818 } 791 }
819 return _dispatch(_FILE_WRITE_BYTE, [null, value]).then((response) { 792 return _dispatch(_FILE_WRITE_BYTE, [null, value]).then((response) {
820 if (_isErrorResponse(response)) { 793 if (_isErrorResponse(response)) {
821 throw _exceptionFromResponse(response, "writeByte failed", path); 794 throw _exceptionFromResponse(response, "writeByte failed", path);
822 } 795 }
823 _resourceInfo.addWrite(1); 796 _resourceInfo.addWrite(1);
824 return this; 797 return this;
825 }); 798 });
826 } 799 }
827 800
828 int writeByteSync(int value) { 801 int writeByteSync(int value) {
829 _checkAvailable(); 802 _checkAvailable();
830 if (value is !int) { 803 if (value is! int) {
831 throw new ArgumentError(value); 804 throw new ArgumentError(value);
832 } 805 }
833 var result = _ops.writeByte(value); 806 var result = _ops.writeByte(value);
834 if (result is OSError) { 807 if (result is OSError) {
835 throw new FileSystemException("writeByte failed", path, result); 808 throw new FileSystemException("writeByte failed", path, result);
836 } 809 }
837 _resourceInfo.addWrite(1); 810 _resourceInfo.addWrite(1);
838 return result; 811 return result;
839 } 812 }
840 813
841 Future<RandomAccessFile> writeFrom( 814 Future<RandomAccessFile> writeFrom(List<int> buffer,
842 List<int> buffer, [int start = 0, int end]) { 815 [int start = 0, int end]) {
843 if ((buffer is !List) || 816 if ((buffer is! List) ||
844 ((start != null) && (start is !int)) || 817 ((start != null) && (start is! int)) ||
845 ((end != null) && (end is !int))) { 818 ((end != null) && (end is! int))) {
846 throw new ArgumentError("Invalid arguments to writeFrom"); 819 throw new ArgumentError("Invalid arguments to writeFrom");
847 } 820 }
848 end = RangeError.checkValidRange(start, end, buffer.length); 821 end = RangeError.checkValidRange(start, end, buffer.length);
849 if (end == start) { 822 if (end == start) {
850 return new Future.value(this); 823 return new Future.value(this);
851 } 824 }
852 _BufferAndStart result; 825 _BufferAndStart result;
853 try { 826 try {
854 result = _ensureFastAndSerializableByteData(buffer, start, end); 827 result = _ensureFastAndSerializableByteData(buffer, start, end);
855 } catch (e) { 828 } catch (e) {
856 return new Future.error(e); 829 return new Future.error(e);
857 } 830 }
858 831
859 List request = new List(4); 832 List request = new List(4);
860 request[0] = null; 833 request[0] = null;
861 request[1] = result.buffer; 834 request[1] = result.buffer;
862 request[2] = result.start; 835 request[2] = result.start;
863 request[3] = end - (start - result.start); 836 request[3] = end - (start - result.start);
864 return _dispatch(_FILE_WRITE_FROM, request).then((response) { 837 return _dispatch(_FILE_WRITE_FROM, request).then((response) {
865 if (_isErrorResponse(response)) { 838 if (_isErrorResponse(response)) {
866 throw _exceptionFromResponse(response, "writeFrom failed", path); 839 throw _exceptionFromResponse(response, "writeFrom failed", path);
867 } 840 }
868 _resourceInfo.addWrite(end - (start - result.start)); 841 _resourceInfo.addWrite(end - (start - result.start));
869 return this; 842 return this;
870 }); 843 });
871 } 844 }
872 845
873 void writeFromSync(List<int> buffer, [int start = 0, int end]) { 846 void writeFromSync(List<int> buffer, [int start = 0, int end]) {
874 _checkAvailable(); 847 _checkAvailable();
875 if ((buffer is !List) || 848 if ((buffer is! List) ||
876 ((start != null) && (start is !int)) || 849 ((start != null) && (start is! int)) ||
877 ((end != null) && (end is !int))) { 850 ((end != null) && (end is! int))) {
878 throw new ArgumentError("Invalid arguments to writeFromSync"); 851 throw new ArgumentError("Invalid arguments to writeFromSync");
879 } 852 }
880 end = RangeError.checkValidRange(start, end, buffer.length); 853 end = RangeError.checkValidRange(start, end, buffer.length);
881 if (end == start) { 854 if (end == start) {
882 return; 855 return;
883 } 856 }
884 _BufferAndStart bufferAndStart = 857 _BufferAndStart bufferAndStart =
885 _ensureFastAndSerializableByteData(buffer, start, end); 858 _ensureFastAndSerializableByteData(buffer, start, end);
886 var result = _ops.writeFrom(bufferAndStart.buffer, 859 var result = _ops.writeFrom(bufferAndStart.buffer, bufferAndStart.start,
887 bufferAndStart.start, 860 end - (start - bufferAndStart.start));
888 end - (start - bufferAndStart.start));
889 if (result is OSError) { 861 if (result is OSError) {
890 throw new FileSystemException("writeFrom failed", path, result); 862 throw new FileSystemException("writeFrom failed", path, result);
891 } 863 }
892 _resourceInfo.addWrite(end - (start - bufferAndStart.start)); 864 _resourceInfo.addWrite(end - (start - bufferAndStart.start));
893 } 865 }
894 866
895 Future<RandomAccessFile> writeString(String string, 867 Future<RandomAccessFile> writeString(String string,
896 {Encoding encoding: UTF8}) { 868 {Encoding encoding: UTF8}) {
897 if (encoding is! Encoding) { 869 if (encoding is! Encoding) {
898 throw new ArgumentError(encoding); 870 throw new ArgumentError(encoding);
899 } 871 }
900 var data = encoding.encode(string); 872 var data = encoding.encode(string);
901 return writeFrom(data, 0, data.length); 873 return writeFrom(data, 0, data.length);
902 } 874 }
903 875
904 void writeStringSync(String string, {Encoding encoding: UTF8}) { 876 void writeStringSync(String string, {Encoding encoding: UTF8}) {
905 if (encoding is! Encoding) { 877 if (encoding is! Encoding) {
906 throw new ArgumentError(encoding); 878 throw new ArgumentError(encoding);
(...skipping 14 matching lines...) Expand all
921 int positionSync() { 893 int positionSync() {
922 _checkAvailable(); 894 _checkAvailable();
923 var result = _ops.position(); 895 var result = _ops.position();
924 if (result is OSError) { 896 if (result is OSError) {
925 throw new FileSystemException("position failed", path, result); 897 throw new FileSystemException("position failed", path, result);
926 } 898 }
927 return result; 899 return result;
928 } 900 }
929 901
930 Future<RandomAccessFile> setPosition(int position) { 902 Future<RandomAccessFile> setPosition(int position) {
931 return _dispatch(_FILE_SET_POSITION, [null, position]) 903 return _dispatch(_FILE_SET_POSITION, [null, position]).then((response) {
932 .then((response) { 904 if (_isErrorResponse(response)) {
933 if (_isErrorResponse(response)) { 905 throw _exceptionFromResponse(response, "setPosition failed", path);
934 throw _exceptionFromResponse(response, "setPosition failed", path); 906 }
935 } 907 return this;
936 return this; 908 });
937 });
938 } 909 }
939 910
940 void setPositionSync(int position) { 911 void setPositionSync(int position) {
941 _checkAvailable(); 912 _checkAvailable();
942 var result = _ops.setPosition(position); 913 var result = _ops.setPosition(position);
943 if (result is OSError) { 914 if (result is OSError) {
944 throw new FileSystemException("setPosition failed", path, result); 915 throw new FileSystemException("setPosition failed", path, result);
945 } 916 }
946 } 917 }
947 918
(...skipping 28 matching lines...) Expand all
976 var result = _ops.length(); 947 var result = _ops.length();
977 if (result is OSError) { 948 if (result is OSError) {
978 throw new FileSystemException("length failed", path, result); 949 throw new FileSystemException("length failed", path, result);
979 } 950 }
980 return result; 951 return result;
981 } 952 }
982 953
983 Future<RandomAccessFile> flush() { 954 Future<RandomAccessFile> flush() {
984 return _dispatch(_FILE_FLUSH, [null]).then((response) { 955 return _dispatch(_FILE_FLUSH, [null]).then((response) {
985 if (_isErrorResponse(response)) { 956 if (_isErrorResponse(response)) {
986 throw _exceptionFromResponse(response, 957 throw _exceptionFromResponse(response, "flush failed", path);
987 "flush failed",
988 path);
989 } 958 }
990 return this; 959 return this;
991 }); 960 });
992 } 961 }
993 962
994 void flushSync() { 963 void flushSync() {
995 _checkAvailable(); 964 _checkAvailable();
996 var result = _ops.flush(); 965 var result = _ops.flush();
997 if (result is OSError) { 966 if (result is OSError) {
998 throw new FileSystemException("flush failed", path, result); 967 throw new FileSystemException("flush failed", path, result);
999 } 968 }
1000 } 969 }
1001 970
1002 static final int LOCK_UNLOCK = 0; 971 static final int LOCK_UNLOCK = 0;
1003 static final int LOCK_SHARED = 1; 972 static final int LOCK_SHARED = 1;
1004 static final int LOCK_EXCLUSIVE = 2; 973 static final int LOCK_EXCLUSIVE = 2;
1005 static final int LOCK_BLOCKING_SHARED = 3; 974 static final int LOCK_BLOCKING_SHARED = 3;
1006 static final int LOCK_BLOCKING_EXCLUSIVE = 4; 975 static final int LOCK_BLOCKING_EXCLUSIVE = 4;
1007 976
1008 int _fileLockValue(FileLock fl) { 977 int _fileLockValue(FileLock fl) {
1009 switch (fl) { 978 switch (fl) {
1010 case FileLock.SHARED: return LOCK_SHARED; 979 case FileLock.SHARED:
1011 case FileLock.EXCLUSIVE: return LOCK_EXCLUSIVE; 980 return LOCK_SHARED;
1012 case FileLock.BLOCKING_SHARED: return LOCK_BLOCKING_SHARED; 981 case FileLock.EXCLUSIVE:
1013 case FileLock.BLOCKING_EXCLUSIVE: return LOCK_BLOCKING_EXCLUSIVE; 982 return LOCK_EXCLUSIVE;
1014 default: return -1; 983 case FileLock.BLOCKING_SHARED:
984 return LOCK_BLOCKING_SHARED;
985 case FileLock.BLOCKING_EXCLUSIVE:
986 return LOCK_BLOCKING_EXCLUSIVE;
987 default:
988 return -1;
1015 } 989 }
1016 } 990 }
1017 991
1018 Future<RandomAccessFile> lock( 992 Future<RandomAccessFile> lock(
1019 [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end = -1]) { 993 [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end = -1]) {
1020 if ((mode is !FileLock) || (start is !int) || (end is !int)) { 994 if ((mode is! FileLock) || (start is! int) || (end is! int)) {
1021 throw new ArgumentError(); 995 throw new ArgumentError();
1022 } 996 }
1023 if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) { 997 if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) {
1024 throw new ArgumentError(); 998 throw new ArgumentError();
1025 } 999 }
1026 int lock = _fileLockValue(mode); 1000 int lock = _fileLockValue(mode);
1027 return _dispatch(_FILE_LOCK, [null, lock, start, end]) 1001 return _dispatch(_FILE_LOCK, [null, lock, start, end]).then((response) {
1028 .then((response) { 1002 if (_isErrorResponse(response)) {
1029 if (_isErrorResponse(response)) { 1003 throw _exceptionFromResponse(response, 'lock failed', path);
1030 throw _exceptionFromResponse(response, 'lock failed', path); 1004 }
1031 } 1005 return this;
1032 return this; 1006 });
1033 });
1034 } 1007 }
1035 1008
1036 Future<RandomAccessFile> unlock([int start = 0, int end = -1]) { 1009 Future<RandomAccessFile> unlock([int start = 0, int end = -1]) {
1037 if ((start is !int) || (end is !int)) { 1010 if ((start is! int) || (end is! int)) {
1038 throw new ArgumentError(); 1011 throw new ArgumentError();
1039 } 1012 }
1040 if (start == end) { 1013 if (start == end) {
1041 throw new ArgumentError(); 1014 throw new ArgumentError();
1042 } 1015 }
1043 return _dispatch(_FILE_LOCK, [null, LOCK_UNLOCK, start, end]) 1016 return _dispatch(_FILE_LOCK, [null, LOCK_UNLOCK, start, end])
1044 .then((response) { 1017 .then((response) {
1045 if (_isErrorResponse(response)) { 1018 if (_isErrorResponse(response)) {
1046 throw _exceptionFromResponse(response, 'unlock failed', path); 1019 throw _exceptionFromResponse(response, 'unlock failed', path);
1047 } 1020 }
1048 return this; 1021 return this;
1049 }); 1022 });
1050 } 1023 }
1051 1024
1052 void lockSync( 1025 void lockSync(
1053 [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end = -1]) { 1026 [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end = -1]) {
1054 _checkAvailable(); 1027 _checkAvailable();
1055 if ((mode is !FileLock) || (start is !int) || (end is !int)) { 1028 if ((mode is! FileLock) || (start is! int) || (end is! int)) {
1056 throw new ArgumentError(); 1029 throw new ArgumentError();
1057 } 1030 }
1058 if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) { 1031 if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) {
1059 throw new ArgumentError(); 1032 throw new ArgumentError();
1060 } 1033 }
1061 int lock = _fileLockValue(mode); 1034 int lock = _fileLockValue(mode);
1062 var result = _ops.lock(lock, start, end); 1035 var result = _ops.lock(lock, start, end);
1063 if (result is OSError) { 1036 if (result is OSError) {
1064 throw new FileSystemException('lock failed', path, result); 1037 throw new FileSystemException('lock failed', path, result);
1065 } 1038 }
1066 } 1039 }
1067 1040
1068 void unlockSync([int start = 0, int end = -1]) { 1041 void unlockSync([int start = 0, int end = -1]) {
1069 _checkAvailable(); 1042 _checkAvailable();
1070 if ((start is !int) || (end is !int)) { 1043 if ((start is! int) || (end is! int)) {
1071 throw new ArgumentError(); 1044 throw new ArgumentError();
1072 } 1045 }
1073 if (start == end) { 1046 if (start == end) {
1074 throw new ArgumentError(); 1047 throw new ArgumentError();
1075 } 1048 }
1076 var result = _ops.lock(LOCK_UNLOCK, start, end); 1049 var result = _ops.lock(LOCK_UNLOCK, start, end);
1077 if (result is OSError) { 1050 if (result is OSError) {
1078 throw new FileSystemException('unlock failed', path, result); 1051 throw new FileSystemException('unlock failed', path, result);
1079 } 1052 }
1080 } 1053 }
1081 1054
1082 _FileTranslation get translation => _translation; 1055 _FileTranslation get translation => _translation;
1083 1056
1084 void set translation(_FileTranslation translation) { 1057 void set translation(_FileTranslation translation) {
1085 if (_translation != translation) { 1058 if (_translation != translation) {
1086 _ops.setTranslation(translation.index); 1059 _ops.setTranslation(translation.index);
1087 _translation = translation; 1060 _translation = translation;
1088 } 1061 }
1089 } 1062 }
1090 1063
1091 bool closed = false; 1064 bool closed = false;
1092 1065
1093 // Calling this function will increase the reference count on the native 1066 // Calling this function will increase the reference count on the native
1094 // object that implements the file operations. It should only be called to 1067 // object that implements the file operations. It should only be called to
1095 // pass the pointer to the IO Service, which will decrement the reference 1068 // pass the pointer to the IO Service, which will decrement the reference
1096 // count when it is finished with it. 1069 // count when it is finished with it.
1097 int _pointer() => _ops.getPointer(); 1070 int _pointer() => _ops.getPointer();
1098 1071
1099 Future _dispatch(int request, List data, { bool markClosed: false }) { 1072 Future _dispatch(int request, List data, {bool markClosed: false}) {
1100 if (closed) { 1073 if (closed) {
1101 return new Future.error(new FileSystemException("File closed", path)); 1074 return new Future.error(new FileSystemException("File closed", path));
1102 } 1075 }
1103 if (_asyncDispatched) { 1076 if (_asyncDispatched) {
1104 var msg = "An async operation is currently pending"; 1077 var msg = "An async operation is currently pending";
1105 return new Future.error(new FileSystemException(msg, path)); 1078 return new Future.error(new FileSystemException(msg, path));
1106 } 1079 }
1107 if (markClosed) { 1080 if (markClosed) {
1108 // Set closed to true to ensure that no more async requests can be issued 1081 // Set closed to true to ensure that no more async requests can be issued
1109 // for this file. 1082 // for this file.
1110 closed = true; 1083 closed = true;
1111 } 1084 }
1112 _asyncDispatched = true; 1085 _asyncDispatched = true;
1113 data[0] = _pointer(); 1086 data[0] = _pointer();
1114 return _IOService._dispatch(request, data) 1087 return _IOService._dispatch(request, data).whenComplete(() {
1115 .whenComplete(() { 1088 _asyncDispatched = false;
1116 _asyncDispatched = false; 1089 });
1117 });
1118 } 1090 }
1119 1091
1120 void _checkAvailable() { 1092 void _checkAvailable() {
1121 if (_asyncDispatched) { 1093 if (_asyncDispatched) {
1122 throw new FileSystemException("An async operation is currently pending", 1094 throw new FileSystemException(
1123 path); 1095 "An async operation is currently pending", path);
1124 } 1096 }
1125 if (closed) { 1097 if (closed) {
1126 throw new FileSystemException("File closed", path); 1098 throw new FileSystemException("File closed", path);
1127 } 1099 }
1128 } 1100 }
1129 } 1101 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698