worldspawn/include/iarchive.h

164 lines
4.6 KiB
C++

/*
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 <cstddef>
#include "generic/constant.h"
class InputStream;
/// \brief A file opened in binary mode.
class ArchiveFile
{
public:
virtual ~ArchiveFile() = default;
/// \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:
virtual ~ArchiveTextFile() = default;
/// \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:
virtual ~Archive() = default;
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<typename Type>
class Modules;
typedef Modules<_QERArchiveTable> ArchiveModules;
template<typename Type>
class ModulesRef;
typedef ModulesRef<_QERArchiveTable> ArchiveModulesRef;
#endif