]> icculus.org git repositories - divverent/netradiant.git/blob - plugins/vfspk3/archive.cpp
automatically run the decompiler when specifying a BSP file in Import...
[divverent/netradiant.git] / plugins / vfspk3 / archive.cpp
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 #include "archive.h"
23
24 #include "idatastream.h"
25 #include "iarchive.h"
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <vector>
30
31 #include "stream/filestream.h"
32 #include "stream/textfilestream.h"
33 #include "string/string.h"
34 #include "os/path.h"
35 #include "os/file.h"
36 #include "os/dir.h"
37 #include "archivelib.h"
38 #include "fs_path.h"
39
40 #include "vfspk3.h"
41
42
43 class DirectoryArchive : public Archive
44 {
45   CopiedString m_root;
46 public:
47   DirectoryArchive(const char* root) : m_root(root)
48   {
49   }
50
51   void release()
52   {
53     delete this;
54   }
55   virtual ArchiveFile* openFile(const char* name)
56   {
57     UnixPath path(m_root.c_str());
58     path.push_filename(name);
59     DirectoryArchiveFile* file = new DirectoryArchiveFile(name, path.c_str());
60     if(!file->failed())
61     {
62       return file;
63     }
64     file->release();
65     return 0;
66   }
67   virtual ArchiveTextFile* openTextFile(const char* name)
68   {
69     UnixPath path(m_root.c_str());
70     path.push_filename(name);
71     DirectoryArchiveTextFile* file = new DirectoryArchiveTextFile(name, path.c_str());
72     if(!file->failed())
73     {
74       return file;
75     }
76     file->release();
77     return 0;
78   }
79   virtual bool containsFile(const char* name)
80   {
81     UnixPath path(m_root.c_str());
82     path.push_filename(name);
83     return file_readable(path.c_str());
84   }
85   virtual void forEachFile(VisitorFunc visitor, const char* root)
86   {
87     std::vector<Directory*> dirs;
88     UnixPath path(m_root.c_str());
89     path.push(root);
90     dirs.push_back(directory_open(path.c_str()));
91
92     while(!dirs.empty() && directory_good(dirs.back()))
93     {
94       const char* name = directory_read_and_increment(dirs.back());
95
96       if(name == 0)
97       {
98         directory_close(dirs.back());
99         dirs.pop_back();
100         path.pop();
101       }
102       else if(!string_equal(name, ".") && !string_equal(name, ".."))
103       {
104         path.push_filename(name);
105
106         bool is_directory = file_is_directory(path.c_str());
107
108         if(!is_directory)
109           visitor.file(path_make_relative(path.c_str(), m_root.c_str()));
110
111         path.pop();
112
113         if(is_directory)
114         {
115           path.push(name);
116
117           if(!visitor.directory(path_make_relative(path.c_str(), m_root.c_str()), dirs.size()))
118             dirs.push_back(directory_open(path.c_str()));
119           else
120             path.pop();
121         }
122       }
123     }
124   }
125 };
126
127 Archive* OpenArchive(const char* name)
128 {
129   return new DirectoryArchive(name);
130 }
131
132 #if 0
133
134 class TestArchive
135 {
136   class TestVisitor : public Archive::IVisitor
137   {
138   public:
139     virtual void visit(const char* name)
140     {
141       int bleh = 0;
142     }
143   };
144 public:
145   void test1()
146   {
147     Archive* archive = OpenArchive("d:/quake/id1/");
148     ArchiveFile* file = archive->openFile("quake101.wad");
149     if(file != 0)
150     {
151       char buffer[1024];
152       file->getInputStream().read(buffer, 1024);
153       file->release();
154     }
155     TestVisitor visitor;
156     archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 0), "");
157     archive->release();
158   }
159   void test2()
160   {
161     Archive* archive = OpenArchive("d:/gtkradiant_root/baseq3/");
162     TestVisitor visitor;
163     archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 2), "");
164     archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFiles, 1), "textures");
165     archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eDirectories, 1), "textures");
166     archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 1), "textures");
167     archive->release();
168   }
169   TestArchive()
170   {
171     test1();
172     test2();
173   }
174 };
175
176 TestArchive g_test;
177
178 #endif