fix a scanf warning
[divverent/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   /// \brief Destroys the file object.
35   virtual void release() = 0;
36   /// \brief Returns the size of the file data in bytes.
37   virtual std::size_t size() const = 0;
38   /// \brief Returns the path to this file (relative to the filesystem root)
39   virtual const char* getName() const = 0;
40   /// \brief Returns the stream associated with this file.
41   /// Subsequent calls return the same stream.
42   /// The stream may be read forwards until it is exhausted.
43   /// The stream remains valid for the lifetime of the file.
44   virtual InputStream& getInputStream() = 0;
45 };
46
47 class TextInputStream;
48
49 /// \brief A file opened in text mode.
50 class ArchiveTextFile
51 {
52 public:
53   /// \brief Destroys the file object.
54   virtual void release() = 0;
55   /// \brief Returns the stream associated with this file.
56   /// Subsequent calls return the same stream.
57   /// The stream may be read forwards until it is exhausted.
58   /// The stream remains valid for the lifetime of the file.
59   virtual TextInputStream& getInputStream() = 0;
60 };
61
62 class ScopedArchiveFile
63 {
64   ArchiveFile& m_file;
65 public:
66   ScopedArchiveFile(ArchiveFile& file) : m_file(file)
67   {
68   }
69   ~ScopedArchiveFile()
70   {
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 void visit(const char* name) = 0;
85   };
86
87   typedef CustomArchiveVisitor VisitorFunc;
88
89   enum EMode
90   {
91     eFiles = 0x01,
92     eDirectories = 0x02,
93     eFilesAndDirectories = 0x03,
94   };
95
96   /// \brief Destroys the archive object.
97   /// Any unreleased file object associated with the archive remains valid. */
98   virtual void release() = 0;
99   /// \brief Returns a new object associated with the file identified by \p name, or 0 if the file cannot be opened.
100   /// Name comparisons are case-insensitive.
101   virtual ArchiveFile* openFile(const char* name) = 0;
102   /// \brief Returns a new object associated with the file identified by \p name, or 0 if the file cannot be opened.
103   /// Name comparisons are case-insensitive.
104   virtual ArchiveTextFile* openTextFile(const char* name) = 0;
105   /// Returns true if the file identified by \p name can be opened.
106   /// Name comparisons are case-insensitive.
107   virtual bool containsFile(const char* name) = 0;
108   /// \brief Performs a depth-first traversal of the archive tree starting at \p root.
109   /// Traverses the entire tree if \p root is "".
110   /// When a file is encountered, calls \c visitor.file passing the file name.
111   /// When a directory is encountered, calls \c visitor.directory passing the directory name.
112   /// Skips the directory if \c visitor.directory returned true.
113   /// Root comparisons are case-insensitive.
114   /// Names are mixed-case.
115   virtual void forEachFile(VisitorFunc visitor, const char* root) = 0;
116 };
117
118 class CustomArchiveVisitor
119 {
120   Archive::Visitor* m_visitor;
121   Archive::EMode m_mode;
122   std::size_t m_depth;
123 public:
124   CustomArchiveVisitor(Archive::Visitor& visitor, Archive::EMode mode, std::size_t depth)
125     : m_visitor(&visitor), m_mode(mode), m_depth(depth)
126   {
127   }
128   void file(const char* name)
129   {
130     if((m_mode & Archive::eFiles) != 0)
131       m_visitor->visit(name);
132   }
133   bool directory(const char* name, std::size_t depth)
134   {
135     if((m_mode & Archive::eDirectories) != 0)
136       m_visitor->visit(name);
137     if(depth == m_depth)
138       return true;
139     return false;
140   }
141 };
142
143 typedef Archive* (*PFN_OPENARCHIVE) (const char* name);
144
145 class _QERArchiveTable
146 {
147 public:
148   INTEGER_CONSTANT(Version, 1);
149   STRING_CONSTANT(Name, "archive");
150
151   PFN_OPENARCHIVE              m_pfnOpenArchive;
152 };
153
154 template<typename Type>
155 class Modules;
156 typedef Modules<_QERArchiveTable> ArchiveModules;
157
158 template<typename Type>
159 class ModulesRef;
160 typedef ModulesRef<_QERArchiveTable> ArchiveModulesRef;
161
162 #endif