00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00028
00029 #if !defined __cplusplus
00030 #error C++ compiler required
00031 #endif
00032
00033
00034 #include <algorithm>
00035 #include <fstream>
00036 #include <list>
00037 #include <sstream>
00038 #include <string>
00039 #include <vector>
00040
00041
00042 #include "global.hpp"
00043 #include "wad.hpp"
00044
00045 using namespace Doomwad;
00046
00050 Wad::Wad (void) throw () : m_type (PWAD)
00051 {
00052 }
00053
00059 Wad::Wad (wad_type type) throw ()
00060 {
00061 this->setType (type);
00062 }
00063
00069 Wad::Wad (const std::string &filename) throw ()
00070 {
00071 this->readFromFile (filename);
00072 }
00073
00080 Wad::Wad (const Lump &lump, wad_type type) throw ()
00081 {
00082 this->m_type = type;
00083 this->assign (1, lump);
00084 }
00085
00096 bool Wad::operator== (const Wad &wad) const throw ()
00097 {
00098 const_iterator iter, iter2, last;
00099
00100
00101 if (this == &wad)
00102 {
00103 return true;
00104 }
00105
00106
00107 if (this->m_type != wad.m_type || this->size () != wad.size ())
00108 {
00109 return false;
00110 }
00111
00112
00113
00114
00115 for (iter = this->begin (), iter2 = wad.begin (), last = this->end (); iter != last; ++iter, ++iter2)
00116 {
00117 if (*iter != *iter2)
00118 {
00119 return false;
00120 }
00121 }
00122 return true;
00123 }
00124
00132 bool Wad::operator!= (const Wad &wad) const throw ()
00133 {
00134 return !(*this == wad);
00135 }
00136
00144 Wad& Wad::operator+= (const Wad &wad) throw ()
00145 {
00146
00147
00148 for (const_iterator iter = wad.begin (); iter != wad.end (); ++iter)
00149 {
00150 this->insert (this->end (), *iter);
00151 }
00152 return *this;
00153 }
00154
00162 Wad Wad::operator+ (const Wad &wad) const throw ()
00163 {
00164 Wad w (*this);
00165 return w += wad;
00166 }
00167
00173 bool Wad::isIwad (void) const throw ()
00174 {
00175 return this->m_type == IWAD;
00176 }
00177
00183 bool Wad::isPwad (void) const throw ()
00184 {
00185 return this->m_type == PWAD;
00186 }
00187
00193 Wad::wad_type Wad::getType (void) const throw ()
00194 {
00195 return this->m_type;
00196 }
00197
00205 bool Wad::setType (wad_type type) throw ()
00206 {
00207 this->m_type = type;
00208 return true;
00209 }
00210
00221 std::string Wad::getWadDirectory (char delimiter) const throw ()
00222 {
00223 std::ostringstream str;
00224 const_iterator iter = this->begin ();
00225
00226 for (; iter != this->end (); ++iter)
00227 {
00228 str << iter->getName () << delimiter;
00229 }
00230
00231 return str.str ();
00232 }
00233
00243 bool Wad::writeToFile (const std::string &filename) const throw ()
00244 {
00245
00246
00247 std::ofstream out;
00248
00249
00250 std::vector<int> dir_offset;
00251 dir_offset.reserve (2 * this->size ());
00252
00253
00254 std::vector<int>::const_iterator iter_offset, iter_offset_end;
00255 Wad::const_iterator iter_lump, iter_lump_end;
00256
00257
00258 size_t loc_dir = 0;
00259 size_t lumpsize = 0;
00260 char buffer_name[9];
00261 size_t num_entries = this->size ();
00262
00263
00264 if (filename.empty ())
00265 {
00266 return false;
00267 }
00268
00269
00270 out.open (filename.c_str (), std::ios::out | std::ios::binary | std::ios::trunc);
00271 if (!out)
00272 {
00273 return false;
00274 }
00275
00276
00277 out.write ((this->m_type == IWAD ? "IWAD" : "PWAD"), 4);
00278 out.write (reinterpret_cast<const char *> (&num_entries), 4);
00279 out.write (reinterpret_cast<const char *> (&loc_dir), 4);
00280
00281
00282 for
00283 (
00284 iter_lump = this->begin (),
00285 iter_lump_end = this->end ();
00286
00287 iter_lump != iter_lump_end;
00288
00289 ++iter_lump
00290 )
00291 {
00292 while (out.tellp () % 4)
00293 {
00294 out << static_cast<const char> (NULL);
00295 }
00296 dir_offset.push_back (out.tellp ());
00297 (*iter_lump).writeToStream (out);
00298 }
00299
00300
00301 while (out.tellp () % 4)
00302 {
00303 out << static_cast<const char> (NULL);
00304 }
00305 for
00306 (
00307 iter_offset = dir_offset.begin (),
00308 iter_offset_end = dir_offset.end (),
00309 iter_lump = this->begin (),
00310 iter_lump_end = this->end (),
00311 loc_dir = out.tellp ();
00312
00313 iter_offset != iter_offset_end
00314 && iter_lump != iter_lump_end;
00315
00316 ++iter_offset,
00317 ++iter_lump
00318 )
00319 {
00320
00321
00322 out.write (reinterpret_cast<const char *> (&(*iter_offset)), 4);
00323
00324 lumpsize = (*iter_lump).size ();
00325 out.write (reinterpret_cast<const char *> (&lumpsize), 4);
00326
00327
00328 memset (buffer_name, '\0', 8);
00329 strncpy (buffer_name, (*iter_lump).getName ().c_str (), 8);
00330 out.write (buffer_name, 8);
00331 }
00332
00333
00334 out.seekp (8, std::ios::beg);
00335 out.write (reinterpret_cast<const char *> (&loc_dir), 4);
00336
00337
00338 out.close ();
00339 return true;
00340 }
00341
00352 bool Wad::readFromFile (const std::string &filename) throw ()
00353 {
00354
00355
00356 std::ifstream in;
00357
00358
00359 std::vector<size_t> entry_offset, entry_size;
00360 std::vector<std::string> entry_name;
00361
00362
00363 std::vector<size_t>::iterator iter_offset, iter_size, iter_end;
00364 std::vector<std::string>::iterator iter_name;
00365
00366
00367 size_t num_entries = 0;
00368 size_t loc_dir = 0;
00369 size_t i = 0;
00370 char type[5];
00371 char buffer_dir[17];
00372
00373
00374 size_t buffer_len = 0;
00375 char *buffer = NULL;
00376 Lump temp_lump;
00377
00378
00379 if (filename.empty ())
00380 {
00381 return false;
00382 }
00383
00384
00385 in.open (filename.c_str (), std::ios::in | std::ios::binary);
00386 if (!in)
00387 {
00388 return false;
00389 }
00390
00391
00392 this->clear ();
00393
00394
00395 in.read (type, 4);
00396 type[4] = 0;
00397 in.read (reinterpret_cast<char *> (&num_entries), 4);
00398 in.read (reinterpret_cast<char *> (&loc_dir), 4);
00399
00400
00401 this->m_type = (strcmp (type, "IWAD") ? PWAD : IWAD);
00402
00403
00404 in.seekg (loc_dir, std::ios::beg);
00405 entry_offset.reserve (2 * num_entries);
00406 entry_size.reserve (2 * num_entries);
00407 entry_name.reserve (2 * num_entries);
00408 for (i = buffer_dir[17] = 0; i < num_entries; ++i)
00409 {
00410 in.read (buffer_dir, 16);
00411 entry_offset.push_back (*(reinterpret_cast<int *> (&buffer_dir[0])));
00412 entry_size.push_back (*(reinterpret_cast<int *> (&buffer_dir[4])));
00413 entry_name.push_back (&buffer_dir[8]);
00414 buffer_len = std::max<size_t> (buffer_len, entry_size.back ());
00415 }
00416
00417
00418
00419 buffer = new char[buffer_len];
00420
00421
00422 for
00423 (
00424 iter_offset = entry_offset.begin (),
00425 iter_size = entry_size.begin (),
00426 iter_end = entry_size.end (),
00427 iter_name = entry_name.begin ();
00428
00429 iter_size != iter_end;
00430
00431 ++iter_offset,
00432 ++iter_size,
00433 ++iter_name
00434 )
00435 {
00436
00437
00438 in.seekg (*iter_offset, std::ios::beg);
00439 in.read (buffer, *iter_size);
00440
00441
00442 temp_lump.setName (*iter_name);
00443 temp_lump.assign (reinterpret_cast<byte *> (buffer), *iter_size);
00444
00445 this->push_back (temp_lump);
00446 }
00447
00448
00449 in.close ();
00450 delete [] buffer;
00451 return true;
00452 }