2
0

BinaryDeserializer.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #include "StdInc.h"
  2. #include "BinaryDeserializer.h"
  3. #include "../registerTypes/RegisterTypes.h"
  4. /*
  5. * BinaryDeserializer.cpp, part of VCMI engine
  6. *
  7. * Authors: listed in file AUTHORS in main folder
  8. *
  9. * License: GNU General Public License v2.0 or later
  10. * Full text of license available in license.txt file, in main folder
  11. *
  12. */
  13. extern template void registerTypes<BinaryDeserializer>(BinaryDeserializer & s);
  14. CLoadFile::CLoadFile(const boost::filesystem::path & fname, int minimalVersion /*= version*/)
  15. : serializer(this)
  16. {
  17. registerTypes(serializer);
  18. openNextFile(fname, minimalVersion);
  19. }
  20. CLoadFile::~CLoadFile()
  21. {
  22. }
  23. int CLoadFile::read(void * data, unsigned size)
  24. {
  25. sfile->read((char*)data,size);
  26. return size;
  27. }
  28. void CLoadFile::openNextFile(const boost::filesystem::path & fname, int minimalVersion)
  29. {
  30. assert(!serializer.reverseEndianess);
  31. assert(minimalVersion <= SERIALIZATION_VERSION);
  32. try
  33. {
  34. fName = fname.string();
  35. sfile = make_unique<FileStream>(fname, std::ios::in | std::ios::binary);
  36. sfile->exceptions(std::ifstream::failbit | std::ifstream::badbit); //we throw a lot anyway
  37. if(!(*sfile))
  38. THROW_FORMAT("Error: cannot open to read %s!", fName);
  39. //we can read
  40. char buffer[4];
  41. sfile->read(buffer, 4);
  42. if(std::memcmp(buffer,"VCMI",4))
  43. THROW_FORMAT("Error: not a VCMI file(%s)!", fName);
  44. serializer & serializer.fileVersion;
  45. if(serializer.fileVersion < minimalVersion)
  46. THROW_FORMAT("Error: too old file format (%s)!", fName);
  47. if(serializer.fileVersion > SERIALIZATION_VERSION)
  48. {
  49. logGlobal->warnStream() << boost::format("Warning format version mismatch: found %d when current is %d! (file %s)\n") % serializer.fileVersion % SERIALIZATION_VERSION % fName;
  50. auto versionptr = (char*)&serializer.fileVersion;
  51. std::reverse(versionptr, versionptr + 4);
  52. logGlobal->warnStream() << "Version number reversed is " << serializer.fileVersion << ", checking...";
  53. if(serializer.fileVersion == SERIALIZATION_VERSION)
  54. {
  55. logGlobal->warnStream() << fname << " seems to have different endianness! Entering reversing mode.";
  56. serializer.reverseEndianess = true;
  57. }
  58. else
  59. THROW_FORMAT("Error: too new file format (%s)!", fName);
  60. }
  61. }
  62. catch(...)
  63. {
  64. clear(); //if anything went wrong, we delete file and rethrow
  65. throw;
  66. }
  67. }
  68. void CLoadFile::reportState(CLogger * out)
  69. {
  70. out->debugStream() << "CLoadFile";
  71. if(!!sfile && *sfile)
  72. {
  73. out->debugStream() << "\tOpened " << fName << "\n\tPosition: " << sfile->tellg();
  74. }
  75. }
  76. void CLoadFile::clear()
  77. {
  78. sfile = nullptr;
  79. fName.clear();
  80. serializer.fileVersion = 0;
  81. }
  82. void CLoadFile::checkMagicBytes(const std::string &text)
  83. {
  84. std::string loaded = text;
  85. read((void*)loaded.data(), text.length());
  86. if(loaded != text)
  87. throw std::runtime_error("Magic bytes doesn't match!");
  88. }