From cd6ef194d0ede7c4cb23667d7cba19f0425183a6 Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 24 Jun 2014 19:37:16 +0000 Subject: Add directory_iterator for (non-recursive) iteration of VFS directories The API is based on sys::fs::directory_iterator, but it allows iterating over overlays and the yaml-based VFS. For now, it isn't used by anything (except its tests). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@211623 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/VirtualFileSystem.h | 84 +++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h index 83e0fb52e5..8c83012ebd 100644 --- a/include/clang/Basic/VirtualFileSystem.h +++ b/include/clang/Basic/VirtualFileSystem.h @@ -100,6 +100,64 @@ public: virtual void setName(StringRef Name) = 0; }; +namespace detail { +/// \brief An interface for virtual file systems to provide an iterator over the +/// (non-recursive) contents of a directory. +struct DirIterImpl { + virtual ~DirIterImpl(); + /// \brief Sets \c CurrentEntry to the next entry in the directory on success, + /// or returns a system-defined \c error_code. + virtual std::error_code increment() = 0; + Status CurrentEntry; +}; +} // end namespace detail + +/// \brief An input iterator over the entries in a virtual path, similar to +/// llvm::sys::fs::directory_iterator. +class directory_iterator { + std::shared_ptr Impl; // Input iterator semantics on copy + +public: + directory_iterator(std::shared_ptr I) : Impl(I) { + assert(Impl.get() != nullptr && "requires non-null implementation"); + if (!Impl->CurrentEntry.isStatusKnown()) + Impl.reset(); // Normalize the end iterator to Impl == nullptr. + } + + /// \brief Construct an 'end' iterator. + directory_iterator() { } + + /// \brief Equivalent to operator++, with an error code. + directory_iterator &increment(std::error_code &EC) { + assert(Impl && "attempting to increment past end"); + EC = Impl->increment(); + if (EC || !Impl->CurrentEntry.isStatusKnown()) + Impl.reset(); // Normalize the end iterator to Impl == nullptr. + return *this; + } + + const Status &operator*() const { return Impl->CurrentEntry; } + const Status *operator->() const { return &Impl->CurrentEntry; } + + bool operator==(const directory_iterator &RHS) const { + if (Impl && RHS.Impl) + return Impl->CurrentEntry.equivalent(RHS.Impl->CurrentEntry); + return !Impl && !RHS.Impl; + } + bool operator!=(const directory_iterator &RHS) const { + return !(*this == RHS); + } + + /// For testing only. Directory iteration does not always succeed! + directory_iterator &operator++() { + std::error_code EC; + increment(EC); + if (EC) + llvm::report_fatal_error("directory iteration failed!"); + return *this; + } +}; + /// \brief The virtual file system interface. class FileSystem : public llvm::ThreadSafeRefCountedBase { public: @@ -118,6 +176,13 @@ public: int64_t FileSize = -1, bool RequiresNullTerminator = true, bool IsVolatile = false); + + /// \brief Get a directory_iterator for \p Dir. + /// \note The 'end' iterator is directory_iterator() + virtual directory_iterator dir_begin(const Twine &Dir, + std::error_code &EC) = 0; + + // TODO: recursive directory iterators }; /// \brief Gets an \p vfs::FileSystem for the 'real' file system, as seen by @@ -136,19 +201,10 @@ IntrusiveRefCntPtr getRealFileSystem(); /// system overrides the other(s). class OverlayFileSystem : public FileSystem { typedef SmallVector, 1> FileSystemList; - typedef FileSystemList::reverse_iterator iterator; - /// \brief The stack of file systems, implemented as a list in order of /// their addition. FileSystemList FSList; - /// \brief Get an iterator pointing to the most recently added file system. - iterator overlays_begin() { return FSList.rbegin(); } - - /// \brief Get an iterator pointing one-past the least recently added file - /// system. - iterator overlays_end() { return FSList.rend(); } - public: OverlayFileSystem(IntrusiveRefCntPtr Base); /// \brief Pushes a file system on top of the stack. @@ -157,6 +213,16 @@ public: llvm::ErrorOr status(const Twine &Path) override; std::error_code openFileForRead(const Twine &Path, std::unique_ptr &Result) override; + directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; + + typedef FileSystemList::reverse_iterator iterator; + + /// \brief Get an iterator pointing to the most recently added file system. + iterator overlays_begin() { return FSList.rbegin(); } + + /// \brief Get an iterator pointing one-past the least recently added file + /// system. + iterator overlays_end() { return FSList.rend(); } }; /// \brief Get a globally unique ID for a virtual file or directory. -- cgit v1.2.3