| // 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. |
| |
| patch class _File { |
| /* patch */ static _exists(String path) native "File_Exists"; |
| /* patch */ static _create(String path) native "File_Create"; |
| /* patch */ static _createLink(String path, String target) |
| native "File_CreateLink"; |
| /* patch */ static _linkTarget(String path) native "File_LinkTarget"; |
| /* patch */ static _deleteNative(String path) native "File_Delete"; |
| /* patch */ static _deleteLinkNative(String path) native "File_DeleteLink"; |
| /* patch */ static _rename(String oldPath, String newPath) |
| native "File_Rename"; |
| /* patch */ static _renameLink(String oldPath, String newPath) |
| native "File_RenameLink"; |
| /* patch */ static _lengthFromPath(String path) native "File_LengthFromPath"; |
| /* patch */ static _lastModified(String path) native "File_LastModified"; |
| /* patch */ static _open(String path, int mode) native "File_Open"; |
| /* patch */ static int _openStdio(int fd) native "File_OpenStdio"; |
| } |
| |
| patch class _RandomAccessFile { |
| /* patch */ static int _close(int id) native "File_Close"; |
| /* patch */ static _readByte(int id) native "File_ReadByte"; |
| /* patch */ static _read(int id, int bytes) native "File_Read"; |
| /* patch */ static _readInto(int id, List<int> buffer, int start, int end) |
| native "File_ReadInto"; |
| /* patch */ static _writeByte(int id, int value) native "File_WriteByte"; |
| /* patch */ static _writeFrom(int id, List<int> buffer, int start, int end) |
| native "File_WriteFrom"; |
| /* patch */ static _position(int id) native "File_Position"; |
| /* patch */ static _setPosition(int id, int position) |
| native "File_SetPosition"; |
| /* patch */ static _truncate(int id, int length) native "File_Truncate"; |
| /* patch */ static _length(int id) native "File_Length"; |
| /* patch */ static _flush(int id) native "File_Flush"; |
| } |
| |
| patch class _FileSystemWatcher { |
| /* patch */ factory _FileSystemWatcher( |
| String path, int events, bool recursive) |
| => new _FileSystemWatcherImpl(path, events, recursive); |
| |
| /* patch */ static bool get isSupported => _FileSystemWatcherImpl.isSupported; |
| } |
| |
| class _FileSystemWatcherImpl |
| extends NativeFieldWrapperClass1 |
| implements _FileSystemWatcher { |
| final String _path; |
| final int _events; |
| final bool _recursive; |
| |
| StreamController _controller; |
| StreamSubscription _subscription; |
| |
| _FileSystemWatcherImpl(this._path, this._events, this._recursive) { |
| if (!isSupported) { |
| throw new FileException( |
| "File system watching is not supported on this system", |
| _path); |
| } |
| _controller = new StreamController(onListen: _listen, onCancel: _cancel); |
| } |
| |
| void _listen() { |
| int socketId; |
| try { |
| socketId = _watchPath(_path, _events, identical(true, _recursive)); |
| } catch (e) { |
| throw new FileException( |
| "Failed to watch path", |
| _path, |
| e); |
| } |
| var socket = new _RawSocket(new _NativeSocket.watch(socketId)); |
| _subscription = socket.expand((event) { |
| var events = []; |
| var pair = {}; |
| if (event == RawSocketEvent.READ) { |
| String getPath(event) { |
| var path = _path; |
| if (event[2] != null) { |
| path += Platform.pathSeparator; |
| path += event[2]; |
| } |
| return path; |
| } |
| while (socket.available() > 0) { |
| for (var event in _readEvents()) { |
| if (event == null) continue; |
| var path = getPath(event); |
| if ((event[0] & FileSystemEvent.CREATE) != 0) { |
| events.add(new FileSystemCreateEvent._(path)); |
| } |
| if ((event[0] & FileSystemEvent.MODIFY) != 0) { |
| events.add(new FileSystemModifyEvent._(path, true)); |
| } |
| if ((event[0] & FileSystemEvent._MODIFY_ATTRIBUTES) != 0) { |
| events.add(new FileSystemModifyEvent._(path, false)); |
| } |
| if ((event[0] & FileSystemEvent.MOVE) != 0) { |
| int link = event[1]; |
| if (link > 0) { |
| if (pair.containsKey(link)) { |
| events.add( |
| new FileSystemMoveEvent._(getPath(pair[link]), path)); |
| pair.remove(link); |
| } else { |
| pair[link] = event; |
| } |
| } else { |
| events.add(new FileSystemMoveEvent._(path, null)); |
| } |
| } |
| if ((event[0] & FileSystemEvent.DELETE) != 0) { |
| events.add(new FileSystemDeleteEvent._(path)); |
| } |
| } |
| } |
| for (var event in pair.values) { |
| events.add(new FileSystemMoveEvent._(getPath(event), null)); |
| } |
| } else if (event == RawSocketEvent.CLOSED) { |
| } else if (event == RawSocketEvent.READ_CLOSED) { |
| } else { |
| assert(false); |
| } |
| return events; |
| }) |
| .where((event) => (event.type & _events) != 0) |
| .listen(_controller.add, onDone: _cancel); |
| } |
| |
| void _cancel() { |
| _unwatchPath(); |
| if (_subscription != null) { |
| _subscription.cancel(); |
| } |
| } |
| |
| Stream<FileSystemEvent> get stream => _controller.stream; |
| |
| static bool get isSupported native "FileSystemWatcher_IsSupported"; |
| |
| int _watchPath(String path, int events, bool recursive) |
| native "FileSystemWatcher_WatchPath"; |
| void _unwatchPath() native "FileSystemWatcher_UnwatchPath"; |
| List _readEvents() native "FileSystemWatcher_ReadEvents"; |
| } |
| |
| Uint8List _makeUint8ListView(Uint8List source, int offsetInBytes, int length) { |
| return new Uint8List.view(source.buffer, offsetInBytes, length); |
| } |