Added Serializer and Deserializer classes for Data
This commit is contained in:
parent
f88221a0c6
commit
7abbb33654
1
data/Deserializer.cpp
Normal file
1
data/Deserializer.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "Deserializer.h"
|
108
data/Deserializer.h
Normal file
108
data/Deserializer.h
Normal file
@ -0,0 +1,108 @@
|
||||
#pragma once
|
||||
#ifndef MESSMER_CPPUTILS_DATA_DESERIALIZER_H
|
||||
#define MESSMER_CPPUTILS_DATA_DESERIALIZER_H
|
||||
|
||||
#include "Data.h"
|
||||
#include "../macros.h"
|
||||
#include "../assert/assert.h"
|
||||
|
||||
namespace cpputils {
|
||||
class Deserializer final {
|
||||
public:
|
||||
Deserializer(const Data *source);
|
||||
~Deserializer();
|
||||
|
||||
uint8_t readUint8();
|
||||
int8_t readInt8();
|
||||
uint16_t readUint16();
|
||||
int16_t readInt16();
|
||||
uint32_t readUint32();
|
||||
int32_t readInt32();
|
||||
uint64_t readUint64();
|
||||
int64_t readInt64();
|
||||
Data readData();
|
||||
|
||||
void finished();
|
||||
|
||||
private:
|
||||
template<typename DataType> DataType _read();
|
||||
|
||||
size_t _pos;
|
||||
const Data *_source;
|
||||
bool _finishedCalled;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Deserializer);
|
||||
};
|
||||
|
||||
inline Deserializer::Deserializer(const Data *source): _pos(0), _source(source), _finishedCalled(false) {
|
||||
}
|
||||
|
||||
inline Deserializer::~Deserializer() {
|
||||
ASSERT(_finishedCalled, "Forgot to call Deserializer::finished()");
|
||||
}
|
||||
|
||||
inline uint8_t Deserializer::readUint8() {
|
||||
return _read<uint8_t>();
|
||||
}
|
||||
|
||||
inline int8_t Deserializer::readInt8() {
|
||||
return _read<int8_t>();
|
||||
}
|
||||
|
||||
inline uint16_t Deserializer::readUint16() {
|
||||
return _read<uint16_t>();
|
||||
}
|
||||
|
||||
inline int16_t Deserializer::readInt16() {
|
||||
return _read<int16_t>();
|
||||
}
|
||||
|
||||
inline uint32_t Deserializer::readUint32() {
|
||||
return _read<uint32_t>();
|
||||
}
|
||||
|
||||
inline int32_t Deserializer::readInt32() {
|
||||
return _read<int32_t>();
|
||||
}
|
||||
|
||||
inline uint64_t Deserializer::readUint64() {
|
||||
return _read<uint64_t>();
|
||||
}
|
||||
|
||||
inline int64_t Deserializer::readInt64() {
|
||||
return _read<int64_t>();
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
inline DataType Deserializer::_read() {
|
||||
static_assert(std::is_pod<DataType>::value, "Can only deserialize PODs");
|
||||
if (_pos + sizeof(DataType) > _source->size()) {
|
||||
_finishedCalled = true; // We don't want the destructor assertion to fail when destructor is called because of the exception
|
||||
throw std::runtime_error("Deserialization failed - size overflow");
|
||||
}
|
||||
DataType result = *reinterpret_cast<const DataType*>(_source->dataOffset(_pos));
|
||||
_pos += sizeof(DataType);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Data Deserializer::readData() {
|
||||
uint64_t size = readUint64();
|
||||
if (_pos + size > _source->size()) {
|
||||
_finishedCalled = true; // We don't want the destructor assertion to fail when destructor is called because of the exception
|
||||
throw std::runtime_error("Deserialization failed - size overflow");
|
||||
}
|
||||
Data result(size);
|
||||
std::memcpy(static_cast<char*>(result.data()), static_cast<const char*>(_source->dataOffset(_pos)), size);
|
||||
_pos += size;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void Deserializer::finished() {
|
||||
_finishedCalled = true;
|
||||
if (_pos != _source->size()) {
|
||||
throw std::runtime_error("Deserialization failed - size not fully used.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
1
data/Serializer.cpp
Normal file
1
data/Serializer.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "Serializer.h"
|
104
data/Serializer.h
Normal file
104
data/Serializer.h
Normal file
@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
#ifndef MESSMER_CPPUTILS_DATA_SERIALIZER_H
|
||||
#define MESSMER_CPPUTILS_DATA_SERIALIZER_H
|
||||
|
||||
#include "Data.h"
|
||||
#include "../macros.h"
|
||||
|
||||
namespace cpputils {
|
||||
//TODO Test Serializer/Deserializer
|
||||
//TODO Also test system (big endian/little endian) by adding a serialized data file to the repository and (a) reading it and (b) rewriting and comparing it
|
||||
class Serializer final {
|
||||
public:
|
||||
Serializer(size_t size);
|
||||
|
||||
void writeUint8(uint8_t value);
|
||||
void writeInt8(int8_t value);
|
||||
void writeUint16(uint16_t value);
|
||||
void writeInt16(int16_t value);
|
||||
void writeUint32(uint32_t value);
|
||||
void writeInt32(int32_t value);
|
||||
void writeUint64(uint64_t value);
|
||||
void writeInt64(int64_t value);
|
||||
void writeData(const Data &data);
|
||||
|
||||
static size_t DataSize(const Data &data);
|
||||
|
||||
Data finished();
|
||||
|
||||
private:
|
||||
template<typename DataType> void _write(DataType obj);
|
||||
|
||||
size_t _pos;
|
||||
Data _result;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Serializer);
|
||||
};
|
||||
|
||||
inline Serializer::Serializer(size_t size): _pos(0), _result(size) {
|
||||
}
|
||||
|
||||
inline void Serializer::writeUint8(uint8_t value) {
|
||||
_write<uint8_t>(value);
|
||||
}
|
||||
|
||||
inline void Serializer::writeInt8(int8_t value) {
|
||||
_write<int8_t>(value);
|
||||
}
|
||||
|
||||
inline void Serializer::writeUint16(uint16_t value) {
|
||||
_write<uint16_t>(value);
|
||||
}
|
||||
|
||||
inline void Serializer::writeInt16(int16_t value) {
|
||||
_write<int16_t>(value);
|
||||
}
|
||||
|
||||
inline void Serializer::writeUint32(uint32_t value) {
|
||||
_write<uint32_t>(value);
|
||||
}
|
||||
|
||||
inline void Serializer::writeInt32(int32_t value) {
|
||||
_write<int32_t>(value);
|
||||
}
|
||||
|
||||
inline void Serializer::writeUint64(uint64_t value) {
|
||||
_write<uint64_t>(value);
|
||||
}
|
||||
|
||||
inline void Serializer::writeInt64(int64_t value) {
|
||||
_write<int64_t>(value);
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
inline void Serializer::_write(DataType obj) {
|
||||
static_assert(std::is_pod<DataType>::value, "Can only serialize PODs");
|
||||
if (_pos + sizeof(DataType) > _result.size()) {
|
||||
throw std::runtime_error("Serialization failed - size overflow");
|
||||
}
|
||||
*reinterpret_cast<DataType*>(_result.dataOffset(_pos)) = obj;
|
||||
_pos += sizeof(DataType);
|
||||
}
|
||||
|
||||
inline void Serializer::writeData(const Data &data) {
|
||||
writeUint64(data.size());
|
||||
if (_pos + data.size() > _result.size()) {
|
||||
throw std::runtime_error("Serialization failed - size overflow");
|
||||
}
|
||||
std::memcpy(static_cast<char*>(_result.dataOffset(_pos)), static_cast<const char*>(data.data()), data.size());
|
||||
_pos += data.size();
|
||||
}
|
||||
|
||||
inline size_t Serializer::DataSize(const Data &data) {
|
||||
return sizeof(uint64_t) + data.size();
|
||||
}
|
||||
|
||||
Data Serializer::finished() {
|
||||
if (_pos != _result.size()) {
|
||||
throw std::runtime_error("Serialization failed - size not fully used.");
|
||||
}
|
||||
return std::move(_result);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user