Parcel Pattern

// STL Archive + stuff
#include <boost/serialization/export.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/shared_ptr.hpp>

// IMPORTANT: Archive Headers at last
// include headers that implement a archive in xml format
#include <boost/archive/archive_exception.hpp>

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

typedef boost::archive::text_oarchive oarchive;
typedef boost::archive::text_iarchive iarchive;

#include <iostream>
#include <sstream>
#include <fstream>
#include <functional>
#include <string>
#include <memory>

struct runtime
{
	template <typename T>
	void accept(const T& t)
	{
		std::cout << "runtime::accept(): " << t << std::endl;
	}
};

struct base
{
	template<class Archive>
	void serialize(Archive & ar, const unsigned int version)
	{
		// we need it, even it is empty for the serialization
	}
	virtual void operator()(runtime& rt) = 0;
};

template <typename T>
struct parcel : base
{
	parcel() : data(T()) {}
	parcel(const T& d)
	{
		data = d;
	}

	T data;

	template<class Archive>
	void serialize(Archive & ar, const unsigned int version)
	{
		ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(base);

		ar & BOOST_SERIALIZATION_NVP(data);
	}
	virtual void operator()(runtime& rt) override
	{
		rt.accept(data);
	}
};

template <typename T>
std::unique_ptr<base> create_parcel(const T& d)
{
	 return std::make_unique<parcel<T>>(parcel<T>(d));
}

std::string wrap_parcel(base* p_envelope)
{
	std::string ret;
	{
		std::ostringstream oss;
		boost::archive::text_oarchive oa(oss);

		// serialize the base pointer
		oa & BOOST_SERIALIZATION_NVP(p_envelope);

		ret = oss.str();
	}
	return ret;
}

std::unique_ptr<base> unwarp_parcel(std::string data)
{
	std::istringstream iss(data);
	boost::archive::text_iarchive ia(iss);
	base* p = nullptr;
	ia & BOOST_SERIALIZATION_NVP(p);
	return std::unique_ptr<base>(p);
}

void out()
{
	std::ofstream ofs("test.txt");
	int payload{ 100 };
	auto envelope = create_parcel(payload);
	auto data = wrap_parcel(envelope.get());
	ofs << data;
}
void in()
{
	std::ifstream ifs("test.txt");
	std::string data;
	std::getline(ifs, data, '\0');
	auto a = unwarp_parcel(data);

	runtime rt;
	(*a)(rt);
}

BOOST_CLASS_EXPORT(parcel<int>)

int main(int argc, char* argv[])
{
	out();
	in();
}

Categories software
Tags c++