| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart.io; | 5 part of dart.io; |
| 6 | 6 |
| 7 // Read the file in blocks of size 64k. | 7 // Read the file in blocks of size 64k. |
| 8 const int _BLOCK_SIZE = 64 * 1024; | 8 const int _BLOCK_SIZE = 64 * 1024; |
| 9 | 9 |
| 10 | 10 |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 }); | 192 }); |
| 193 return completer.future; | 193 return completer.future; |
| 194 } | 194 } |
| 195 | 195 |
| 196 Future<File> close() { | 196 Future<File> close() { |
| 197 return _openFuture.then((openedFile) => openedFile.close()); | 197 return _openFuture.then((openedFile) => openedFile.close()); |
| 198 } | 198 } |
| 199 } | 199 } |
| 200 | 200 |
| 201 | 201 |
| 202 const int _EXISTS_REQUEST = 0; | |
| 203 const int _CREATE_REQUEST = 1; | |
| 204 const int _DELETE_REQUEST = 2; | |
| 205 const int _RENAME_REQUEST = 3; | |
| 206 const int _OPEN_REQUEST = 4; | |
| 207 const int _RESOLVE_SYMBOLIC_LINKS_REQUEST = 5; | |
| 208 const int _CLOSE_REQUEST = 6; | |
| 209 const int _POSITION_REQUEST = 7; | |
| 210 const int _SET_POSITION_REQUEST = 8; | |
| 211 const int _TRUNCATE_REQUEST = 9; | |
| 212 const int _LENGTH_REQUEST = 10; | |
| 213 const int _LENGTH_FROM_PATH_REQUEST = 11; | |
| 214 const int _LAST_MODIFIED_REQUEST = 12; | |
| 215 const int _FLUSH_REQUEST = 13; | |
| 216 const int _READ_BYTE_REQUEST = 14; | |
| 217 const int _WRITE_BYTE_REQUEST = 15; | |
| 218 const int _READ_REQUEST = 16; | |
| 219 const int _READ_LIST_REQUEST = 17; | |
| 220 const int _WRITE_LIST_REQUEST = 18; | |
| 221 const int _CREATE_LINK_REQUEST = 19; | |
| 222 const int _DELETE_LINK_REQUEST = 20; | |
| 223 const int _RENAME_LINK_REQUEST = 21; | |
| 224 const int _LINK_TARGET_REQUEST = 22; | |
| 225 const int _TYPE_REQUEST = 23; | |
| 226 const int _IDENTICAL_REQUEST = 24; | |
| 227 const int _STAT_REQUEST = 25; | |
| 228 | |
| 229 // TODO(ager): The only reason for this class is that the patching | |
| 230 // mechanism doesn't seem to like patching a private top level | |
| 231 // function. | |
| 232 class _FileUtils { | |
| 233 external static SendPort _newServicePort(); | |
| 234 } | |
| 235 | |
| 236 // Class for encapsulating the native implementation of files. | 202 // Class for encapsulating the native implementation of files. |
| 237 class _File extends FileSystemEntity implements File { | 203 class _File extends FileSystemEntity implements File { |
| 238 final String path; | 204 final String path; |
| 239 SendPort _fileService; | |
| 240 | 205 |
| 241 // Constructor for file. | 206 // Constructor for file. |
| 242 _File(String this.path) { | 207 _File(String this.path) { |
| 243 if (path is! String) { | 208 if (path is! String) { |
| 244 throw new ArgumentError('${Error.safeToString(path)} ' | 209 throw new ArgumentError('${Error.safeToString(path)} ' |
| 245 'is not a String'); | 210 'is not a String'); |
| 246 } | 211 } |
| 247 } | 212 } |
| 248 | 213 |
| 249 Future<bool> exists() { | 214 Future<bool> exists() { |
| 250 _ensureFileService(); | 215 return IOService.dispatch(FILE_EXISTS, [path]).then((response) { |
| 251 List request = new List(2); | |
| 252 request[0] = _EXISTS_REQUEST; | |
| 253 request[1] = path; | |
| 254 return _fileService.call(request).then((response) { | |
| 255 if (_isErrorResponse(response)) { | 216 if (_isErrorResponse(response)) { |
| 256 throw _exceptionFromResponse(response, "Cannot check existence", path); | 217 throw _exceptionFromResponse(response, "Cannot check existence", path); |
| 257 } | 218 } |
| 258 return response; | 219 return response; |
| 259 }); | 220 }); |
| 260 } | 221 } |
| 261 | 222 |
| 262 external static _exists(String path); | 223 external static _exists(String path); |
| 263 | 224 |
| 264 bool existsSync() { | 225 bool existsSync() { |
| 265 var result = _exists(path); | 226 var result = _exists(path); |
| 266 throwIfError(result, "Cannot check existence of file", path); | 227 throwIfError(result, "Cannot check existence of file", path); |
| 267 return result; | 228 return result; |
| 268 } | 229 } |
| 269 | 230 |
| 270 File get absolute => new File(_absolutePath); | 231 File get absolute => new File(_absolutePath); |
| 271 | 232 |
| 272 Future<FileStat> stat() => FileStat.stat(path); | 233 Future<FileStat> stat() => FileStat.stat(path); |
| 273 | 234 |
| 274 FileStat statSync() => FileStat.statSync(path); | 235 FileStat statSync() => FileStat.statSync(path); |
| 275 | 236 |
| 276 Future<File> create() { | 237 Future<File> create() { |
| 277 _ensureFileService(); | 238 return IOService.dispatch(FILE_CREATE, [path]).then((response) { |
| 278 List request = new List(2); | |
| 279 request[0] = _CREATE_REQUEST; | |
| 280 request[1] = path; | |
| 281 return _fileService.call(request).then((response) { | |
| 282 if (_isErrorResponse(response)) { | 239 if (_isErrorResponse(response)) { |
| 283 throw _exceptionFromResponse(response, "Cannot create file", path); | 240 throw _exceptionFromResponse(response, "Cannot create file", path); |
| 284 } | 241 } |
| 285 return this; | 242 return this; |
| 286 }); | 243 }); |
| 287 } | 244 } |
| 288 | 245 |
| 289 external static _create(String path); | 246 external static _create(String path); |
| 290 | 247 |
| 291 external static _createLink(String path, String target); | 248 external static _createLink(String path, String target); |
| 292 | 249 |
| 293 external static _linkTarget(String path); | 250 external static _linkTarget(String path); |
| 294 | 251 |
| 295 void createSync() { | 252 void createSync() { |
| 296 var result = _create(path); | 253 var result = _create(path); |
| 297 throwIfError(result, "Cannot create file", path); | 254 throwIfError(result, "Cannot create file", path); |
| 298 } | 255 } |
| 299 | 256 |
| 300 Future<File> _delete({bool recursive: false}) { | 257 Future<File> _delete({bool recursive: false}) { |
| 301 if (recursive) { | 258 if (recursive) { |
| 302 return new Directory(path).delete(recursive: true).then((_) => this); | 259 return new Directory(path).delete(recursive: true).then((_) => this); |
| 303 } | 260 } |
| 304 _ensureFileService(); | 261 return IOService.dispatch(FILE_DELETE, [path]).then((response) { |
| 305 List request = new List(2); | |
| 306 request[0] = _DELETE_REQUEST; | |
| 307 request[1] = path; | |
| 308 return _fileService.call(request).then((response) { | |
| 309 if (_isErrorResponse(response)) { | 262 if (_isErrorResponse(response)) { |
| 310 throw _exceptionFromResponse(response, "Cannot delete file", path); | 263 throw _exceptionFromResponse(response, "Cannot delete file", path); |
| 311 } | 264 } |
| 312 return this; | 265 return this; |
| 313 }); | 266 }); |
| 314 } | 267 } |
| 315 | 268 |
| 316 external static _deleteNative(String path); | 269 external static _deleteNative(String path); |
| 317 | 270 |
| 318 external static _deleteLinkNative(String path); | 271 external static _deleteLinkNative(String path); |
| 319 | 272 |
| 320 void _deleteSync({bool recursive: false}) { | 273 void _deleteSync({bool recursive: false}) { |
| 321 if (recursive) { | 274 if (recursive) { |
| 322 return new Directory(path).deleteSync(recursive: true); | 275 return new Directory(path).deleteSync(recursive: true); |
| 323 } | 276 } |
| 324 var result = _deleteNative(path); | 277 var result = _deleteNative(path); |
| 325 throwIfError(result, "Cannot delete file", path); | 278 throwIfError(result, "Cannot delete file", path); |
| 326 } | 279 } |
| 327 | 280 |
| 328 Future<File> rename(String newPath) { | 281 Future<File> rename(String newPath) { |
| 329 _ensureFileService(); | 282 return IOService.dispatch(FILE_RENAME, [path, newPath]).then((response) { |
| 330 List request = new List(3); | |
| 331 request[0] = _RENAME_REQUEST; | |
| 332 request[1] = path; | |
| 333 request[2] = newPath; | |
| 334 return _fileService.call(request).then((response) { | |
| 335 if (_isErrorResponse(response)) { | 283 if (_isErrorResponse(response)) { |
| 336 throw _exceptionFromResponse( | 284 throw _exceptionFromResponse( |
| 337 response, "Cannot rename file to '$newPath'", path); | 285 response, "Cannot rename file to '$newPath'", path); |
| 338 } | 286 } |
| 339 return new File(newPath); | 287 return new File(newPath); |
| 340 }); | 288 }); |
| 341 } | 289 } |
| 342 | 290 |
| 343 external static _rename(String oldPath, String newPath); | 291 external static _rename(String oldPath, String newPath); |
| 344 | 292 |
| 345 external static _renameLink(String oldPath, String newPath); | 293 external static _renameLink(String oldPath, String newPath); |
| 346 | 294 |
| 347 File renameSync(String newPath) { | 295 File renameSync(String newPath) { |
| 348 var result = _rename(path, newPath); | 296 var result = _rename(path, newPath); |
| 349 throwIfError(result, "Cannot rename file to '$newPath'", path); | 297 throwIfError(result, "Cannot rename file to '$newPath'", path); |
| 350 return new File(newPath); | 298 return new File(newPath); |
| 351 } | 299 } |
| 352 | 300 |
| 353 Directory get directory { | 301 Directory get directory { |
| 354 _Path path = new _Path(this.path).directoryPath; | 302 _Path path = new _Path(this.path).directoryPath; |
| 355 return new Directory(path.toNativePath()); | 303 return new Directory(path.toNativePath()); |
| 356 } | 304 } |
| 357 | 305 |
| 358 Future<RandomAccessFile> open({FileMode mode: FileMode.READ}) { | 306 Future<RandomAccessFile> open({FileMode mode: FileMode.READ}) { |
| 359 _ensureFileService(); | |
| 360 if (mode != FileMode.READ && | 307 if (mode != FileMode.READ && |
| 361 mode != FileMode.WRITE && | 308 mode != FileMode.WRITE && |
| 362 mode != FileMode.APPEND) { | 309 mode != FileMode.APPEND) { |
| 363 return new Future.error(new ArgumentError()); | 310 return new Future.error(new ArgumentError()); |
| 364 } | 311 } |
| 365 List request = new List(3); | 312 return IOService.dispatch(FILE_OPEN, [path, mode._mode]).then((response) { |
| 366 request[0] = _OPEN_REQUEST; | |
| 367 request[1] = path; | |
| 368 request[2] = mode._mode; // Direct int value for serialization. | |
| 369 return _fileService.call(request).then((response) { | |
| 370 if (_isErrorResponse(response)) { | 313 if (_isErrorResponse(response)) { |
| 371 throw _exceptionFromResponse(response, "Cannot open file", path); | 314 throw _exceptionFromResponse(response, "Cannot open file", path); |
| 372 } | 315 } |
| 373 return new _RandomAccessFile(response, path); | 316 return new _RandomAccessFile(response, path); |
| 374 }); | 317 }); |
| 375 } | 318 } |
| 376 | 319 |
| 377 Future<int> length() { | 320 Future<int> length() { |
| 378 _ensureFileService(); | 321 return IOService.dispatch(FILE_LENGTH_FROM_PATH, [path]).then((response) { |
| 379 List request = new List(2); | |
| 380 request[0] = _LENGTH_FROM_PATH_REQUEST; | |
| 381 request[1] = path; | |
| 382 return _fileService.call(request).then((response) { | |
| 383 if (_isErrorResponse(response)) { | 322 if (_isErrorResponse(response)) { |
| 384 throw _exceptionFromResponse(response, | 323 throw _exceptionFromResponse(response, |
| 385 "Cannot retrieve length of file", | 324 "Cannot retrieve length of file", |
| 386 path); | 325 path); |
| 387 } | 326 } |
| 388 return response; | 327 return response; |
| 389 }); | 328 }); |
| 390 } | 329 } |
| 391 | 330 |
| 392 | 331 |
| 393 external static _lengthFromPath(String path); | 332 external static _lengthFromPath(String path); |
| 394 | 333 |
| 395 int lengthSync() { | 334 int lengthSync() { |
| 396 var result = _lengthFromPath(path); | 335 var result = _lengthFromPath(path); |
| 397 throwIfError(result, "Cannot retrieve length of file", path); | 336 throwIfError(result, "Cannot retrieve length of file", path); |
| 398 return result; | 337 return result; |
| 399 } | 338 } |
| 400 | 339 |
| 401 Future<DateTime> lastModified() { | 340 Future<DateTime> lastModified() { |
| 402 _ensureFileService(); | 341 return IOService.dispatch(FILE_LAST_MODIFIED, [path]).then((response) { |
| 403 List request = new List(2); | |
| 404 request[0] = _LAST_MODIFIED_REQUEST; | |
| 405 request[1] = path; | |
| 406 return _fileService.call(request).then((response) { | |
| 407 if (_isErrorResponse(response)) { | 342 if (_isErrorResponse(response)) { |
| 408 throw _exceptionFromResponse(response, | 343 throw _exceptionFromResponse(response, |
| 409 "Cannot retrieve modification time", | 344 "Cannot retrieve modification time", |
| 410 path); | 345 path); |
| 411 } | 346 } |
| 412 return new DateTime.fromMillisecondsSinceEpoch(response); | 347 return new DateTime.fromMillisecondsSinceEpoch(response); |
| 413 }); | 348 }); |
| 414 } | 349 } |
| 415 | 350 |
| 416 external static _lastModified(String path); | 351 external static _lastModified(String path); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 if (mode != FileMode.WRITE && | 394 if (mode != FileMode.WRITE && |
| 460 mode != FileMode.APPEND) { | 395 mode != FileMode.APPEND) { |
| 461 throw new ArgumentError( | 396 throw new ArgumentError( |
| 462 "Wrong FileMode. Use FileMode.WRITE or FileMode.APPEND"); | 397 "Wrong FileMode. Use FileMode.WRITE or FileMode.APPEND"); |
| 463 } | 398 } |
| 464 var consumer = new _FileStreamConsumer(this, mode); | 399 var consumer = new _FileStreamConsumer(this, mode); |
| 465 return new IOSink(consumer, encoding: encoding); | 400 return new IOSink(consumer, encoding: encoding); |
| 466 } | 401 } |
| 467 | 402 |
| 468 Future<List<int>> readAsBytes() { | 403 Future<List<int>> readAsBytes() { |
| 469 _ensureFileService(); | |
| 470 Completer<List<int>> completer = new Completer<List<int>>(); | 404 Completer<List<int>> completer = new Completer<List<int>>(); |
| 471 var builder = new BytesBuilder(); | 405 var builder = new BytesBuilder(); |
| 472 openRead().listen( | 406 openRead().listen( |
| 473 (d) => builder.add(d), | 407 (d) => builder.add(d), |
| 474 onDone: () { | 408 onDone: () { |
| 475 completer.complete(builder.takeBytes()); | 409 completer.complete(builder.takeBytes()); |
| 476 }, | 410 }, |
| 477 onError: (e) { | 411 onError: (e) { |
| 478 completer.completeError(e); | 412 completer.completeError(e); |
| 479 }, | 413 }, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 495 String _tryDecode(List<int> bytes, Encoding encoding) { | 429 String _tryDecode(List<int> bytes, Encoding encoding) { |
| 496 try { | 430 try { |
| 497 return encoding.decode(bytes); | 431 return encoding.decode(bytes); |
| 498 } catch (_) { | 432 } catch (_) { |
| 499 throw new FileException( | 433 throw new FileException( |
| 500 "Failed to decode data using encoding '${encoding.name}'", path); | 434 "Failed to decode data using encoding '${encoding.name}'", path); |
| 501 } | 435 } |
| 502 } | 436 } |
| 503 | 437 |
| 504 Future<String> readAsString({Encoding encoding: UTF8}) { | 438 Future<String> readAsString({Encoding encoding: UTF8}) { |
| 505 _ensureFileService(); | |
| 506 return readAsBytes().then((bytes) { | 439 return readAsBytes().then((bytes) { |
| 507 return _tryDecode(bytes, encoding); | 440 return _tryDecode(bytes, encoding); |
| 508 }); | 441 }); |
| 509 } | 442 } |
| 510 | 443 |
| 511 String readAsStringSync({Encoding encoding: UTF8}) { | 444 String readAsStringSync({Encoding encoding: UTF8}) { |
| 512 List<int> bytes = readAsBytesSync(); | 445 List<int> bytes = readAsBytesSync(); |
| 513 return _tryDecode(bytes, encoding); | 446 return _tryDecode(bytes, encoding); |
| 514 } | 447 } |
| 515 | 448 |
| 516 List<String> _decodeLines(List<int> bytes, Encoding encoding) { | 449 List<String> _decodeLines(List<int> bytes, Encoding encoding) { |
| 517 if (bytes.length == 0) return []; | 450 if (bytes.length == 0) return []; |
| 518 var list = []; | 451 var list = []; |
| 519 var controller = new StreamController(sync: true); | 452 var controller = new StreamController(sync: true); |
| 520 var error = null; | 453 var error = null; |
| 521 controller.stream | 454 controller.stream |
| 522 .transform(encoding.decoder) | 455 .transform(encoding.decoder) |
| 523 .transform(new LineSplitter()) | 456 .transform(new LineSplitter()) |
| 524 .listen((line) => list.add(line), onError: (e) => error = e); | 457 .listen((line) => list.add(line), onError: (e) => error = e); |
| 525 controller.add(bytes); | 458 controller.add(bytes); |
| 526 controller.close(); | 459 controller.close(); |
| 527 if (error != null) { | 460 if (error != null) { |
| 528 throw new FileException( | 461 throw new FileException( |
| 529 "Failed to decode data using encoding '${encoding.name}'", path); | 462 "Failed to decode data using encoding '${encoding.name}'", path); |
| 530 } | 463 } |
| 531 return list; | 464 return list; |
| 532 } | 465 } |
| 533 | 466 |
| 534 Future<List<String>> readAsLines({Encoding encoding: UTF8}) { | 467 Future<List<String>> readAsLines({Encoding encoding: UTF8}) { |
| 535 _ensureFileService(); | |
| 536 return readAsBytes().then((bytes) { | 468 return readAsBytes().then((bytes) { |
| 537 return _decodeLines(bytes, encoding); | 469 return _decodeLines(bytes, encoding); |
| 538 }); | 470 }); |
| 539 } | 471 } |
| 540 | 472 |
| 541 List<String> readAsLinesSync({Encoding encoding: UTF8}) { | 473 List<String> readAsLinesSync({Encoding encoding: UTF8}) { |
| 542 return _decodeLines(readAsBytesSync(), encoding); | 474 return _decodeLines(readAsBytesSync(), encoding); |
| 543 } | 475 } |
| 544 | 476 |
| 545 Future<File> writeAsBytes(List<int> bytes, | 477 Future<File> writeAsBytes(List<int> bytes, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 571 } | 503 } |
| 572 | 504 |
| 573 void writeAsStringSync(String contents, | 505 void writeAsStringSync(String contents, |
| 574 {FileMode mode: FileMode.WRITE, | 506 {FileMode mode: FileMode.WRITE, |
| 575 Encoding encoding: UTF8}) { | 507 Encoding encoding: UTF8}) { |
| 576 writeAsBytesSync(encoding.encode(contents), mode: mode); | 508 writeAsBytesSync(encoding.encode(contents), mode: mode); |
| 577 } | 509 } |
| 578 | 510 |
| 579 String toString() => "File: '$path'"; | 511 String toString() => "File: '$path'"; |
| 580 | 512 |
| 581 void _ensureFileService() { | |
| 582 if (_fileService == null) { | |
| 583 _fileService = _FileUtils._newServicePort(); | |
| 584 } | |
| 585 } | |
| 586 | |
| 587 static throwIfError(Object result, String msg, String path) { | 513 static throwIfError(Object result, String msg, String path) { |
| 588 if (result is OSError) { | 514 if (result is OSError) { |
| 589 throw new FileException(msg, path, result); | 515 throw new FileException(msg, path, result); |
| 590 } | 516 } |
| 591 } | 517 } |
| 592 } | 518 } |
| 593 | 519 |
| 594 | 520 |
| 595 class _RandomAccessFile implements RandomAccessFile { | 521 class _RandomAccessFile implements RandomAccessFile { |
| 596 final String path; | 522 final String path; |
| 597 int _id; | 523 int _id; |
| 598 SendPort _fileService; | 524 SendPort _fileService; |
| 599 | 525 |
| 600 _RandomAccessFile(int this._id, String this.path); | 526 _RandomAccessFile(int this._id, String this.path); |
| 601 | 527 |
| 602 Future<RandomAccessFile> close() { | 528 Future<RandomAccessFile> close() { |
| 603 if (closed) return _closedException(); | 529 if (closed) return _closedException(); |
| 604 _ensureFileService(); | |
| 605 List request = new List(2); | |
| 606 request[0] = _CLOSE_REQUEST; | |
| 607 request[1] = _id; | |
| 608 // Set the id_ to 0 (NULL) to ensure the no more async requests | 530 // Set the id_ to 0 (NULL) to ensure the no more async requests |
| 609 // can be issued for this file. | 531 // can be issued for this file. |
| 532 int id = _id; |
| 610 _id = 0; | 533 _id = 0; |
| 611 return _fileService.call(request).then((result) { | 534 return IOService.dispatch(FILE_CLOSE, [id]).then((result) { |
| 612 if (result != -1) { | 535 if (result != -1) { |
| 613 _id = result; | 536 _id = result; |
| 614 return this; | 537 return this; |
| 615 } else { | 538 } else { |
| 616 throw new FileException("Cannot close file", path); | 539 throw new FileException("Cannot close file", path); |
| 617 } | 540 } |
| 618 }); | 541 }); |
| 619 } | 542 } |
| 620 | 543 |
| 621 external static int _close(int id); | 544 external static int _close(int id); |
| 622 | 545 |
| 623 void closeSync() { | 546 void closeSync() { |
| 624 _checkNotClosed(); | 547 _checkNotClosed(); |
| 625 var id = _close(_id); | 548 var id = _close(_id); |
| 626 if (id == -1) { | 549 if (id == -1) { |
| 627 throw new FileException("Cannot close file", path); | 550 throw new FileException("Cannot close file", path); |
| 628 } | 551 } |
| 629 _id = id; | 552 _id = id; |
| 630 } | 553 } |
| 631 | 554 |
| 632 Future<int> readByte() { | 555 Future<int> readByte() { |
| 633 _ensureFileService(); | |
| 634 if (closed) return _closedException(); | 556 if (closed) return _closedException(); |
| 635 List request = new List(2); | 557 return IOService.dispatch(FILE_READ_BYTE, [_id]).then((response) { |
| 636 request[0] = _READ_BYTE_REQUEST; | |
| 637 request[1] = _id; | |
| 638 return _fileService.call(request).then((response) { | |
| 639 if (_isErrorResponse(response)) { | 558 if (_isErrorResponse(response)) { |
| 640 throw _exceptionFromResponse(response, "readByte failed", path); | 559 throw _exceptionFromResponse(response, "readByte failed", path); |
| 641 } | 560 } |
| 642 return response; | 561 return response; |
| 643 }); | 562 }); |
| 644 } | 563 } |
| 645 | 564 |
| 646 external static _readByte(int id); | 565 external static _readByte(int id); |
| 647 | 566 |
| 648 int readByteSync() { | 567 int readByteSync() { |
| 649 _checkNotClosed(); | 568 _checkNotClosed(); |
| 650 var result = _readByte(_id); | 569 var result = _readByte(_id); |
| 651 if (result is OSError) { | 570 if (result is OSError) { |
| 652 throw new FileException("readByte failed", path, result); | 571 throw new FileException("readByte failed", path, result); |
| 653 } | 572 } |
| 654 return result; | 573 return result; |
| 655 } | 574 } |
| 656 | 575 |
| 657 Future<List<int>> read(int bytes) { | 576 Future<List<int>> read(int bytes) { |
| 658 _ensureFileService(); | |
| 659 if (bytes is !int) { | 577 if (bytes is !int) { |
| 660 throw new ArgumentError(bytes); | 578 throw new ArgumentError(bytes); |
| 661 } | 579 } |
| 662 if (closed) return _closedException(); | 580 if (closed) return _closedException(); |
| 663 List request = new List(3); | 581 return IOService.dispatch(FILE_READ, [_id, bytes]).then((response) { |
| 664 request[0] = _READ_REQUEST; | |
| 665 request[1] = _id; | |
| 666 request[2] = bytes; | |
| 667 return _fileService.call(request).then((response) { | |
| 668 if (_isErrorResponse(response)) { | 582 if (_isErrorResponse(response)) { |
| 669 throw _exceptionFromResponse(response, "read failed", path); | 583 throw _exceptionFromResponse(response, "read failed", path); |
| 670 } | 584 } |
| 671 return response[1]; | 585 return response[1]; |
| 672 }); | 586 }); |
| 673 } | 587 } |
| 674 | 588 |
| 675 external static _read(int id, int bytes); | 589 external static _read(int id, int bytes); |
| 676 | 590 |
| 677 List<int> readSync(int bytes) { | 591 List<int> readSync(int bytes) { |
| 678 _checkNotClosed(); | 592 _checkNotClosed(); |
| 679 if (bytes is !int) { | 593 if (bytes is !int) { |
| 680 throw new ArgumentError(bytes); | 594 throw new ArgumentError(bytes); |
| 681 } | 595 } |
| 682 var result = _read(_id, bytes); | 596 var result = _read(_id, bytes); |
| 683 if (result is OSError) { | 597 if (result is OSError) { |
| 684 throw new FileException("readSync failed", path, result); | 598 throw new FileException("readSync failed", path, result); |
| 685 } | 599 } |
| 686 return result; | 600 return result; |
| 687 } | 601 } |
| 688 | 602 |
| 689 Future<int> readInto(List<int> buffer, [int start, int end]) { | 603 Future<int> readInto(List<int> buffer, [int start, int end]) { |
| 690 _ensureFileService(); | |
| 691 if (buffer is !List || | 604 if (buffer is !List || |
| 692 (start != null && start is !int) || | 605 (start != null && start is !int) || |
| 693 (end != null && end is !int)) { | 606 (end != null && end is !int)) { |
| 694 throw new ArgumentError(); | 607 throw new ArgumentError(); |
| 695 } | 608 } |
| 696 if (closed) return _closedException(); | 609 if (closed) return _closedException(); |
| 697 List request = new List(3); | |
| 698 if (start == null) start = 0; | 610 if (start == null) start = 0; |
| 699 if (end == null) end = buffer.length; | 611 if (end == null) end = buffer.length; |
| 700 request[0] = _READ_LIST_REQUEST; | 612 int length = end - start; |
| 701 request[1] = _id; | 613 return IOService.dispatch(FILE_READ_INTO, [_id, length]).then((response) { |
| 702 request[2] = end - start; | |
| 703 return _fileService.call(request).then((response) { | |
| 704 if (_isErrorResponse(response)) { | 614 if (_isErrorResponse(response)) { |
| 705 throw _exceptionFromResponse(response, "readInto failed", path); | 615 throw _exceptionFromResponse(response, "readInto failed", path); |
| 706 } | 616 } |
| 707 var read = response[1]; | 617 var read = response[1]; |
| 708 var data = response[2]; | 618 var data = response[2]; |
| 709 buffer.setRange(start, start + read, data); | 619 buffer.setRange(start, start + read, data); |
| 710 return read; | 620 return read; |
| 711 }); | 621 }); |
| 712 } | 622 } |
| 713 | 623 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 733 if (end == start) return 0; | 643 if (end == start) return 0; |
| 734 _checkReadWriteListArguments(buffer.length, start, end); | 644 _checkReadWriteListArguments(buffer.length, start, end); |
| 735 var result = _readInto(_id, buffer, start, end); | 645 var result = _readInto(_id, buffer, start, end); |
| 736 if (result is OSError) { | 646 if (result is OSError) { |
| 737 throw new FileException("readInto failed", path, result); | 647 throw new FileException("readInto failed", path, result); |
| 738 } | 648 } |
| 739 return result; | 649 return result; |
| 740 } | 650 } |
| 741 | 651 |
| 742 Future<RandomAccessFile> writeByte(int value) { | 652 Future<RandomAccessFile> writeByte(int value) { |
| 743 _ensureFileService(); | |
| 744 if (value is !int) { | 653 if (value is !int) { |
| 745 throw new ArgumentError(value); | 654 throw new ArgumentError(value); |
| 746 } | 655 } |
| 747 if (closed) return _closedException(); | 656 if (closed) return _closedException(); |
| 748 List request = new List(3); | 657 return IOService.dispatch(FILE_WRITE_BYTE, [_id, value]).then((response) { |
| 749 request[0] = _WRITE_BYTE_REQUEST; | |
| 750 request[1] = _id; | |
| 751 request[2] = value; | |
| 752 return _fileService.call(request).then((response) { | |
| 753 if (_isErrorResponse(response)) { | 658 if (_isErrorResponse(response)) { |
| 754 throw _exceptionFromResponse(response, "writeByte failed", path); | 659 throw _exceptionFromResponse(response, "writeByte failed", path); |
| 755 } | 660 } |
| 756 return this; | 661 return this; |
| 757 }); | 662 }); |
| 758 } | 663 } |
| 759 | 664 |
| 760 external static _writeByte(int id, int value); | 665 external static _writeByte(int id, int value); |
| 761 | 666 |
| 762 int writeByteSync(int value) { | 667 int writeByteSync(int value) { |
| 763 _checkNotClosed(); | 668 _checkNotClosed(); |
| 764 if (value is !int) { | 669 if (value is !int) { |
| 765 throw new ArgumentError(value); | 670 throw new ArgumentError(value); |
| 766 } | 671 } |
| 767 var result = _writeByte(_id, value); | 672 var result = _writeByte(_id, value); |
| 768 if (result is OSError) { | 673 if (result is OSError) { |
| 769 throw new FileException("writeByte failed", path, result); | 674 throw new FileException("writeByte failed", path, result); |
| 770 } | 675 } |
| 771 return result; | 676 return result; |
| 772 } | 677 } |
| 773 | 678 |
| 774 Future<RandomAccessFile> writeFrom(List<int> buffer, [int start, int end]) { | 679 Future<RandomAccessFile> writeFrom(List<int> buffer, [int start, int end]) { |
| 775 _ensureFileService(); | |
| 776 if ((buffer is !List && buffer is !ByteData) || | 680 if ((buffer is !List && buffer is !ByteData) || |
| 777 (start != null && start is !int) || | 681 (start != null && start is !int) || |
| 778 (end != null && end is !int)) { | 682 (end != null && end is !int)) { |
| 779 throw new ArgumentError("Invalid arguments to writeFrom"); | 683 throw new ArgumentError("Invalid arguments to writeFrom"); |
| 780 } | 684 } |
| 781 | 685 |
| 782 if (closed) return _closedException(); | 686 if (closed) return _closedException(); |
| 783 | 687 |
| 784 _BufferAndStart result; | 688 _BufferAndStart result; |
| 785 try { | 689 try { |
| 786 result = _ensureFastAndSerializableByteData(buffer, start, end); | 690 result = _ensureFastAndSerializableByteData(buffer, start, end); |
| 787 } catch (e) { | 691 } catch (e) { |
| 788 return new Future.error(e); | 692 return new Future.error(e); |
| 789 } | 693 } |
| 790 | 694 |
| 791 List request = new List(5); | 695 List request = new List(4); |
| 792 request[0] = _WRITE_LIST_REQUEST; | 696 request[0] = _id; |
| 793 request[1] = _id; | 697 request[1] = result.buffer; |
| 794 request[2] = result.buffer; | 698 request[2] = result.start; |
| 795 request[3] = result.start; | 699 request[3] = end - (start - result.start); |
| 796 request[4] = end - (start - result.start); | 700 return IOService.dispatch(FILE_WRITE_FROM, request).then((response) { |
| 797 return _fileService.call(request).then((response) { | |
| 798 if (_isErrorResponse(response)) { | 701 if (_isErrorResponse(response)) { |
| 799 throw _exceptionFromResponse(response, "writeFrom failed", path); | 702 throw _exceptionFromResponse(response, "writeFrom failed", path); |
| 800 } | 703 } |
| 801 return this; | 704 return this; |
| 802 }); | 705 }); |
| 803 } | 706 } |
| 804 | 707 |
| 805 external static _writeFrom(int id, List<int> buffer, int start, int end); | 708 external static _writeFrom(int id, List<int> buffer, int start, int end); |
| 806 | 709 |
| 807 void writeFromSync(List<int> buffer, [int start, int end]) { | 710 void writeFromSync(List<int> buffer, [int start, int end]) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 837 | 740 |
| 838 void writeStringSync(String string, {Encoding encoding: UTF8}) { | 741 void writeStringSync(String string, {Encoding encoding: UTF8}) { |
| 839 if (encoding is! Encoding) { | 742 if (encoding is! Encoding) { |
| 840 throw new ArgumentError(encoding); | 743 throw new ArgumentError(encoding); |
| 841 } | 744 } |
| 842 var data = encoding.encode(string); | 745 var data = encoding.encode(string); |
| 843 writeFromSync(data, 0, data.length); | 746 writeFromSync(data, 0, data.length); |
| 844 } | 747 } |
| 845 | 748 |
| 846 Future<int> position() { | 749 Future<int> position() { |
| 847 _ensureFileService(); | |
| 848 if (closed) return _closedException(); | 750 if (closed) return _closedException(); |
| 849 List request = new List(2); | 751 return IOService.dispatch(FILE_POSITION, [_id]).then((response) { |
| 850 request[0] = _POSITION_REQUEST; | |
| 851 request[1] = _id; | |
| 852 return _fileService.call(request).then((response) { | |
| 853 if (_isErrorResponse(response)) { | 752 if (_isErrorResponse(response)) { |
| 854 throw _exceptionFromResponse(response, "position failed", path); | 753 throw _exceptionFromResponse(response, "position failed", path); |
| 855 } | 754 } |
| 856 return response; | 755 return response; |
| 857 }); | 756 }); |
| 858 } | 757 } |
| 859 | 758 |
| 860 external static _position(int id); | 759 external static _position(int id); |
| 861 | 760 |
| 862 int positionSync() { | 761 int positionSync() { |
| 863 _checkNotClosed(); | 762 _checkNotClosed(); |
| 864 var result = _position(_id); | 763 var result = _position(_id); |
| 865 if (result is OSError) { | 764 if (result is OSError) { |
| 866 throw new FileException("position failed", path, result); | 765 throw new FileException("position failed", path, result); |
| 867 } | 766 } |
| 868 return result; | 767 return result; |
| 869 } | 768 } |
| 870 | 769 |
| 871 Future<RandomAccessFile> setPosition(int position) { | 770 Future<RandomAccessFile> setPosition(int position) { |
| 872 _ensureFileService(); | |
| 873 if (closed) return _closedException(); | 771 if (closed) return _closedException(); |
| 874 List request = new List(3); | 772 return IOService.dispatch(FILE_SET_POSITION, [_id, position]) |
| 875 request[0] = _SET_POSITION_REQUEST; | 773 .then((response) { |
| 876 request[1] = _id; | 774 if (_isErrorResponse(response)) { |
| 877 request[2] = position; | 775 throw _exceptionFromResponse(response, "setPosition failed", path); |
| 878 return _fileService.call(request).then((response) { | 776 } |
| 879 if (_isErrorResponse(response)) { | 777 return this; |
| 880 throw _exceptionFromResponse(response, "setPosition failed", path); | 778 }); |
| 881 } | |
| 882 return this; | |
| 883 }); | |
| 884 } | 779 } |
| 885 | 780 |
| 886 external static _setPosition(int id, int position); | 781 external static _setPosition(int id, int position); |
| 887 | 782 |
| 888 void setPositionSync(int position) { | 783 void setPositionSync(int position) { |
| 889 _checkNotClosed(); | 784 _checkNotClosed(); |
| 890 var result = _setPosition(_id, position); | 785 var result = _setPosition(_id, position); |
| 891 if (result is OSError) { | 786 if (result is OSError) { |
| 892 throw new FileException("setPosition failed", path, result); | 787 throw new FileException("setPosition failed", path, result); |
| 893 } | 788 } |
| 894 } | 789 } |
| 895 | 790 |
| 896 Future<RandomAccessFile> truncate(int length) { | 791 Future<RandomAccessFile> truncate(int length) { |
| 897 _ensureFileService(); | |
| 898 if (closed) return _closedException(); | 792 if (closed) return _closedException(); |
| 899 List request = new List(3); | 793 return IOService.dispatch(FILE_TRUNCATE, [_id, length]).then((response) { |
| 900 request[0] = _TRUNCATE_REQUEST; | |
| 901 request[1] = _id; | |
| 902 request[2] = length; | |
| 903 return _fileService.call(request).then((response) { | |
| 904 if (_isErrorResponse(response)) { | 794 if (_isErrorResponse(response)) { |
| 905 throw _exceptionFromResponse(response, "truncate failed", path); | 795 throw _exceptionFromResponse(response, "truncate failed", path); |
| 906 } | 796 } |
| 907 return this; | 797 return this; |
| 908 }); | 798 }); |
| 909 } | 799 } |
| 910 | 800 |
| 911 external static _truncate(int id, int length); | 801 external static _truncate(int id, int length); |
| 912 | 802 |
| 913 void truncateSync(int length) { | 803 void truncateSync(int length) { |
| 914 _checkNotClosed(); | 804 _checkNotClosed(); |
| 915 var result = _truncate(_id, length); | 805 var result = _truncate(_id, length); |
| 916 if (result is OSError) { | 806 if (result is OSError) { |
| 917 throw new FileException("truncate failed", path, result); | 807 throw new FileException("truncate failed", path, result); |
| 918 } | 808 } |
| 919 } | 809 } |
| 920 | 810 |
| 921 Future<int> length() { | 811 Future<int> length() { |
| 922 _ensureFileService(); | |
| 923 if (closed) return _closedException(); | 812 if (closed) return _closedException(); |
| 924 List request = new List(2); | 813 return IOService.dispatch(FILE_LENGTH, [_id]).then((response) { |
| 925 request[0] = _LENGTH_REQUEST; | |
| 926 request[1] = _id; | |
| 927 return _fileService.call(request).then((response) { | |
| 928 if (_isErrorResponse(response)) { | 814 if (_isErrorResponse(response)) { |
| 929 throw _exceptionFromResponse(response, "length failed", path); | 815 throw _exceptionFromResponse(response, "length failed", path); |
| 930 } | 816 } |
| 931 return response; | 817 return response; |
| 932 }); | 818 }); |
| 933 } | 819 } |
| 934 | 820 |
| 935 external static _length(int id); | 821 external static _length(int id); |
| 936 | 822 |
| 937 int lengthSync() { | 823 int lengthSync() { |
| 938 _checkNotClosed(); | 824 _checkNotClosed(); |
| 939 var result = _length(_id); | 825 var result = _length(_id); |
| 940 if (result is OSError) { | 826 if (result is OSError) { |
| 941 throw new FileException("length failed", path, result); | 827 throw new FileException("length failed", path, result); |
| 942 } | 828 } |
| 943 return result; | 829 return result; |
| 944 } | 830 } |
| 945 | 831 |
| 946 Future<RandomAccessFile> flush() { | 832 Future<RandomAccessFile> flush() { |
| 947 _ensureFileService(); | |
| 948 if (closed) return _closedException(); | 833 if (closed) return _closedException(); |
| 949 List request = new List(2); | 834 return IOService.dispatch(FILE_FLUSH, [_id]).then((response) { |
| 950 request[0] = _FLUSH_REQUEST; | |
| 951 request[1] = _id; | |
| 952 return _fileService.call(request).then((response) { | |
| 953 if (_isErrorResponse(response)) { | 835 if (_isErrorResponse(response)) { |
| 954 throw _exceptionFromResponse(response, | 836 throw _exceptionFromResponse(response, |
| 955 "flush failed", | 837 "flush failed", |
| 956 path); | 838 path); |
| 957 } | 839 } |
| 958 return this; | 840 return this; |
| 959 }); | 841 }); |
| 960 } | 842 } |
| 961 | 843 |
| 962 external static _flush(int id); | 844 external static _flush(int id); |
| 963 | 845 |
| 964 void flushSync() { | 846 void flushSync() { |
| 965 _checkNotClosed(); | 847 _checkNotClosed(); |
| 966 var result = _flush(_id); | 848 var result = _flush(_id); |
| 967 if (result is OSError) { | 849 if (result is OSError) { |
| 968 throw new FileException("flush failed", path, result); | 850 throw new FileException("flush failed", path, result); |
| 969 } | 851 } |
| 970 } | 852 } |
| 971 | 853 |
| 972 void _ensureFileService() { | |
| 973 if (_fileService == null) { | |
| 974 _fileService = _FileUtils._newServicePort(); | |
| 975 } | |
| 976 } | |
| 977 | |
| 978 bool get closed => _id == 0; | 854 bool get closed => _id == 0; |
| 979 | 855 |
| 980 void _checkNotClosed() { | 856 void _checkNotClosed() { |
| 981 if (closed) { | 857 if (closed) { |
| 982 throw new FileException("File closed", path); | 858 throw new FileException("File closed", path); |
| 983 } | 859 } |
| 984 } | 860 } |
| 985 | 861 |
| 986 Future _closedException() { | 862 Future _closedException() { |
| 987 return new Future.error(new FileException("File closed", path)); | 863 return new Future.error(new FileException("File closed", path)); |
| 988 } | 864 } |
| 989 } | 865 } |
| OLD | NEW |