2
0

BinaryDeserializer.cpp 2.8 KB

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