FIFE  6e1afdbeda11afe9ac53e6023a4be96ef88f1dc6
dat2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2017 by the FIFE team *
3  * http://www.fifengine.net *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 
24 // 3rd party library includes
25 #include <boost/bind.hpp>
26 
27 // FIFE includes
28 // These includes are split up in two parts, separated by one empty line
29 // First block: files included from the FIFE root src directory
30 // Second block: files included from the same folder
31 #include "vfs/raw/rawdata.h"
32 #include "util/base/exception.h"
33 #include "util/log/logger.h"
34 
35 #include "dat2.h"
36 
37 namespace FIFE {
41  static Logger _log(LM_FO_LOADERS);
42 
43  DAT2::DAT2(VFS* vfs, const std::string& file)
44  : VFSSource(vfs), m_datpath(file), m_data(vfs->open(file)), m_filelist() {
45 
46  FL_LOG(_log, LMsg("MFFalloutDAT2")
47  << "loading: " << file
48  << " filesize: " << m_data->getDataLength());
49 
50  m_data->setIndex(m_data->getDataLength() - 8);
51  uint32_t fileListLength = m_data->read32Little();
52  uint32_t archiveSize = m_data->read32Little();
53 
54  FL_LOG(_log, LMsg("MFFalloutDAT2")
55  << "FileListLength: " << fileListLength
56  << " ArchiveSize: " << archiveSize);
57 
58  if (archiveSize != m_data->getDataLength())
59  throw InvalidFormat("size mismatch");
60 
61  m_data->setIndex( archiveSize - fileListLength - 8);
62  m_filecount = m_data->read32Little();
63  m_currentIndex = m_data->getCurrentIndex();
64 
65  FL_LOG(_log, LMsg("MFFalloutDAT2 FileCount: ") << m_filecount);
66 
67  // Do not read the complete file list at startup.
68  // Instead read a chunk each frame.
70  m_timer.setCallback( boost::bind( &DAT2::readFileEntry, this) );
71  m_timer.start();
72  }
73 
74  void DAT2::readFileEntry() const {
75  assert( m_filecount != 0);
76 
77  // Load more items per call,
78  // otherwise it takes _ages_ until everything is in.
79  uint32_t load_per_cycle = 50;
80  if( load_per_cycle > m_filecount )
81  load_per_cycle = m_filecount;
82  m_filecount -= load_per_cycle;
83 
84  // Save the old index in an exception save way.
85  IndexSaver isaver(m_data.get());
86 
87  // Move index to file list and read the entries.
88  m_data->setIndex(m_currentIndex);
90  while( load_per_cycle-- ) {
91  uint32_t namelen = m_data->read32Little();
92  info.name = fixPath(m_data->readString(namelen));
93 
94  info.type = m_data->read8();
95  info.unpackedLength = m_data->read32Little();
96  info.packedLength = m_data->read32Little();
97  info.offset = m_data->read32Little();
98 
99  m_filelist.insert(std::make_pair(info.name, info));
100  }
101  m_currentIndex = m_data->getCurrentIndex();
102 
103  // Finally log on completion and stop the timer.
104  if( m_filecount == 0 ) {
105  FL_LOG(_log, LMsg("MFFalloutDAT2, All file entries in '") << m_datpath << "' loaded.");
106  m_timer.stop();
107  }
108  }
109 
110  RawData* DAT2::open(const std::string& file) const {
111  const RawDataDAT2::s_info& info = getInfo(file);
112  return new RawData(new RawDataDAT2(getVFS(), m_datpath, info));
113  }
114 
115  bool DAT2::fileExists(const std::string& name) const {
116  return findFileEntry(name) != m_filelist.end();
117  }
118 
119  const RawDataDAT2::s_info& DAT2::getInfo(const std::string& name) const {
120  type_filelist::const_iterator i = findFileEntry(name);
121  if (i == m_filelist.end()) {
122  throw NotFound(name);
123  }
124  return i->second;
125  }
126 
127  DAT2::type_filelist::const_iterator DAT2::findFileEntry(const std::string& path) const {
128 
129  // Either the normalization is bogus, or we have to do
130  // it here, too. Otherwise we can't load the files returned
131  // by listFiles.
132 
133  std::string name = path;
134 
135  // Normalize the path
136  if (name.find("./") == 0) {
137  name.erase(0, 2);
138  }
139 
140  type_filelist::const_iterator i = m_filelist.find(name);
141 
142  // We might have another chance to find the file
143  // if the number of file entries not zero.
144  if ( m_filecount && i == m_filelist.end()) {
145  FL_LOG(_log, LMsg("MFFalloutDAT2")
146  << "Missing '" << name
147  << "' in partially(" << m_filecount <<") loaded "<< m_datpath);
148  while( m_filecount && i == m_filelist.end()) {
149  readFileEntry();
150  i = m_filelist.find(name);
151  }
152  }
153  return i;
154  }
155 
156 
157  std::set<std::string> DAT2::listFiles(const std::string& pathstr) const {
158  return list(pathstr, false);
159  }
160 
161  std::set<std::string> DAT2::listDirectories(const std::string& pathstr) const {
162  return list(pathstr, true);
163  }
164 
165  std::set<std::string> DAT2::list(const std::string& pathstr, bool dirs) const {
166  std::set<std::string> list;
167  std::string path = pathstr;
168 
169  // Force loading the complete file entries
170  // This is a costly operation... right after startup.
171  // Later this should do nothing.
172  while( m_filecount ) {
173  readFileEntry();
174  }
175 
176  // Normalize the path
177  if (path.find("./") == 0) {
178  path.erase(0, 2);
179  }
180 
181  size_t lastIndex = path.size();
182  if (lastIndex != 0 && path[lastIndex-1] != '/') {
183  path += '/';
184  }
185 
186  type_filelist::const_iterator end = m_filelist.end();
187  for (type_filelist::const_iterator i = m_filelist.begin(); i != end; ++i) {
188  const std::string& file = i->first;
189  if (file.find(path) == 0) {
190  std::string cleanedfile = file.substr(path.size(), file.size()); // strip the pathstr
191  bool isdir = cleanedfile.find('/') != std::string::npos; // if we still have a / it's a subdir
192 
193  if (isdir) {
194  cleanedfile = cleanedfile.substr(0, cleanedfile.find('/'));
195  if (cleanedfile.find('/') != cleanedfile.rfind('/')) {
196  // check if this is a direct subdir
197  continue;
198  }
199  }
200 
201  if (isdir == dirs) {
202  list.insert(cleanedfile);
203  }
204  }
205  }
206 
207  return list;
208  }
209 } // FIFE
uint32_t m_filecount
number of file entries to read
Definition: dat2.h:88
bool fileExists(const std::string &name) const
check if the given file exists
Definition: dat2.cpp:115
RawData * open(const std::string &file) const
open a file inside this source
Definition: dat2.cpp:110
The needed information for the extraction.
Definition: rawdatadat2.h:51
Timer m_timer
lazy loading timer
Definition: dat2.h:92
Helper class to create log strings out from separate parts Usage: LMsg("some text") << variable << "...
Definition: logger.h:82
VFSSource abstract baseclass.
Definition: vfssource.h:46
VFS * getVFS() const
get the VFS this source is associated with.
Definition: vfssource.h:60
static Logger _log(LM_AUDIO)
boost::scoped_ptr< RawData > m_data
Definition: dat2.h:83
void setInterval(int32_t msec)
Set the interval in milliseconds.
Definition: timer.cpp:60
type_filelist::const_iterator findFileEntry(const std::string &name) const
find a file entry
Definition: dat2.cpp:127
void start()
Start the timer.
Definition: timer.cpp:45
std::set< std::string > list(const std::string &pathstr, bool dirs) const
Definition: dat2.cpp:165
A subclass of RawDataMemSource, that fills itself with a FALLOUT1 .DAT file entry.
Definition: rawdatadat2.h:46
std::set< std::string > listDirectories(const std::string &pathstr) const
list all directories in a directory of this source
Definition: dat2.cpp:161
const RawDataDAT2::s_info & getInfo(const std::string &name) const
Get Information needed to unpack and extract data.
Definition: dat2.cpp:119
void readFileEntry() const
read a bunch of file entries
Definition: dat2.cpp:74
uint32_t m_currentIndex
current index in file
Definition: dat2.h:90
#define FL_LOG(logger, msg)
Definition: logger.h:71
std::set< std::string > listFiles(const std::string &pathstr) const
list all files in a directory of this source
Definition: dat2.cpp:157
void stop()
Stop the timer.
Definition: timer.cpp:53
the main VFS (virtual file system) class
Definition: vfs.h:58
unsigned int uint32_t
Definition: core.h:40
std::string fixPath(std::string path) const
Definition: vfssource.cpp:45
DAT2(VFS *vfs, const std::string &path)
Constructor Create a VFSSource for a Fallout2 DAT file.
Definition: dat2.cpp:43
void setCallback(const type_callback &callback)
Set the callback that will be called.
Definition: timer.cpp:64
type_filelist m_filelist
Definition: dat2.h:85
std::string m_datpath
Definition: dat2.h:82
Used to access diffrent kinds of data.
Definition: rawdata.h:48