FIFE 2008.0
dat1.cpp
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2008 by the FIFE team                              *
00003  *   http://www.fifengine.de                                               *
00004  *   This file is part of FIFE.                                            *
00005  *                                                                         *
00006  *   FIFE is free software; you can redistribute it and/or                 *
00007  *   modify it under the terms of the GNU Lesser General Public            *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2.1 of the License, or (at your option) any later version.    *
00010  *                                                                         *
00011  *   This library is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the                 *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
00020  ***************************************************************************/
00021 
00022 // Standard C++ library includes
00023 
00024 // 3rd party library includes
00025 
00026 // FIFE includes
00027 // These includes are split up in two parts, separated by one empty line
00028 // First block: files included from the FIFE root src directory
00029 // Second block: files included from the same folder
00030 #include "vfs/raw/rawdata.h"
00031 #include "util/base/exception.h"
00032 #include "util/log/logger.h"
00033 
00034 #include "dat1.h"
00035 
00036 namespace FIFE {
00037     static Logger _log(LM_FO_LOADERS);
00038 
00039     DAT1::DAT1(VFS* vfs, const std::string& file) : VFSSource(vfs), m_datpath(file), m_data(vfs->open(file))  {
00040         FL_LOG(_log, LMsg("MFFalloutDAT1") 
00041             << "loading: " << file 
00042             << " filesize: " << m_data->getDataLength());
00043 
00044         m_data->setIndex(0);
00045 
00046         const uint32_t dircount = m_data->read32Big();
00047         m_data->moveIndex(4*3);
00048 
00049         FL_LOG(_log, LMsg("MFFalloutDAT1") 
00050             << "number of directories " << dircount);
00051 
00052         // Sanity check. Each dir entry needs min. 16 bytes.
00053         if( dircount*16 > m_data->getDataLength() ) {
00054             throw InvalidFormat("directory count larger than filesize.");
00055         }
00056 
00057         std::list<std::string> dir_names;
00058         for (uint32_t i = 0; i < dircount; ++i) {
00059             std::string name = readString();
00060             if (name == ".") {
00061                 name = "";
00062             }
00063             dir_names.push_back(name);
00064         }
00065 
00066         for(std::list<std::string>::iterator i= dir_names.begin(); i!= dir_names.end(); ++i)
00067             loadFileList(*i);
00068     }
00069 
00070     void DAT1::loadFileList(const std::string& dirname) {
00071         const uint32_t filecount = m_data->read32Big();
00072         m_data->moveIndex(4*3);
00073         for (uint32_t i = 0; i < filecount; ++i) {
00074             RawDataDAT1::s_info info;
00075             info.name = fixPath(dirname + "/" + readString());
00076             info.type = m_data->read32Big();
00077             info.offset = m_data->read32Big();
00078             info.unpackedLength = m_data->read32Big();
00079             info.packedLength = m_data->read32Big();
00080 
00081             m_filelist.insert(std::make_pair(info.name, info));
00082         }
00083     }
00084 
00085     std::string DAT1::readString() {
00086         uint8_t length = m_data->read8();
00087         return m_data->readString(length);
00088     }
00089 
00090     RawData* DAT1::open(const std::string& file) const {
00091         const RawDataDAT1::s_info& info = getInfo(file);
00092         return new RawData(new RawDataDAT1(getVFS(), m_datpath, info));
00093     }
00094 
00095     bool DAT1::fileExists(const std::string& name) const {
00096         return m_filelist.find(name) != m_filelist.end();
00097     }
00098 
00099     const RawDataDAT1::s_info& DAT1::getInfo(const std::string& name) const {
00100         type_filelist::const_iterator i = m_filelist.find(name);
00101         if (i == m_filelist.end())
00102             throw NotFound(name);
00103 
00104         return i->second;
00105     }
00106 
00107     std::set<std::string> DAT1::listFiles(const std::string& pathstr) const {
00108         return list(pathstr, false);
00109     }
00110 
00111     std::set<std::string> DAT1::listDirectories(const std::string& pathstr) const {
00112         return list(pathstr, true);
00113     }
00114 
00115     std::set<std::string> DAT1::list(const std::string& pathstr, bool dirs) const {
00116         std::set<std::string> list;
00117         std::string path = pathstr;
00118 
00119         // Normalize the path
00120         if (path.find("./") == 0) {
00121             path.erase(0, 2);
00122         }
00123         
00124         int lastIndex = path.size() - 1;
00125         if ((lastIndex != -1) && path[lastIndex] != '/') {
00126             path += '/';
00127         }
00128 
00129         type_filelist::const_iterator end = m_filelist.end();
00130         for (type_filelist::const_iterator i = m_filelist.begin(); i != end; ++i) {
00131             const std::string& file = i->first;
00132             if (file.find(path) == 0) {
00133                 std::string cleanedfile = file.substr(path.size(), file.size()); // strip the pathstr
00134                 bool isdir = cleanedfile.find('/') != std::string::npos; // if we still have a / it's a subdir
00135 
00136                 if (isdir) {
00137                     cleanedfile = cleanedfile.substr(0, cleanedfile.find('/'));
00138                     if (cleanedfile.find('/') != cleanedfile.rfind('/')) {
00139                         // check if this is a direct subdir
00140                         continue;
00141                     }
00142                 }
00143 
00144                 if (isdir == dirs) {
00145                     list.insert(cleanedfile);
00146                 }
00147             }
00148         }
00149 
00150         return list;
00151     }
00152 } // FIFE
 All Classes Namespaces Functions Variables Enumerations Enumerator