aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/dexon-foundation/mcl/include/cybozu/serializer.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/dexon-foundation/mcl/include/cybozu/serializer.hpp')
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/cybozu/serializer.hpp363
1 files changed, 363 insertions, 0 deletions
diff --git a/vendor/github.com/dexon-foundation/mcl/include/cybozu/serializer.hpp b/vendor/github.com/dexon-foundation/mcl/include/cybozu/serializer.hpp
new file mode 100644
index 000000000..1e23c8f42
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/include/cybozu/serializer.hpp
@@ -0,0 +1,363 @@
+#pragma once
+/**
+ @file
+ @brief serializer for vector, list, map and so on
+
+ @author MITSUNARI Shigeo(@herumi)
+*/
+#include <assert.h>
+#include <cybozu/stream.hpp>
+
+#ifdef _MSC_VER
+ #pragma warning(push)
+ #pragma warning(disable : 4127)
+#endif
+
+//#define CYBOZU_SERIALIZER_FIXED_SIZE_INTEGER
+
+namespace cybozu {
+
+namespace serializer_local {
+
+template<class T>
+union ci {
+ T i;
+ uint8_t c[sizeof(T)];
+};
+
+template<class S, void (S::*)(size_t)>
+struct HasMemFunc { };
+
+template<class T>
+void dispatch_reserve(T& t, size_t size, int, HasMemFunc<T, &T::reserve>* = 0)
+{
+ t.reserve(size);
+}
+
+template<class T>
+void dispatch_reserve(T&, size_t, int*)
+{
+}
+
+template<class T>
+void reserve_if_exists(T& t, size_t size)
+{
+ dispatch_reserve(t, size, 0);
+}
+
+} // serializer_local
+
+template<class InputStream, class T>
+void loadRange(T *p, size_t num, InputStream& is)
+{
+ cybozu::read(p, num * sizeof(T), is);
+}
+
+template<class OutputStream, class T>
+void saveRange(OutputStream& os, const T *p, size_t num)
+{
+ cybozu::write(os, p, num * sizeof(T));
+}
+
+template<class InputStream, class T>
+void loadPod(T& x, InputStream& is)
+{
+ serializer_local::ci<T> ci;
+ loadRange(ci.c, sizeof(ci.c), is);
+ x = ci.i;
+}
+
+template<class OutputStream, class T>
+void savePod(OutputStream& os, const T& x)
+{
+ serializer_local::ci<T> ci;
+ ci.i = x;
+ saveRange(os, ci.c, sizeof(ci.c));
+}
+
+template<class InputStream, class T>
+void load(T& x, InputStream& is)
+{
+ x.load(is);
+}
+
+template<class OutputStream, class T>
+void save(OutputStream& os, const T& x)
+{
+ x.save(os);
+}
+
+#define CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(type) \
+template<class InputStream>void load(type& x, InputStream& is) { loadPod(x, is); } \
+template<class OutputStream>void save(OutputStream& os, type x) { savePod(os, x); }
+
+CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(bool)
+CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(char)
+CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(short)
+CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(unsigned char)
+CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(unsigned short)
+CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(wchar_t)
+
+CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(float)
+CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(double)
+
+#ifdef CYBOZU_SERIALIZER_FIXED_SIZE_INTEGER
+
+#define CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(type) CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(type)
+
+#else
+
+namespace serializer_local {
+
+template<class S, class T>
+bool isRecoverable(T x)
+{
+ return T(S(x)) == x;
+}
+/*
+ data structure H:D of integer x
+ H:header(1byte)
+ 0x80 ; D = 1 byte zero ext
+ 0x81 ; D = 2 byte zero ext
+ 0x82 ; D = 4 byte zero ext
+ 0x83 ; D = 8 byte zero ext
+ 0x84 ; D = 1 byte signed ext
+ 0x85 ; D = 2 byte signed ext
+ 0x86 ; D = 4 byte signed ext
+ 0x87 ; D = 8 byte signed ext
+ other; x = signed H, D = none
+*/
+template<class OutputStream, class T>
+void saveVariableInt(OutputStream& os, const T& x)
+{
+ if (isRecoverable<int8_t>(x)) {
+ uint8_t u8 = uint8_t(x);
+ if (unsigned(u8 - 0x80) <= 7) {
+ savePod(os, uint8_t(0x84));
+ }
+ savePod(os, u8);
+ } else if (isRecoverable<uint8_t>(x)) {
+ savePod(os, uint8_t(0x80));
+ savePod(os, uint8_t(x));
+ } else if (isRecoverable<uint16_t>(x) || isRecoverable<int16_t>(x)) {
+ savePod(os, uint8_t(isRecoverable<uint16_t>(x) ? 0x81 : 0x85));
+ savePod(os, uint16_t(x));
+ } else if (isRecoverable<uint32_t>(x) || isRecoverable<int32_t>(x)) {
+ savePod(os, uint8_t(isRecoverable<uint32_t>(x) ? 0x82 : 0x86));
+ savePod(os, uint32_t(x));
+ } else {
+ assert(sizeof(T) == 8);
+ savePod(os, uint8_t(0x83));
+ savePod(os, uint64_t(x));
+ }
+}
+
+template<class InputStream, class T>
+void loadVariableInt(T& x, InputStream& is)
+{
+ uint8_t h;
+ loadPod(h, is);
+ if (h == 0x80) {
+ uint8_t v;
+ loadPod(v, is);
+ x = v;
+ } else if (h == 0x81) {
+ uint16_t v;
+ loadPod(v, is);
+ x = v;
+ } else if (h == 0x82) {
+ uint32_t v;
+ loadPod(v, is);
+ x = v;
+ } else if (h == 0x83) {
+ if (sizeof(T) == 4) throw cybozu::Exception("loadVariableInt:bad header") << h;
+ uint64_t v;
+ loadPod(v, is);
+ x = static_cast<T>(v);
+ } else if (h == 0x84) {
+ int8_t v;
+ loadPod(v, is);
+ x = v;
+ } else if (h == 0x85) {
+ int16_t v;
+ loadPod(v, is);
+ x = v;
+ } else if (h == 0x86) {
+ int32_t v;
+ loadPod(v, is);
+ x = v;
+ } else if (h == 0x87) {
+ if (sizeof(T) == 4) throw cybozu::Exception("loadVariableInt:bad header") << h;
+ int64_t v;
+ loadPod(v, is);
+ x = static_cast<T>(v);
+ } else {
+ x = static_cast<int8_t>(h);
+ }
+}
+
+} // serializer_local
+
+#define CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(type) \
+template<class InputStream>void load(type& x, InputStream& is) { serializer_local::loadVariableInt(x, is); } \
+template<class OutputStream>void save(OutputStream& os, type x) { serializer_local::saveVariableInt(os, x); }
+
+#endif
+
+CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(int)
+CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(long)
+CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(long long)
+CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(unsigned int)
+CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(unsigned long)
+CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(unsigned long long)
+
+#undef CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER
+#undef CYBOZU_SERIALIZER_MAKE_UNT_SERIALIZER
+#undef CYBOZU_SERIALIZER_MAKE_SERIALIZER_F
+#undef CYBOZU_SERIALIZER_MAKE_SERIALIZER_V
+
+// only for std::vector<POD>
+template<class V, class InputStream>
+void loadPodVec(V& v, InputStream& is)
+{
+ size_t size;
+ load(size, is);
+ v.resize(size);
+ if (size > 0) loadRange(&v[0], size, is);
+}
+
+// only for std::vector<POD>
+template<class V, class OutputStream>
+void savePodVec(OutputStream& os, const V& v)
+{
+ save(os, v.size());
+ if (!v.empty()) saveRange(os, &v[0], v.size());
+}
+
+template<class InputStream>
+void load(std::string& str, InputStream& is)
+{
+ loadPodVec(str, is);
+}
+
+template<class OutputStream>
+void save(OutputStream& os, const std::string& str)
+{
+ savePodVec(os, str);
+}
+
+template<class OutputStream>
+void save(OutputStream& os, const char *x)
+{
+ const size_t len = strlen(x);
+ save(os, len);
+ if (len > 0) saveRange(os, x, len);
+}
+
+
+// for vector, list
+template<class InputStream, class T, class Alloc, template<class T_, class Alloc_>class Container>
+void load(Container<T, Alloc>& x, InputStream& is)
+{
+ size_t size;
+ load(size, is);
+ serializer_local::reserve_if_exists(x, size);
+ for (size_t i = 0; i < size; i++) {
+ x.push_back(T());
+ T& t = x.back();
+ load(t, is);
+ }
+}
+
+template<class OutputStream, class T, class Alloc, template<class T_, class Alloc_>class Container>
+void save(OutputStream& os, const Container<T, Alloc>& x)
+{
+ typedef Container<T, Alloc> V;
+ save(os, x.size());
+ for (typename V::const_iterator i = x.begin(), end = x.end(); i != end; ++i) {
+ save(os, *i);
+ }
+}
+
+// for set
+template<class InputStream, class K, class Pred, class Alloc, template<class K_, class Pred_, class Alloc_>class Container>
+void load(Container<K, Pred, Alloc>& x, InputStream& is)
+{
+ size_t size;
+ load(size, is);
+ for (size_t i = 0; i < size; i++) {
+ K t;
+ load(t, is);
+ x.insert(t);
+ }
+}
+
+template<class OutputStream, class K, class Pred, class Alloc, template<class K_, class Pred_, class Alloc_>class Container>
+void save(OutputStream& os, const Container<K, Pred, Alloc>& x)
+{
+ typedef Container<K, Pred, Alloc> Set;
+ save(os, x.size());
+ for (typename Set::const_iterator i = x.begin(), end = x.end(); i != end; ++i) {
+ save(os, *i);
+ }
+}
+
+// for map
+template<class InputStream, class K, class V, class Pred, class Alloc, template<class K_, class V_, class Pred_, class Alloc_>class Container>
+void load(Container<K, V, Pred, Alloc>& x, InputStream& is)
+{
+ typedef Container<K, V, Pred, Alloc> Map;
+ size_t size;
+ load(size, is);
+ for (size_t i = 0; i < size; i++) {
+ std::pair<typename Map::key_type, typename Map::mapped_type> vt;
+ load(vt.first, is);
+ load(vt.second, is);
+ x.insert(vt);
+ }
+}
+
+template<class OutputStream, class K, class V, class Pred, class Alloc, template<class K_, class V_, class Pred_, class Alloc_>class Container>
+void save(OutputStream& os, const Container<K, V, Pred, Alloc>& x)
+{
+ typedef Container<K, V, Pred, Alloc> Map;
+ save(os, x.size());
+ for (typename Map::const_iterator i = x.begin(), end = x.end(); i != end; ++i) {
+ save(os, i->first);
+ save(os, i->second);
+ }
+}
+
+// unordered_map
+template<class InputStream, class K, class V, class Hash, class Pred, class Alloc, template<class K_, class V_, class Hash_, class Pred_, class Alloc_>class Container>
+void load(Container<K, V, Hash, Pred, Alloc>& x, InputStream& is)
+{
+ typedef Container<K, V, Hash, Pred, Alloc> Map;
+ size_t size;
+ load(size, is);
+// x.reserve(size); // tr1::unordered_map may not have reserve
+ cybozu::serializer_local::reserve_if_exists(x, size);
+ for (size_t i = 0; i < size; i++) {
+ std::pair<typename Map::key_type, typename Map::mapped_type> vt;
+ load(vt.first, is);
+ load(vt.second, is);
+ x.insert(vt);
+ }
+}
+
+template<class OutputStream, class K, class V, class Hash, class Pred, class Alloc, template<class K_, class V_, class Hash_, class Pred_, class Alloc_>class Container>
+void save(OutputStream& os, const Container<K, V, Hash, Pred, Alloc>& x)
+{
+ typedef Container<K, V, Hash, Pred, Alloc> Map;
+ save(os, x.size());
+ for (typename Map::const_iterator i = x.begin(), end = x.end(); i != end; ++i) {
+ save(os, i->first);
+ save(os, i->second);
+ }
+}
+
+} // cybozu
+
+#ifdef _MSC_VER
+ #pragma warning(pop)
+#endif