mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Added serializer-based class able to make deep copies of objects — CMemorySerializer.
CGameState::init will work on the deep copy of StartInfo. Some casts to reduce warnings.
This commit is contained in:
		| @@ -19,13 +19,13 @@ | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> | ||||
|     <ConfigurationType>Application</ConfigurationType> | ||||
|     <UseDebugLibraries>true</UseDebugLibraries> | ||||
|     <PlatformToolset>v110</PlatformToolset> | ||||
|     <PlatformToolset>v120_xp</PlatformToolset> | ||||
|     <CharacterSet>Unicode</CharacterSet> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'" Label="Configuration"> | ||||
|     <ConfigurationType>Application</ConfigurationType> | ||||
|     <UseDebugLibraries>false</UseDebugLibraries> | ||||
|     <PlatformToolset>v110_xp</PlatformToolset> | ||||
|     <PlatformToolset>v120_xp</PlatformToolset> | ||||
|     <WholeProgramOptimization>true</WholeProgramOptimization> | ||||
|     <CharacterSet>Unicode</CharacterSet> | ||||
|   </PropertyGroup> | ||||
|   | ||||
| @@ -763,8 +763,8 @@ void CGameState::init(StartInfo * si) | ||||
| { | ||||
|     logGlobal->infoStream() << "\tUsing random seed: "<< si->seedToBeUsed; | ||||
| 	ran.seed((boost::int32_t)si->seedToBeUsed); | ||||
| 	scenarioOps = new StartInfo(*si); | ||||
| 	initialOpts = new StartInfo(*si); | ||||
| 	scenarioOps = CMemorySerializer::deepCopy(*si).release(); | ||||
| 	initialOpts = CMemorySerializer::deepCopy(*si).release(); | ||||
| 	si = nullptr; | ||||
|  | ||||
| 	switch(scenarioOps->mode) | ||||
|   | ||||
| @@ -26,7 +26,7 @@ public: | ||||
| 	/// Seeds the generator with the current time by default. | ||||
| 	CRandomGenerator()  | ||||
| 	{ | ||||
| 		gen.seed(std::time(nullptr)); | ||||
| 		gen.seed((unsigned long)std::time(nullptr)); | ||||
| 	} | ||||
|  | ||||
| 	void seed(int value) | ||||
|   | ||||
| @@ -20,6 +20,8 @@ using namespace boost::asio::ip; | ||||
|  | ||||
| extern template void registerTypes<CISer<CConnection> >(CISer<CConnection>& s); | ||||
| extern template void registerTypes<COSer<CConnection> >(COSer<CConnection>& s); | ||||
| extern template void registerTypes<CISer<CMemorySerializer> >(CISer<CMemorySerializer>& s); | ||||
| extern template void registerTypes<COSer<CMemorySerializer> >(COSer<CMemorySerializer>& s); | ||||
| extern template void registerTypes<CSaveFile>(CSaveFile & s); | ||||
| extern template void registerTypes<CLoadFile>(CLoadFile & s); | ||||
| extern template void registerTypes<CTypeList>(CTypeList & s); | ||||
| @@ -40,6 +42,7 @@ CTypeList typeList; | ||||
| #define LIL_ENDIAN | ||||
| #endif | ||||
|  | ||||
|  | ||||
| void CConnection::init() | ||||
| { | ||||
| 	enableSmartPointerSerializatoin(); | ||||
| @@ -354,9 +357,9 @@ CLoadFile::~CLoadFile() | ||||
| { | ||||
| } | ||||
|  | ||||
| int CLoadFile::read( const void * data, unsigned size ) | ||||
| int CLoadFile::read(void * data, unsigned size) | ||||
| { | ||||
| 	sfile->read((char *)data,size); | ||||
| 	sfile->read((char*)data,size); | ||||
| 	return size; | ||||
| } | ||||
|  | ||||
| @@ -427,7 +430,7 @@ void CLoadFile::clear() | ||||
| void CLoadFile::checkMagicBytes( const std::string &text ) | ||||
| { | ||||
| 	std::string loaded = text; | ||||
| 	read(loaded.c_str(), text.length()); | ||||
| 	read((void*)loaded.data(), text.length()); | ||||
| 	if(loaded != text) | ||||
| 		throw std::runtime_error("Magic bytes doesn't match!"); | ||||
| } | ||||
| @@ -506,7 +509,7 @@ CLoadIntegrityValidator::CLoadIntegrityValidator( const std::string &primaryFile | ||||
| 	fileVersion = primaryFile->fileVersion; | ||||
| } | ||||
|  | ||||
| int CLoadIntegrityValidator::read( const void * data, unsigned size ) | ||||
| int CLoadIntegrityValidator::read( void * data, unsigned size ) | ||||
| { | ||||
| 	assert(primaryFile); | ||||
| 	assert(controlFile); | ||||
| @@ -544,3 +547,29 @@ void CLoadIntegrityValidator::checkMagicBytes( const std::string &text ) | ||||
| 	primaryFile->checkMagicBytes(text); | ||||
| 	controlFile->checkMagicBytes(text); | ||||
| } | ||||
|  | ||||
| int CMemorySerializer::read(void * data, unsigned size) | ||||
| { | ||||
| 	if(buffer.size() < readPos + size) | ||||
| 		throw std::runtime_error(boost::str(boost::format("Cannot read past the buffer (accessing index %d, while size is %d)!") % (readPos + size - 1) % buffer.size())); | ||||
|  | ||||
| 	std::memcpy(data, buffer.data() + readPos, size); | ||||
| 	readPos += size; | ||||
| 	return size; | ||||
| } | ||||
|  | ||||
| int CMemorySerializer::write(const void * data, unsigned size) | ||||
| { | ||||
| 	auto oldSize = buffer.size(); //and the pos to write from | ||||
| 	buffer.resize(oldSize + size); | ||||
| 	std::memcpy(buffer.data() + oldSize, data, size); | ||||
| 	return size; | ||||
| } | ||||
|  | ||||
| CMemorySerializer::CMemorySerializer() | ||||
| { | ||||
| 	readPos = 0; | ||||
| 	registerTypes(static_cast<CISer<CMemorySerializer>&>(*this)); | ||||
| 	registerTypes(static_cast<COSer<CMemorySerializer>&>(*this)); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1320,7 +1320,7 @@ public: | ||||
|  | ||||
| 	CLoadFile(const std::string &fname, int minimalVersion = version); //throws! | ||||
| 	~CLoadFile(); | ||||
| 	int read(const void * data, unsigned size); //throws! | ||||
| 	int read(void * data, unsigned size); //throws! | ||||
|  | ||||
| 	void openNextFile(const std::string &fname, int minimalVersion); //throws! | ||||
| 	void clear(); | ||||
| @@ -1337,7 +1337,7 @@ public: | ||||
| 	 | ||||
| 	CLoadIntegrityValidator(const std::string &primaryFileName, const std::string &controlFileName, int minimalVersion = version); //throws! | ||||
|  | ||||
| 	int read(const void * data, unsigned size); //throws! | ||||
| 	int read( void * data, unsigned size); //throws! | ||||
| 	void checkMagicBytes(const std::string &text); | ||||
|  | ||||
| 	unique_ptr<CLoadFile> decay(); //returns primary file. CLoadIntegrityValidator stops being usable anymore | ||||
| @@ -1347,7 +1347,7 @@ typedef boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::s | ||||
| typedef boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::socket_acceptor_service<boost::asio::ip::tcp> > TAcceptor; | ||||
|  | ||||
| class DLL_LINKAGE CConnection | ||||
| 	:public CISer<CConnection>, public COSer<CConnection> | ||||
| 	: public CISer<CConnection>, public COSer<CConnection> | ||||
| { | ||||
| 	//CGameState *gs; | ||||
| 	CConnection(void); | ||||
| @@ -1396,6 +1396,32 @@ public: | ||||
|  | ||||
| DLL_LINKAGE std::ostream &operator<<(std::ostream &str, const CConnection &cpc); | ||||
|  | ||||
|  | ||||
| // Serializer that stores objects in the dynamic buffer. Allows performing deep object copies. | ||||
| class DLL_LINKAGE CMemorySerializer | ||||
| 	: public CISer<CMemorySerializer>, public COSer<CMemorySerializer> | ||||
| { | ||||
| 	std::vector<ui8> buffer; | ||||
|  | ||||
| 	size_t readPos; //index of the next byte to be read | ||||
| public: | ||||
| 	int read(void * data, unsigned size); //throws! | ||||
| 	int write(const void * data, unsigned size); | ||||
|  | ||||
| 	CMemorySerializer(); | ||||
|  | ||||
| 	template <typename T> | ||||
| 	static unique_ptr<T> deepCopy(const T &data) | ||||
| 	{ | ||||
| 		CMemorySerializer mem; | ||||
| 		mem << &data; | ||||
|  | ||||
| 		unique_ptr<T> ret; | ||||
| 		mem >> ret; | ||||
| 		return ret; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| class CApplier | ||||
| { | ||||
|   | ||||
| @@ -17,7 +17,7 @@ class CStackInstance; | ||||
| class CArmedInstance; | ||||
| class CArtifactSet; | ||||
| class CBonusSystemNode; | ||||
| class ArtSlotInfo; | ||||
| struct ArtSlotInfo; | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -31,6 +31,8 @@ | ||||
|  | ||||
| template void registerTypes<CISer<CConnection>>(CISer<CConnection>& s); | ||||
| template void registerTypes<COSer<CConnection>>(COSer<CConnection>& s); | ||||
| template void registerTypes<CISer<CMemorySerializer>>(CISer<CMemorySerializer>& s); | ||||
| template void registerTypes<COSer<CMemorySerializer>>(COSer<CMemorySerializer>& s); | ||||
| template void registerTypes<CSaveFile>(CSaveFile & s); | ||||
| template void registerTypes<CLoadFile>(CLoadFile & s); | ||||
| template void registerTypes<CTypeList>(CTypeList & s); | ||||
|   | ||||
| @@ -40,7 +40,7 @@ namespace Res | ||||
| 		ResourceSet operator OPSIGN(const TResource &rhs) const	\ | ||||
| 		{														\ | ||||
| 			ResourceSet ret = *this;							\ | ||||
| 			for(int i = 0; i < size(); i++)						\ | ||||
| 			for(int i = 0; i < (int)size(); i++)						\ | ||||
| 				ret[i] = at(i) OPSIGN rhs;						\ | ||||
| 																\ | ||||
| 			return ret;											\ | ||||
| @@ -52,7 +52,7 @@ namespace Res | ||||
| 		ResourceSet operator OPSIGN(const ResourceSet &rhs) const	\ | ||||
| 		{															\ | ||||
| 			ResourceSet ret = *this;								\ | ||||
| 			for(int i = 0; i < size(); i++)							\ | ||||
| 			for(int i = 0; i < (int)size(); i++)							\ | ||||
| 				ret[i] = at(i) OPSIGN rhs[i];						\ | ||||
| 																	\ | ||||
| 			return ret;												\ | ||||
| @@ -85,7 +85,7 @@ namespace Res | ||||
| 		int operator/(const ResourceSet &rhs) | ||||
| 		{ | ||||
| 			int ret = INT_MAX; | ||||
| 			for(int i = 0; i < size(); i++) | ||||
| 			for(int i = 0; i < (int)size(); i++) | ||||
| 				if(rhs[i]) | ||||
| 					vstd::amin(ret, at(i) / rhs[i]); | ||||
|  | ||||
| @@ -94,7 +94,7 @@ namespace Res | ||||
|  | ||||
| 		ResourceSet & operator=(const TResource &rhs) | ||||
| 		{ | ||||
| 			for(int i = 0; i < size(); i++) | ||||
| 			for(int i = 0; i < (int)size(); i++) | ||||
| 				at(i) = rhs; | ||||
|  | ||||
| 			return *this; | ||||
| @@ -103,7 +103,7 @@ namespace Res | ||||
| 		ResourceSet operator-() const | ||||
| 		{ | ||||
| 			ResourceSet ret; | ||||
| 			for(int i = 0; i < size(); i++) | ||||
| 			for(int i = 0; i < (int)size(); i++) | ||||
| 				ret[i] = -at(i); | ||||
| 			return ret; | ||||
| 		} | ||||
|   | ||||
| @@ -65,12 +65,12 @@ public: | ||||
| 	 * | ||||
| 	 * @return pair, first = raw data, second = size of data | ||||
| 	 */ | ||||
| 	std::pair<std::unique_ptr<ui8[]>, size_t> readAll() | ||||
| 	std::pair<std::unique_ptr<ui8[]>, si64> readAll() | ||||
| 	{ | ||||
| 		std::unique_ptr<ui8[]> data(new ui8[getSize()]); | ||||
|  | ||||
| 		seek(0); | ||||
| 		size_t readSize = read(data.get(), getSize()); | ||||
| 		auto readSize = read(data.get(), getSize()); | ||||
| 		assert(readSize == getSize()); | ||||
| 		UNUSED(readSize); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user