/* Copyright (C) 2001-2006, William Joseph. All Rights Reserved. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined(INCLUDED_IARCHIVE_H) #define INCLUDED_IARCHIVE_H #include #include "generic/constant.h" class InputStream; /// \brief A file opened in binary mode. class ArchiveFile { public: /// \brief Destroys the file object. virtual void release() = 0; /// \brief Returns the size of the file data in bytes. virtual std::size_t size() const = 0; /// \brief Returns the path to this file (relative to the filesystem root) virtual const char* getName() const = 0; /// \brief Returns the stream associated with this file. /// Subsequent calls return the same stream. /// The stream may be read forwards until it is exhausted. /// The stream remains valid for the lifetime of the file. virtual InputStream& getInputStream() = 0; }; class TextInputStream; /// \brief A file opened in text mode. class ArchiveTextFile { public: /// \brief Destroys the file object. virtual void release() = 0; /// \brief Returns the stream associated with this file. /// Subsequent calls return the same stream. /// The stream may be read forwards until it is exhausted. /// The stream remains valid for the lifetime of the file. virtual TextInputStream& getInputStream() = 0; }; class ScopedArchiveFile { ArchiveFile& m_file; public: ScopedArchiveFile(ArchiveFile& file) : m_file(file) { } ~ScopedArchiveFile() { m_file.release(); } }; class CustomArchiveVisitor; class Archive { public: class Visitor { public: virtual void visit(const char* name) = 0; }; typedef CustomArchiveVisitor VisitorFunc; enum EMode { eFiles = 0x01, eDirectories = 0x02, eFilesAndDirectories = 0x03, }; /// \brief Destroys the archive object. /// Any unreleased file object associated with the archive remains valid. */ virtual void release() = 0; /// \brief Returns a new object associated with the file identified by \p name, or 0 if the file cannot be opened. /// Name comparisons are case-insensitive. virtual ArchiveFile* openFile(const char* name) = 0; /// \brief Returns a new object associated with the file identified by \p name, or 0 if the file cannot be opened. /// Name comparisons are case-insensitive. virtual ArchiveTextFile* openTextFile(const char* name) = 0; /// Returns true if the file identified by \p name can be opened. /// Name comparisons are case-insensitive. virtual bool containsFile(const char* name) = 0; /// \brief Performs a depth-first traversal of the archive tree starting at \p root. /// Traverses the entire tree if \p root is "". /// When a file is encountered, calls \c visitor.file passing the file name. /// When a directory is encountered, calls \c visitor.directory passing the directory name. /// Skips the directory if \c visitor.directory returned true. /// Root comparisons are case-insensitive. /// Names are mixed-case. virtual void forEachFile(VisitorFunc visitor, const char* root) = 0; }; class CustomArchiveVisitor { Archive::Visitor* m_visitor; Archive::EMode m_mode; std::size_t m_depth; public: CustomArchiveVisitor(Archive::Visitor& visitor, Archive::EMode mode, std::size_t depth) : m_visitor(&visitor), m_mode(mode), m_depth(depth) { } void file(const char* name) { if((m_mode & Archive::eFiles) != 0) m_visitor->visit(name); } bool directory(const char* name, std::size_t depth) { if((m_mode & Archive::eDirectories) != 0) m_visitor->visit(name); if(depth == m_depth) return true; return false; } }; typedef Archive* (*PFN_OPENARCHIVE) (const char* name); class _QERArchiveTable { public: INTEGER_CONSTANT(Version, 1); STRING_CONSTANT(Name, "archive"); PFN_OPENARCHIVE m_pfnOpenArchive; }; template class Modules; typedef Modules<_QERArchiveTable> ArchiveModules; template class ModulesRef; typedef ModulesRef<_QERArchiveTable> ArchiveModulesRef; #endif