/* 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 */ #include "archive.h" #include "idatastream.h" #include "iarchive.h" #include #include #include #include "stream/filestream.h" #include "stream/textfilestream.h" #include "string/string.h" #include "os/path.h" #include "os/file.h" #include "os/dir.h" #include "archivelib.h" #include "fs_path.h" class DirectoryArchive : public Archive { CopiedString m_root; public: DirectoryArchive(const char *root) : m_root(root) { } void release() { delete this; } virtual ArchiveFile *openFile(const char *name) { UnixPath path(m_root.c_str()); path.push_filename(name); DirectoryArchiveFile *file = new DirectoryArchiveFile(name, path.c_str()); if (!file->failed()) { return file; } file->release(); return 0; } virtual ArchiveTextFile *openTextFile(const char *name) { UnixPath path(m_root.c_str()); path.push_filename(name); DirectoryArchiveTextFile *file = new DirectoryArchiveTextFile(name, path.c_str()); if (!file->failed()) { return file; } file->release(); return 0; } virtual bool containsFile(const char *name) { UnixPath path(m_root.c_str()); path.push_filename(name); return file_readable(path.c_str()); } virtual void forEachFile(VisitorFunc visitor, const char *root) { std::vector dirs; UnixPath path(m_root.c_str()); path.push(root); dirs.push_back(directory_open(path.c_str())); while (!dirs.empty() && directory_good(dirs.back())) { const char *name = directory_read_and_increment(dirs.back()); if (name == 0) { directory_close(dirs.back()); dirs.pop_back(); path.pop(); } else if (!string_equal(name, ".") && !string_equal(name, "..")) { path.push_filename(name); bool is_directory = file_is_directory(path.c_str()); if (!is_directory) { visitor.file(path_make_relative(path.c_str(), m_root.c_str())); } path.pop(); if (is_directory) { path.push(name); if (!visitor.directory(path_make_relative(path.c_str(), m_root.c_str()), dirs.size())) { dirs.push_back(directory_open(path.c_str())); } else { path.pop(); } } } } } }; Archive *OpenArchive(const char *name) { return new DirectoryArchive(name); } #if 0 class TestArchive { class TestVisitor : public Archive::IVisitor { public: virtual void visit( const char* name ){ int bleh = 0; } }; public: void test1(){ Archive* archive = OpenArchive( "d:/quake/id1/" ); ArchiveFile* file = archive->openFile( "quake101.wad" ); if ( file != 0 ) { char buffer[1024]; file->getInputStream().read( buffer, 1024 ); file->release(); } TestVisitor visitor; archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" ); archive->release(); } void test2(){ Archive* archive = OpenArchive( "d:/gtkradiant_root/baseq3/" ); TestVisitor visitor; archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 2 ), "" ); archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 1 ), "textures" ); archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eDirectories, 1 ), "textures" ); archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures" ); archive->release(); } TestArchive(){ test1(); test2(); } }; TestArchive g_test; #endif