2019-03-12 09:15:57 -04:00
|
|
|
#include "stdafx.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include "Serializer.h"
|
|
|
|
#include "ISerializable.h"
|
2019-10-23 18:19:49 -04:00
|
|
|
#include "miniz.h"
|
2019-03-12 09:15:57 -04:00
|
|
|
|
|
|
|
Serializer::Serializer(uint32_t version)
|
|
|
|
{
|
|
|
|
_version = version;
|
|
|
|
|
2019-12-26 12:03:38 -05:00
|
|
|
_block.reset(new BlockData());
|
|
|
|
_block->Data = vector<uint8_t>(0x50000);
|
|
|
|
_block->Position = 0;
|
2019-03-12 09:15:57 -04:00
|
|
|
_saving = true;
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
Serializer::Serializer(istream &file, uint32_t version, bool compressed)
|
2019-03-12 09:15:57 -04:00
|
|
|
{
|
|
|
|
_version = version;
|
|
|
|
|
2019-12-26 12:03:38 -05:00
|
|
|
_block.reset(new BlockData());
|
|
|
|
_block->Position = 0;
|
2019-03-12 09:15:57 -04:00
|
|
|
_saving = false;
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(compressed) {
|
2019-12-26 12:03:38 -05:00
|
|
|
uint32_t decompressedSize;
|
|
|
|
file.read((char*)&decompressedSize, sizeof(decompressedSize));
|
2019-03-12 09:15:57 -04:00
|
|
|
|
2019-12-26 12:03:38 -05:00
|
|
|
uint32_t compressedSize;
|
|
|
|
file.read((char*)&compressedSize, sizeof(compressedSize));
|
2019-10-23 18:19:49 -04:00
|
|
|
|
2019-12-26 12:03:38 -05:00
|
|
|
vector<uint8_t> compressedData(compressedSize, 0);
|
|
|
|
file.read((char*)compressedData.data(), compressedSize);
|
2019-10-23 18:19:49 -04:00
|
|
|
|
2019-12-26 12:03:38 -05:00
|
|
|
_block->Data = vector<uint8_t>(decompressedSize, 0);
|
2019-10-23 18:19:49 -04:00
|
|
|
|
2019-12-26 12:03:38 -05:00
|
|
|
unsigned long decompSize = decompressedSize;
|
|
|
|
uncompress(_block->Data.data(), &decompSize, compressedData.data(), (unsigned long)compressedData.size());
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2019-12-26 12:03:38 -05:00
|
|
|
file.seekg(0, std::ios::end);
|
|
|
|
uint32_t size = (uint32_t)file.tellg();
|
|
|
|
file.seekg(0, std::ios::beg);
|
|
|
|
|
|
|
|
_block->Data = vector<uint8_t>(size, 0);
|
|
|
|
file.read((char*)_block->Data.data(), size);
|
|
|
|
}
|
2019-03-12 09:15:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void Serializer::EnsureCapacity(uint32_t typeSize)
|
|
|
|
{
|
|
|
|
//Make sure the current block/stream is large enough to fit the next write
|
2019-12-26 12:03:38 -05:00
|
|
|
uint32_t oldSize = (uint32_t)_block->Data.size();
|
2021-03-10 11:13:28 -05:00
|
|
|
if(oldSize == 0) {
|
2019-10-24 23:33:14 -04:00
|
|
|
oldSize = typeSize * 2;
|
|
|
|
}
|
|
|
|
|
2019-12-26 12:03:38 -05:00
|
|
|
uint32_t sizeRequired = _block->Position + typeSize;
|
2021-03-10 11:13:28 -05:00
|
|
|
|
2019-10-23 18:19:49 -04:00
|
|
|
uint32_t newSize = oldSize;
|
2021-03-10 11:13:28 -05:00
|
|
|
while(newSize < sizeRequired) {
|
2019-10-23 18:19:49 -04:00
|
|
|
newSize *= 2;
|
2019-03-12 09:15:57 -04:00
|
|
|
}
|
|
|
|
|
2019-12-26 12:03:38 -05:00
|
|
|
_block->Data.resize(newSize);
|
2019-03-12 09:15:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void Serializer::RecursiveStream()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void Serializer::StreamStartBlock()
|
|
|
|
{
|
2019-12-26 12:03:38 -05:00
|
|
|
unique_ptr<BlockData> block(new BlockData());
|
|
|
|
block->Position = 0;
|
2019-03-12 09:15:57 -04:00
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(!_saving) {
|
|
|
|
VectorInfo<uint8_t> vectorInfo = { &block->Data };
|
2019-10-23 18:19:49 -04:00
|
|
|
InternalStream(vectorInfo);
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2019-12-26 12:03:38 -05:00
|
|
|
block->Data = vector<uint8_t>(0x100);
|
2019-03-12 09:15:57 -04:00
|
|
|
}
|
2019-10-23 18:19:49 -04:00
|
|
|
|
2019-12-26 12:03:38 -05:00
|
|
|
_blocks.push_back(std::move(_block));
|
|
|
|
_block = std::move(block);
|
2019-03-12 09:15:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void Serializer::StreamEndBlock()
|
|
|
|
{
|
2021-03-10 11:13:28 -05:00
|
|
|
if(_blocks.empty()) {
|
2019-10-23 18:19:49 -04:00
|
|
|
throw std::runtime_error("Invalid call to end block");
|
|
|
|
}
|
|
|
|
|
2019-12-26 12:03:38 -05:00
|
|
|
unique_ptr<BlockData> block = std::move(_block);
|
2019-10-23 18:19:49 -04:00
|
|
|
|
2019-12-26 12:03:38 -05:00
|
|
|
_block = std::move(_blocks.back());
|
2019-10-23 18:19:49 -04:00
|
|
|
_blocks.pop_back();
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(_saving) {
|
|
|
|
ArrayInfo<uint8_t> arrayInfo { block->Data.data(), block->Position };
|
2019-03-12 09:15:57 -04:00
|
|
|
InternalStream(arrayInfo);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-23 18:19:49 -04:00
|
|
|
void Serializer::Save(ostream& file, int compressionLevel)
|
2019-03-12 09:15:57 -04:00
|
|
|
{
|
2021-03-10 11:13:28 -05:00
|
|
|
if(compressionLevel == 0) {
|
2019-12-26 12:03:38 -05:00
|
|
|
file.write((char*)_block->Data.data(), _block->Position);
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2019-12-26 12:03:38 -05:00
|
|
|
unsigned long compressedSize = compressBound((unsigned long)_block->Position);
|
|
|
|
uint8_t* compressedData = new uint8_t[compressedSize];
|
2021-03-10 11:13:28 -05:00
|
|
|
compress2(compressedData, &compressedSize, (unsigned char*)_block->Data.data(), (unsigned long)_block->Position, compressionLevel);
|
2019-12-26 12:03:38 -05:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2019-03-12 09:15:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
void Serializer::Stream(ISerializable &obj)
|
2019-03-12 09:15:57 -04:00
|
|
|
{
|
2019-10-23 18:19:49 -04:00
|
|
|
StreamStartBlock();
|
2019-03-12 09:15:57 -04:00
|
|
|
obj.Serialize(*this);
|
2019-10-23 18:19:49 -04:00
|
|
|
StreamEndBlock();
|
2019-03-12 09:15:57 -04:00
|
|
|
}
|
2021-03-10 11:13:28 -05:00
|
|
|
void Serializer::Stream(ISerializable *obj)
|
2019-03-12 09:15:57 -04:00
|
|
|
{
|
2019-10-23 18:19:49 -04:00
|
|
|
StreamStartBlock();
|
2019-03-12 09:15:57 -04:00
|
|
|
obj->Serialize(*this);
|
2019-10-23 18:19:49 -04:00
|
|
|
StreamEndBlock();
|
2019-10-24 23:33:14 -04:00
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
void Serializer::InternalStream(string &str)
|
2019-10-24 23:33:14 -04:00
|
|
|
{
|
2021-03-10 11:13:28 -05:00
|
|
|
if(_saving) {
|
2019-10-24 23:33:14 -04:00
|
|
|
vector<uint8_t> stringData;
|
|
|
|
stringData.resize(str.size());
|
|
|
|
memcpy(stringData.data(), str.data(), str.size());
|
|
|
|
StreamVector(stringData);
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2019-10-24 23:33:14 -04:00
|
|
|
vector<uint8_t> stringData;
|
|
|
|
StreamVector(stringData);
|
|
|
|
str = string(stringData.begin(), stringData.end());
|
|
|
|
}
|
|
|
|
}
|