| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 class _FileInputStream extends _BaseDataInputStream implements InputStream { | 5 class _FileInputStream extends _BaseDataInputStream implements InputStream { |
| 6 _FileInputStream(String name) { | 6 _FileInputStream(String name) { |
| 7 _file = new File(name); | 7 _file = new File(name); |
| 8 _data = []; | 8 _data = []; |
| 9 _position = 0; | 9 _position = 0; |
| 10 _file.errorHandler = (String s) { | 10 _file.onError = (String s) { |
| 11 if (_clientErrorHandler != null) { | 11 if (_clientErrorHandler != null) { |
| 12 _clientErrorHandler(); | 12 _clientErrorHandler(); |
| 13 } | 13 } |
| 14 }; | 14 }; |
| 15 _file.open(); | 15 _file.open(FileMode.READ, (openedFile) { |
| 16 _file.openHandler = (openedFile) { | |
| 17 _readDataFromFile(openedFile); | 16 _readDataFromFile(openedFile); |
| 18 }; | 17 }); |
| 19 } | 18 } |
| 20 | 19 |
| 21 _FileInputStream.fromStdio(int fd) { | 20 _FileInputStream.fromStdio(int fd) { |
| 22 assert(fd == 0); | 21 assert(fd == 0); |
| 23 _file = _File._openStdioSync(fd); | 22 _file = _File._openStdioSync(fd); |
| 24 _data = []; | 23 _data = []; |
| 25 _position = 0; | 24 _position = 0; |
| 26 _readDataFromFile(_file); | 25 _readDataFromFile(_file); |
| 27 } | 26 } |
| 28 | 27 |
| 29 void _readDataFromFile(RandomAccessFile openedFile) { | 28 void _readDataFromFile(RandomAccessFile openedFile) { |
| 30 openedFile.errorHandler = (String s) { | 29 openedFile.onError = (String s) { |
| 31 if (_clientErrorHandler != null) { | 30 if (_clientErrorHandler != null) { |
| 32 _clientErrorHandler(); | 31 _clientErrorHandler(); |
| 33 } | 32 } |
| 34 }; | 33 }; |
| 35 openedFile.length(); | 34 openedFile.length((length) { |
| 36 openedFile.lengthHandler = (length) { | |
| 37 var contents = new ByteArray(length); | 35 var contents = new ByteArray(length); |
| 38 if (length != 0) { | 36 if (length != 0) { |
| 39 openedFile.readList(contents, 0, length); | 37 openedFile.readList(contents, 0, length, (read) { |
| 40 openedFile.readListHandler = (read) { | |
| 41 if (read != length) { | 38 if (read != length) { |
| 42 if (_clientErrorHandler != null) { | 39 if (_clientErrorHandler != null) { |
| 43 _clientErrorHandler(); | 40 _clientErrorHandler(); |
| 44 } | 41 } |
| 45 } else { | 42 } else { |
| 46 _data = contents; | 43 _data = contents; |
| 47 } | 44 } |
| 48 openedFile.close(); | 45 openedFile.close(() { |
| 49 openedFile.closeHandler = () { | |
| 50 _streamMarkedClosed = true; | 46 _streamMarkedClosed = true; |
| 51 _checkScheduleCallbacks(); | 47 _checkScheduleCallbacks(); |
| 52 }; | 48 }); |
| 53 }; | 49 }); |
| 54 } else { | 50 } else { |
| 55 openedFile.close(); | 51 openedFile.close(() { |
| 56 openedFile.closeHandler = () { | |
| 57 _streamMarkedClosed = true; | 52 _streamMarkedClosed = true; |
| 58 _checkScheduleCallbacks(); | 53 _checkScheduleCallbacks(); |
| 59 }; | 54 }); |
| 60 }; | 55 } |
| 61 }; | 56 }); |
| 62 } | 57 } |
| 63 | 58 |
| 64 int available() { | 59 int available() { |
| 65 return _closed ? 0 : _data.length - _position; | 60 return _closed ? 0 : _data.length - _position; |
| 66 } | 61 } |
| 67 | 62 |
| 68 void pipe(OutputStream output, [bool close = true]) { | 63 void pipe(OutputStream output, [bool close = true]) { |
| 69 _pipe(this, output, close: close); | 64 _pipe(this, output, close: close); |
| 70 } | 65 } |
| 71 | 66 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 93 List<int> _data; | 88 List<int> _data; |
| 94 int _position; | 89 int _position; |
| 95 bool _closed = false; | 90 bool _closed = false; |
| 96 } | 91 } |
| 97 | 92 |
| 98 | 93 |
| 99 class _FileOutputStream implements OutputStream { | 94 class _FileOutputStream implements OutputStream { |
| 100 _FileOutputStream(String name, FileMode mode) { | 95 _FileOutputStream(String name, FileMode mode) { |
| 101 _pendingOperations = new List<List<int>>(); | 96 _pendingOperations = new List<List<int>>(); |
| 102 var f = new File(name); | 97 var f = new File(name); |
| 103 f.open(mode); | 98 f.open(mode, (openedFile) { |
| 104 f.openHandler = (openedFile) { | |
| 105 _file = openedFile; | 99 _file = openedFile; |
| 106 _setupFileHandlers(); | 100 _setupFileHandlers(); |
| 107 _processPendingOperations(); | 101 _processPendingOperations(); |
| 108 }; | 102 }); |
| 109 f.errorHandler = (e) { | 103 f.onError = (e) { |
| 110 if (_errorHandler != null) _errorHandler(); | 104 if (_onError != null) _onError(); |
| 111 }; | 105 }; |
| 112 } | 106 } |
| 113 | 107 |
| 114 _FileOutputStream.fromStdio(int fd) { | 108 _FileOutputStream.fromStdio(int fd) { |
| 115 assert(1 <= fd && fd <= 2); | 109 assert(1 <= fd && fd <= 2); |
| 116 _file = _File._openStdioSync(fd); | 110 _file = _File._openStdioSync(fd); |
| 117 _setupFileHandlers(); | 111 _setupFileHandlers(); |
| 118 } | 112 } |
| 119 | 113 |
| 120 | 114 |
| 121 void _setupFileHandlers() { | 115 void _setupFileHandlers() { |
| 122 _file.errorHandler = (e) { | 116 _file.onError = (e) { |
| 123 if (_errorHandler != null) _errorHandler(); | 117 if (_onError != null) _onError(); |
| 124 }; | 118 }; |
| 125 _file.noPendingWriteHandler = () { | 119 _file.onNoPendingWrites = () { |
| 126 if (!_streamMarkedClosed && _noPendingWriteHandler != null) { | 120 if (!_streamMarkedClosed && _onNoPendingWrites != null) { |
| 127 _noPendingWriteHandler(); | 121 _onNoPendingWrites(); |
| 128 } | 122 } |
| 129 }; | 123 }; |
| 130 _file.closeHandler = () { | |
| 131 if (_closeHandler != null) _closeHandler(); | |
| 132 }; | |
| 133 } | 124 } |
| 134 | 125 |
| 135 bool write(List<int> buffer, [bool copyBuffer = false]) { | 126 bool write(List<int> buffer, [bool copyBuffer = false]) { |
| 136 var data = buffer; | 127 var data = buffer; |
| 137 if (copyBuffer) { | 128 if (copyBuffer) { |
| 138 var length = buffer.length; | 129 var length = buffer.length; |
| 139 data = new ByteArray(length); | 130 data = new ByteArray(length); |
| 140 data.setRange(0, length, buffer, 0); | 131 data.setRange(0, length, buffer, 0); |
| 141 } | 132 } |
| 142 if (_file == null) { | 133 if (_file == null) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 156 } | 147 } |
| 157 var copy = new ByteArray(length); | 148 var copy = new ByteArray(length); |
| 158 copy.setRange(0, length, buffer, offset); | 149 copy.setRange(0, length, buffer, offset); |
| 159 return write(copy); | 150 return write(copy); |
| 160 } | 151 } |
| 161 | 152 |
| 162 void close() { | 153 void close() { |
| 163 if (_file == null) { | 154 if (_file == null) { |
| 164 _pendingOperations.add(null); | 155 _pendingOperations.add(null); |
| 165 } else if (!_streamMarkedClosed) { | 156 } else if (!_streamMarkedClosed) { |
| 166 _file.close(); | 157 _file.close(() { |
| 158 if (_onClosed != null) _onClosed(); |
| 159 }); |
| 167 _streamMarkedClosed = true; | 160 _streamMarkedClosed = true; |
| 168 } | 161 } |
| 169 } | 162 } |
| 170 | 163 |
| 171 void set noPendingWriteHandler(void callback()) { | 164 void set onNoPendingWrites(void callback()) { |
| 172 _noPendingWriteHandler = callback; | 165 _onNoPendingWrites = callback; |
| 173 } | 166 } |
| 174 | 167 |
| 175 void set closeHandler(void callback()) { | 168 void set onClosed(void callback()) { |
| 176 _closeHandler = callback; | 169 _onClosed = callback; |
| 177 } | 170 } |
| 178 | 171 |
| 179 void set errorHandler(void callback()) { | 172 void set onError(void callback()) { |
| 180 _errorHandler = callback; | 173 _onError = callback; |
| 181 } | 174 } |
| 182 | 175 |
| 183 void _processPendingOperations() { | 176 void _processPendingOperations() { |
| 184 _pendingOperations.forEach((buffer) { | 177 _pendingOperations.forEach((buffer) { |
| 185 (buffer != null) ? write(buffer) : close(); | 178 (buffer != null) ? write(buffer) : close(); |
| 186 }); | 179 }); |
| 187 _pendingOperations = null; | 180 _pendingOperations = null; |
| 188 } | 181 } |
| 189 | 182 |
| 190 void _write(List<int> buffer, int offset, int len) { | 183 void _write(List<int> buffer, int offset, int len) { |
| 191 _file.writeList(buffer, offset, len); | 184 _file.writeList(buffer, offset, len); |
| 192 } | 185 } |
| 193 | 186 |
| 194 RandomAccessFile _file; | 187 RandomAccessFile _file; |
| 195 | 188 |
| 196 // When this is set to true the stream is marked closed. When a | 189 // When this is set to true the stream is marked closed. When a |
| 197 // stream is marked closed no more data can be written. | 190 // stream is marked closed no more data can be written. |
| 198 bool _streamMarkedClosed = false; | 191 bool _streamMarkedClosed = false; |
| 199 | 192 |
| 200 // When this is set to true the close callback has been called and | 193 // When this is set to true the close callback has been called and |
| 201 // the stream is fully closed. | 194 // the stream is fully closed. |
| 202 bool _closeCallbackCalled = false; | 195 bool _closeCallbackCalled = false; |
| 203 | 196 |
| 204 // List of pending writes that were issued before the underlying | 197 // List of pending writes that were issued before the underlying |
| 205 // file was successfully opened. | 198 // file was successfully opened. |
| 206 List<List<int>> _pendingOperations; | 199 List<List<int>> _pendingOperations; |
| 207 | 200 |
| 208 Function _noPendingWriteHandler; | 201 Function _onNoPendingWrites; |
| 209 Function _closeHandler; | 202 Function _onClosed; |
| 210 Function _errorHandler; | 203 Function _onError; |
| 211 } | 204 } |
| 212 | 205 |
| 213 | 206 |
| 214 // Helper class containing static file helper methods. | 207 // Helper class containing static file helper methods. |
| 215 class _FileUtils { | 208 class _FileUtils { |
| 216 static final kExistsRequest = 0; | 209 static final kExistsRequest = 0; |
| 217 static final kCreateRequest = 1; | 210 static final kCreateRequest = 1; |
| 218 static final kDeleteRequest = 2; | 211 static final kDeleteRequest = 2; |
| 219 static final kOpenRequest = 3; | 212 static final kOpenRequest = 3; |
| 220 static final kFullPathRequest = 4; | 213 static final kFullPathRequest = 4; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 return writeString(id, string); | 311 return writeString(id, string); |
| 319 } | 312 } |
| 320 } | 313 } |
| 321 | 314 |
| 322 | 315 |
| 323 // Class for encapsulating the native implementation of files. | 316 // Class for encapsulating the native implementation of files. |
| 324 class _File implements File { | 317 class _File implements File { |
| 325 // Constructor for file. | 318 // Constructor for file. |
| 326 _File(String this._name) : _asyncUsed = false; | 319 _File(String this._name) : _asyncUsed = false; |
| 327 | 320 |
| 328 void exists() { | 321 void exists(void callback(bool exists)) { |
| 329 _ensureFileService(); | 322 _ensureFileService(); |
| 330 _asyncUsed = true; | 323 _asyncUsed = true; |
| 331 if (_name is !String) { | 324 if (_name is !String) { |
| 332 if (_errorHandler != null) { | 325 if (_onError != null) { |
| 333 _errorHandler('File name is not a string: $_name'); | 326 _onError('File name is not a string: $_name'); |
| 334 } | 327 } |
| 335 return; | 328 return; |
| 336 } | 329 } |
| 337 List request = new List(2); | 330 List request = new List(2); |
| 338 request[0] = _FileUtils.kExistsRequest; | 331 request[0] = _FileUtils.kExistsRequest; |
| 339 request[1] = _name; | 332 request[1] = _name; |
| 340 _fileService.call(request).receive((exists, replyTo) { | 333 _fileService.call(request).receive((exists, replyTo) { |
| 341 if (_existsHandler != null) _existsHandler(exists); | 334 callback(exists); |
| 342 }); | 335 }); |
| 343 } | 336 } |
| 344 | 337 |
| 345 bool existsSync() { | 338 bool existsSync() { |
| 346 if (_asyncUsed) { | 339 if (_asyncUsed) { |
| 347 throw new FileIOException( | 340 throw new FileIOException( |
| 348 "Mixed use of synchronous and asynchronous API"); | 341 "Mixed use of synchronous and asynchronous API"); |
| 349 } | 342 } |
| 350 if (_name is !String) { | 343 if (_name is !String) { |
| 351 throw new FileIOException('File name is not a string: $_name'); | 344 throw new FileIOException('File name is not a string: $_name'); |
| 352 } | 345 } |
| 353 return _FileUtils.exists(_name); | 346 return _FileUtils.exists(_name); |
| 354 } | 347 } |
| 355 | 348 |
| 356 void create() { | 349 void create(void callback()) { |
| 357 _ensureFileService(); | 350 _ensureFileService(); |
| 358 _asyncUsed = true; | 351 _asyncUsed = true; |
| 359 List request = new List(2); | 352 List request = new List(2); |
| 360 request[0] = _FileUtils.kCreateRequest; | 353 request[0] = _FileUtils.kCreateRequest; |
| 361 request[1] = _name; | 354 request[1] = _name; |
| 362 _fileService.call(request).receive((created, replyTo) { | 355 _fileService.call(request).receive((created, replyTo) { |
| 363 if (created) { | 356 if (created) { |
| 364 if (_createHandler != null) _createHandler(); | 357 callback(); |
| 365 } else if (_errorHandler != null) { | 358 } else if (_onError != null) { |
| 366 _errorHandler("Cannot create file: $_name"); | 359 _onError("Cannot create file: $_name"); |
| 367 } | 360 } |
| 368 }); | 361 }); |
| 369 } | 362 } |
| 370 | 363 |
| 371 void createSync() { | 364 void createSync() { |
| 372 if (_asyncUsed) { | 365 if (_asyncUsed) { |
| 373 throw new FileIOException( | 366 throw new FileIOException( |
| 374 "Mixed use of synchronous and asynchronous API"); | 367 "Mixed use of synchronous and asynchronous API"); |
| 375 } | 368 } |
| 376 bool created = _FileUtils.checkedCreate(_name); | 369 bool created = _FileUtils.checkedCreate(_name); |
| 377 if (!created) { | 370 if (!created) { |
| 378 throw new FileIOException("Cannot create file: $_name"); | 371 throw new FileIOException("Cannot create file: $_name"); |
| 379 } | 372 } |
| 380 } | 373 } |
| 381 | 374 |
| 382 void delete() { | 375 void delete(void callback()) { |
| 383 _ensureFileService(); | 376 _ensureFileService(); |
| 384 _asyncUsed = true; | 377 _asyncUsed = true; |
| 385 List request = new List(2); | 378 List request = new List(2); |
| 386 request[0] = _FileUtils.kDeleteRequest; | 379 request[0] = _FileUtils.kDeleteRequest; |
| 387 request[1] = _name; | 380 request[1] = _name; |
| 388 _fileService.call(request).receive((deleted, replyTo) { | 381 _fileService.call(request).receive((deleted, replyTo) { |
| 389 if (deleted) { | 382 if (deleted) { |
| 390 if (_deleteHandler != null) _deleteHandler(); | 383 callback(); |
| 391 } else if (_errorHandler != null) { | 384 } else if (_onError != null) { |
| 392 _errorHandler("Cannot delete file: $_name"); | 385 _onError("Cannot delete file: $_name"); |
| 393 } | 386 } |
| 394 }); | 387 }); |
| 395 } | 388 } |
| 396 | 389 |
| 397 void deleteSync() { | 390 void deleteSync() { |
| 398 if (_asyncUsed) { | 391 if (_asyncUsed) { |
| 399 throw new FileIOException( | 392 throw new FileIOException( |
| 400 "Mixed use of synchronous and asynchronous API"); | 393 "Mixed use of synchronous and asynchronous API"); |
| 401 } | 394 } |
| 402 bool deleted = _FileUtils.checkedDelete(_name); | 395 bool deleted = _FileUtils.checkedDelete(_name); |
| 403 if (!deleted) { | 396 if (!deleted) { |
| 404 throw new FileIOException("Cannot delete file: $_name"); | 397 throw new FileIOException("Cannot delete file: $_name"); |
| 405 } | 398 } |
| 406 } | 399 } |
| 407 | 400 |
| 408 void directory() { | 401 void directory(void callback(Directory dir)) { |
| 409 _ensureFileService(); | 402 _ensureFileService(); |
| 410 _asyncUsed = true; | 403 _asyncUsed = true; |
| 411 List request = new List(2); | 404 List request = new List(2); |
| 412 request[0] = _FileUtils.kDirectoryRequest; | 405 request[0] = _FileUtils.kDirectoryRequest; |
| 413 request[1] = _name; | 406 request[1] = _name; |
| 414 _fileService.call(request).receive((path, replyTo) { | 407 _fileService.call(request).receive((path, replyTo) { |
| 415 if (path != null) { | 408 if (path != null) { |
| 416 if (_directoryHandler != null) _directoryHandler(new Directory(path)); | 409 callback(new Directory(path)); |
| 417 } else if (_errorHandler != null) { | 410 } else if (_onError != null) { |
| 418 _errorHandler("Cannot get directory for: ${_name}"); | 411 _onError("Cannot get directory for: ${_name}"); |
| 419 } | 412 } |
| 420 }); | 413 }); |
| 421 } | 414 } |
| 422 | 415 |
| 423 Directory directorySync() { | 416 Directory directorySync() { |
| 424 if (_asyncUsed) { | 417 if (_asyncUsed) { |
| 425 throw new FileIOException( | 418 throw new FileIOException( |
| 426 "Mixed use of synchronous and asynchronous API"); | 419 "Mixed use of synchronous and asynchronous API"); |
| 427 } | 420 } |
| 428 if (!existsSync()) { | 421 if (!existsSync()) { |
| 429 throw new FileIOException("Cannot get directory for: $_name"); | 422 throw new FileIOException("Cannot get directory for: $_name"); |
| 430 } | 423 } |
| 431 return new Directory(_FileUtils.directory(_name)); | 424 return new Directory(_FileUtils.directory(_name)); |
| 432 } | 425 } |
| 433 | 426 |
| 434 void open([FileMode mode = FileMode.READ]) { | 427 void open(FileMode mode, void callback(RandomAccessFile file)) { |
| 435 _ensureFileService(); | 428 _ensureFileService(); |
| 436 _asyncUsed = true; | 429 _asyncUsed = true; |
| 437 if (mode != FileMode.READ && | 430 if (mode != FileMode.READ && |
| 438 mode != FileMode.WRITE && | 431 mode != FileMode.WRITE && |
| 439 mode != FileMode.APPEND) { | 432 mode != FileMode.APPEND) { |
| 440 if (_errorHandler != null) { | 433 if (_onError != null) { |
| 441 _errorHandler("Unknown file mode. Use FileMode.READ, FileMode.WRITE " + | 434 _onError("Unknown file mode. Use FileMode.READ, FileMode.WRITE " + |
| 442 "or FileMode.APPEND."); | 435 "or FileMode.APPEND."); |
| 443 return; | 436 return; |
| 444 } | 437 } |
| 445 } | 438 } |
| 446 List request = new List(3); | 439 List request = new List(3); |
| 447 request[0] = _FileUtils.kOpenRequest; | 440 request[0] = _FileUtils.kOpenRequest; |
| 448 request[1] = _name; | 441 request[1] = _name; |
| 449 request[2] = mode._mode; // Direct int value for serialization. | 442 request[2] = mode._mode; // Direct int value for serialization. |
| 450 _fileService.call(request).receive((id, replyTo) { | 443 _fileService.call(request).receive((id, replyTo) { |
| 451 var handler = _openHandler; | |
| 452 if (handler === null) { | |
| 453 // If no open handler is present, close the file immediately to | |
| 454 // avoid leaking an open file descriptor. | |
| 455 handler = (file) => file.close(); | |
| 456 } | |
| 457 if (id != 0) { | 444 if (id != 0) { |
| 458 var randomAccessFile = new _RandomAccessFile(id, _name); | 445 callback(new _RandomAccessFile(id, _name)); |
| 459 handler(randomAccessFile); | 446 } else if (_onError != null) { |
| 460 } else if (_errorHandler != null) { | 447 _onError("Cannot open file: $_name"); |
| 461 _errorHandler("Cannot open file: $_name"); | |
| 462 } | 448 } |
| 463 }); | 449 }); |
| 464 } | 450 } |
| 465 | 451 |
| 466 RandomAccessFile openSync([FileMode mode = FileMode.READ]) { | 452 RandomAccessFile openSync([FileMode mode = FileMode.READ]) { |
| 467 if (_asyncUsed) { | 453 if (_asyncUsed) { |
| 468 throw new FileIOException( | 454 throw new FileIOException( |
| 469 "Mixed use of synchronous and asynchronous API"); | 455 "Mixed use of synchronous and asynchronous API"); |
| 470 } | 456 } |
| 471 if (mode != FileMode.READ && | 457 if (mode != FileMode.READ && |
| (...skipping 10 matching lines...) Expand all Loading... |
| 482 } | 468 } |
| 483 | 469 |
| 484 static RandomAccessFile _openStdioSync(int fd) { | 470 static RandomAccessFile _openStdioSync(int fd) { |
| 485 var id = _FileUtils.openStdio(fd); | 471 var id = _FileUtils.openStdio(fd); |
| 486 if (id == 0) { | 472 if (id == 0) { |
| 487 throw new FileIOException("Cannot open stdio file for: $fd"); | 473 throw new FileIOException("Cannot open stdio file for: $fd"); |
| 488 } | 474 } |
| 489 return new _RandomAccessFile(id, ""); | 475 return new _RandomAccessFile(id, ""); |
| 490 } | 476 } |
| 491 | 477 |
| 492 void fullPath() { | 478 void fullPath(void callback(String result)) { |
| 493 _ensureFileService(); | 479 _ensureFileService(); |
| 494 _asyncUsed = true; | 480 _asyncUsed = true; |
| 495 List request = new List(2); | 481 List request = new List(2); |
| 496 request[0] = _FileUtils.kFullPathRequest; | 482 request[0] = _FileUtils.kFullPathRequest; |
| 497 request[1] = _name; | 483 request[1] = _name; |
| 498 _fileService.call(request).receive((result, replyTo) { | 484 _fileService.call(request).receive((result, replyTo) { |
| 499 if (result != null) { | 485 if (result != null) { |
| 500 if (_fullPathHandler != null) _fullPathHandler(result); | 486 callback(result); |
| 501 } else if (_errorHandler != null) { | 487 } else if (_onError != null) { |
| 502 _errorHandler("fullPath failed"); | 488 _onError("fullPath failed"); |
| 503 } | 489 } |
| 504 }); | 490 }); |
| 505 } | 491 } |
| 506 | 492 |
| 507 String fullPathSync() { | 493 String fullPathSync() { |
| 508 if (_asyncUsed) { | 494 if (_asyncUsed) { |
| 509 throw new FileIOException( | 495 throw new FileIOException( |
| 510 "Mixed use of synchronous and asynchronous API"); | 496 "Mixed use of synchronous and asynchronous API"); |
| 511 } | 497 } |
| 512 String result = _FileUtils.checkedFullPath(_name); | 498 String result = _FileUtils.checkedFullPath(_name); |
| 513 if (result == null) { | 499 if (result == null) { |
| 514 throw new FileIOException("fullPath failed"); | 500 throw new FileIOException("fullPath failed"); |
| 515 } | 501 } |
| 516 return result; | 502 return result; |
| 517 } | 503 } |
| 518 | 504 |
| 519 InputStream openInputStream() { | 505 InputStream openInputStream() { |
| 520 return new _FileInputStream(_name); | 506 return new _FileInputStream(_name); |
| 521 } | 507 } |
| 522 | 508 |
| 523 OutputStream openOutputStream([FileMode mode = FileMode.WRITE]) { | 509 OutputStream openOutputStream([FileMode mode = FileMode.WRITE]) { |
| 524 if (mode != FileMode.WRITE && | 510 if (mode != FileMode.WRITE && |
| 525 mode != FileMode.APPEND) { | 511 mode != FileMode.APPEND) { |
| 526 throw new FileIOException( | 512 throw new FileIOException( |
| 527 "Wrong FileMode. Use FileMode.WRITE or FileMode.APPEND"); | 513 "Wrong FileMode. Use FileMode.WRITE or FileMode.APPEND"); |
| 528 } | 514 } |
| 529 return new _FileOutputStream(_name, mode); | 515 return new _FileOutputStream(_name, mode); |
| 530 } | 516 } |
| 531 | 517 |
| 532 void readAsBytes() { | 518 void readAsBytes(void callback(List<int> bytes)) { |
| 533 _asyncUsed = true; | 519 _asyncUsed = true; |
| 534 var chunks = new _BufferList(); | 520 var chunks = new _BufferList(); |
| 535 var stream = openInputStream(); | 521 var stream = openInputStream(); |
| 536 stream.closeHandler = () { | 522 stream.onClosed = () { |
| 537 if (_readAsBytesHandler != null) { | 523 callback(chunks.readBytes(chunks.length)); |
| 538 _readAsBytesHandler(chunks.readBytes(chunks.length)); | |
| 539 } | |
| 540 }; | 524 }; |
| 541 stream.dataHandler = () { | 525 stream.onData = () { |
| 542 var chunk = stream.read(); | 526 var chunk = stream.read(); |
| 543 chunks.add(chunk); | 527 chunks.add(chunk); |
| 544 }; | 528 }; |
| 545 stream.errorHandler = () { | 529 stream.onError = () { |
| 546 if (_errorHandler != null) { | 530 if (_onError != null) { |
| 547 _errorHandler("Failed to read file as bytes: $_name"); | 531 _onError("Failed to read file as bytes: $_name"); |
| 548 } | 532 } |
| 549 }; | 533 }; |
| 550 } | 534 } |
| 551 | 535 |
| 552 List<int> readAsBytesSync() { | 536 List<int> readAsBytesSync() { |
| 553 if (_asyncUsed) { | 537 if (_asyncUsed) { |
| 554 throw new FileIOException( | 538 throw new FileIOException( |
| 555 "Mixed use of synchronous and asynchronous API"); | 539 "Mixed use of synchronous and asynchronous API"); |
| 556 } | 540 } |
| 557 var opened = openSync(); | 541 var opened = openSync(); |
| 558 var length = opened.lengthSync(); | 542 var length = opened.lengthSync(); |
| 559 var result = new ByteArray(length); | 543 var result = new ByteArray(length); |
| 560 var read = opened.readListSync(result, 0, length); | 544 var read = opened.readListSync(result, 0, length); |
| 561 if (read != length) { | 545 if (read != length) { |
| 562 throw new FileIOException("Failed reading file as bytes: $_name"); | 546 throw new FileIOException("Failed reading file as bytes: $_name"); |
| 563 } | 547 } |
| 564 opened.close(); | 548 opened.closeSync(); |
| 565 return result; | 549 return result; |
| 566 } | 550 } |
| 567 | 551 |
| 568 _StringDecoder _getDecoder(encoding) { | 552 _StringDecoder _getDecoder(encoding) { |
| 569 if (encoding == "UTF-8") { | 553 if (encoding == "UTF-8") { |
| 570 return new _UTF8Decoder(); | 554 return new _UTF8Decoder(); |
| 571 } else if (encoding == "ISO-8859-1") { | 555 } else if (encoding == "ISO-8859-1") { |
| 572 return new _Latin1Decoder(); | 556 return new _Latin1Decoder(); |
| 573 } else if (encoding == "ASCII") { | 557 } else if (encoding == "ASCII") { |
| 574 return new _AsciiDecoder(); | 558 return new _AsciiDecoder(); |
| 575 } | 559 } |
| 576 throw new FileIOException("Unsupported encoding $_encoding"); | 560 throw new FileIOException("Unsupported encoding $_encoding"); |
| 577 } | 561 } |
| 578 | 562 |
| 579 void readAsText([String encoding = "UTF-8"]) { | 563 void readAsText(String encoding, void callback(String text)) { |
| 580 _asyncUsed = true; | 564 _asyncUsed = true; |
| 581 var decoder = _getDecoder(encoding); | 565 var decoder = _getDecoder(encoding); |
| 582 readAsBytes(); | 566 readAsBytes((bytes) { |
| 583 readAsBytesHandler = (bytes) { | 567 try { |
| 584 if (_readAsTextHandler != null) { | 568 decoder.write(bytes); |
| 585 try { | 569 } catch (var e) { |
| 586 decoder.write(bytes); | 570 if (_onError != null) { |
| 587 } catch (var e) { | 571 _onError(e.toString()); |
| 588 if (_errorHandler != null) { | 572 return; |
| 589 _errorHandler(e.toString()); | |
| 590 return; | |
| 591 } | |
| 592 } | 573 } |
| 593 _readAsTextHandler(decoder.decoded); | |
| 594 } | 574 } |
| 595 }; | 575 callback(decoder.decoded); |
| 576 }); |
| 596 } | 577 } |
| 597 | 578 |
| 598 String readAsTextSync([String encoding = "UTF-8"]) { | 579 String readAsTextSync([String encoding = 'UTF-8']) { |
| 599 if (_asyncUsed) { | 580 if (_asyncUsed) { |
| 600 throw new FileIOException( | 581 throw new FileIOException( |
| 601 "Mixed use of synchronous and asynchronous API"); | 582 "Mixed use of synchronous and asynchronous API"); |
| 602 } | 583 } |
| 603 var decoder = _getDecoder(encoding); | 584 var decoder = _getDecoder(encoding); |
| 604 List<int> bytes = readAsBytesSync(); | 585 List<int> bytes = readAsBytesSync(); |
| 605 decoder.write(bytes); | 586 decoder.write(bytes); |
| 606 return decoder.decoded; | 587 return decoder.decoded; |
| 607 } | 588 } |
| 608 | 589 |
| 609 List<String> _getDecodedLines(_StringDecoder decoder) { | 590 List<String> _getDecodedLines(_StringDecoder decoder) { |
| 610 List<String> result = []; | 591 List<String> result = []; |
| 611 var line = decoder.decodedLine; | 592 var line = decoder.decodedLine; |
| 612 while (line != null) { | 593 while (line != null) { |
| 613 result.add(line); | 594 result.add(line); |
| 614 line = decoder.decodedLine; | 595 line = decoder.decodedLine; |
| 615 } | 596 } |
| 616 // If there is more data with no terminating line break we treat | 597 // If there is more data with no terminating line break we treat |
| 617 // it as the last line. | 598 // it as the last line. |
| 618 var data = decoder.decoded; | 599 var data = decoder.decoded; |
| 619 if (data != null) { | 600 if (data != null) { |
| 620 result.add(data); | 601 result.add(data); |
| 621 } | 602 } |
| 622 return result; | 603 return result; |
| 623 } | 604 } |
| 624 | 605 |
| 625 void readAsLines([String encoding = "UTF-8"]) { | 606 void readAsLines(String encoding, void callback(List<String> lines)) { |
| 626 _asyncUsed = true; | 607 _asyncUsed = true; |
| 627 var decoder = _getDecoder(encoding); | 608 var decoder = _getDecoder(encoding); |
| 628 readAsBytes(); | 609 readAsBytes((bytes) { |
| 629 readAsBytesHandler = (bytes) { | 610 try { |
| 630 if (_readAsLinesHandler != null) { | 611 decoder.write(bytes); |
| 631 try { | 612 } catch (var e) { |
| 632 decoder.write(bytes); | 613 if (_onError != null) { |
| 633 } catch (var e) { | 614 _onError(e.toString()); |
| 634 if (_errorHandler != null) { | 615 return; |
| 635 _errorHandler(e.toString()); | |
| 636 return; | |
| 637 } | |
| 638 } | 616 } |
| 639 _readAsLinesHandler(_getDecodedLines(decoder)); | |
| 640 } | 617 } |
| 641 }; | 618 callback(_getDecodedLines(decoder)); |
| 619 }); |
| 642 } | 620 } |
| 643 | 621 |
| 644 List<String> readAsLinesSync([String encoding = "UTF-8"]) { | 622 List<String> readAsLinesSync([String encoding = "UTF-8"]) { |
| 645 if (_asyncUsed) { | 623 if (_asyncUsed) { |
| 646 throw new FileIOException( | 624 throw new FileIOException( |
| 647 "Mixed use of synchronous and asynchronous API"); | 625 "Mixed use of synchronous and asynchronous API"); |
| 648 } | 626 } |
| 649 var decoder = _getDecoder(encoding); | 627 var decoder = _getDecoder(encoding); |
| 650 List<int> bytes = readAsBytesSync(); | 628 List<int> bytes = readAsBytesSync(); |
| 651 decoder.write(bytes); | 629 decoder.write(bytes); |
| 652 return _getDecodedLines(decoder); | 630 return _getDecodedLines(decoder); |
| 653 } | 631 } |
| 654 | 632 |
| 655 String get name() => _name; | 633 String get name() => _name; |
| 656 | 634 |
| 657 void set existsHandler(void handler(bool exists)) { | 635 void set onError(void handler(String error)) { |
| 658 _existsHandler = handler; | 636 _onError = handler; |
| 659 } | |
| 660 | |
| 661 void set createHandler(void handler()) { | |
| 662 _createHandler = handler; | |
| 663 } | |
| 664 | |
| 665 void set deleteHandler(void handler()) { | |
| 666 _deleteHandler = handler; | |
| 667 } | |
| 668 | |
| 669 void set directoryHandler(void handler(Directory directory)) { | |
| 670 _directoryHandler = handler; | |
| 671 } | |
| 672 | |
| 673 void set openHandler(void handler(RandomAccessFile file)) { | |
| 674 _openHandler = handler; | |
| 675 } | |
| 676 | |
| 677 void set readAsBytesHandler(void handler(List<int> bytes)) { | |
| 678 _readAsBytesHandler = handler; | |
| 679 } | |
| 680 | |
| 681 void set readAsTextHandler(void handler(String text)) { | |
| 682 _readAsTextHandler = handler; | |
| 683 } | |
| 684 | |
| 685 void set readAsLinesHandler(void handler(List<String> lines)) { | |
| 686 _readAsLinesHandler = handler; | |
| 687 } | |
| 688 | |
| 689 void set fullPathHandler(void handler(String)) { | |
| 690 _fullPathHandler = handler; | |
| 691 } | |
| 692 | |
| 693 void set errorHandler(void handler(String error)) { | |
| 694 _errorHandler = handler; | |
| 695 } | 637 } |
| 696 | 638 |
| 697 void _ensureFileService() { | 639 void _ensureFileService() { |
| 698 if (_fileService == null) { | 640 if (_fileService == null) { |
| 699 _fileService = _FileUtils.newServicePort(); | 641 _fileService = _FileUtils.newServicePort(); |
| 700 } | 642 } |
| 701 } | 643 } |
| 702 | 644 |
| 703 String _name; | 645 String _name; |
| 704 bool _asyncUsed; | 646 bool _asyncUsed; |
| 705 | 647 |
| 706 SendPort _fileService; | 648 SendPort _fileService; |
| 707 | 649 |
| 708 Function _existsHandler; | 650 Function _onError; |
| 709 Function _createHandler; | |
| 710 Function _deleteHandler; | |
| 711 Function _directoryHandler; | |
| 712 Function _openHandler; | |
| 713 Function _readAsBytesHandler; | |
| 714 Function _readAsTextHandler; | |
| 715 Function _readAsLinesHandler; | |
| 716 Function _fullPathHandler; | |
| 717 Function _errorHandler; | |
| 718 } | 651 } |
| 719 | 652 |
| 720 | 653 |
| 721 class _RandomAccessFile implements RandomAccessFile { | 654 class _RandomAccessFile implements RandomAccessFile { |
| 722 _RandomAccessFile(int this._id, String this._name) : _asyncUsed = false; | 655 _RandomAccessFile(int this._id, String this._name) : _asyncUsed = false; |
| 723 | 656 |
| 724 void close() { | 657 void close(void callback()) { |
| 725 if (_id == 0) return; | 658 if (_id == 0) return; |
| 726 _ensureFileService(); | 659 _ensureFileService(); |
| 727 _asyncUsed = true; | 660 _asyncUsed = true; |
| 728 List request = new List(2); | 661 List request = new List(2); |
| 729 request[0] = _FileUtils.kCloseRequest; | 662 request[0] = _FileUtils.kCloseRequest; |
| 730 request[1] = _id; | 663 request[1] = _id; |
| 731 // Set the id_ to 0 (NULL) to ensure the no more async requests | 664 // Set the id_ to 0 (NULL) to ensure the no more async requests |
| 732 // can be issues for this file. | 665 // can be issues for this file. |
| 733 _id = 0; | 666 _id = 0; |
| 734 _fileService.call(request).receive((result, replyTo) { | 667 _fileService.call(request).receive((result, replyTo) { |
| 735 if (result != -1) { | 668 if (result != -1) { |
| 736 _id = result; | 669 _id = result; |
| 737 if (_closeHandler != null) _closeHandler(); | 670 callback(); |
| 738 } else if (_errorHandler != null) { | 671 } else if (_onError != null) { |
| 739 _errorHandler("Cannot close file: $_name"); | 672 _onError("Cannot close file: $_name"); |
| 740 } | 673 } |
| 741 }); | 674 }); |
| 742 } | 675 } |
| 743 | 676 |
| 744 void closeSync() { | 677 void closeSync() { |
| 745 if (_asyncUsed) { | 678 if (_asyncUsed) { |
| 746 throw new FileIOException( | 679 throw new FileIOException( |
| 747 "Mixed use of synchronous and asynchronous API"); | 680 "Mixed use of synchronous and asynchronous API"); |
| 748 } | 681 } |
| 749 var id = _FileUtils.close(_id); | 682 var id = _FileUtils.close(_id); |
| 750 if (id == -1) { | 683 if (id == -1) { |
| 751 throw new FileIOException("Cannot close file: $_name"); | 684 throw new FileIOException("Cannot close file: $_name"); |
| 752 } | 685 } |
| 753 _id = id; | 686 _id = id; |
| 754 } | 687 } |
| 755 | 688 |
| 756 void readByte() { | 689 void readByte(void callback(int byte)) { |
| 757 _ensureFileService(); | 690 _ensureFileService(); |
| 758 _asyncUsed = true; | 691 _asyncUsed = true; |
| 759 List request = new List(2); | 692 List request = new List(2); |
| 760 request[0] = _FileUtils.kReadByteRequest; | 693 request[0] = _FileUtils.kReadByteRequest; |
| 761 request[1] = _id; | 694 request[1] = _id; |
| 762 _fileService.call(request).receive((result, replyTo) { | 695 _fileService.call(request).receive((result, replyTo) { |
| 763 if (result != -1) { | 696 if (result != -1) { |
| 764 if (_readByteHandler != null) _readByteHandler(result); | 697 callback(result); |
| 765 } else if (_errorHandler != null) { | 698 } else if (_onError != null) { |
| 766 _errorHandler("readByte failed"); | 699 _onError("readByte failed"); |
| 767 } | 700 } |
| 768 }); | 701 }); |
| 769 } | 702 } |
| 770 | 703 |
| 771 int readByteSync() { | 704 int readByteSync() { |
| 772 if (_asyncUsed) { | 705 if (_asyncUsed) { |
| 773 throw new FileIOException( | 706 throw new FileIOException( |
| 774 "Mixed use of synchronous and asynchronous API"); | 707 "Mixed use of synchronous and asynchronous API"); |
| 775 } | 708 } |
| 776 int result = _FileUtils.readByte(_id); | 709 int result = _FileUtils.readByte(_id); |
| 777 if (result == -1) { | 710 if (result == -1) { |
| 778 throw new FileIOException("readByte failed"); | 711 throw new FileIOException("readByte failed"); |
| 779 } | 712 } |
| 780 return result; | 713 return result; |
| 781 } | 714 } |
| 782 | 715 |
| 783 void readList(List<int> buffer, int offset, int bytes) { | 716 void readList(List<int> buffer, int offset, int bytes, |
| 717 void callback(int read)) { |
| 784 _ensureFileService(); | 718 _ensureFileService(); |
| 785 _asyncUsed = true; | 719 _asyncUsed = true; |
| 786 if (buffer is !List || offset is !int || bytes is !int) { | 720 if (buffer is !List || offset is !int || bytes is !int) { |
| 787 if (_errorHandler != null) { | 721 if (_onError != null) { |
| 788 _errorHandler("Invalid arguments to readList"); | 722 _onError("Invalid arguments to readList"); |
| 789 } | 723 } |
| 790 return; | 724 return; |
| 791 }; | 725 }; |
| 792 List request = new List(3); | 726 List request = new List(3); |
| 793 request[0] = _FileUtils.kReadListRequest; | 727 request[0] = _FileUtils.kReadListRequest; |
| 794 request[1] = _id; | 728 request[1] = _id; |
| 795 request[2] = bytes; | 729 request[2] = bytes; |
| 796 _fileService.call(request).receive((result, replyTo) { | 730 _fileService.call(request).receive((result, replyTo) { |
| 797 if (result is List && result.length == 2 && result[0] != -1) { | 731 if (result is List && result.length == 2 && result[0] != -1) { |
| 798 var read = result[0]; | 732 var read = result[0]; |
| 799 var data = result[1]; | 733 var data = result[1]; |
| 800 buffer.setRange(offset, read, data); | 734 buffer.setRange(offset, read, data); |
| 801 if (_readListHandler != null) _readListHandler(read); | 735 callback(read); |
| 802 return; | 736 return; |
| 803 } else if (_errorHandler != null) { | 737 } else if (_onError != null) { |
| 804 _errorHandler(result is String ? result : "readList failed"); | 738 _onError(result is String ? result : "readList failed"); |
| 805 } | 739 } |
| 806 }); | 740 }); |
| 807 } | 741 } |
| 808 | 742 |
| 809 int readListSync(List<int> buffer, int offset, int bytes) { | 743 int readListSync(List<int> buffer, int offset, int bytes) { |
| 810 if (_asyncUsed) { | 744 if (_asyncUsed) { |
| 811 throw new FileIOException( | 745 throw new FileIOException( |
| 812 "Mixed use of synchronous and asynchronous API"); | 746 "Mixed use of synchronous and asynchronous API"); |
| 813 } | 747 } |
| 814 if (buffer is !List || offset is !int || bytes is !int) { | 748 if (buffer is !List || offset is !int || bytes is !int) { |
| 815 throw new FileIOException("Invalid arguments to readList"); | 749 throw new FileIOException("Invalid arguments to readList"); |
| 816 } | 750 } |
| 817 if (bytes == 0) return 0; | 751 if (bytes == 0) return 0; |
| 818 int index = | 752 int index = |
| 819 _FileUtils.checkReadWriteListArguments(buffer.length, offset, bytes); | 753 _FileUtils.checkReadWriteListArguments(buffer.length, offset, bytes); |
| 820 if (index != 0) { | 754 if (index != 0) { |
| 821 throw new IndexOutOfRangeException(index); | 755 throw new IndexOutOfRangeException(index); |
| 822 } | 756 } |
| 823 int result = _FileUtils.readList(_id, buffer, offset, bytes); | 757 int result = _FileUtils.readList(_id, buffer, offset, bytes); |
| 824 if (result == -1) { | 758 if (result == -1) { |
| 825 throw new FileIOException("readList failed"); | 759 throw new FileIOException("readList failed"); |
| 826 } | 760 } |
| 827 return result; | 761 return result; |
| 828 } | 762 } |
| 829 | 763 |
| 830 void writeByte(int value) { | 764 void writeByte(int value) { |
| 831 _ensureFileService(); | 765 _ensureFileService(); |
| 832 _asyncUsed = true; | 766 _asyncUsed = true; |
| 833 if (value is !int) { | 767 if (value is !int) { |
| 834 if (_errorHandler != null) { | 768 if (_onError != null) { |
| 835 _errorHandler("Invalid argument to writeByte"); | 769 _onError("Invalid argument to writeByte"); |
| 836 } | 770 } |
| 837 return; | 771 return; |
| 838 } | 772 } |
| 839 List request = new List(3); | 773 List request = new List(3); |
| 840 request[0] = _FileUtils.kWriteByteRequest; | 774 request[0] = _FileUtils.kWriteByteRequest; |
| 841 request[1] = _id; | 775 request[1] = _id; |
| 842 request[2] = value; | 776 request[2] = value; |
| 843 _writeEnqueued(); | 777 _writeEnqueued(); |
| 844 _fileService.call(request).receive((result, replyTo) { | 778 _fileService.call(request).receive((result, replyTo) { |
| 845 _writeCompleted(); | 779 _writeCompleted(); |
| 846 if (result == -1 && _errorHandler !== null) { | 780 if (result == -1 && _onError !== null) { |
| 847 _errorHandler("writeByte failed"); | 781 _onError("writeByte failed"); |
| 848 } | 782 } |
| 849 }); | 783 }); |
| 850 } | 784 } |
| 851 | 785 |
| 852 int writeByteSync(int value) { | 786 int writeByteSync(int value) { |
| 853 if (_asyncUsed) { | 787 if (_asyncUsed) { |
| 854 throw new FileIOException( | 788 throw new FileIOException( |
| 855 "Mixed use of synchronous and asynchronous API"); | 789 "Mixed use of synchronous and asynchronous API"); |
| 856 } | 790 } |
| 857 if (value is !int) { | 791 if (value is !int) { |
| 858 throw new FileIOException("Invalid argument to writeByte"); | 792 throw new FileIOException("Invalid argument to writeByte"); |
| 859 } | 793 } |
| 860 int result = _FileUtils.writeByte(_id, value); | 794 int result = _FileUtils.writeByte(_id, value); |
| 861 if (result == -1) { | 795 if (result == -1) { |
| 862 throw new FileIOException("writeByte failed"); | 796 throw new FileIOException("writeByte failed"); |
| 863 } | 797 } |
| 864 return result; | 798 return result; |
| 865 } | 799 } |
| 866 | 800 |
| 867 void writeList(List<int> buffer, int offset, int bytes) { | 801 void writeList(List<int> buffer, int offset, int bytes) { |
| 868 _ensureFileService(); | 802 _ensureFileService(); |
| 869 _asyncUsed = true; | 803 _asyncUsed = true; |
| 870 if (buffer is !List || offset is !int || bytes is !int) { | 804 if (buffer is !List || offset is !int || bytes is !int) { |
| 871 if (_errorHandler != null) { | 805 if (_onError != null) { |
| 872 _errorHandler("Invalid arguments to writeList"); | 806 _onError("Invalid arguments to writeList"); |
| 873 } | 807 } |
| 874 return; | 808 return; |
| 875 } | 809 } |
| 876 | 810 |
| 877 List result = | 811 List result = |
| 878 _FileUtils.ensureFastAndSerializableBuffer(buffer, offset, bytes); | 812 _FileUtils.ensureFastAndSerializableBuffer(buffer, offset, bytes); |
| 879 List outBuffer = result[0]; | 813 List outBuffer = result[0]; |
| 880 int outOffset = result[1]; | 814 int outOffset = result[1]; |
| 881 | 815 |
| 882 List request = new List(5); | 816 List request = new List(5); |
| 883 request[0] = _FileUtils.kWriteListRequest; | 817 request[0] = _FileUtils.kWriteListRequest; |
| 884 request[1] = _id; | 818 request[1] = _id; |
| 885 request[2] = outBuffer; | 819 request[2] = outBuffer; |
| 886 request[3] = outOffset; | 820 request[3] = outOffset; |
| 887 request[4] = bytes; | 821 request[4] = bytes; |
| 888 _writeEnqueued(); | 822 _writeEnqueued(); |
| 889 _fileService.call(request).receive((result, replyTo) { | 823 _fileService.call(request).receive((result, replyTo) { |
| 890 _writeCompleted(); | 824 _writeCompleted(); |
| 891 if (result == -1 && _errorHandler !== null) { | 825 if (result == -1 && _onError !== null) { |
| 892 _errorHandler("writeList failed"); | 826 _onError("writeList failed"); |
| 893 } | 827 } |
| 894 }); | 828 }); |
| 895 } | 829 } |
| 896 | 830 |
| 897 int writeListSync(List<int> buffer, int offset, int bytes) { | 831 int writeListSync(List<int> buffer, int offset, int bytes) { |
| 898 if (_asyncUsed) { | 832 if (_asyncUsed) { |
| 899 throw new FileIOException( | 833 throw new FileIOException( |
| 900 "Mixed use of synchronous and asynchronous API"); | 834 "Mixed use of synchronous and asynchronous API"); |
| 901 } | 835 } |
| 902 if (buffer is !List || offset is !int || bytes is !int) { | 836 if (buffer is !List || offset is !int || bytes is !int) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 918 void writeString(String string) { | 852 void writeString(String string) { |
| 919 _ensureFileService(); | 853 _ensureFileService(); |
| 920 _asyncUsed = true; | 854 _asyncUsed = true; |
| 921 List request = new List(3); | 855 List request = new List(3); |
| 922 request[0] = _FileUtils.kWriteStringRequest; | 856 request[0] = _FileUtils.kWriteStringRequest; |
| 923 request[1] = _id; | 857 request[1] = _id; |
| 924 request[2] = string; | 858 request[2] = string; |
| 925 _writeEnqueued(); | 859 _writeEnqueued(); |
| 926 _fileService.call(request).receive((result, replyTo) { | 860 _fileService.call(request).receive((result, replyTo) { |
| 927 _writeCompleted(); | 861 _writeCompleted(); |
| 928 if (result == -1 && _errorHandler !== null) { | 862 if (result == -1 && _onError !== null) { |
| 929 _errorHandler("writeString failed"); | 863 _onError("writeString failed"); |
| 930 } | 864 } |
| 931 }); | 865 }); |
| 932 } | 866 } |
| 933 | 867 |
| 934 int writeStringSync(String string) { | 868 int writeStringSync(String string) { |
| 935 if (_asyncUsed) { | 869 if (_asyncUsed) { |
| 936 throw new FileIOException( | 870 throw new FileIOException( |
| 937 "Mixed use of synchronous and asynchronous API"); | 871 "Mixed use of synchronous and asynchronous API"); |
| 938 } | 872 } |
| 939 int result = _FileUtils.checkedWriteString(_id, string); | 873 int result = _FileUtils.checkedWriteString(_id, string); |
| 940 if (result == -1) { | 874 if (result == -1) { |
| 941 throw new FileIOException("writeString failed"); | 875 throw new FileIOException("writeString failed"); |
| 942 } | 876 } |
| 943 return result; | 877 return result; |
| 944 } | 878 } |
| 945 | 879 |
| 946 void position() { | 880 void position(void callback(int position)) { |
| 947 _ensureFileService(); | 881 _ensureFileService(); |
| 948 _asyncUsed = true; | 882 _asyncUsed = true; |
| 949 List request = new List(2); | 883 List request = new List(2); |
| 950 request[0] = _FileUtils.kPositionRequest; | 884 request[0] = _FileUtils.kPositionRequest; |
| 951 request[1] = _id; | 885 request[1] = _id; |
| 952 _fileService.call(request).receive((result, replyTo) { | 886 _fileService.call(request).receive((result, replyTo) { |
| 953 if (result != -1) { | 887 if (result != -1) { |
| 954 if (_positionHandler != null) _positionHandler(result); | 888 callback(result); |
| 955 } else if (_errorHandler != null) { | 889 } else if (_onError != null) { |
| 956 _errorHandler("position failed"); | 890 _onError("position failed"); |
| 957 } | 891 } |
| 958 }); | 892 }); |
| 959 } | 893 } |
| 960 | 894 |
| 961 int positionSync() { | 895 int positionSync() { |
| 962 if (_asyncUsed) { | 896 if (_asyncUsed) { |
| 963 throw new FileIOException( | 897 throw new FileIOException( |
| 964 "Mixed use of synchronous and asynchronous API"); | 898 "Mixed use of synchronous and asynchronous API"); |
| 965 } | 899 } |
| 966 int result = _FileUtils.position(_id); | 900 int result = _FileUtils.position(_id); |
| 967 if (result == -1) { | 901 if (result == -1) { |
| 968 throw new FileIOException("position failed"); | 902 throw new FileIOException("position failed"); |
| 969 } | 903 } |
| 970 return result; | 904 return result; |
| 971 } | 905 } |
| 972 | 906 |
| 973 void setPosition(int position) { | 907 void setPosition(int position, void callback()) { |
| 974 _ensureFileService(); | 908 _ensureFileService(); |
| 975 _asyncUsed = true; | 909 _asyncUsed = true; |
| 976 List request = new List(3); | 910 List request = new List(3); |
| 977 request[0] = _FileUtils.kSetPositionRequest; | 911 request[0] = _FileUtils.kSetPositionRequest; |
| 978 request[1] = _id; | 912 request[1] = _id; |
| 979 request[2] = position; | 913 request[2] = position; |
| 980 _fileService.call(request).receive((result, replyTo) { | 914 _fileService.call(request).receive((result, replyTo) { |
| 981 if (result) { | 915 if (result) { |
| 982 if (_setPositionHandler != null) _setPositionHandler(); | 916 callback(); |
| 983 } else if (_errorHandler != null) { | 917 } else if (_onError != null) { |
| 984 _errorHandler("setPosition failed"); | 918 _onError("setPosition failed"); |
| 985 } | 919 } |
| 986 }); | 920 }); |
| 987 } | 921 } |
| 988 | 922 |
| 989 void setPositionSync(int position) { | 923 void setPositionSync(int position) { |
| 990 _ensureFileService(); | 924 _ensureFileService(); |
| 991 if (_asyncUsed) { | 925 if (_asyncUsed) { |
| 992 throw new FileIOException( | 926 throw new FileIOException( |
| 993 "Mixed use of synchronous and asynchronous API"); | 927 "Mixed use of synchronous and asynchronous API"); |
| 994 } | 928 } |
| 995 bool result = _FileUtils.setPosition(_id, position); | 929 bool result = _FileUtils.setPosition(_id, position); |
| 996 if (result == false) { | 930 if (result == false) { |
| 997 throw new FileIOException("setPosition failed"); | 931 throw new FileIOException("setPosition failed"); |
| 998 } | 932 } |
| 999 } | 933 } |
| 1000 | 934 |
| 1001 void truncate(int length) { | 935 void truncate(int length, void callback()) { |
| 1002 _ensureFileService(); | 936 _ensureFileService(); |
| 1003 _asyncUsed = true; | 937 _asyncUsed = true; |
| 1004 List request = new List(3); | 938 List request = new List(3); |
| 1005 request[0] = _FileUtils.kTruncateRequest; | 939 request[0] = _FileUtils.kTruncateRequest; |
| 1006 request[1] = _id; | 940 request[1] = _id; |
| 1007 request[2] = length; | 941 request[2] = length; |
| 1008 _fileService.call(request).receive((result, replyTo) { | 942 _fileService.call(request).receive((result, replyTo) { |
| 1009 if (result) { | 943 if (result) { |
| 1010 if (_truncateHandler != null) _truncateHandler(); | 944 callback(); |
| 1011 } else if (_errorHandler != null) { | 945 } else if (_onError != null) { |
| 1012 _errorHandler("truncate failed"); | 946 _onError("truncate failed"); |
| 1013 } | 947 } |
| 1014 }); | 948 }); |
| 1015 } | 949 } |
| 1016 | 950 |
| 1017 void truncateSync(int length) { | 951 void truncateSync(int length) { |
| 1018 if (_asyncUsed) { | 952 if (_asyncUsed) { |
| 1019 throw new FileIOException( | 953 throw new FileIOException( |
| 1020 "Mixed use of synchronous and asynchronous API"); | 954 "Mixed use of synchronous and asynchronous API"); |
| 1021 } | 955 } |
| 1022 bool result = _FileUtils.truncate(_id, length); | 956 bool result = _FileUtils.truncate(_id, length); |
| 1023 if (result == false) { | 957 if (result == false) { |
| 1024 throw new FileIOException("truncate failed"); | 958 throw new FileIOException("truncate failed"); |
| 1025 } | 959 } |
| 1026 } | 960 } |
| 1027 | 961 |
| 1028 void length() { | 962 void length(void callback(int length)) { |
| 1029 _ensureFileService(); | 963 _ensureFileService(); |
| 1030 _asyncUsed = true; | 964 _asyncUsed = true; |
| 1031 List request = new List(2); | 965 List request = new List(2); |
| 1032 request[0] = _FileUtils.kLengthRequest; | 966 request[0] = _FileUtils.kLengthRequest; |
| 1033 request[1] = _id; | 967 request[1] = _id; |
| 1034 _fileService.call(request).receive((result, replyTo) { | 968 _fileService.call(request).receive((result, replyTo) { |
| 1035 if (result != -1) { | 969 if (result != -1) { |
| 1036 if (_lengthHandler != null) _lengthHandler(result); | 970 callback(result); |
| 1037 } else if (_errorHandler != null) { | 971 } else if (_onError != null) { |
| 1038 _errorHandler("length failed"); | 972 _onError("length failed"); |
| 1039 } | 973 } |
| 1040 }); | 974 }); |
| 1041 } | 975 } |
| 1042 | 976 |
| 1043 int lengthSync() { | 977 int lengthSync() { |
| 1044 if (_asyncUsed) { | 978 if (_asyncUsed) { |
| 1045 throw new FileIOException( | 979 throw new FileIOException( |
| 1046 "Mixed use of synchronous and asynchronous API"); | 980 "Mixed use of synchronous and asynchronous API"); |
| 1047 } | 981 } |
| 1048 int result = _FileUtils.length(_id); | 982 int result = _FileUtils.length(_id); |
| 1049 if (result == -1) { | 983 if (result == -1) { |
| 1050 throw new FileIOException("length failed"); | 984 throw new FileIOException("length failed"); |
| 1051 } | 985 } |
| 1052 return result; | 986 return result; |
| 1053 } | 987 } |
| 1054 | 988 |
| 1055 void flush() { | 989 void flush(void callback()) { |
| 1056 _ensureFileService(); | 990 _ensureFileService(); |
| 1057 _asyncUsed = true; | 991 _asyncUsed = true; |
| 1058 List request = new List(2); | 992 List request = new List(2); |
| 1059 request[0] = _FileUtils.kFlushRequest; | 993 request[0] = _FileUtils.kFlushRequest; |
| 1060 request[1] = _id; | 994 request[1] = _id; |
| 1061 _fileService.call(request).receive((result, replyTo) { | 995 _fileService.call(request).receive((result, replyTo) { |
| 1062 if (result != -1) { | 996 if (result != -1) { |
| 1063 if (_flushHandler != null) _flushHandler(); | 997 callback(); |
| 1064 } else if (_errorHandler != null) { | 998 } else if (_onError != null) { |
| 1065 _errorHandler("flush failed"); | 999 _onError("flush failed"); |
| 1066 } | 1000 } |
| 1067 }); | 1001 }); |
| 1068 } | 1002 } |
| 1069 | 1003 |
| 1070 void flushSync() { | 1004 void flushSync() { |
| 1071 if (_asyncUsed) { | 1005 if (_asyncUsed) { |
| 1072 throw new FileIOException( | 1006 throw new FileIOException( |
| 1073 "Mixed use of synchronous and asynchronous API"); | 1007 "Mixed use of synchronous and asynchronous API"); |
| 1074 } | 1008 } |
| 1075 int result = _FileUtils.flush(_id); | 1009 int result = _FileUtils.flush(_id); |
| 1076 if (result == -1) { | 1010 if (result == -1) { |
| 1077 throw new FileIOException("flush failed"); | 1011 throw new FileIOException("flush failed"); |
| 1078 } | 1012 } |
| 1079 } | 1013 } |
| 1080 | 1014 |
| 1081 String get name() => _name; | 1015 String get name() => _name; |
| 1082 | 1016 |
| 1083 void set errorHandler(void handler(String error)) { | 1017 void set onError(void handler(String error)) { |
| 1084 _errorHandler = handler; | 1018 _onError = handler; |
| 1085 } | 1019 } |
| 1086 | 1020 |
| 1087 void set closeHandler(void handler()) { | 1021 void set onNoPendingWrites(void handler()) { |
| 1088 _closeHandler = handler; | 1022 _onNoPendingWrites = handler; |
| 1089 } | |
| 1090 | |
| 1091 void set readByteHandler(void handler(int byte)) { | |
| 1092 _readByteHandler = handler; | |
| 1093 } | |
| 1094 | |
| 1095 void set readListHandler(void handler(int read)) { | |
| 1096 _readListHandler = handler; | |
| 1097 } | |
| 1098 | |
| 1099 void set noPendingWriteHandler(void handler()) { | |
| 1100 _noPendingWriteHandler = handler; | |
| 1101 if (_pendingWrites == 0) { | 1023 if (_pendingWrites == 0) { |
| 1102 _noPendingWriteTimer = new Timer((t) { | 1024 _noPendingWriteTimer = new Timer((t) { |
| 1103 if (_noPendingWriteHandler != null) _noPendingWriteHandler(); | 1025 if (_onNoPendingWrites != null) _onNoPendingWrites(); |
| 1104 }, 0); | 1026 }, 0); |
| 1105 } | 1027 } |
| 1106 } | 1028 } |
| 1107 | 1029 |
| 1108 void set positionHandler(void handler(int pos)) { | |
| 1109 _positionHandler = handler; | |
| 1110 } | |
| 1111 | |
| 1112 void set setPositionHandler(void handler()) { | |
| 1113 _setPositionHandler = handler; | |
| 1114 } | |
| 1115 | |
| 1116 void set truncateHandler(void handler()) { | |
| 1117 _truncateHandler = handler; | |
| 1118 } | |
| 1119 | |
| 1120 void set lengthHandler(void handler(int length)) { | |
| 1121 _lengthHandler = handler; | |
| 1122 } | |
| 1123 | |
| 1124 void set flushHandler(void handler()) { | |
| 1125 _flushHandler = handler; | |
| 1126 } | |
| 1127 | |
| 1128 void _ensureFileService() { | 1030 void _ensureFileService() { |
| 1129 if (_fileService == null) { | 1031 if (_fileService == null) { |
| 1130 _fileService = _FileUtils.newServicePort(); | 1032 _fileService = _FileUtils.newServicePort(); |
| 1131 } | 1033 } |
| 1132 } | 1034 } |
| 1133 | 1035 |
| 1134 void _writeEnqueued() { | 1036 void _writeEnqueued() { |
| 1135 _pendingWrites++; | 1037 _pendingWrites++; |
| 1136 if (_noPendingWriteTimer != null) { | 1038 if (_noPendingWriteTimer != null) { |
| 1137 _noPendingWriteTimer.cancel(); | 1039 _noPendingWriteTimer.cancel(); |
| 1138 _noPendingWriteTimer = null; | 1040 _noPendingWriteTimer = null; |
| 1139 } | 1041 } |
| 1140 } | 1042 } |
| 1141 | 1043 |
| 1142 void _writeCompleted() { | 1044 void _writeCompleted() { |
| 1143 _pendingWrites--; | 1045 _pendingWrites--; |
| 1144 if (_pendingWrites == 0 && _noPendingWriteHandler != null) { | 1046 if (_pendingWrites == 0 && _onNoPendingWrites != null) { |
| 1145 _noPendingWriteHandler(); | 1047 _onNoPendingWrites(); |
| 1146 } | 1048 } |
| 1147 } | 1049 } |
| 1148 | 1050 |
| 1149 | 1051 |
| 1150 String _name; | 1052 String _name; |
| 1151 int _id; | 1053 int _id; |
| 1152 bool _asyncUsed; | 1054 bool _asyncUsed; |
| 1153 int _pendingWrites = 0; | 1055 int _pendingWrites = 0; |
| 1154 | 1056 |
| 1155 SendPort _fileService; | 1057 SendPort _fileService; |
| 1156 | 1058 |
| 1157 Timer _noPendingWriteTimer; | 1059 Timer _noPendingWriteTimer; |
| 1158 | 1060 |
| 1159 Function _closeHandler; | 1061 Function _onNoPendingWrites; |
| 1160 Function _readByteHandler; | 1062 Function _onError; |
| 1161 Function _readListHandler; | |
| 1162 Function _noPendingWriteHandler; | |
| 1163 Function _positionHandler; | |
| 1164 Function _setPositionHandler; | |
| 1165 Function _truncateHandler; | |
| 1166 Function _lengthHandler; | |
| 1167 Function _flushHandler; | |
| 1168 Function _errorHandler; | |
| 1169 } | 1063 } |
| OLD | NEW |