FIFE
2008.0
|
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