| 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 | 7 |
| 8 class _FileStream extends Stream<List<int>> { | 8 class _FileStream extends Stream<List<int>> { |
| 9 // Stream controller. | 9 // Stream controller. |
| 10 StreamController<List<int>> _controller; | 10 StreamController<List<int>> _controller; |
| 11 | 11 |
| 12 // Read the file in blocks of size 64k. | 12 // Read the file in blocks of size 64k. |
| 13 final int _blockSize = 64 * 1024; | 13 final int _blockSize = 64 * 1024; |
| 14 | 14 |
| 15 // Information about the underlying file. | 15 // Information about the underlying file. |
| 16 String _name; | 16 String _path; |
| 17 RandomAccessFile _openedFile; | 17 RandomAccessFile _openedFile; |
| 18 int _position; | 18 int _position; |
| 19 | 19 |
| 20 // Has the stream been paused or unsubscribed? | 20 // Has the stream been paused or unsubscribed? |
| 21 bool _paused = false; | 21 bool _paused = false; |
| 22 bool _unsubscribed = false; | 22 bool _unsubscribed = false; |
| 23 | 23 |
| 24 // Is there a read currently in progress? | 24 // Is there a read currently in progress? |
| 25 bool _readInProgress = false; | 25 bool _readInProgress = false; |
| 26 | 26 |
| 27 // Block read but not yet send because stream is paused. | 27 // Block read but not yet send because stream is paused. |
| 28 List<int> _currentBlock; | 28 List<int> _currentBlock; |
| 29 | 29 |
| 30 _FileStream(String this._name) : _position = 0 { | 30 _FileStream(String this._path) : _position = 0 { |
| 31 _setupController(); | 31 _setupController(); |
| 32 } | 32 } |
| 33 | 33 |
| 34 _FileStream.forStdin() : _position = 0 { | 34 _FileStream.forStdin() : _position = 0 { |
| 35 _setupController(); | 35 _setupController(); |
| 36 } | 36 } |
| 37 | 37 |
| 38 StreamSubscription<List<int>> listen(void onData(List<int> event), | 38 StreamSubscription<List<int>> listen(void onData(List<int> event), |
| 39 {void onError(AsyncError error), | 39 {void onError(AsyncError error), |
| 40 void onDone(), | 40 void onDone(), |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 if (!_unsubscribed) { | 96 if (!_unsubscribed) { |
| 97 _controller.signalError(e); | 97 _controller.signalError(e); |
| 98 _closeFile().then((_) { _controller.close(); }); | 98 _closeFile().then((_) { _controller.close(); }); |
| 99 _unsubscribed = true; | 99 _unsubscribed = true; |
| 100 } | 100 } |
| 101 }); | 101 }); |
| 102 } | 102 } |
| 103 | 103 |
| 104 void _start() { | 104 void _start() { |
| 105 Future<RandomAccessFile> openFuture; | 105 Future<RandomAccessFile> openFuture; |
| 106 if (_name != null) { | 106 if (_path != null) { |
| 107 openFuture = new File(_name).open(FileMode.READ); | 107 openFuture = new File(_path).open(FileMode.READ); |
| 108 } else { | 108 } else { |
| 109 openFuture = new Future.immediate(_File._openStdioSync(0)); | 109 openFuture = new Future.immediate(_File._openStdioSync(0)); |
| 110 } | 110 } |
| 111 openFuture | 111 openFuture |
| 112 .then((RandomAccessFile opened) { | 112 .then((RandomAccessFile opened) { |
| 113 _openedFile = opened; | 113 _openedFile = opened; |
| 114 _readBlock(); | 114 _readBlock(); |
| 115 }) | 115 }) |
| 116 .catchError((e) { | 116 .catchError((e) { |
| 117 _controller.signalError(e); | 117 _controller.signalError(e); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 const int _CREATE_REQUEST = 1; | 204 const int _CREATE_REQUEST = 1; |
| 205 const int _DELETE_REQUEST = 2; | 205 const int _DELETE_REQUEST = 2; |
| 206 const int _OPEN_REQUEST = 3; | 206 const int _OPEN_REQUEST = 3; |
| 207 const int _FULL_PATH_REQUEST = 4; | 207 const int _FULL_PATH_REQUEST = 4; |
| 208 const int _DIRECTORY_REQUEST = 5; | 208 const int _DIRECTORY_REQUEST = 5; |
| 209 const int _CLOSE_REQUEST = 6; | 209 const int _CLOSE_REQUEST = 6; |
| 210 const int _POSITION_REQUEST = 7; | 210 const int _POSITION_REQUEST = 7; |
| 211 const int _SET_POSITION_REQUEST = 8; | 211 const int _SET_POSITION_REQUEST = 8; |
| 212 const int _TRUNCATE_REQUEST = 9; | 212 const int _TRUNCATE_REQUEST = 9; |
| 213 const int _LENGTH_REQUEST = 10; | 213 const int _LENGTH_REQUEST = 10; |
| 214 const int _LENGTH_FROM_NAME_REQUEST = 11; | 214 const int _LENGTH_FROM_PATH_REQUEST = 11; |
| 215 const int _LAST_MODIFIED_REQUEST = 12; | 215 const int _LAST_MODIFIED_REQUEST = 12; |
| 216 const int _FLUSH_REQUEST = 13; | 216 const int _FLUSH_REQUEST = 13; |
| 217 const int _READ_BYTE_REQUEST = 14; | 217 const int _READ_BYTE_REQUEST = 14; |
| 218 const int _WRITE_BYTE_REQUEST = 15; | 218 const int _WRITE_BYTE_REQUEST = 15; |
| 219 const int _READ_REQUEST = 16; | 219 const int _READ_REQUEST = 16; |
| 220 const int _READ_LIST_REQUEST = 17; | 220 const int _READ_LIST_REQUEST = 17; |
| 221 const int _WRITE_LIST_REQUEST = 18; | 221 const int _WRITE_LIST_REQUEST = 18; |
| 222 | 222 |
| 223 // Base class for _File and _RandomAccessFile with shared functions. | 223 // Base class for _File and _RandomAccessFile with shared functions. |
| 224 class _FileBase { | 224 class _FileBase { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 246 // TODO(ager): The only reason for this class is that the patching | 246 // TODO(ager): The only reason for this class is that the patching |
| 247 // mechanism doesn't seem to like patching a private top level | 247 // mechanism doesn't seem to like patching a private top level |
| 248 // function. | 248 // function. |
| 249 class _FileUtils { | 249 class _FileUtils { |
| 250 external static SendPort _newServicePort(); | 250 external static SendPort _newServicePort(); |
| 251 } | 251 } |
| 252 | 252 |
| 253 // Class for encapsulating the native implementation of files. | 253 // Class for encapsulating the native implementation of files. |
| 254 class _File extends _FileBase implements File { | 254 class _File extends _FileBase implements File { |
| 255 // Constructor for file. | 255 // Constructor for file. |
| 256 _File(String this._name) { | 256 _File(String this._path) { |
| 257 if (_name is! String) { | 257 if (_path is! String) { |
| 258 throw new ArgumentError('${Error.safeToString(_name)} ' | 258 throw new ArgumentError('${Error.safeToString(_path)} ' |
| 259 'is not a String'); | 259 'is not a String'); |
| 260 } | 260 } |
| 261 } | 261 } |
| 262 | 262 |
| 263 // Constructor from Path for file. | 263 // Constructor from Path for file. |
| 264 _File.fromPath(Path path) : this(path.toNativePath()); | 264 _File.fromPath(Path path) : this(path.toNativePath()); |
| 265 | 265 |
| 266 Future<bool> exists() { | 266 Future<bool> exists() { |
| 267 _ensureFileService(); | 267 _ensureFileService(); |
| 268 List request = new List(2); | 268 List request = new List(2); |
| 269 request[0] = _EXISTS_REQUEST; | 269 request[0] = _EXISTS_REQUEST; |
| 270 request[1] = _name; | 270 request[1] = _path; |
| 271 return _fileService.call(request).then((response) { | 271 return _fileService.call(request).then((response) { |
| 272 if (_isErrorResponse(response)) { | 272 if (_isErrorResponse(response)) { |
| 273 throw _exceptionFromResponse(response, "Cannot open file '$_name'"); | 273 throw _exceptionFromResponse(response, "Cannot open file '$_path'"); |
| 274 } | 274 } |
| 275 return response; | 275 return response; |
| 276 }); | 276 }); |
| 277 } | 277 } |
| 278 | 278 |
| 279 external static _exists(String name); | 279 external static _exists(String path); |
| 280 | 280 |
| 281 bool existsSync() { | 281 bool existsSync() { |
| 282 var result = _exists(_name); | 282 var result = _exists(_path); |
| 283 throwIfError(result, "Cannot check existence of file '$_name'"); | 283 throwIfError(result, "Cannot check existence of file '$_path'"); |
| 284 return result; | 284 return result; |
| 285 } | 285 } |
| 286 | 286 |
| 287 Future<File> create() { | 287 Future<File> create() { |
| 288 _ensureFileService(); | 288 _ensureFileService(); |
| 289 List request = new List(2); | 289 List request = new List(2); |
| 290 request[0] = _CREATE_REQUEST; | 290 request[0] = _CREATE_REQUEST; |
| 291 request[1] = _name; | 291 request[1] = _path; |
| 292 return _fileService.call(request).then((response) { | 292 return _fileService.call(request).then((response) { |
| 293 if (_isErrorResponse(response)) { | 293 if (_isErrorResponse(response)) { |
| 294 throw _exceptionFromResponse(response, "Cannot create file '$_name'"); | 294 throw _exceptionFromResponse(response, "Cannot create file '$_path'"); |
| 295 } | 295 } |
| 296 return this; | 296 return this; |
| 297 }); | 297 }); |
| 298 } | 298 } |
| 299 | 299 |
| 300 external static _create(String name); | 300 external static _create(String path); |
| 301 | 301 |
| 302 void createSync() { | 302 void createSync() { |
| 303 var result = _create(_name); | 303 var result = _create(_path); |
| 304 throwIfError(result, "Cannot create file '$_name'"); | 304 throwIfError(result, "Cannot create file '$_path'"); |
| 305 } | 305 } |
| 306 | 306 |
| 307 Future<File> delete() { | 307 Future<File> delete() { |
| 308 _ensureFileService(); | 308 _ensureFileService(); |
| 309 List request = new List(2); | 309 List request = new List(2); |
| 310 request[0] = _DELETE_REQUEST; | 310 request[0] = _DELETE_REQUEST; |
| 311 request[1] = _name; | 311 request[1] = _path; |
| 312 return _fileService.call(request).then((response) { | 312 return _fileService.call(request).then((response) { |
| 313 if (_isErrorResponse(response)) { | 313 if (_isErrorResponse(response)) { |
| 314 throw _exceptionFromResponse(response, "Cannot delete file '$_name'"); | 314 throw _exceptionFromResponse(response, "Cannot delete file '$_path'"); |
| 315 } | 315 } |
| 316 return this; | 316 return this; |
| 317 }); | 317 }); |
| 318 } | 318 } |
| 319 | 319 |
| 320 external static _delete(String name); | 320 external static _delete(String path); |
| 321 | 321 |
| 322 void deleteSync() { | 322 void deleteSync() { |
| 323 var result = _delete(_name); | 323 var result = _delete(_path); |
| 324 throwIfError(result, "Cannot delete file '$_name'"); | 324 throwIfError(result, "Cannot delete file '$_path'"); |
| 325 } | 325 } |
| 326 | 326 |
| 327 Future<Directory> directory() { | 327 Future<Directory> directory() { |
| 328 _ensureFileService(); | 328 _ensureFileService(); |
| 329 List request = new List(2); | 329 List request = new List(2); |
| 330 request[0] = _DIRECTORY_REQUEST; | 330 request[0] = _DIRECTORY_REQUEST; |
| 331 request[1] = _name; | 331 request[1] = _path; |
| 332 return _fileService.call(request).then((response) { | 332 return _fileService.call(request).then((response) { |
| 333 if (_isErrorResponse(response)) { | 333 if (_isErrorResponse(response)) { |
| 334 throw _exceptionFromResponse(response, | 334 throw _exceptionFromResponse(response, |
| 335 "Cannot retrieve directory for " | 335 "Cannot retrieve directory for " |
| 336 "file '$_name'"); | 336 "file '$_path'"); |
| 337 } | 337 } |
| 338 return new Directory(response); | 338 return new Directory(response); |
| 339 }); | 339 }); |
| 340 } | 340 } |
| 341 | 341 |
| 342 external static _directory(String name); | 342 external static _directory(String path); |
| 343 | 343 |
| 344 Directory directorySync() { | 344 Directory directorySync() { |
| 345 var result = _directory(name); | 345 var result = _directory(path); |
| 346 throwIfError(result, "Cannot retrieve directory for file '$_name'"); | 346 throwIfError(result, "Cannot retrieve directory for file '$_path'"); |
| 347 return new Directory(result); | 347 return new Directory(result); |
| 348 } | 348 } |
| 349 | 349 |
| 350 Future<RandomAccessFile> open([FileMode mode = FileMode.READ]) { | 350 Future<RandomAccessFile> open([FileMode mode = FileMode.READ]) { |
| 351 _ensureFileService(); | 351 _ensureFileService(); |
| 352 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); | 352 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
| 353 if (mode != FileMode.READ && | 353 if (mode != FileMode.READ && |
| 354 mode != FileMode.WRITE && | 354 mode != FileMode.WRITE && |
| 355 mode != FileMode.APPEND) { | 355 mode != FileMode.APPEND) { |
| 356 Timer.run(() { | 356 Timer.run(() { |
| 357 completer.completeError(new ArgumentError()); | 357 completer.completeError(new ArgumentError()); |
| 358 }); | 358 }); |
| 359 return completer.future; | 359 return completer.future; |
| 360 } | 360 } |
| 361 List request = new List(3); | 361 List request = new List(3); |
| 362 request[0] = _OPEN_REQUEST; | 362 request[0] = _OPEN_REQUEST; |
| 363 request[1] = _name; | 363 request[1] = _path; |
| 364 request[2] = mode._mode; // Direct int value for serialization. | 364 request[2] = mode._mode; // Direct int value for serialization. |
| 365 return _fileService.call(request).then((response) { | 365 return _fileService.call(request).then((response) { |
| 366 if (_isErrorResponse(response)) { | 366 if (_isErrorResponse(response)) { |
| 367 throw _exceptionFromResponse(response, "Cannot open file '$_name'"); | 367 throw _exceptionFromResponse(response, "Cannot open file '$_path'"); |
| 368 } | 368 } |
| 369 return new _RandomAccessFile(response, _name); | 369 return new _RandomAccessFile(response, _path); |
| 370 }); | 370 }); |
| 371 } | 371 } |
| 372 | 372 |
| 373 Future<int> length() { | 373 Future<int> length() { |
| 374 _ensureFileService(); | 374 _ensureFileService(); |
| 375 List request = new List(2); | 375 List request = new List(2); |
| 376 request[0] = _LENGTH_FROM_NAME_REQUEST; | 376 request[0] = _LENGTH_FROM_PATH_REQUEST; |
| 377 request[1] = _name; | 377 request[1] = _path; |
| 378 return _fileService.call(request).then((response) { | 378 return _fileService.call(request).then((response) { |
| 379 if (_isErrorResponse(response)) { | 379 if (_isErrorResponse(response)) { |
| 380 throw _exceptionFromResponse(response, | 380 throw _exceptionFromResponse(response, |
| 381 "Cannot retrieve length of " | 381 "Cannot retrieve length of " |
| 382 "file '$_name'"); | 382 "file '$_path'"); |
| 383 } | 383 } |
| 384 return response; | 384 return response; |
| 385 }); | 385 }); |
| 386 } | 386 } |
| 387 | 387 |
| 388 | 388 |
| 389 external static _lengthFromName(String name); | 389 external static _lengthFromPath(String path); |
| 390 | 390 |
| 391 int lengthSync() { | 391 int lengthSync() { |
| 392 var result = _lengthFromName(_name); | 392 var result = _lengthFromPath(_path); |
| 393 throwIfError(result, "Cannot retrieve length of file '$_name'"); | 393 throwIfError(result, "Cannot retrieve length of file '$_path'"); |
| 394 return result; | 394 return result; |
| 395 } | 395 } |
| 396 | 396 |
| 397 Future<DateTime> lastModified() { | 397 Future<DateTime> lastModified() { |
| 398 _ensureFileService(); | 398 _ensureFileService(); |
| 399 List request = new List(2); | 399 List request = new List(2); |
| 400 request[0] = _LAST_MODIFIED_REQUEST; | 400 request[0] = _LAST_MODIFIED_REQUEST; |
| 401 request[1] = _name; | 401 request[1] = _path; |
| 402 return _fileService.call(request).then((response) { | 402 return _fileService.call(request).then((response) { |
| 403 if (_isErrorResponse(response)) { | 403 if (_isErrorResponse(response)) { |
| 404 throw _exceptionFromResponse(response, | 404 throw _exceptionFromResponse(response, |
| 405 "Cannot retrieve modification time " | 405 "Cannot retrieve modification time " |
| 406 "for file '$_name'"); | 406 "for file '$_path'"); |
| 407 } | 407 } |
| 408 return new DateTime.fromMillisecondsSinceEpoch(response); | 408 return new DateTime.fromMillisecondsSinceEpoch(response); |
| 409 }); | 409 }); |
| 410 } | 410 } |
| 411 | 411 |
| 412 external static _lastModified(String name); | 412 external static _lastModified(String path); |
| 413 | 413 |
| 414 DateTime lastModifiedSync() { | 414 DateTime lastModifiedSync() { |
| 415 var ms = _lastModified(name); | 415 var ms = _lastModified(path); |
| 416 throwIfError(ms, "Cannot retrieve modification time for file '$_name'"); | 416 throwIfError(ms, "Cannot retrieve modification time for file '$_path'"); |
| 417 return new DateTime.fromMillisecondsSinceEpoch(ms); | 417 return new DateTime.fromMillisecondsSinceEpoch(ms); |
| 418 } | 418 } |
| 419 | 419 |
| 420 external static _open(String name, int mode); | 420 external static _open(String path, int mode); |
| 421 | 421 |
| 422 RandomAccessFile openSync([FileMode mode = FileMode.READ]) { | 422 RandomAccessFile openSync([FileMode mode = FileMode.READ]) { |
| 423 if (mode != FileMode.READ && | 423 if (mode != FileMode.READ && |
| 424 mode != FileMode.WRITE && | 424 mode != FileMode.WRITE && |
| 425 mode != FileMode.APPEND) { | 425 mode != FileMode.APPEND) { |
| 426 throw new FileIOException("Unknown file mode. Use FileMode.READ, " | 426 throw new FileIOException("Unknown file mode. Use FileMode.READ, " |
| 427 "FileMode.WRITE or FileMode.APPEND."); | 427 "FileMode.WRITE or FileMode.APPEND."); |
| 428 } | 428 } |
| 429 var id = _open(_name, mode._mode); | 429 var id = _open(_path, mode._mode); |
| 430 throwIfError(id, "Cannot open file '$_name'"); | 430 throwIfError(id, "Cannot open file '$_path'"); |
| 431 return new _RandomAccessFile(id, _name); | 431 return new _RandomAccessFile(id, _path); |
| 432 } | 432 } |
| 433 | 433 |
| 434 external static int _openStdio(int fd); | 434 external static int _openStdio(int fd); |
| 435 | 435 |
| 436 static RandomAccessFile _openStdioSync(int fd) { | 436 static RandomAccessFile _openStdioSync(int fd) { |
| 437 var id = _openStdio(fd); | 437 var id = _openStdio(fd); |
| 438 if (id == 0) { | 438 if (id == 0) { |
| 439 throw new FileIOException("Cannot open stdio file for: $fd"); | 439 throw new FileIOException("Cannot open stdio file for: $fd"); |
| 440 } | 440 } |
| 441 return new _RandomAccessFile(id, ""); | 441 return new _RandomAccessFile(id, ""); |
| 442 } | 442 } |
| 443 | 443 |
| 444 Future<String> fullPath() { | 444 Future<String> fullPath() { |
| 445 _ensureFileService(); | 445 _ensureFileService(); |
| 446 List request = new List(2); | 446 List request = new List(2); |
| 447 request[0] = _FULL_PATH_REQUEST; | 447 request[0] = _FULL_PATH_REQUEST; |
| 448 request[1] = _name; | 448 request[1] = _path; |
| 449 return _fileService.call(request).then((response) { | 449 return _fileService.call(request).then((response) { |
| 450 if (_isErrorResponse(response)) { | 450 if (_isErrorResponse(response)) { |
| 451 throw _exceptionFromResponse(response, | 451 throw _exceptionFromResponse(response, |
| 452 "Cannot retrieve full path" | 452 "Cannot retrieve full path" |
| 453 " for '$_name'"); | 453 " for '$_path'"); |
| 454 } | 454 } |
| 455 return response; | 455 return response; |
| 456 }); | 456 }); |
| 457 } | 457 } |
| 458 | 458 |
| 459 external static _fullPath(String name); | 459 external static _fullPath(String path); |
| 460 | 460 |
| 461 String fullPathSync() { | 461 String fullPathSync() { |
| 462 var result = _fullPath(_name); | 462 var result = _fullPath(_path); |
| 463 throwIfError(result, "Cannot retrieve full path for file '$_name'"); | 463 throwIfError(result, "Cannot retrieve full path for file '$_path'"); |
| 464 return result; | 464 return result; |
| 465 } | 465 } |
| 466 | 466 |
| 467 Stream<List<int>> openRead() { | 467 Stream<List<int>> openRead() { |
| 468 return new _FileStream(_name); | 468 return new _FileStream(_path); |
| 469 } | 469 } |
| 470 | 470 |
| 471 IOSink<File> openWrite([FileMode mode = FileMode.WRITE]) { | 471 IOSink<File> openWrite([FileMode mode = FileMode.WRITE]) { |
| 472 if (mode != FileMode.WRITE && | 472 if (mode != FileMode.WRITE && |
| 473 mode != FileMode.APPEND) { | 473 mode != FileMode.APPEND) { |
| 474 throw new FileIOException( | 474 throw new FileIOException( |
| 475 "Wrong FileMode. Use FileMode.WRITE or FileMode.APPEND"); | 475 "Wrong FileMode. Use FileMode.WRITE or FileMode.APPEND"); |
| 476 } | 476 } |
| 477 var consumer = new _FileStreamConsumer(this, mode); | 477 var consumer = new _FileStreamConsumer(this, mode); |
| 478 return new IOSink<File>(consumer); | 478 return new IOSink<File>(consumer); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 return completer.future; | 583 return completer.future; |
| 584 } | 584 } |
| 585 } | 585 } |
| 586 | 586 |
| 587 void writeAsStringSync(String contents, | 587 void writeAsStringSync(String contents, |
| 588 {FileMode mode: FileMode.WRITE, | 588 {FileMode mode: FileMode.WRITE, |
| 589 Encoding encoding: Encoding.UTF_8}) { | 589 Encoding encoding: Encoding.UTF_8}) { |
| 590 writeAsBytesSync(_encodeString(contents, encoding), mode); | 590 writeAsBytesSync(_encodeString(contents, encoding), mode); |
| 591 } | 591 } |
| 592 | 592 |
| 593 String get name => _name; | 593 String get path => _path; |
| 594 | 594 |
| 595 String toString() => "File: '$name'"; | 595 String toString() => "File: '$path'"; |
| 596 | 596 |
| 597 void _ensureFileService() { | 597 void _ensureFileService() { |
| 598 if (_fileService == null) { | 598 if (_fileService == null) { |
| 599 _fileService = _FileUtils._newServicePort(); | 599 _fileService = _FileUtils._newServicePort(); |
| 600 } | 600 } |
| 601 } | 601 } |
| 602 | 602 |
| 603 static throwIfError(Object result, String msg) { | 603 static throwIfError(Object result, String msg) { |
| 604 if (result is OSError) { | 604 if (result is OSError) { |
| 605 throw new FileIOException(msg, result); | 605 throw new FileIOException(msg, result); |
| 606 } | 606 } |
| 607 } | 607 } |
| 608 | 608 |
| 609 final String _name; | 609 final String _path; |
| 610 | 610 |
| 611 SendPort _fileService; | 611 SendPort _fileService; |
| 612 } | 612 } |
| 613 | 613 |
| 614 | 614 |
| 615 class _RandomAccessFile extends _FileBase implements RandomAccessFile { | 615 class _RandomAccessFile extends _FileBase implements RandomAccessFile { |
| 616 _RandomAccessFile(int this._id, String this._name); | 616 _RandomAccessFile(int this._id, String this._path); |
| 617 | 617 |
| 618 Future<RandomAccessFile> close() { | 618 Future<RandomAccessFile> close() { |
| 619 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); | 619 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
| 620 if (closed) return _completeWithClosedException(completer); | 620 if (closed) return _completeWithClosedException(completer); |
| 621 _ensureFileService(); | 621 _ensureFileService(); |
| 622 List request = new List(2); | 622 List request = new List(2); |
| 623 request[0] = _CLOSE_REQUEST; | 623 request[0] = _CLOSE_REQUEST; |
| 624 request[1] = _id; | 624 request[1] = _id; |
| 625 // Set the id_ to 0 (NULL) to ensure the no more async requests | 625 // Set the id_ to 0 (NULL) to ensure the no more async requests |
| 626 // can be issued for this file. | 626 // can be issued for this file. |
| 627 _id = 0; | 627 _id = 0; |
| 628 return _fileService.call(request).then((result) { | 628 return _fileService.call(request).then((result) { |
| 629 if (result != -1) { | 629 if (result != -1) { |
| 630 _id = result; | 630 _id = result; |
| 631 return this; | 631 return this; |
| 632 } else { | 632 } else { |
| 633 throw new FileIOException("Cannot close file '$_name'"); | 633 throw new FileIOException("Cannot close file '$_path'"); |
| 634 } | 634 } |
| 635 }); | 635 }); |
| 636 } | 636 } |
| 637 | 637 |
| 638 external static int _close(int id); | 638 external static int _close(int id); |
| 639 | 639 |
| 640 void closeSync() { | 640 void closeSync() { |
| 641 _checkNotClosed(); | 641 _checkNotClosed(); |
| 642 var id = _close(_id); | 642 var id = _close(_id); |
| 643 if (id == -1) { | 643 if (id == -1) { |
| 644 throw new FileIOException("Cannot close file '$_name'"); | 644 throw new FileIOException("Cannot close file '$_path'"); |
| 645 } | 645 } |
| 646 _id = id; | 646 _id = id; |
| 647 } | 647 } |
| 648 | 648 |
| 649 Future<int> readByte() { | 649 Future<int> readByte() { |
| 650 _ensureFileService(); | 650 _ensureFileService(); |
| 651 Completer<int> completer = new Completer<int>(); | 651 Completer<int> completer = new Completer<int>(); |
| 652 if (closed) return _completeWithClosedException(completer); | 652 if (closed) return _completeWithClosedException(completer); |
| 653 List request = new List(2); | 653 List request = new List(2); |
| 654 request[0] = _READ_BYTE_REQUEST; | 654 request[0] = _READ_BYTE_REQUEST; |
| 655 request[1] = _id; | 655 request[1] = _id; |
| 656 return _fileService.call(request).then((response) { | 656 return _fileService.call(request).then((response) { |
| 657 if (_isErrorResponse(response)) { | 657 if (_isErrorResponse(response)) { |
| 658 throw _exceptionFromResponse(response, | 658 throw _exceptionFromResponse(response, |
| 659 "readByte failed for file '$_name'"); | 659 "readByte failed for file '$_path'"); |
| 660 } | 660 } |
| 661 return response; | 661 return response; |
| 662 }); | 662 }); |
| 663 } | 663 } |
| 664 | 664 |
| 665 external static _readByte(int id); | 665 external static _readByte(int id); |
| 666 | 666 |
| 667 int readByteSync() { | 667 int readByteSync() { |
| 668 _checkNotClosed(); | 668 _checkNotClosed(); |
| 669 var result = _readByte(_id); | 669 var result = _readByte(_id); |
| 670 if (result is OSError) { | 670 if (result is OSError) { |
| 671 throw new FileIOException("readByte failed for file '$_name'", result); | 671 throw new FileIOException("readByte failed for file '$_path'", result); |
| 672 } | 672 } |
| 673 return result; | 673 return result; |
| 674 } | 674 } |
| 675 | 675 |
| 676 Future<List<int>> read(int bytes) { | 676 Future<List<int>> read(int bytes) { |
| 677 _ensureFileService(); | 677 _ensureFileService(); |
| 678 Completer<List<int>> completer = new Completer<List<int>>(); | 678 Completer<List<int>> completer = new Completer<List<int>>(); |
| 679 if (bytes is !int) { | 679 if (bytes is !int) { |
| 680 // Complete asynchronously so the user has a chance to setup | 680 // Complete asynchronously so the user has a chance to setup |
| 681 // handlers without getting exceptions when registering the | 681 // handlers without getting exceptions when registering the |
| 682 // then handler. | 682 // then handler. |
| 683 Timer.run(() { | 683 Timer.run(() { |
| 684 completer.completeError(new FileIOException( | 684 completer.completeError(new FileIOException( |
| 685 "Invalid arguments to read for file '$_name'")); | 685 "Invalid arguments to read for file '$_path'")); |
| 686 }); | 686 }); |
| 687 return completer.future; | 687 return completer.future; |
| 688 }; | 688 }; |
| 689 if (closed) return _completeWithClosedException(completer); | 689 if (closed) return _completeWithClosedException(completer); |
| 690 List request = new List(3); | 690 List request = new List(3); |
| 691 request[0] = _READ_REQUEST; | 691 request[0] = _READ_REQUEST; |
| 692 request[1] = _id; | 692 request[1] = _id; |
| 693 request[2] = bytes; | 693 request[2] = bytes; |
| 694 return _fileService.call(request).then((response) { | 694 return _fileService.call(request).then((response) { |
| 695 if (_isErrorResponse(response)) { | 695 if (_isErrorResponse(response)) { |
| 696 throw _exceptionFromResponse(response, | 696 throw _exceptionFromResponse(response, |
| 697 "read failed for file '$_name'"); | 697 "read failed for file '$_path'"); |
| 698 } | 698 } |
| 699 return response[1]; | 699 return response[1]; |
| 700 }); | 700 }); |
| 701 } | 701 } |
| 702 | 702 |
| 703 external static _read(int id, int bytes); | 703 external static _read(int id, int bytes); |
| 704 | 704 |
| 705 List<int> readSync(int bytes) { | 705 List<int> readSync(int bytes) { |
| 706 if (bytes is !int) { | 706 if (bytes is !int) { |
| 707 throw new FileIOException( | 707 throw new FileIOException( |
| 708 "Invalid arguments to readSync for file '$_name'"); | 708 "Invalid arguments to readSync for file '$_path'"); |
| 709 } | 709 } |
| 710 return _read(_id, bytes); | 710 return _read(_id, bytes); |
| 711 } | 711 } |
| 712 | 712 |
| 713 Future<int> readList(List<int> buffer, int offset, int bytes) { | 713 Future<int> readList(List<int> buffer, int offset, int bytes) { |
| 714 _ensureFileService(); | 714 _ensureFileService(); |
| 715 Completer<int> completer = new Completer<int>(); | 715 Completer<int> completer = new Completer<int>(); |
| 716 if (buffer is !List || offset is !int || bytes is !int) { | 716 if (buffer is !List || offset is !int || bytes is !int) { |
| 717 // Complete asynchronously so the user has a chance to setup | 717 // Complete asynchronously so the user has a chance to setup |
| 718 // handlers without getting exceptions when registering the | 718 // handlers without getting exceptions when registering the |
| 719 // then handler. | 719 // then handler. |
| 720 Timer.run(() { | 720 Timer.run(() { |
| 721 completer.completeError(new FileIOException( | 721 completer.completeError(new FileIOException( |
| 722 "Invalid arguments to readList for file '$_name'")); | 722 "Invalid arguments to readList for file '$_path'")); |
| 723 }); | 723 }); |
| 724 return completer.future; | 724 return completer.future; |
| 725 }; | 725 }; |
| 726 if (closed) return _completeWithClosedException(completer); | 726 if (closed) return _completeWithClosedException(completer); |
| 727 List request = new List(3); | 727 List request = new List(3); |
| 728 request[0] = _READ_LIST_REQUEST; | 728 request[0] = _READ_LIST_REQUEST; |
| 729 request[1] = _id; | 729 request[1] = _id; |
| 730 request[2] = bytes; | 730 request[2] = bytes; |
| 731 return _fileService.call(request).then((response) { | 731 return _fileService.call(request).then((response) { |
| 732 if (_isErrorResponse(response)) { | 732 if (_isErrorResponse(response)) { |
| 733 throw _exceptionFromResponse(response, | 733 throw _exceptionFromResponse(response, |
| 734 "readList failed for file '$_name'"); | 734 "readList failed for file '$_path'"); |
| 735 } | 735 } |
| 736 var read = response[1]; | 736 var read = response[1]; |
| 737 var data = response[2]; | 737 var data = response[2]; |
| 738 buffer.setRange(offset, read, data); | 738 buffer.setRange(offset, read, data); |
| 739 return read; | 739 return read; |
| 740 }); | 740 }); |
| 741 } | 741 } |
| 742 | 742 |
| 743 static void _checkReadWriteListArguments(int length, int offset, int bytes) { | 743 static void _checkReadWriteListArguments(int length, int offset, int bytes) { |
| 744 if (offset < 0) throw new RangeError.value(offset); | 744 if (offset < 0) throw new RangeError.value(offset); |
| 745 if (bytes < 0) throw new RangeError.value(bytes); | 745 if (bytes < 0) throw new RangeError.value(bytes); |
| 746 if ((offset + bytes) > length) { | 746 if ((offset + bytes) > length) { |
| 747 throw new RangeError.value(offset + bytes); | 747 throw new RangeError.value(offset + bytes); |
| 748 } | 748 } |
| 749 } | 749 } |
| 750 | 750 |
| 751 external static _readList(int id, List<int> buffer, int offset, int bytes); | 751 external static _readList(int id, List<int> buffer, int offset, int bytes); |
| 752 | 752 |
| 753 int readListSync(List<int> buffer, int offset, int bytes) { | 753 int readListSync(List<int> buffer, int offset, int bytes) { |
| 754 _checkNotClosed(); | 754 _checkNotClosed(); |
| 755 if (buffer is !List || offset is !int || bytes is !int) { | 755 if (buffer is !List || offset is !int || bytes is !int) { |
| 756 throw new FileIOException( | 756 throw new FileIOException( |
| 757 "Invalid arguments to readList for file '$_name'"); | 757 "Invalid arguments to readList for file '$_path'"); |
| 758 } | 758 } |
| 759 if (bytes == 0) return 0; | 759 if (bytes == 0) return 0; |
| 760 _checkReadWriteListArguments(buffer.length, offset, bytes); | 760 _checkReadWriteListArguments(buffer.length, offset, bytes); |
| 761 var result = _readList(_id, buffer, offset, bytes); | 761 var result = _readList(_id, buffer, offset, bytes); |
| 762 if (result is OSError) { | 762 if (result is OSError) { |
| 763 throw new FileIOException("readList failed for file '$_name'", | 763 throw new FileIOException("readList failed for file '$_path'", |
| 764 result); | 764 result); |
| 765 } | 765 } |
| 766 return result; | 766 return result; |
| 767 } | 767 } |
| 768 | 768 |
| 769 Future<RandomAccessFile> writeByte(int value) { | 769 Future<RandomAccessFile> writeByte(int value) { |
| 770 _ensureFileService(); | 770 _ensureFileService(); |
| 771 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); | 771 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
| 772 if (value is !int) { | 772 if (value is !int) { |
| 773 // Complete asynchronously so the user has a chance to setup | 773 // Complete asynchronously so the user has a chance to setup |
| 774 // handlers without getting exceptions when registering the | 774 // handlers without getting exceptions when registering the |
| 775 // then handler. | 775 // then handler. |
| 776 Timer.run(() { | 776 Timer.run(() { |
| 777 completer.completeError(new FileIOException( | 777 completer.completeError(new FileIOException( |
| 778 "Invalid argument to writeByte for file '$_name'")); | 778 "Invalid argument to writeByte for file '$_path'")); |
| 779 }); | 779 }); |
| 780 return completer.future; | 780 return completer.future; |
| 781 } | 781 } |
| 782 if (closed) return _completeWithClosedException(completer); | 782 if (closed) return _completeWithClosedException(completer); |
| 783 List request = new List(3); | 783 List request = new List(3); |
| 784 request[0] = _WRITE_BYTE_REQUEST; | 784 request[0] = _WRITE_BYTE_REQUEST; |
| 785 request[1] = _id; | 785 request[1] = _id; |
| 786 request[2] = value; | 786 request[2] = value; |
| 787 return _fileService.call(request).then((response) { | 787 return _fileService.call(request).then((response) { |
| 788 if (_isErrorResponse(response)) { | 788 if (_isErrorResponse(response)) { |
| 789 throw _exceptionFromResponse(response, | 789 throw _exceptionFromResponse(response, |
| 790 "writeByte failed for file '$_name'"); | 790 "writeByte failed for file '$_path'"); |
| 791 } | 791 } |
| 792 return this; | 792 return this; |
| 793 }); | 793 }); |
| 794 } | 794 } |
| 795 | 795 |
| 796 external static _writeByte(int id, int value); | 796 external static _writeByte(int id, int value); |
| 797 | 797 |
| 798 int writeByteSync(int value) { | 798 int writeByteSync(int value) { |
| 799 _checkNotClosed(); | 799 _checkNotClosed(); |
| 800 if (value is !int) { | 800 if (value is !int) { |
| 801 throw new FileIOException( | 801 throw new FileIOException( |
| 802 "Invalid argument to writeByte for file '$_name'"); | 802 "Invalid argument to writeByte for file '$_path'"); |
| 803 } | 803 } |
| 804 var result = _writeByte(_id, value); | 804 var result = _writeByte(_id, value); |
| 805 if (result is OSError) { | 805 if (result is OSError) { |
| 806 throw new FileIOException("writeByte failed for file '$_name'", | 806 throw new FileIOException("writeByte failed for file '$_path'", |
| 807 result); | 807 result); |
| 808 } | 808 } |
| 809 return result; | 809 return result; |
| 810 } | 810 } |
| 811 | 811 |
| 812 Future<RandomAccessFile> writeList(List<int> buffer, int offset, int bytes) { | 812 Future<RandomAccessFile> writeList(List<int> buffer, int offset, int bytes) { |
| 813 _ensureFileService(); | 813 _ensureFileService(); |
| 814 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); | 814 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
| 815 if (buffer is !List || offset is !int || bytes is !int) { | 815 if (buffer is !List || offset is !int || bytes is !int) { |
| 816 // Complete asynchronously so the user has a chance to setup | 816 // Complete asynchronously so the user has a chance to setup |
| 817 // handlers without getting exceptions when registering the | 817 // handlers without getting exceptions when registering the |
| 818 // then handler. | 818 // then handler. |
| 819 Timer.run(() { | 819 Timer.run(() { |
| 820 completer.completeError(new FileIOException( | 820 completer.completeError(new FileIOException( |
| 821 "Invalid arguments to writeList for file '$_name'")); | 821 "Invalid arguments to writeList for file '$_path'")); |
| 822 }); | 822 }); |
| 823 return completer.future; | 823 return completer.future; |
| 824 } | 824 } |
| 825 if (closed) return _completeWithClosedException(completer); | 825 if (closed) return _completeWithClosedException(completer); |
| 826 | 826 |
| 827 _BufferAndOffset result; | 827 _BufferAndOffset result; |
| 828 try { | 828 try { |
| 829 result = _ensureFastAndSerializableBuffer(buffer, offset, bytes); | 829 result = _ensureFastAndSerializableBuffer(buffer, offset, bytes); |
| 830 } catch (e) { | 830 } catch (e) { |
| 831 // Complete asynchronously so the user has a chance to setup | 831 // Complete asynchronously so the user has a chance to setup |
| 832 // handlers without getting exceptions when registering the | 832 // handlers without getting exceptions when registering the |
| 833 // then handler. | 833 // then handler. |
| 834 Timer.run(() => completer.completeError(e)); | 834 Timer.run(() => completer.completeError(e)); |
| 835 return completer.future; | 835 return completer.future; |
| 836 } | 836 } |
| 837 | 837 |
| 838 List request = new List(5); | 838 List request = new List(5); |
| 839 request[0] = _WRITE_LIST_REQUEST; | 839 request[0] = _WRITE_LIST_REQUEST; |
| 840 request[1] = _id; | 840 request[1] = _id; |
| 841 request[2] = result.buffer; | 841 request[2] = result.buffer; |
| 842 request[3] = result.offset; | 842 request[3] = result.offset; |
| 843 request[4] = bytes; | 843 request[4] = bytes; |
| 844 return _fileService.call(request).then((response) { | 844 return _fileService.call(request).then((response) { |
| 845 if (_isErrorResponse(response)) { | 845 if (_isErrorResponse(response)) { |
| 846 throw _exceptionFromResponse(response, | 846 throw _exceptionFromResponse(response, |
| 847 "writeList failed for file '$_name'"); | 847 "writeList failed for file '$_path'"); |
| 848 } | 848 } |
| 849 return this; | 849 return this; |
| 850 }); | 850 }); |
| 851 } | 851 } |
| 852 | 852 |
| 853 external static _writeList(int id, List<int> buffer, int offset, int bytes); | 853 external static _writeList(int id, List<int> buffer, int offset, int bytes); |
| 854 | 854 |
| 855 int writeListSync(List<int> buffer, int offset, int bytes) { | 855 int writeListSync(List<int> buffer, int offset, int bytes) { |
| 856 _checkNotClosed(); | 856 _checkNotClosed(); |
| 857 if (buffer is !List || offset is !int || bytes is !int) { | 857 if (buffer is !List || offset is !int || bytes is !int) { |
| 858 throw new FileIOException( | 858 throw new FileIOException( |
| 859 "Invalid arguments to writeList for file '$_name'"); | 859 "Invalid arguments to writeList for file '$_path'"); |
| 860 } | 860 } |
| 861 if (bytes == 0) return 0; | 861 if (bytes == 0) return 0; |
| 862 _checkReadWriteListArguments(buffer.length, offset, bytes); | 862 _checkReadWriteListArguments(buffer.length, offset, bytes); |
| 863 _BufferAndOffset bufferAndOffset = | 863 _BufferAndOffset bufferAndOffset = |
| 864 _ensureFastAndSerializableBuffer(buffer, offset, bytes); | 864 _ensureFastAndSerializableBuffer(buffer, offset, bytes); |
| 865 var result = | 865 var result = |
| 866 _writeList(_id, bufferAndOffset.buffer, bufferAndOffset.offset, bytes); | 866 _writeList(_id, bufferAndOffset.buffer, bufferAndOffset.offset, bytes); |
| 867 if (result is OSError) { | 867 if (result is OSError) { |
| 868 throw new FileIOException("writeList failed for file '$_name'", result); | 868 throw new FileIOException("writeList failed for file '$_path'", result); |
| 869 } | 869 } |
| 870 return result; | 870 return result; |
| 871 } | 871 } |
| 872 | 872 |
| 873 Future<RandomAccessFile> writeString(String string, | 873 Future<RandomAccessFile> writeString(String string, |
| 874 [Encoding encoding = Encoding.UTF_8]) { | 874 [Encoding encoding = Encoding.UTF_8]) { |
| 875 if (encoding is! Encoding) { | 875 if (encoding is! Encoding) { |
| 876 var completer = new Completer(); | 876 var completer = new Completer(); |
| 877 Timer.run(() { | 877 Timer.run(() { |
| 878 completer.completeError(new FileIOException( | 878 completer.completeError(new FileIOException( |
| (...skipping 17 matching lines...) Expand all Loading... |
| 896 Future<int> position() { | 896 Future<int> position() { |
| 897 _ensureFileService(); | 897 _ensureFileService(); |
| 898 Completer<int> completer = new Completer<int>(); | 898 Completer<int> completer = new Completer<int>(); |
| 899 if (closed) return _completeWithClosedException(completer); | 899 if (closed) return _completeWithClosedException(completer); |
| 900 List request = new List(2); | 900 List request = new List(2); |
| 901 request[0] = _POSITION_REQUEST; | 901 request[0] = _POSITION_REQUEST; |
| 902 request[1] = _id; | 902 request[1] = _id; |
| 903 return _fileService.call(request).then((response) { | 903 return _fileService.call(request).then((response) { |
| 904 if (_isErrorResponse(response)) { | 904 if (_isErrorResponse(response)) { |
| 905 throw _exceptionFromResponse(response, | 905 throw _exceptionFromResponse(response, |
| 906 "position failed for file '$_name'"); | 906 "position failed for file '$_path'"); |
| 907 } | 907 } |
| 908 return response; | 908 return response; |
| 909 }); | 909 }); |
| 910 } | 910 } |
| 911 | 911 |
| 912 external static _position(int id); | 912 external static _position(int id); |
| 913 | 913 |
| 914 int positionSync() { | 914 int positionSync() { |
| 915 _checkNotClosed(); | 915 _checkNotClosed(); |
| 916 var result = _position(_id); | 916 var result = _position(_id); |
| 917 if (result is OSError) { | 917 if (result is OSError) { |
| 918 throw new FileIOException("position failed for file '$_name'", result); | 918 throw new FileIOException("position failed for file '$_path'", result); |
| 919 } | 919 } |
| 920 return result; | 920 return result; |
| 921 } | 921 } |
| 922 | 922 |
| 923 Future<RandomAccessFile> setPosition(int position) { | 923 Future<RandomAccessFile> setPosition(int position) { |
| 924 _ensureFileService(); | 924 _ensureFileService(); |
| 925 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); | 925 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
| 926 if (closed) return _completeWithClosedException(completer); | 926 if (closed) return _completeWithClosedException(completer); |
| 927 List request = new List(3); | 927 List request = new List(3); |
| 928 request[0] = _SET_POSITION_REQUEST; | 928 request[0] = _SET_POSITION_REQUEST; |
| 929 request[1] = _id; | 929 request[1] = _id; |
| 930 request[2] = position; | 930 request[2] = position; |
| 931 return _fileService.call(request).then((response) { | 931 return _fileService.call(request).then((response) { |
| 932 if (_isErrorResponse(response)) { | 932 if (_isErrorResponse(response)) { |
| 933 throw _exceptionFromResponse(response, | 933 throw _exceptionFromResponse(response, |
| 934 "setPosition failed for file '$_name'"); | 934 "setPosition failed for file '$_path'"); |
| 935 } | 935 } |
| 936 return this; | 936 return this; |
| 937 }); | 937 }); |
| 938 } | 938 } |
| 939 | 939 |
| 940 external static _setPosition(int id, int position); | 940 external static _setPosition(int id, int position); |
| 941 | 941 |
| 942 void setPositionSync(int position) { | 942 void setPositionSync(int position) { |
| 943 _checkNotClosed(); | 943 _checkNotClosed(); |
| 944 var result = _setPosition(_id, position); | 944 var result = _setPosition(_id, position); |
| 945 if (result is OSError) { | 945 if (result is OSError) { |
| 946 throw new FileIOException("setPosition failed for file '$_name'", result); | 946 throw new FileIOException("setPosition failed for file '$_path'", result); |
| 947 } | 947 } |
| 948 } | 948 } |
| 949 | 949 |
| 950 Future<RandomAccessFile> truncate(int length) { | 950 Future<RandomAccessFile> truncate(int length) { |
| 951 _ensureFileService(); | 951 _ensureFileService(); |
| 952 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); | 952 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
| 953 if (closed) return _completeWithClosedException(completer); | 953 if (closed) return _completeWithClosedException(completer); |
| 954 List request = new List(3); | 954 List request = new List(3); |
| 955 request[0] = _TRUNCATE_REQUEST; | 955 request[0] = _TRUNCATE_REQUEST; |
| 956 request[1] = _id; | 956 request[1] = _id; |
| 957 request[2] = length; | 957 request[2] = length; |
| 958 return _fileService.call(request).then((response) { | 958 return _fileService.call(request).then((response) { |
| 959 if (_isErrorResponse(response)) { | 959 if (_isErrorResponse(response)) { |
| 960 throw _exceptionFromResponse(response, | 960 throw _exceptionFromResponse(response, |
| 961 "truncate failed for file '$_name'"); | 961 "truncate failed for file '$_path'"); |
| 962 } | 962 } |
| 963 return this; | 963 return this; |
| 964 }); | 964 }); |
| 965 } | 965 } |
| 966 | 966 |
| 967 external static _truncate(int id, int length); | 967 external static _truncate(int id, int length); |
| 968 | 968 |
| 969 void truncateSync(int length) { | 969 void truncateSync(int length) { |
| 970 _checkNotClosed(); | 970 _checkNotClosed(); |
| 971 var result = _truncate(_id, length); | 971 var result = _truncate(_id, length); |
| 972 if (result is OSError) { | 972 if (result is OSError) { |
| 973 throw new FileIOException("truncate failed for file '$_name'", result); | 973 throw new FileIOException("truncate failed for file '$_path'", result); |
| 974 } | 974 } |
| 975 } | 975 } |
| 976 | 976 |
| 977 Future<int> length() { | 977 Future<int> length() { |
| 978 _ensureFileService(); | 978 _ensureFileService(); |
| 979 Completer<int> completer = new Completer<int>(); | 979 Completer<int> completer = new Completer<int>(); |
| 980 if (closed) return _completeWithClosedException(completer); | 980 if (closed) return _completeWithClosedException(completer); |
| 981 List request = new List(2); | 981 List request = new List(2); |
| 982 request[0] = _LENGTH_REQUEST; | 982 request[0] = _LENGTH_REQUEST; |
| 983 request[1] = _id; | 983 request[1] = _id; |
| 984 return _fileService.call(request).then((response) { | 984 return _fileService.call(request).then((response) { |
| 985 if (_isErrorResponse(response)) { | 985 if (_isErrorResponse(response)) { |
| 986 throw _exceptionFromResponse(response, | 986 throw _exceptionFromResponse(response, |
| 987 "length failed for file '$_name'"); | 987 "length failed for file '$_path'"); |
| 988 } | 988 } |
| 989 return response; | 989 return response; |
| 990 }); | 990 }); |
| 991 } | 991 } |
| 992 | 992 |
| 993 external static _length(int id); | 993 external static _length(int id); |
| 994 | 994 |
| 995 int lengthSync() { | 995 int lengthSync() { |
| 996 _checkNotClosed(); | 996 _checkNotClosed(); |
| 997 var result = _length(_id); | 997 var result = _length(_id); |
| 998 if (result is OSError) { | 998 if (result is OSError) { |
| 999 throw new FileIOException("length failed for file '$_name'", result); | 999 throw new FileIOException("length failed for file '$_path'", result); |
| 1000 } | 1000 } |
| 1001 return result; | 1001 return result; |
| 1002 } | 1002 } |
| 1003 | 1003 |
| 1004 Future<RandomAccessFile> flush() { | 1004 Future<RandomAccessFile> flush() { |
| 1005 _ensureFileService(); | 1005 _ensureFileService(); |
| 1006 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); | 1006 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
| 1007 if (closed) return _completeWithClosedException(completer); | 1007 if (closed) return _completeWithClosedException(completer); |
| 1008 List request = new List(2); | 1008 List request = new List(2); |
| 1009 request[0] = _FLUSH_REQUEST; | 1009 request[0] = _FLUSH_REQUEST; |
| 1010 request[1] = _id; | 1010 request[1] = _id; |
| 1011 return _fileService.call(request).then((response) { | 1011 return _fileService.call(request).then((response) { |
| 1012 if (_isErrorResponse(response)) { | 1012 if (_isErrorResponse(response)) { |
| 1013 throw _exceptionFromResponse(response, | 1013 throw _exceptionFromResponse(response, |
| 1014 "flush failed for file '$_name'"); | 1014 "flush failed for file '$_path'"); |
| 1015 } | 1015 } |
| 1016 return this; | 1016 return this; |
| 1017 }); | 1017 }); |
| 1018 } | 1018 } |
| 1019 | 1019 |
| 1020 external static _flush(int id); | 1020 external static _flush(int id); |
| 1021 | 1021 |
| 1022 void flushSync() { | 1022 void flushSync() { |
| 1023 _checkNotClosed(); | 1023 _checkNotClosed(); |
| 1024 var result = _flush(_id); | 1024 var result = _flush(_id); |
| 1025 if (result is OSError) { | 1025 if (result is OSError) { |
| 1026 throw new FileIOException("flush failed for file '$_name'", result); | 1026 throw new FileIOException("flush failed for file '$_path'", result); |
| 1027 } | 1027 } |
| 1028 } | 1028 } |
| 1029 | 1029 |
| 1030 String get name => _name; | 1030 String get path => _path; |
| 1031 | 1031 |
| 1032 void _ensureFileService() { | 1032 void _ensureFileService() { |
| 1033 if (_fileService == null) { | 1033 if (_fileService == null) { |
| 1034 _fileService = _FileUtils._newServicePort(); | 1034 _fileService = _FileUtils._newServicePort(); |
| 1035 } | 1035 } |
| 1036 } | 1036 } |
| 1037 | 1037 |
| 1038 bool get closed => _id == 0; | 1038 bool get closed => _id == 0; |
| 1039 | 1039 |
| 1040 void _checkNotClosed() { | 1040 void _checkNotClosed() { |
| 1041 if (closed) { | 1041 if (closed) { |
| 1042 throw new FileIOException("File closed '$_name'"); | 1042 throw new FileIOException("File closed '$_path'"); |
| 1043 } | 1043 } |
| 1044 } | 1044 } |
| 1045 | 1045 |
| 1046 Future _completeWithClosedException(Completer completer) { | 1046 Future _completeWithClosedException(Completer completer) { |
| 1047 Timer.run(() { | 1047 Timer.run(() { |
| 1048 completer.completeError( | 1048 completer.completeError( |
| 1049 new FileIOException("File closed '$_name'")); | 1049 new FileIOException("File closed '$_path'")); |
| 1050 }); | 1050 }); |
| 1051 return completer.future; | 1051 return completer.future; |
| 1052 } | 1052 } |
| 1053 | 1053 |
| 1054 final String _name; | 1054 final String _path; |
| 1055 int _id; | 1055 int _id; |
| 1056 | 1056 |
| 1057 SendPort _fileService; | 1057 SendPort _fileService; |
| 1058 } | 1058 } |
| OLD | NEW |