Mercurial > fife-parpg
diff engine/core/vfs/dat/dat1.cpp @ 0:4a0efb7baf70
* Datasets becomes the new trunk and retires after that :-)
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 29 Jun 2008 18:44:17 +0000 |
parents | |
children | 90005975cdbb |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/core/vfs/dat/dat1.cpp Sun Jun 29 18:44:17 2008 +0000 @@ -0,0 +1,152 @@ +/*************************************************************************** + * Copyright (C) 2005-2008 by the FIFE team * + * http://www.fifengine.de * + * This file is part of FIFE. * + * * + * FIFE 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. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +// Standard C++ library includes + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "vfs/raw/rawdata.h" +#include "util/base/exception.h" +#include "util/log/logger.h" + +#include "dat1.h" + +namespace FIFE { + static Logger _log(LM_FO_LOADERS); + + DAT1::DAT1(VFS* vfs, const std::string& file) : VFSSource(vfs), m_datpath(file), m_data(vfs->open(file)) { + FL_LOG(_log, LMsg("MFFalloutDAT1") + << "loading: " << file + << " filesize: " << m_data->getDataLength()); + + m_data->setIndex(0); + + const uint32_t dircount = m_data->read32Big(); + m_data->moveIndex(4*3); + + FL_LOG(_log, LMsg("MFFalloutDAT1") + << "number of directories " << dircount); + + // Sanity check. Each dir entry needs min. 16 bytes. + if( dircount*16 > m_data->getDataLength() ) { + throw InvalidFormat("directory count larger than filesize."); + } + + std::list<std::string> dir_names; + for (uint32_t i = 0; i < dircount; ++i) { + std::string name = readString(); + if (name == ".") { + name = ""; + } + dir_names.push_back(name); + } + + for(std::list<std::string>::iterator i= dir_names.begin(); i!= dir_names.end(); ++i) + loadFileList(*i); + } + + void DAT1::loadFileList(const std::string& dirname) { + const uint32_t filecount = m_data->read32Big(); + m_data->moveIndex(4*3); + for (uint32_t i = 0; i < filecount; ++i) { + RawDataDAT1::s_info info; + info.name = fixPath(dirname + "/" + readString()); + info.type = m_data->read32Big(); + info.offset = m_data->read32Big(); + info.unpackedLength = m_data->read32Big(); + info.packedLength = m_data->read32Big(); + + m_filelist.insert(std::make_pair(info.name, info)); + } + } + + std::string DAT1::readString() { + uint8_t length = m_data->read8(); + return m_data->readString(length); + } + + RawData* DAT1::open(const std::string& file) const { + const RawDataDAT1::s_info& info = getInfo(file); + return new RawData(new RawDataDAT1(getVFS(), m_datpath, info)); + } + + bool DAT1::fileExists(const std::string& name) const { + return m_filelist.find(name) != m_filelist.end(); + } + + const RawDataDAT1::s_info& DAT1::getInfo(const std::string& name) const { + type_filelist::const_iterator i = m_filelist.find(name); + if (i == m_filelist.end()) + throw NotFound(name); + + return i->second; + } + + std::set<std::string> DAT1::listFiles(const std::string& pathstr) const { + return list(pathstr, false); + } + + std::set<std::string> DAT1::listDirectories(const std::string& pathstr) const { + return list(pathstr, true); + } + + std::set<std::string> DAT1::list(const std::string& pathstr, bool dirs) const { + std::set<std::string> list; + std::string path = pathstr; + + // Normalize the path + if (path.find("./") == 0) { + path.erase(0, 2); + } + + int lastIndex = path.size() - 1; + if ((lastIndex != -1) && path[lastIndex] != '/') { + path += '/'; + } + + type_filelist::const_iterator end = m_filelist.end(); + for (type_filelist::const_iterator i = m_filelist.begin(); i != end; ++i) { + const std::string& file = i->first; + if (file.find(path) == 0) { + std::string cleanedfile = file.substr(path.size(), file.size()); // strip the pathstr + bool isdir = cleanedfile.find('/') != std::string::npos; // if we still have a / it's a subdir + + if (isdir) { + cleanedfile = cleanedfile.substr(0, cleanedfile.find('/')); + if (cleanedfile.find('/') != cleanedfile.rfind('/')) { + // check if this is a direct subdir + continue; + } + } + + if (isdir == dirs) { + list.insert(cleanedfile); + } + } + } + + return list; + } +} // FIFE