#include "stdafx.h" #include #include "Serializer.h" #include "ISerializable.h" #include "miniz.h" Serializer::Serializer(uint32_t version) { _version = version; _block.reset(new BlockData()); _block->Data = vector(0x50000); _block->Position = 0; _saving = true; } Serializer::Serializer(istream &file, uint32_t version, bool compressed) { _version = version; _block.reset(new BlockData()); _block->Position = 0; _saving = false; if(compressed) { uint32_t decompressedSize; file.read((char*)&decompressedSize, sizeof(decompressedSize)); uint32_t compressedSize; file.read((char*)&compressedSize, sizeof(compressedSize)); vector compressedData(compressedSize, 0); file.read((char*)compressedData.data(), compressedSize); _block->Data = vector(decompressedSize, 0); unsigned long decompSize = decompressedSize; uncompress(_block->Data.data(), &decompSize, compressedData.data(), (unsigned long)compressedData.size()); } else { file.seekg(0, std::ios::end); uint32_t size = (uint32_t)file.tellg(); file.seekg(0, std::ios::beg); _block->Data = vector(size, 0); file.read((char*)_block->Data.data(), size); } } void Serializer::EnsureCapacity(uint32_t typeSize) { //Make sure the current block/stream is large enough to fit the next write uint32_t oldSize = (uint32_t)_block->Data.size(); if(oldSize == 0) { oldSize = typeSize * 2; } uint32_t sizeRequired = _block->Position + typeSize; uint32_t newSize = oldSize; while(newSize < sizeRequired) { newSize *= 2; } _block->Data.resize(newSize); } void Serializer::RecursiveStream() { } void Serializer::StreamStartBlock() { unique_ptr block(new BlockData()); block->Position = 0; if(!_saving) { VectorInfo vectorInfo = { &block->Data }; InternalStream(vectorInfo); } else { block->Data = vector(0x100); } _blocks.push_back(std::move(_block)); _block = std::move(block); } void Serializer::StreamEndBlock() { if(_blocks.empty()) { throw std::runtime_error("Invalid call to end block"); } unique_ptr block = std::move(_block); _block = std::move(_blocks.back()); _blocks.pop_back(); if(_saving) { ArrayInfo arrayInfo { block->Data.data(), block->Position }; InternalStream(arrayInfo); } } void Serializer::Save(ostream& file, int compressionLevel) { if(compressionLevel == 0) { file.write((char*)_block->Data.data(), _block->Position); } else { unsigned long compressedSize = compressBound((unsigned long)_block->Position); uint8_t* compressedData = new uint8_t[compressedSize]; compress2(compressedData, &compressedSize, (unsigned char*)_block->Data.data(), (unsigned long)_block->Position, compressionLevel); uint32_t size = (uint32_t)compressedSize; file.write((char*)&_block->Position, sizeof(uint32_t)); file.write((char*)&size, sizeof(uint32_t)); file.write((char*)compressedData, compressedSize); delete[] compressedData; } } void Serializer::WriteEmptyBlock(ostream* file) { int blockSize = 0; file->write((char*)&blockSize, sizeof(blockSize)); } void Serializer::SkipBlock(istream* file) { int blockSize = 0; file->read((char*)&blockSize, sizeof(blockSize)); file->seekg(blockSize, std::ios::cur); } void Serializer::Stream(ISerializable &obj) { StreamStartBlock(); obj.Serialize(*this); StreamEndBlock(); } void Serializer::Stream(ISerializable *obj) { StreamStartBlock(); obj->Serialize(*this); StreamEndBlock(); } void Serializer::InternalStream(string &str) { if(_saving) { vector stringData; stringData.resize(str.size()); memcpy(stringData.data(), str.data(), str.size()); StreamVector(stringData); } else { vector stringData; StreamVector(stringData); str = string(stringData.begin(), stringData.end()); } }