summaryrefslogtreecommitdiffhomepage
path: root/archive.h
diff options
context:
space:
mode:
Diffstat (limited to 'archive.h')
-rw-r--r--archive.h206
1 files changed, 206 insertions, 0 deletions
diff --git a/archive.h b/archive.h
new file mode 100644
index 0000000..a98921a
--- /dev/null
+++ b/archive.h
@@ -0,0 +1,206 @@
+#pragma once
+
+#include <boost/coroutine2/coroutine.hpp>
+#include <boost/endian/conversion.hpp>
+
+#include <cstdint>
+#include <ostream>
+#include <istream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+typedef boost::coroutines2::coroutine<void> coro_t;
+
+// Serialization, similar to Boost Serialization
+// but for portable binary archive
+// using big endian coding (network byte order)
+namespace Serialization {
+
+class OArchive
+{
+public:
+ OArchive(std::ostream& os): os(os) {}
+ ~OArchive() {}
+
+ template<class T>
+ OArchive& operator &(T& v) {
+ v.serialize(*this);
+
+ return *this;
+ };
+
+ template <class T>
+ OArchive& write_fundamental(T& v)
+ {
+ T value = boost::endian::native_to_big(v);
+ os.write((char*)&value, sizeof(value));
+ return *this;
+ }
+
+ OArchive& operator &(uint8_t& v)
+ {
+ return write_fundamental(v);
+ };
+
+ OArchive& operator &(uint16_t& v)
+ {
+ return write_fundamental(v);
+ };
+
+ OArchive& operator &(uint32_t& v)
+ {
+ return write_fundamental(v);
+ };
+
+ OArchive& operator &(uint64_t& v)
+ {
+ return write_fundamental(v);
+ };
+
+ OArchive& operator &(int64_t& v)
+ {
+ return write_fundamental(*reinterpret_cast<uint64_t*>(v));
+ };
+
+ OArchive& operator &(std::vector<uint8_t>& v)
+ {
+ uint32_t size = static_cast<uint32_t>(v.size());
+ *this & size;
+ os.write((char*)v.data(), size);
+ return *this;
+ };
+
+ OArchive& operator &(std::string& v)
+ {
+ uint32_t size = static_cast<uint32_t>(v.size());
+ *this & size;
+ os.write((char*)v.data(), v.size());
+ return *this;
+ };
+
+private:
+ std::ostream &os;
+};
+
+class IArchive
+{
+public:
+ IArchive(std::istream& is): is(is) {}
+ IArchive(std::stringstream& is, coro_t::pull_type& coro) : is(is), mStringStream(&is), mCoro(&coro) {}
+ ~IArchive() {}
+
+ template<class T>
+ IArchive& operator &(T& v)
+ {
+ v.serialize(*this);
+
+ return *this;
+ };
+
+ template <class T>
+ IArchive& read_fundamental(T& v)
+ {
+ // in coroutine case, wait for input, if necessary
+ if (mCoro && mStringStream) {
+ while (mStringStream->tellp() - mStringStream->tellg() < sizeof(v)) {
+ (*mCoro)();
+ }
+ }
+
+ // now, we have enough bytes available
+ T value;
+ is.read((char*)&value, sizeof(value));
+ v = boost::endian::big_to_native(value);
+ return *this;
+ }
+
+ IArchive& operator &(uint8_t& v)
+ {
+ return read_fundamental(v);
+ };
+
+ IArchive& operator &(uint16_t& v)
+ {
+ return read_fundamental(v);
+ };
+
+ IArchive& operator &(uint32_t& v)
+ {
+ return read_fundamental(v);
+ };
+
+ IArchive& operator &(uint64_t& v)
+ {
+ return read_fundamental(v);
+ };
+
+ IArchive& operator &(int64_t& v)
+ {
+ uint64_t uv;
+ read_fundamental(uv);
+ v = *reinterpret_cast<int64_t*>(uv);
+ return *this;
+ };
+
+ template <class T>
+ IArchive& read_bytes_vector(T& v)
+ {
+ uint32_t size;
+ *this & size;
+
+ v.resize(size);
+
+ // in coroutine case, wait for input, if necessary
+ if (mCoro && mStringStream) {
+ while (mStringStream->tellp() - mStringStream->tellg() < size) {
+ (*mCoro)();
+ }
+ }
+
+ // now, we have enough bytes available
+ is.read((char*)v.data(), size);
+ return *this;
+ }
+
+ IArchive& operator &(std::vector<uint8_t>& v)
+ {
+ return read_bytes_vector(v);
+ };
+
+ IArchive& operator &(std::string& v)
+ {
+ return read_bytes_vector(v);
+ };
+
+private:
+ std::istream &is;
+ std::stringstream* mStringStream{ }; // for i/o sizes access
+ coro_t::pull_type* mCoro{ }; // optional for coroutine
+};
+
+// - Free functions ----------------------------------------------------------
+
+template<class Archive, class T>
+void serialize(Archive& ar, T& v)
+{
+ ar & v;
+}
+
+template<class T>
+OArchive& operator <<(OArchive& ar, T& v)
+{
+ serialize(ar, v);
+
+ return ar;
+};
+
+template<class T>
+IArchive& operator >>(IArchive& ar, T& v)
+{
+ serialize(ar, v);
+
+ return ar;
+};
+
+}