zeus

Unnamed repository; edit this file 'description' to name the repository.
git clone Unknown
Log | Files | Refs

commit aa505b60b28bf9baaaa6df40fe24ebcb9d743f22
parent 70a52be7e4bd76dfac7397ab7d33de06f08a7c83
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Mon, 12 May 2025 19:21:23 +0200

Factory serialization

Diffstat:
A factory_serialization.cpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

1 files changed, 137 insertions(+), 0 deletions(-)


diff --git a/ factory_serialization.cpp b/ factory_serialization.cpp

@@ -0,0 +1,137 @@

#include <cstddef>
#include <iostream>
#include <istream>
#include <memory>
#include <ostream>
#include <vector>

class SerializerBase {
static std::size_t type_count;

using Factory = SerializerBase *(*)(std::istream &s);
static std::vector<Factory> registry;

protected:
virtual void Serialize(std::ostream &s) const = 0;

public:
virtual ~SerializerBase() = default;

static size_t RegisterType(Factory factory) {
registry.emplace_back(std::move(factory));
return type_count++;
}

static auto Deserialize(size_t type, std::istream &s) {
return std::unique_ptr<SerializerBase>(registry[type](s));
}
};

std::vector<SerializerBase::Factory> SerializerBase::registry;
size_t SerializerBase::type_count = 0;

class DeserializerFactory {
std::istream &m_s;

public:
explicit DeserializerFactory(std::istream &s) : m_s(s) {}

template <typename It> void Deserialize(It iter) {
while (true) {
size_t type;
m_s >> type;
if (m_s.eof()) {
return;
}
iter = SerializerBase::Deserialize(type, m_s);
}
}
};

class Derived1 : public SerializerBase {
int m_i;

public:
static const size_t type_tag;

Derived1(int i) : m_i(i) { /* ... */ }

void Serialize(std::ostream &s) const override {
s << type_tag << ' ' << m_i << std::endl;
}
};

const size_t Derived1::type_tag =
RegisterType([](std::istream &s) -> SerializerBase * {
int i;
s >> i;
return new Derived1(i);
});

class Derived2 : public SerializerBase {
double m_x;
double m_y;

public:
static const size_t type_tag;

Derived2(double x, double y) : m_x(x), m_y(y) { /* ... */ }

void Serialize(std::ostream &s) const override {
s << type_tag << ' ' << m_x << ' ' << m_y << std::endl;
}
};

const size_t Derived2::type_tag =
RegisterType([](std::istream &s) -> SerializerBase * {
double x;
double y;
s >> x >> y;
return new Derived2(x, y);
});

class Derived3 : public SerializerBase {
bool m_integer;

int m_i;
double m_x;

public:
static const size_t type_tag;

Derived3(int i) : m_i(i) { /* ... */ }
Derived3(double x) : m_x(x) { /* ... */ }

void Serialize(std::ostream &s) const override {
s << type_tag << ' ' << m_integer << ' ';
if (m_integer) {
s << m_i;
} else {
s << m_x;
}
s << std::endl;
}
};

const size_t Derived3::type_tag =
RegisterType([](std::istream &s) -> SerializerBase * {
bool integer;
s >> integer;

if (integer) {
int i;
s >> i;
return new Derived3(i);
} else {
double d;
s >> d;
return new Derived3(d);
}
});

int main() {
Derived1 d(42);
d.Serialize(std::cout);

return 0;
}