Index: runtime/bin/file_impl.dart |
diff --git a/runtime/bin/file_impl.dart b/runtime/bin/file_impl.dart |
deleted file mode 100644 |
index 0aa31fb0291a2ec2602b7a9c2b002804d072e117..0000000000000000000000000000000000000000 |
--- a/runtime/bin/file_impl.dart |
+++ /dev/null |
@@ -1,1095 +0,0 @@ |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-class _FileInputStream extends _BaseDataInputStream implements InputStream { |
- _FileInputStream(String name) |
- : _data = const [], |
- _position = 0, |
- _filePosition = 0 { |
- var file = new File(name); |
- var future = file.open(FileMode.READ); |
- future.handleException((e) { |
- _reportError(e); |
- return true; |
- }); |
- future.then(_setupOpenedFile); |
- } |
- |
- _FileInputStream.fromStdio(int fd) |
- : _data = const [], |
- _position = 0, |
- _filePosition = 0 { |
- assert(fd == 0); |
- _setupOpenedFile(_File._openStdioSync(fd)); |
- } |
- |
- void _setupOpenedFile(RandomAccessFile openedFile) { |
- _openedFile = openedFile; |
- if (_streamMarkedClosed) { |
- // This input stream has already been closed. |
- _fileLength = 0; |
- _closeFile(); |
- return; |
- } |
- var futureOpen = _openedFile.length(); |
- futureOpen.then((len) { |
- _fileLength = len; |
- _fillBuffer(); |
- }); |
- futureOpen.handleException((e) { |
- _reportError(e); |
- return true; |
- }); |
- } |
- |
- void _closeFile() { |
- if (_openedFile == null) { |
- _streamMarkedClosed = true; |
- return; |
- } |
- if (available() == 0) _cancelScheduledDataCallback(); |
- if (!_openedFile.closed) { |
- _openedFile.close().then((ignore) { |
- _streamMarkedClosed = true; |
- _checkScheduleCallbacks(); |
- }); |
- } |
- } |
- |
- void _fillBuffer() { |
- Expect.equals(_position, _data.length); |
- if (_openedFile == null) return; // Called before the file is opened. |
- int size = min(_bufferLength, _fileLength - _filePosition); |
- if (size == 0) { |
- _closeFile(); |
- return; |
- } |
- // If there is currently a _fillBuffer call waiting on readList, |
- // let it fill the buffer instead of us. |
- if (_activeFillBufferCall) return; |
- _activeFillBufferCall = true; |
- if (_data.length != size) { |
- _data = new Uint8List(size); |
- // Maintain the invariant signalling that the buffer is empty. |
- _position = _data.length; |
- } |
- var future = _openedFile.readList(_data, 0, _data.length); |
- future.then((read) { |
- _filePosition += read; |
- if (read != _data.length) { |
- _data = _data.getRange(0, read); |
- } |
- _position = 0; |
- _activeFillBufferCall = false; |
- |
- if (_fileLength == _filePosition) { |
- _closeFile(); |
- } |
- _checkScheduleCallbacks(); |
- }); |
- future.handleException((e) { |
- _activeFillBufferCall = false; |
- _reportError(e); |
- return true; |
- }); |
- } |
- |
- int available() { |
- return closed ? 0 : _data.length - _position; |
- } |
- |
- void pipe(OutputStream output, {bool close: true}) { |
- _pipe(this, output, close: close); |
- } |
- |
- void _finishRead() { |
- if (_position == _data.length && !_streamMarkedClosed) { |
- _fillBuffer(); |
- } else { |
- _checkScheduleCallbacks(); |
- } |
- } |
- |
- List<int> _read(int bytesToRead) { |
- List<int> result; |
- if (_position == 0 && bytesToRead == _data.length) { |
- result = _data; |
- _data = const []; |
- } else { |
- result = new Uint8List(bytesToRead); |
- result.setRange(0, bytesToRead, _data, _position); |
- _position += bytesToRead; |
- } |
- _finishRead(); |
- return result; |
- } |
- |
- int _readInto(List<int> buffer, int offset, int len) { |
- buffer.setRange(offset, len, _data, _position); |
- _position += len; |
- _finishRead(); |
- return len; |
- } |
- |
- void _close() { |
- _data = const []; |
- _position = 0; |
- _filePosition = 0; |
- _fileLength = 0; |
- _closeFile(); |
- } |
- |
- static const int _bufferLength = 64 * 1024; |
- |
- RandomAccessFile _openedFile; |
- List<int> _data; |
- int _position; |
- int _filePosition; |
- int _fileLength; |
- bool _activeFillBufferCall = false; |
-} |
- |
- |
-class _PendingOperation { |
- const _PendingOperation(this._id); |
- static const _PendingOperation CLOSE = const _PendingOperation(0); |
- static const _PendingOperation FLUSH = const _PendingOperation(1); |
- final int _id; |
-} |
- |
- |
-class _FileOutputStream extends _BaseOutputStream implements OutputStream { |
- _FileOutputStream(String name, FileMode mode) { |
- _pendingOperations = new List(); |
- var f = new File(name); |
- var openFuture = f.open(mode); |
- openFuture.then((openedFile) { |
- _file = openedFile; |
- _processPendingOperations(); |
- }); |
- openFuture.handleException((e) { |
- _reportError(e); |
- return true; |
- }); |
- } |
- |
- _FileOutputStream.fromStdio(int fd) { |
- assert(1 <= fd && fd <= 2); |
- _file = _File._openStdioSync(fd); |
- } |
- |
- bool write(List<int> buffer, [bool copyBuffer = false]) { |
- var data = buffer; |
- if (copyBuffer) { |
- var length = buffer.length; |
- data = new Uint8List(length); |
- data.setRange(0, length, buffer, 0); |
- } |
- if (_file == null) { |
- _pendingOperations.add(data); |
- } else { |
- _write(data, 0, data.length); |
- } |
- return false; |
- } |
- |
- bool writeFrom(List<int> buffer, [int offset = 0, int len]) { |
- // A copy is required by the interface. |
- var length = buffer.length - offset; |
- if (len != null) { |
- if (len > length) throw new IndexOutOfRangeException(len); |
- length = len; |
- } |
- var copy = new Uint8List(length); |
- copy.setRange(0, length, buffer, offset); |
- return write(copy); |
- } |
- |
- |
- void flush() { |
- if (_file == null) { |
- _pendingOperations.add(_PendingOperation.FLUSH); |
- } else { |
- _file.flush().then((ignored) => null); |
- } |
- } |
- |
- |
- void close() { |
- _streamMarkedClosed = true; |
- if (_file == null) { |
- _pendingOperations.add(_PendingOperation.CLOSE); |
- } else if (!_closeCallbackScheduled) { |
- _file.close().then((ignore) { |
- if (_onClosed != null) _onClosed(); |
- }); |
- _closeCallbackScheduled = true; |
- } |
- } |
- |
- void set onNoPendingWrites(void callback()) { |
- _onNoPendingWrites = callback; |
- if ((_pendingOperations == null || _pendingOperations.length == 0) && |
- outstandingWrites == 0 && |
- !_streamMarkedClosed && |
- _onNoPendingWrites != null) { |
- new Timer(0, (t) { |
- if (_onNoPendingWrites != null) { |
- _onNoPendingWrites(); |
- } |
- }); |
- } |
- } |
- |
- void set onClosed(void callback()) { |
- _onClosed = callback; |
- } |
- |
- void _processPendingOperations() { |
- _pendingOperations.forEach((buffer) { |
- if (buffer is _PendingOperation) { |
- if (buffer === _PendingOperation.CLOSE) { |
- close(); |
- } else { |
- assert(buffer === _PendingOperation.FLUSH); |
- flush(); |
- } |
- } else { |
- write(buffer); |
- } |
- }); |
- _pendingOperations = null; |
- } |
- |
- void _write(List<int> buffer, int offset, int len) { |
- outstandingWrites++; |
- var writeListFuture = _file.writeList(buffer, offset, len); |
- writeListFuture.then((ignore) { |
- outstandingWrites--; |
- if (outstandingWrites == 0 && |
- !_streamMarkedClosed && |
- _onNoPendingWrites != null) { |
- _onNoPendingWrites(); |
- } |
- }); |
- writeListFuture.handleException((e) { |
- outstandingWrites--; |
- _reportError(e); |
- return true; |
- }); |
- } |
- |
- bool get closed => _streamMarkedClosed; |
- |
- RandomAccessFile _file; |
- |
- // When this is set to true the stream is marked closed. When a |
- // stream is marked closed no more data can be written. |
- bool _streamMarkedClosed = false; |
- |
- // When this is set to true, the close callback has been scheduled and the |
- // stream will be fully closed once it's called. |
- bool _closeCallbackScheduled = false; |
- |
- // Number of writes that have not yet completed. |
- int outstandingWrites = 0; |
- |
- // List of pending writes that were issued before the underlying |
- // file was successfully opened. |
- List _pendingOperations; |
- |
- Function _onNoPendingWrites; |
- Function _onClosed; |
-} |
- |
-const int _EXISTS_REQUEST = 0; |
-const int _CREATE_REQUEST = 1; |
-const int _DELETE_REQUEST = 2; |
-const int _OPEN_REQUEST = 3; |
-const int _FULL_PATH_REQUEST = 4; |
-const int _DIRECTORY_REQUEST = 5; |
-const int _CLOSE_REQUEST = 6; |
-const int _POSITION_REQUEST = 7; |
-const int _SET_POSITION_REQUEST = 8; |
-const int _TRUNCATE_REQUEST = 9; |
-const int _LENGTH_REQUEST = 10; |
-const int _LENGTH_FROM_NAME_REQUEST = 11; |
-const int _LAST_MODIFIED_REQUEST = 12; |
-const int _FLUSH_REQUEST = 13; |
-const int _READ_BYTE_REQUEST = 14; |
-const int _WRITE_BYTE_REQUEST = 15; |
-const int _READ_LIST_REQUEST = 16; |
-const int _WRITE_LIST_REQUEST = 17; |
-const int _WRITE_STRING_REQUEST = 18; |
- |
-// Base class for _File and _RandomAccessFile with shared functions. |
-class _FileBase { |
- bool _isErrorResponse(response) { |
- return response is List && response[0] != _SUCCESS_RESPONSE; |
- } |
- |
- Exception _exceptionFromResponse(response, String message) { |
- assert(_isErrorResponse(response)); |
- switch (response[_ERROR_RESPONSE_ERROR_TYPE]) { |
- case _ILLEGAL_ARGUMENT_RESPONSE: |
- return new ArgumentError(); |
- case _OSERROR_RESPONSE: |
- var err = new OSError(response[_OSERROR_RESPONSE_MESSAGE], |
- response[_OSERROR_RESPONSE_ERROR_CODE]); |
- return new FileIOException(message, err); |
- case _FILE_CLOSED_RESPONSE: |
- return new FileIOException("File closed"); |
- default: |
- return new Exception("Unknown error"); |
- } |
- } |
-} |
- |
-SendPort _newServicePort() native "File_NewServicePort"; |
- |
-// Class for encapsulating the native implementation of files. |
-class _File extends _FileBase implements File { |
- // Constructor for file. |
- _File(String this._name) { |
- if (_name is! String) { |
- throw new ArgumentError('${NoSuchMethodError.safeToString(_name)} ' |
- 'is not a String'); |
- } |
- } |
- |
- // Constructor from Path for file. |
- _File.fromPath(Path path) : this(path.toNativePath()); |
- |
- Future<bool> exists() { |
- _ensureFileService(); |
- List request = new List(2); |
- request[0] = _EXISTS_REQUEST; |
- request[1] = _name; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, "Cannot open file '$_name'"); |
- } |
- return response; |
- }); |
- } |
- |
- |
- static _exists(String name) native "File_Exists"; |
- |
- bool existsSync() { |
- var result = _exists(_name); |
- throwIfError(result, "Cannot check existence of file '$_name'"); |
- return result; |
- } |
- |
- Future<File> create() { |
- _ensureFileService(); |
- List request = new List(2); |
- request[0] = _CREATE_REQUEST; |
- request[1] = _name; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, "Cannot create file '$_name'"); |
- } |
- return this; |
- }); |
- } |
- |
- static _create(String name) native "File_Create"; |
- |
- void createSync() { |
- var result = _create(_name); |
- throwIfError(result, "Cannot create file '$_name'"); |
- } |
- |
- Future<File> delete() { |
- _ensureFileService(); |
- List request = new List(2); |
- request[0] = _DELETE_REQUEST; |
- request[1] = _name; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, "Cannot delete file '$_name'"); |
- } |
- return this; |
- }); |
- } |
- |
- static _delete(String name) native "File_Delete"; |
- |
- void deleteSync() { |
- var result = _delete(_name); |
- throwIfError(result, "Cannot delete file '$_name'"); |
- } |
- |
- Future<Directory> directory() { |
- _ensureFileService(); |
- List request = new List(2); |
- request[0] = _DIRECTORY_REQUEST; |
- request[1] = _name; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, |
- "Cannot retrieve directory for " |
- "file '$_name'"); |
- } |
- return new Directory(response); |
- }); |
- } |
- |
- static _directory(String name) native "File_Directory"; |
- |
- Directory directorySync() { |
- var result = _directory(name); |
- throwIfError(result, "Cannot retrieve directory for file '$_name'"); |
- return new Directory(result); |
- } |
- |
- Future<RandomAccessFile> open([FileMode mode = FileMode.READ]) { |
- _ensureFileService(); |
- Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
- if (mode != FileMode.READ && |
- mode != FileMode.WRITE && |
- mode != FileMode.APPEND) { |
- new Timer(0, (t) { |
- completer.completeException(new ArgumentError()); |
- }); |
- return completer.future; |
- } |
- List request = new List(3); |
- request[0] = _OPEN_REQUEST; |
- request[1] = _name; |
- request[2] = mode._mode; // Direct int value for serialization. |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, "Cannot open file '$_name'"); |
- } |
- return new _RandomAccessFile(response, _name); |
- }); |
- } |
- |
- Future<int> length() { |
- _ensureFileService(); |
- List request = new List(2); |
- request[0] = _LENGTH_FROM_NAME_REQUEST; |
- request[1] = _name; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, |
- "Cannot retrieve length of " |
- "file '$_name'"); |
- } |
- return response; |
- }); |
- } |
- |
- |
- static _lengthFromName(String name) native "File_LengthFromName"; |
- |
- int lengthSync() { |
- var result = _lengthFromName(_name); |
- throwIfError(result, "Cannot retrieve length of file '$_name'"); |
- return result; |
- } |
- |
- Future<Date> lastModified() { |
- _ensureFileService(); |
- List request = new List(2); |
- request[0] = _LAST_MODIFIED_REQUEST; |
- request[1] = _name; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, |
- "Cannot retrieve modification time " |
- "for file '$_name'"); |
- } |
- return new Date.fromMillisecondsSinceEpoch(response); |
- }); |
- } |
- |
- static _lastModified(String name) native "File_LastModified"; |
- |
- Date lastModifiedSync() { |
- var ms = _lastModified(name); |
- throwIfError(ms, "Cannot retrieve modification time for file '$_name'"); |
- return new Date.fromMillisecondsSinceEpoch(ms); |
- } |
- |
- static _open(String name, int mode) native "File_Open"; |
- |
- RandomAccessFile openSync([FileMode mode = FileMode.READ]) { |
- if (mode != FileMode.READ && |
- mode != FileMode.WRITE && |
- mode != FileMode.APPEND) { |
- throw new FileIOException("Unknown file mode. Use FileMode.READ, " |
- "FileMode.WRITE or FileMode.APPEND."); |
- } |
- var id = _open(_name, mode._mode); |
- throwIfError(id, "Cannot open file '$_name'"); |
- return new _RandomAccessFile(id, _name); |
- } |
- |
- static int _openStdio(int fd) native "File_OpenStdio"; |
- |
- static RandomAccessFile _openStdioSync(int fd) { |
- var id = _openStdio(fd); |
- if (id == 0) { |
- throw new FileIOException("Cannot open stdio file for: $fd"); |
- } |
- return new _RandomAccessFile(id, ""); |
- } |
- |
- Future<String> fullPath() { |
- _ensureFileService(); |
- List request = new List(2); |
- request[0] = _FULL_PATH_REQUEST; |
- request[1] = _name; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, |
- "Cannot retrieve full path" |
- " for '$_name'"); |
- } |
- return response; |
- }); |
- } |
- |
- static _fullPath(String name) native "File_FullPath"; |
- |
- String fullPathSync() { |
- var result = _fullPath(_name); |
- throwIfError(result, "Cannot retrieve full path for file '$_name'"); |
- return result; |
- } |
- |
- InputStream openInputStream() { |
- return new _FileInputStream(_name); |
- } |
- |
- OutputStream openOutputStream([FileMode mode = FileMode.WRITE]) { |
- if (mode != FileMode.WRITE && |
- mode != FileMode.APPEND) { |
- throw new FileIOException( |
- "Wrong FileMode. Use FileMode.WRITE or FileMode.APPEND"); |
- } |
- return new _FileOutputStream(_name, mode); |
- } |
- |
- Future<List<int>> readAsBytes() { |
- _ensureFileService(); |
- Completer<List<int>> completer = new Completer<List<int>>(); |
- var chunks = new _BufferList(); |
- var stream = openInputStream(); |
- stream.onClosed = () { |
- var result = chunks.readBytes(chunks.length); |
- if (result == null) result = <int>[]; |
- completer.complete(result); |
- }; |
- stream.onData = () { |
- var chunk = stream.read(); |
- chunks.add(chunk); |
- }; |
- stream.onError = completer.completeException; |
- return completer.future; |
- } |
- |
- List<int> readAsBytesSync() { |
- var opened = openSync(); |
- var length = opened.lengthSync(); |
- var result = new Uint8List(length); |
- var read = opened.readListSync(result, 0, length); |
- if (read != length) { |
- throw new FileIOException("Failed to read file"); |
- } |
- opened.closeSync(); |
- return result; |
- } |
- |
- Future<String> readAsText([Encoding encoding = Encoding.UTF_8]) { |
- _ensureFileService(); |
- return readAsBytes().transform((bytes) { |
- if (bytes.length == 0) return ""; |
- var decoder = _StringDecoders.decoder(encoding); |
- decoder.write(bytes); |
- return decoder.decoded(); |
- }); |
- } |
- |
- String readAsTextSync([Encoding encoding = Encoding.UTF_8]) { |
- var decoder = _StringDecoders.decoder(encoding); |
- List<int> bytes = readAsBytesSync(); |
- if (bytes.length == 0) return ""; |
- decoder.write(bytes); |
- return decoder.decoded(); |
- } |
- |
- List<String> _getDecodedLines(_StringDecoder decoder) { |
- List<String> result = []; |
- var line = decoder.decodedLine; |
- while (line != null) { |
- result.add(line); |
- line = decoder.decodedLine; |
- } |
- // If there is more data with no terminating line break we treat |
- // it as the last line. |
- var data = decoder.decoded(); |
- if (data != null) { |
- result.add(data); |
- } |
- return result; |
- } |
- |
- Future<List<String>> readAsLines([Encoding encoding = Encoding.UTF_8]) { |
- _ensureFileService(); |
- Completer<List<String>> completer = new Completer<List<String>>(); |
- return readAsBytes().transform((bytes) { |
- var decoder = _StringDecoders.decoder(encoding); |
- decoder.write(bytes); |
- return _getDecodedLines(decoder); |
- }); |
- } |
- |
- List<String> readAsLinesSync([Encoding encoding = Encoding.UTF_8]) { |
- var decoder = _StringDecoders.decoder(encoding); |
- List<int> bytes = readAsBytesSync(); |
- decoder.write(bytes); |
- return _getDecodedLines(decoder); |
- } |
- |
- String get name => _name; |
- |
- void _ensureFileService() { |
- if (_fileService == null) { |
- _fileService = _newServicePort(); |
- } |
- } |
- |
- static throwIfError(Object result, String msg) { |
- if (result is OSError) { |
- throw new FileIOException(msg, result); |
- } |
- } |
- |
- final String _name; |
- |
- SendPort _fileService; |
-} |
- |
- |
-class _RandomAccessFile extends _FileBase implements RandomAccessFile { |
- _RandomAccessFile(int this._id, String this._name); |
- |
- Future<RandomAccessFile> close() { |
- Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
- if (closed) return _completeWithClosedException(completer); |
- _ensureFileService(); |
- List request = new List(2); |
- request[0] = _CLOSE_REQUEST; |
- request[1] = _id; |
- // Set the id_ to 0 (NULL) to ensure the no more async requests |
- // can be issued for this file. |
- _id = 0; |
- return _fileService.call(request).transform((result) { |
- if (result != -1) { |
- _id = result; |
- return this; |
- } else { |
- throw new FileIOException("Cannot close file '$_name'"); |
- } |
- }); |
- } |
- |
- static int _close(int id) native "File_Close"; |
- |
- void closeSync() { |
- _checkNotClosed(); |
- var id = _close(_id); |
- if (id == -1) { |
- throw new FileIOException("Cannot close file '$_name'"); |
- } |
- _id = id; |
- } |
- |
- Future<int> readByte() { |
- _ensureFileService(); |
- Completer<int> completer = new Completer<int>(); |
- if (closed) return _completeWithClosedException(completer); |
- List request = new List(2); |
- request[0] = _READ_BYTE_REQUEST; |
- request[1] = _id; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, |
- "readByte failed for file '$_name'"); |
- } |
- return response; |
- }); |
- } |
- |
- static _readByte(int id) native "File_ReadByte"; |
- |
- int readByteSync() { |
- _checkNotClosed(); |
- var result = _readByte(_id); |
- if (result is OSError) { |
- throw new FileIOException("readByte failed for file '$_name'", result); |
- } |
- return result; |
- } |
- |
- Future<int> readList(List<int> buffer, int offset, int bytes) { |
- _ensureFileService(); |
- Completer<int> completer = new Completer<int>(); |
- if (buffer is !List || offset is !int || bytes is !int) { |
- // Complete asynchronously so the user has a chance to setup |
- // handlers without getting exceptions when registering the |
- // then handler. |
- new Timer(0, (t) { |
- completer.completeException(new FileIOException( |
- "Invalid arguments to readList for file '$_name'")); |
- }); |
- return completer.future; |
- }; |
- if (closed) return _completeWithClosedException(completer); |
- List request = new List(3); |
- request[0] = _READ_LIST_REQUEST; |
- request[1] = _id; |
- request[2] = bytes; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, |
- "readList failed for file '$_name'"); |
- } |
- var read = response[1]; |
- var data = response[2]; |
- buffer.setRange(offset, read, data); |
- return read; |
- }); |
- } |
- |
- static void _checkReadWriteListArguments(int length, int offset, int bytes) { |
- if (offset < 0) throw new IndexOutOfRangeException(offset); |
- if (bytes < 0) throw new IndexOutOfRangeException(bytes); |
- if ((offset + bytes) > length) { |
- throw new IndexOutOfRangeException(offset + bytes); |
- } |
- } |
- |
- static _readList(int id, List<int> buffer, int offset, int bytes) |
- native "File_ReadList"; |
- |
- int readListSync(List<int> buffer, int offset, int bytes) { |
- _checkNotClosed(); |
- if (buffer is !List || offset is !int || bytes is !int) { |
- throw new FileIOException( |
- "Invalid arguments to readList for file '$_name'"); |
- } |
- if (bytes == 0) return 0; |
- _checkReadWriteListArguments(buffer.length, offset, bytes); |
- var result = _readList(_id, buffer, offset, bytes); |
- if (result is OSError) { |
- throw new FileIOException("readList failed for file '$_name'", |
- result); |
- } |
- return result; |
- } |
- |
- Future<RandomAccessFile> writeByte(int value) { |
- _ensureFileService(); |
- Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
- if (value is !int) { |
- // Complete asynchronously so the user has a chance to setup |
- // handlers without getting exceptions when registering the |
- // then handler. |
- new Timer(0, (t) { |
- completer.completeException(new FileIOException( |
- "Invalid argument to writeByte for file '$_name'")); |
- }); |
- return completer.future; |
- } |
- if (closed) return _completeWithClosedException(completer); |
- List request = new List(3); |
- request[0] = _WRITE_BYTE_REQUEST; |
- request[1] = _id; |
- request[2] = value; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, |
- "writeByte failed for file '$_name'"); |
- } |
- return this; |
- }); |
- } |
- |
- static _writeByte(int id, int value) native "File_WriteByte"; |
- |
- int writeByteSync(int value) { |
- _checkNotClosed(); |
- if (value is !int) { |
- throw new FileIOException( |
- "Invalid argument to writeByte for file '$_name'"); |
- } |
- var result = _writeByte(_id, value); |
- if (result is OSError) { |
- throw new FileIOException("writeByte failed for file '$_name'", |
- result); |
- } |
- return result; |
- } |
- |
- Future<RandomAccessFile> writeList(List<int> buffer, int offset, int bytes) { |
- _ensureFileService(); |
- Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
- if (buffer is !List || offset is !int || bytes is !int) { |
- // Complete asynchronously so the user has a chance to setup |
- // handlers without getting exceptions when registering the |
- // then handler. |
- new Timer(0, (t) { |
- completer.completeException(new FileIOException( |
- "Invalid arguments to writeList for file '$_name'")); |
- }); |
- return completer.future; |
- } |
- if (closed) return _completeWithClosedException(completer); |
- |
- _BufferAndOffset result; |
- try { |
- result = _ensureFastAndSerializableBuffer(buffer, offset, bytes); |
- } catch (e) { |
- // Complete asynchronously so the user has a chance to setup |
- // handlers without getting exceptions when registering the |
- // then handler. |
- new Timer(0, (t) => completer.completeException(e)); |
- return completer.future; |
- } |
- |
- List request = new List(5); |
- request[0] = _WRITE_LIST_REQUEST; |
- request[1] = _id; |
- request[2] = result.buffer; |
- request[3] = result.offset; |
- request[4] = bytes; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, |
- "writeList failed for file '$_name'"); |
- } |
- return this; |
- }); |
- } |
- |
- static _writeList(int id, List<int> buffer, int offset, int bytes) |
- native "File_WriteList"; |
- |
- int writeListSync(List<int> buffer, int offset, int bytes) { |
- _checkNotClosed(); |
- if (buffer is !List || offset is !int || bytes is !int) { |
- throw new FileIOException( |
- "Invalid arguments to writeList for file '$_name'"); |
- } |
- if (bytes == 0) return 0; |
- _checkReadWriteListArguments(buffer.length, offset, bytes); |
- _BufferAndOffset bufferAndOffset = |
- _ensureFastAndSerializableBuffer(buffer, offset, bytes); |
- var result = |
- _writeList(_id, bufferAndOffset.buffer, bufferAndOffset.offset, bytes); |
- if (result is OSError) { |
- throw new FileIOException("writeList failed for file '$_name'", result); |
- } |
- return result; |
- } |
- |
- Future<RandomAccessFile> writeString(String string, |
- [Encoding encoding = Encoding.UTF_8]) { |
- _ensureFileService(); |
- Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
- if (closed) return _completeWithClosedException(completer); |
- List request = new List(3); |
- request[0] = _WRITE_STRING_REQUEST; |
- request[1] = _id; |
- request[2] = string; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, |
- "writeString failed for file '$_name'"); |
- } |
- return this; |
- }); |
- } |
- |
- static _writeString(int id, String string) native "File_WriteString"; |
- |
- int writeStringSync(String string, [Encoding encoding = Encoding.UTF_8]) { |
- _checkNotClosed(); |
- if (string is !String) throw new ArgumentError(); |
- var result = _writeString(_id, string); |
- if (result is OSError) { |
- throw new FileIOException("writeString failed for file '$_name'"); |
- } |
- return result; |
- } |
- |
- Future<int> position() { |
- _ensureFileService(); |
- Completer<int> completer = new Completer<int>(); |
- if (closed) return _completeWithClosedException(completer); |
- List request = new List(2); |
- request[0] = _POSITION_REQUEST; |
- request[1] = _id; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, |
- "position failed for file '$_name'"); |
- } |
- return response; |
- }); |
- } |
- |
- static _position(int id) native "File_Position"; |
- |
- int positionSync() { |
- _checkNotClosed(); |
- var result = _position(_id); |
- if (result is OSError) { |
- throw new FileIOException("position failed for file '$_name'", result); |
- } |
- return result; |
- } |
- |
- Future<RandomAccessFile> setPosition(int position) { |
- _ensureFileService(); |
- Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
- if (closed) return _completeWithClosedException(completer); |
- List request = new List(3); |
- request[0] = _SET_POSITION_REQUEST; |
- request[1] = _id; |
- request[2] = position; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, |
- "setPosition failed for file '$_name'"); |
- } |
- return this; |
- }); |
- } |
- |
- static _setPosition(int id, int position) native "File_SetPosition"; |
- |
- void setPositionSync(int position) { |
- _checkNotClosed(); |
- var result = _setPosition(_id, position); |
- if (result is OSError) { |
- throw new FileIOException("setPosition failed for file '$_name'", result); |
- } |
- } |
- |
- Future<RandomAccessFile> truncate(int length) { |
- _ensureFileService(); |
- Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
- if (closed) return _completeWithClosedException(completer); |
- List request = new List(3); |
- request[0] = _TRUNCATE_REQUEST; |
- request[1] = _id; |
- request[2] = length; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, |
- "truncate failed for file '$_name'"); |
- } |
- return this; |
- }); |
- } |
- |
- static _truncate(int id, int length) native "File_Truncate"; |
- |
- void truncateSync(int length) { |
- _checkNotClosed(); |
- var result = _truncate(_id, length); |
- if (result is OSError) { |
- throw new FileIOException("truncate failed for file '$_name'", result); |
- } |
- } |
- |
- Future<int> length() { |
- _ensureFileService(); |
- Completer<int> completer = new Completer<int>(); |
- if (closed) return _completeWithClosedException(completer); |
- List request = new List(2); |
- request[0] = _LENGTH_REQUEST; |
- request[1] = _id; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, |
- "length failed for file '$_name'"); |
- } |
- return response; |
- }); |
- } |
- |
- static _length(int id) native "File_Length"; |
- |
- int lengthSync() { |
- _checkNotClosed(); |
- var result = _length(_id); |
- if (result is OSError) { |
- throw new FileIOException("length failed for file '$_name'", result); |
- } |
- return result; |
- } |
- |
- Future<RandomAccessFile> flush() { |
- _ensureFileService(); |
- Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
- if (closed) return _completeWithClosedException(completer); |
- List request = new List(2); |
- request[0] = _FLUSH_REQUEST; |
- request[1] = _id; |
- return _fileService.call(request).transform((response) { |
- if (_isErrorResponse(response)) { |
- throw _exceptionFromResponse(response, |
- "flush failed for file '$_name'"); |
- } |
- return this; |
- }); |
- } |
- |
- static _flush(int id) native "File_Flush"; |
- |
- void flushSync() { |
- _checkNotClosed(); |
- var result = _flush(_id); |
- if (result is OSError) { |
- throw new FileIOException("flush failed for file '$_name'", result); |
- } |
- } |
- |
- String get name => _name; |
- |
- void _ensureFileService() { |
- if (_fileService == null) { |
- _fileService = _newServicePort(); |
- } |
- } |
- |
- bool get closed => _id == 0; |
- |
- void _checkNotClosed() { |
- if (closed) { |
- throw new FileIOException("File closed '$_name'"); |
- } |
- } |
- |
- Future _completeWithClosedException(Completer completer) { |
- new Timer(0, (t) { |
- completer.completeException( |
- new FileIOException("File closed '$_name'")); |
- }); |
- return completer.future; |
- } |
- |
- final String _name; |
- int _id; |
- |
- SendPort _fileService; |
-} |