]> git.xonotic.org Git - xonotic/netradiant.git/blob - include/iarchive.h
Merge remote-tracking branch 'origin' into Melanosuchus/modernize
[xonotic/netradiant.git] / include / iarchive.h
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #if !defined( INCLUDED_IARCHIVE_H )
23 #define INCLUDED_IARCHIVE_H
24
25 #include <cstddef>
26 #include "generic/constant.h"
27
28 class InputStream;
29
30 /// \brief A file opened in binary mode.
31 class ArchiveFile
32 {
33 public:
34 virtual ~ArchiveFile(){}
35 /// \brief Destroys the file object.
36 virtual void release() = 0;
37 /// \brief Returns the size of the file data in bytes.
38 virtual std::size_t size() const = 0;
39 /// \brief Returns the path to this file (relative to the filesystem root)
40 virtual const char* getName() const = 0;
41 /// \brief Returns the stream associated with this file.
42 /// Subsequent calls return the same stream.
43 /// The stream may be read forwards until it is exhausted.
44 /// The stream remains valid for the lifetime of the file.
45 virtual InputStream& getInputStream() = 0;
46 };
47
48 class TextInputStream;
49
50 /// \brief A file opened in text mode.
51 class ArchiveTextFile
52 {
53 public:
54 virtual ~ArchiveTextFile(){}
55 /// \brief Destroys the file object.
56 virtual void release() = 0;
57 /// \brief Returns the stream associated with this file.
58 /// Subsequent calls return the same stream.
59 /// The stream may be read forwards until it is exhausted.
60 /// The stream remains valid for the lifetime of the file.
61 virtual TextInputStream& getInputStream() = 0;
62 };
63
64 class ScopedArchiveFile
65 {
66 ArchiveFile& m_file;
67 public:
68 ScopedArchiveFile( ArchiveFile& file ) : m_file( file ){
69 }
70 ~ScopedArchiveFile(){
71         m_file.release();
72 }
73 };
74
75 class CustomArchiveVisitor;
76
77 class Archive
78 {
79 public:
80
81 class Visitor
82 {
83 public:
84 virtual ~Visitor(){}
85 virtual void visit( const char* name ) = 0;
86 };
87
88 typedef CustomArchiveVisitor VisitorFunc;
89
90 enum EMode
91 {
92         eFiles = 0x01,
93         eDirectories = 0x02,
94         eFilesAndDirectories = 0x03,
95 };
96
97 virtual ~Archive(){}
98 /// \brief Destroys the archive object.
99 /// Any unreleased file object associated with the archive remains valid. */
100 virtual void release() = 0;
101 /// \brief Returns a new object associated with the file identified by \p name, or 0 if the file cannot be opened.
102 /// Name comparisons are case-insensitive.
103 virtual ArchiveFile* openFile( const char* name ) = 0;
104 /// \brief Returns a new object associated with the file identified by \p name, or 0 if the file cannot be opened.
105 /// Name comparisons are case-insensitive.
106 virtual ArchiveTextFile* openTextFile( const char* name ) = 0;
107 /// Returns true if the file identified by \p name can be opened.
108 /// Name comparisons are case-insensitive.
109 virtual bool containsFile( const char* name ) = 0;
110 /// \brief Performs a depth-first traversal of the archive tree starting at \p root.
111 /// Traverses the entire tree if \p root is "".
112 /// When a file is encountered, calls \c visitor.file passing the file name.
113 /// When a directory is encountered, calls \c visitor.directory passing the directory name.
114 /// Skips the directory if \c visitor.directory returned true.
115 /// Root comparisons are case-insensitive.
116 /// Names are mixed-case.
117 virtual void forEachFile( VisitorFunc visitor, const char* root ) = 0;
118 };
119
120 class CustomArchiveVisitor
121 {
122 Archive::Visitor* m_visitor;
123 Archive::EMode m_mode;
124 std::size_t m_depth;
125 public:
126 CustomArchiveVisitor( Archive::Visitor& visitor, Archive::EMode mode, std::size_t depth )
127         : m_visitor( &visitor ), m_mode( mode ), m_depth( depth ){
128 }
129 void file( const char* name ){
130         if ( ( m_mode & Archive::eFiles ) != 0 ) {
131                 m_visitor->visit( name );
132         }
133 }
134 bool directory( const char* name, std::size_t depth ){
135         if ( ( m_mode & Archive::eDirectories ) != 0 ) {
136                 m_visitor->visit( name );
137         }
138         if ( depth == m_depth ) {
139                 return true;
140         }
141         return false;
142 }
143 };
144
145 typedef Archive* ( *PFN_OPENARCHIVE )( const char* name );
146
147 class _QERArchiveTable
148 {
149 public:
150 INTEGER_CONSTANT( Version, 1 );
151 STRING_CONSTANT( Name, "archive" );
152
153 PFN_OPENARCHIVE m_pfnOpenArchive;
154 };
155
156 template<typename Type>
157 class Modules;
158 typedef Modules<_QERArchiveTable> ArchiveModules;
159
160 template<typename Type>
161 class ModulesRef;
162 typedef ModulesRef<_QERArchiveTable> ArchiveModulesRef;
163
164 #endif