2016-09-10 02:28:11 +02:00
# include "StdInc.h"
# include "BinaryDeserializer.h"
# include "../registerTypes/RegisterTypes.h"
/*
* BinaryDeserializer . cpp , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
extern template void registerTypes < BinaryDeserializer > ( BinaryDeserializer & s ) ;
2016-10-30 14:14:59 +02:00
CLoadFile : : CLoadFile ( const boost : : filesystem : : path & fname , int minimalVersion /*= version*/ )
: serializer ( this )
2016-09-10 02:28:11 +02:00
{
registerTypes ( serializer ) ;
openNextFile ( fname , minimalVersion ) ;
}
CLoadFile : : ~ CLoadFile ( )
{
}
int CLoadFile : : read ( void * data , unsigned size )
{
sfile - > read ( ( char * ) data , size ) ;
return size ;
}
void CLoadFile : : openNextFile ( const boost : : filesystem : : path & fname , int minimalVersion )
{
assert ( ! serializer . reverseEndianess ) ;
2016-10-29 18:52:19 +02:00
assert ( minimalVersion < = SERIALIZATION_VERSION ) ;
2016-09-10 02:28:11 +02:00
try
{
fName = fname . string ( ) ;
2016-10-30 14:14:59 +02:00
sfile = make_unique < FileStream > ( fname , std : : ios : : in | std : : ios : : binary ) ;
2016-09-10 02:28:11 +02:00
sfile - > exceptions ( std : : ifstream : : failbit | std : : ifstream : : badbit ) ; //we throw a lot anyway
if ( ! ( * sfile ) )
THROW_FORMAT ( " Error: cannot open to read %s! " , fName ) ;
//we can read
char buffer [ 4 ] ;
sfile - > read ( buffer , 4 ) ;
if ( std : : memcmp ( buffer , " VCMI " , 4 ) )
THROW_FORMAT ( " Error: not a VCMI file(%s)! " , fName ) ;
serializer & serializer . fileVersion ;
if ( serializer . fileVersion < minimalVersion )
THROW_FORMAT ( " Error: too old file format (%s)! " , fName ) ;
2016-10-30 14:14:59 +02:00
if ( serializer . fileVersion > SERIALIZATION_VERSION )
2016-09-10 02:28:11 +02:00
{
2016-10-29 18:52:19 +02:00
logGlobal - > warnStream ( ) < < boost : : format ( " Warning format version mismatch: found %d when current is %d! (file %s) \n " ) % serializer . fileVersion % SERIALIZATION_VERSION % fName ;
2016-09-10 02:28:11 +02:00
auto versionptr = ( char * ) & serializer . fileVersion ;
std : : reverse ( versionptr , versionptr + 4 ) ;
logGlobal - > warnStream ( ) < < " Version number reversed is " < < serializer . fileVersion < < " , checking... " ;
2016-10-29 18:52:19 +02:00
if ( serializer . fileVersion = = SERIALIZATION_VERSION )
2016-09-10 02:28:11 +02:00
{
logGlobal - > warnStream ( ) < < fname < < " seems to have different endianness! Entering reversing mode. " ;
serializer . reverseEndianess = true ;
}
else
THROW_FORMAT ( " Error: too new file format (%s)! " , fName ) ;
}
}
catch ( . . . )
{
clear ( ) ; //if anything went wrong, we delete file and rethrow
throw ;
}
}
void CLoadFile : : reportState ( CLogger * out )
{
out - > debugStream ( ) < < " CLoadFile " ;
if ( ! ! sfile & & * sfile )
{
out - > debugStream ( ) < < " \t Opened " < < fName < < " \n \t Position: " < < sfile - > tellg ( ) ;
}
}
void CLoadFile : : clear ( )
{
sfile = nullptr ;
fName . clear ( ) ;
serializer . fileVersion = 0 ;
}
2016-10-30 14:14:59 +02:00
void CLoadFile : : checkMagicBytes ( const std : : string & text )
2016-09-10 02:28:11 +02:00
{
std : : string loaded = text ;
read ( ( void * ) loaded . data ( ) , text . length ( ) ) ;
if ( loaded ! = text )
throw std : : runtime_error ( " Magic bytes doesn't match! " ) ;
}