Переглянути джерело

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.

Michał W. Urbańczyk 11 роки тому
батько
коміт
43ef565e7e

+ 2 - 2
launcher/VCMI_launcher.vcxproj

@@ -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>

+ 2 - 2
lib/CGameState.cpp

@@ -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)

+ 1 - 1
lib/CRandomGenerator.h

@@ -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)

+ 33 - 4
lib/Connection.cpp

@@ -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));
+}
+

+ 29 - 3
lib/Connection.h

@@ -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
 {

+ 1 - 1
lib/NetPacksBase.h

@@ -17,7 +17,7 @@ class CStackInstance;
 class CArmedInstance;
 class CArtifactSet;
 class CBonusSystemNode;
-class ArtSlotInfo;
+struct ArtSlotInfo;
 
 
 

+ 2 - 0
lib/RegisterTypes.cpp

@@ -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);

+ 5 - 5
lib/ResourceSet.h

@@ -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;
 		}

+ 2 - 2
lib/filesystem/CInputStream.h

@@ -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);