Mesen-SX/Utilities/Serializer.cpp

160 lines
3.7 KiB
C++
Raw Normal View History

2019-03-12 09:15:57 -04:00
#include "stdafx.h"
#include <algorithm>
#include "Serializer.h"
#include "ISerializable.h"
#include "miniz.h"
2019-03-12 09:15:57 -04:00
Serializer::Serializer(uint32_t version)
{
_version = version;
_block.reset(new BlockData());
_block->Data = vector<uint8_t>(0x50000);
_block->Position = 0;
2019-03-12 09:15:57 -04:00
_saving = true;
}
Serializer::Serializer(istream &file, uint32_t version, bool compressed)
2019-03-12 09:15:57 -04:00
{
_version = version;
_block.reset(new BlockData());
_block->Position = 0;
2019-03-12 09:15:57 -04:00
_saving = false;
if(compressed) {
uint32_t decompressedSize;
file.read((char*)&decompressedSize, sizeof(decompressedSize));
2019-03-12 09:15:57 -04:00
uint32_t compressedSize;
file.read((char*)&compressedSize, sizeof(compressedSize));
vector<uint8_t> compressedData(compressedSize, 0);
file.read((char*)compressedData.data(), compressedSize);
_block->Data = vector<uint8_t>(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<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
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;
2019-03-12 09:15:57 -04:00
}
_block->Data.resize(newSize);
2019-03-12 09:15:57 -04:00
}
void Serializer::RecursiveStream()
{
}
void Serializer::StreamStartBlock()
{
unique_ptr<BlockData> block(new BlockData());
block->Position = 0;
2019-03-12 09:15:57 -04:00
if(!_saving) {
VectorInfo<uint8_t> vectorInfo = { &block->Data };
InternalStream(vectorInfo);
} else {
block->Data = vector<uint8_t>(0x100);
2019-03-12 09:15:57 -04:00
}
_blocks.push_back(std::move(_block));
_block = std::move(block);
2019-03-12 09:15:57 -04:00
}
void Serializer::StreamEndBlock()
{
if(_blocks.empty()) {
throw std::runtime_error("Invalid call to end block");
}
unique_ptr<BlockData> block = std::move(_block);
_block = std::move(_blocks.back());
_blocks.pop_back();
if(_saving) {
ArrayInfo<uint8_t> arrayInfo { block->Data.data(), block->Position };
2019-03-12 09:15:57 -04:00
InternalStream(arrayInfo);
}
}
void Serializer::Save(ostream& file, int compressionLevel)
2019-03-12 09:15:57 -04:00
{
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;
}
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);
}
void Serializer::Stream(ISerializable &obj)
2019-03-12 09:15:57 -04:00
{
StreamStartBlock();
2019-03-12 09:15:57 -04:00
obj.Serialize(*this);
StreamEndBlock();
2019-03-12 09:15:57 -04:00
}
void Serializer::Stream(ISerializable *obj)
2019-03-12 09:15:57 -04:00
{
StreamStartBlock();
2019-03-12 09:15:57 -04:00
obj->Serialize(*this);
StreamEndBlock();
}
void Serializer::InternalStream(string &str)
{
if(_saving) {
vector<uint8_t> stringData;
stringData.resize(str.size());
memcpy(stringData.data(), str.data(), str.size());
StreamVector(stringData);
} else {
vector<uint8_t> stringData;
StreamVector(stringData);
str = string(stringData.begin(), stringData.end());
}
}