zeus

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

commit af6947bdb404578a8567b72ad3460c6c16e42b8e
parent 338aa1a5e93c6eeb615db830455e69979ee8e335
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Sat, 17 May 2025 21:16:09 +0200

Visitor serialization

Diffstat:
A visitor_serialization.cpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

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


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

@@ -0,0 +1,179 @@

#include <iostream>
#include <memory>
#include <sstream>

class Visitor;

class Point;
class Circle;
class Line;
class Intersection;

class Geometry {
public:
enum class type_tag { Point = 100, Circle, Line, Intersection };

virtual ~Geometry() = default;

virtual type_tag tag() const = 0;

virtual void accept(Visitor &v) = 0;
};

class Visitor {
public:
static Geometry *make_geometry(Geometry::type_tag tag);

virtual void visit(Geometry::type_tag &tag) = 0;

virtual void visit(double &x) = 0;
virtual void visit(Point &p) = 0;
virtual void visit(Circle &c) = 0;
virtual void visit(Line &l) = 0;
virtual void visit(Intersection &i) = 0;
};

class Point : public Geometry {
double m_x;
double m_y;

public:
Point(double x, double y) : m_x(x), m_y(y) {}
Point() = default;

type_tag tag() const override { return type_tag::Point; }

void accept(Visitor &v) override {
v.visit(m_x);
v.visit(m_y);
}
};

class Circle : public Geometry {
Point m_c;
double m_r;

public:
Circle(Point c, double r) : m_c(c), m_r(r) {}
Circle() = default;

type_tag tag() const override { return type_tag::Circle; }

void accept(Visitor &v) override {
v.visit(m_c);
v.visit(m_r);
}
};

class Line : public Geometry {
Point m_p1;
Point m_p2;

public:
Line(Point p1, Point p2) : m_p1(p1), m_p2(p2) {}
Line() = default;

type_tag tag() const override { return type_tag::Line; }

void accept(Visitor &v) override {
v.visit(m_p1);
v.visit(m_p2);
}
};

class Intersection : public Geometry {
std::unique_ptr<Geometry> m_g1;
std::unique_ptr<Geometry> m_g2;

public:
Intersection(Geometry *g1, Geometry *g2) : m_g1(g1), m_g2(g2) {}
Intersection() = default;

type_tag tag() const override { return type_tag::Intersection; }

void accept(Visitor &v) override {
Geometry::type_tag tag;

if (m_g1) {
tag = m_g1->tag();
}
v.visit(tag);
if (!m_g1) {
m_g1.reset(Visitor::make_geometry(tag));
}
m_g1->accept(v);

if (m_g2) {
tag = m_g2->tag();
}
v.visit(tag);
if (!m_g2) {
m_g2.reset(Visitor::make_geometry(tag));
}
m_g2->accept(v);
}
};

Geometry *Visitor::make_geometry(Geometry::type_tag tag) {
switch (tag) {
case Geometry::type_tag::Point:
return new Point;
case Geometry::type_tag::Circle:
return new Circle;
case Geometry::type_tag::Line:
return new Line;
case Geometry::type_tag::Intersection:
return new Intersection;
}
}

class StringSerializeVisitor : public Visitor {
std::stringstream m_s;

public:
[[nodiscard]] std::string str() const { return m_s.str(); }

void visit(Geometry::type_tag &tag) override { m_s << size_t(tag) << " "; }

void visit(double &x) override { m_s << x << " "; }
void visit(Point &p) override { p.accept(*this); }
void visit(Circle &c) override { c.accept(*this); }
void visit(Line &l) override { l.accept(*this); }
void visit(Intersection &i) override { i.accept(*this); }
};

class StringDeserializeVisitor : public Visitor {
std::stringstream m_s;

public:
StringDeserializeVisitor(const std::string &s) : m_s(s) {}

[[nodiscard]] std::string str() const { return m_s.str(); }

void visit(Geometry::type_tag &tag) override {
size_t t;
m_s >> t;
tag = Geometry::type_tag(t);
}

void visit(double &x) override { m_s >> x; }
void visit(Point &p) override { p.accept(*this); }
void visit(Circle &c) override { c.accept(*this); }
void visit(Line &l) override { l.accept(*this); }
void visit(Intersection &i) override { i.accept(*this); }
};

int main() {
Intersection i(new Line({1, 1}, {4, 4}), new Circle({0, 0}, 4));

StringSerializeVisitor serializer;
serializer.visit(i);

std::cout << serializer.str() << std::endl;

StringDeserializeVisitor deserializer(serializer.str());

Intersection i1;

deserializer.visit(i1);
}