aboutsummaryrefslogtreecommitdiff
path: root/src/serialization
diff options
context:
space:
mode:
authorAntonio Juarez <antonio.maria.juarez@live.com>2014-03-03 22:07:58 +0000
committerAntonio Juarez <antonio.maria.juarez@live.com>2014-03-03 22:07:58 +0000
commit296ae46ed8f8f6e5f986f978febad302e3df231a (patch)
tree1629164454a239308f33c9e12afb22e7f3cd8eeb /src/serialization
parentchanged name (diff)
downloadmonero-296ae46ed8f8f6e5f986f978febad302e3df231a.tar.xz
moved all stuff to github
Diffstat (limited to '')
-rw-r--r--src/serialization/binary_archive.h169
-rw-r--r--src/serialization/binary_utils.h28
-rw-r--r--src/serialization/crypto.h62
-rw-r--r--src/serialization/debug_archive.h28
-rw-r--r--src/serialization/json_archive.h145
-rw-r--r--src/serialization/json_utils.h19
-rw-r--r--src/serialization/serialization.h146
-rw-r--r--src/serialization/string.h35
-rw-r--r--src/serialization/variant.h110
-rw-r--r--src/serialization/vector.h74
10 files changed, 816 insertions, 0 deletions
diff --git a/src/serialization/binary_archive.h b/src/serialization/binary_archive.h
new file mode 100644
index 000000000..f28e45c0c
--- /dev/null
+++ b/src/serialization/binary_archive.h
@@ -0,0 +1,169 @@
+// Copyright (c) 2012-2013 The Cryptonote developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+/* binary_archive.h
+ *
+ * Portable (low-endian) binary archive */
+#pragma once
+
+#include <cassert>
+#include <iostream>
+#include <iterator>
+#include <boost/type_traits/make_unsigned.hpp>
+
+#include "common/varint.h"
+#include "warnings.h"
+
+PUSH_WARNINGS
+DISABLE_VS_WARNINGS(4244)
+
+//TODO: fix size_t warning in x32 platform
+
+template <class Stream, bool IsSaving>
+struct binary_archive_base
+{
+ typedef Stream stream_type;
+ typedef binary_archive_base<Stream, IsSaving> base_type;
+ typedef boost::mpl::bool_<IsSaving> is_saving;
+
+ typedef uint8_t variant_tag_type;
+
+ explicit binary_archive_base(stream_type &s) : stream_(s) { }
+
+ void tag(const char *) { }
+ void begin_object() { }
+ void end_object() { }
+ void begin_variant() { }
+ void end_variant() { }
+ stream_type &stream() { return stream_; }
+protected:
+ stream_type &stream_;
+};
+
+template <bool W>
+struct binary_archive;
+
+template <>
+struct binary_archive<false> : public binary_archive_base<std::istream, false>
+{
+ explicit binary_archive(stream_type &s) : base_type(s) {
+ stream_type::streampos pos = stream_.tellg();
+ stream_.seekg(0, std::ios_base::end);
+ eof_pos_ = stream_.tellg();
+ stream_.seekg(pos);
+ }
+
+ template <class T>
+ void serialize_int(T &v)
+ {
+ serialize_uint(*(typename boost::make_unsigned<T>::type *)&v);
+ }
+
+ template <class T>
+ void serialize_uint(T &v, size_t width = sizeof(T))
+ {
+ T ret = 0;
+ unsigned shift = 0;
+ for (size_t i = 0; i < width; i++) {
+ //std::cerr << "tell: " << stream_.tellg() << " value: " << ret << std::endl;
+ char c;
+ stream_.get(c);
+ T b = (unsigned char)c;
+ ret += (b << shift);
+ shift += 8;
+ }
+ v = ret;
+ }
+ void serialize_blob(void *buf, size_t len, const char *delimiter="") { stream_.read((char *)buf, len); }
+
+ template <class T>
+ void serialize_varint(T &v)
+ {
+ serialize_uvarint(*(typename boost::make_unsigned<T>::type *)(&v));
+ }
+
+ template <class T>
+ void serialize_uvarint(T &v)
+ {
+ typedef std::istreambuf_iterator<char> it;
+ tools::read_varint(it(stream_), it(), v); // XXX handle failure
+ }
+ void begin_array(size_t &s)
+ {
+ serialize_varint(s);
+ }
+ void begin_array() { }
+
+ void delimit_array() { }
+ void end_array() { }
+
+ void begin_string(const char *delimiter="\"") { }
+ void end_string(const char *delimiter="\"") { }
+
+ void read_variant_tag(variant_tag_type &t) {
+ serialize_int(t);
+ }
+
+ size_t remaining_bytes() {
+ if (!stream_.good())
+ return 0;
+ //std::cerr << "tell: " << stream_.tellg() << std::endl;
+ assert(stream_.tellg() <= eof_pos_);
+ return eof_pos_ - stream_.tellg();
+ }
+protected:
+ std::streamoff eof_pos_;
+};
+
+template <>
+struct binary_archive<true> : public binary_archive_base<std::ostream, true>
+{
+ explicit binary_archive(stream_type &s) : base_type(s) { }
+
+ template <class T>
+ void serialize_int(T v)
+ {
+ serialize_uint(static_cast<typename boost::make_unsigned<T>::type>(v));
+ }
+ template <class T>
+ void serialize_uint(T v)
+ {
+ for (size_t i = 0; i < sizeof(T); i++) {
+ stream_.put((char)(v & 0xff));
+ if (1 < sizeof(T)) {
+ v >>= 8;
+ }
+ }
+ }
+ void serialize_blob(void *buf, size_t len, const char *delimiter="") { stream_.write((char *)buf, len); }
+
+ template <class T>
+ void serialize_varint(T &v)
+ {
+ serialize_uvarint(*(typename boost::make_unsigned<T>::type *)(&v));
+ }
+
+ template <class T>
+ void serialize_uvarint(T &v)
+ {
+ typedef std::ostreambuf_iterator<char> it;
+ tools::write_varint(it(stream_), v);
+ }
+ void begin_array(size_t s)
+ {
+ serialize_varint(s);
+ }
+ void begin_array() { }
+ void delimit_array() { }
+ void end_array() { }
+
+ void begin_string(const char *delimiter="\"") { }
+ void end_string(const char *delimiter="\"") { }
+
+ void write_variant_tag(variant_tag_type t) {
+ serialize_int(t);
+ }
+};
+
+POP_WARNINGS
diff --git a/src/serialization/binary_utils.h b/src/serialization/binary_utils.h
new file mode 100644
index 000000000..d06e8a22a
--- /dev/null
+++ b/src/serialization/binary_utils.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2012-2013 The Cryptonote developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <sstream>
+#include "binary_archive.h"
+
+namespace serialization {
+
+template <class T>
+bool parse_binary(const std::string &blob, T &v)
+{
+ std::istringstream istr(blob);
+ binary_archive<false> iar(istr);
+ return ::serialization::serialize(iar, v);
+}
+
+template<class T>
+bool dump_binary(T& v, std::string& blob)
+{
+ std::stringstream ostr;
+ binary_archive<true> oar(ostr);
+ bool success = ::serialization::serialize(oar, v);
+ blob = ostr.str();
+ return success && ostr.good();
+};
+
+} // namespace serialization
diff --git a/src/serialization/crypto.h b/src/serialization/crypto.h
new file mode 100644
index 000000000..89d3c9885
--- /dev/null
+++ b/src/serialization/crypto.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2012-2013 The Cryptonote developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "serialization.h"
+#include "debug_archive.h"
+#include "crypto/chacha8.h"
+#include "crypto/crypto.h"
+#include "crypto/hash.h"
+
+// read
+template <template <bool> class Archive>
+bool do_serialize(Archive<false> &ar, std::vector<crypto::signature> &v)
+{
+ size_t cnt = v.size();
+ v.clear();
+
+ // very basic sanity check
+ if (ar.remaining_bytes() < cnt*sizeof(crypto::signature)) {
+ ar.stream().setstate(std::ios::failbit);
+ return false;
+ }
+
+ v.reserve(cnt);
+ for (size_t i = 0; i < cnt; i++) {
+ v.resize(i+1);
+ ar.serialize_blob(&(v[i]), sizeof(crypto::signature), "");
+ if (!ar.stream().good())
+ return false;
+ }
+ return true;
+}
+
+// write
+template <template <bool> class Archive>
+bool do_serialize(Archive<true> &ar, std::vector<crypto::signature> &v)
+{
+ if (0 == v.size()) return true;
+ ar.begin_string();
+ size_t cnt = v.size();
+ for (size_t i = 0; i < cnt; i++) {
+ ar.serialize_blob(&(v[i]), sizeof(crypto::signature), "");
+ if (!ar.stream().good())
+ return false;
+ }
+ ar.end_string();
+ return true;
+}
+
+BLOB_SERIALIZER(crypto::chacha8_iv);
+BLOB_SERIALIZER(crypto::hash);
+BLOB_SERIALIZER(crypto::public_key);
+BLOB_SERIALIZER(crypto::secret_key);
+BLOB_SERIALIZER(crypto::key_derivation);
+BLOB_SERIALIZER(crypto::key_image);
+BLOB_SERIALIZER(crypto::signature);
+VARIANT_TAG(debug_archive, crypto::hash, "hash");
+VARIANT_TAG(debug_archive, crypto::public_key, "public_key");
+VARIANT_TAG(debug_archive, crypto::secret_key, "secret_key");
+VARIANT_TAG(debug_archive, crypto::key_derivation, "key_derivation");
+VARIANT_TAG(debug_archive, crypto::key_image, "key_image");
+VARIANT_TAG(debug_archive, crypto::signature, "signature");
diff --git a/src/serialization/debug_archive.h b/src/serialization/debug_archive.h
new file mode 100644
index 000000000..08baee016
--- /dev/null
+++ b/src/serialization/debug_archive.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2012-2013 The Cryptonote developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#pragma once
+
+#include "json_archive.h"
+#include "variant.h"
+
+template <bool W>
+struct debug_archive : public json_archive<W> {
+ typedef typename json_archive<W>::stream_type stream_type;
+
+ debug_archive(stream_type &s) : json_archive<W>(s) { }
+};
+
+template <class T>
+struct serializer<debug_archive<true>, T>
+{
+ static void serialize(debug_archive<true> &ar, T &v)
+ {
+ ar.begin_object();
+ ar.tag(variant_serialization_traits<debug_archive<true>, T>::get_tag());
+ serializer<json_archive<true>, T>::serialize(ar, v);
+ ar.end_object();
+ ar.stream() << std::endl;
+ }
+};
diff --git a/src/serialization/json_archive.h b/src/serialization/json_archive.h
new file mode 100644
index 000000000..49ad74d41
--- /dev/null
+++ b/src/serialization/json_archive.h
@@ -0,0 +1,145 @@
+// Copyright (c) 2012-2013 The Cryptonote developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+/* json_archive.h
+ *
+ * JSON archive */
+
+#pragma once
+
+#include "serialization.h"
+#include <cassert>
+#include <iostream>
+#include <iomanip>
+
+template <class Stream, bool IsSaving>
+struct json_archive_base
+{
+ typedef Stream stream_type;
+ typedef json_archive_base<Stream, IsSaving> base_type;
+ typedef boost::mpl::bool_<IsSaving> is_saving;
+
+ typedef const char *variant_tag_type;
+
+ json_archive_base(stream_type &s, bool indent = false) : stream_(s), indent_(indent), object_begin(false), depth_(0) { }
+
+ void tag(const char *tag) {
+ if (!object_begin)
+ stream_ << ", ";
+ make_indent();
+ stream_ << '"' << tag << "\": ";
+ object_begin = false;
+ }
+
+ void begin_object()
+ {
+ stream_ << "{";
+ ++depth_;
+ object_begin = true;
+ }
+
+ void end_object()
+ {
+ --depth_;
+ make_indent();
+ stream_ << "}";
+ }
+
+ void begin_variant() { begin_object(); }
+ void end_variant() { end_object(); }
+ Stream &stream() { return stream_; }
+
+protected:
+ void make_indent()
+ {
+ if (indent_)
+ {
+ stream_ << '\n' << std::string(2 * depth_, ' ');
+ }
+ }
+
+protected:
+ stream_type &stream_;
+ bool indent_;
+ bool object_begin;
+ size_t depth_;
+};
+
+template <bool W>
+struct json_archive;
+
+template <>
+struct json_archive<true> : public json_archive_base<std::ostream, true>
+{
+ json_archive(stream_type &s, bool indent = false) : base_type(s, indent) { }
+
+ template<typename T>
+ static auto promote_to_printable_integer_type(T v) -> decltype(+v)
+ {
+ // Unary operator '+' performs integral promotion on type T [expr.unary.op].
+ // If T is signed or unsigned char, it's promoted to int and printed as number.
+ return +v;
+ }
+
+ template <class T>
+ void serialize_int(T v)
+ {
+ stream_ << std::dec << promote_to_printable_integer_type(v);
+ }
+
+ void serialize_blob(void *buf, size_t len, const char *delimiter="\"") {
+ begin_string(delimiter);
+ for (size_t i = 0; i < len; i++) {
+ unsigned char c = ((unsigned char *)buf)[i];
+ stream_ << std::hex << std::setw(2) << std::setfill('0') << (int)c;
+ }
+ end_string(delimiter);
+ }
+
+ template <class T>
+ void serialize_varint(T &v)
+ {
+ stream_ << std::dec << promote_to_printable_integer_type(v);
+ }
+
+ void begin_string(const char *delimiter="\"")
+ {
+ stream_ << delimiter;
+ }
+
+ void end_string(const char *delimiter="\"")
+ {
+ stream_ << delimiter;
+ }
+
+ void begin_array(size_t s=0)
+ {
+ inner_array_size_ = s;
+ ++depth_;
+ stream_ << "[ ";
+ }
+
+ void delimit_array()
+ {
+ stream_ << ", ";
+ }
+
+ void end_array()
+ {
+ --depth_;
+ if (0 < inner_array_size_)
+ {
+ make_indent();
+ }
+ stream_ << "]";
+ }
+
+ void write_variant_tag(const char *t)
+ {
+ tag(t);
+ }
+
+private:
+ size_t inner_array_size_;
+};
diff --git a/src/serialization/json_utils.h b/src/serialization/json_utils.h
new file mode 100644
index 000000000..35bcc0335
--- /dev/null
+++ b/src/serialization/json_utils.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2012-2013 The Cryptonote developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <sstream>
+#include "json_archive.h"
+
+namespace serialization {
+
+template<class T>
+std::string dump_json(T &v)
+{
+ std::stringstream ostr;
+ json_archive<true> oar(ostr);
+ assert(serialization::serialize(oar, v));
+ return ostr.str();
+};
+
+} // namespace serialization
diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h
new file mode 100644
index 000000000..d1c6f7f63
--- /dev/null
+++ b/src/serialization/serialization.h
@@ -0,0 +1,146 @@
+// Copyright (c) 2012-2013 The Cryptonote developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+/* serialization.h
+ *
+ * Simple templated serialization API */
+
+#pragma once
+#include <vector>
+#include <string>
+#include <boost/type_traits/is_integral.hpp>
+
+template <class T>
+struct is_blob_type { typedef boost::false_type type; };
+template <class T>
+struct has_free_serializer { typedef boost::true_type type; };
+
+template <class Archive, class T>
+struct serializer
+{
+ static bool serialize(Archive &ar, T &v) {
+ return serialize(ar, v, typename boost::is_integral<T>::type(), typename is_blob_type<T>::type());
+ }
+ static bool serialize(Archive &ar, T &v, boost::false_type, boost::true_type) {
+ ar.serialize_blob(&v, sizeof(v));
+ return true;
+ }
+ static bool serialize(Archive &ar, T &v, boost::true_type, boost::false_type) {
+ ar.serialize_int(v);
+ return true;
+ }
+ static bool serialize(Archive &ar, T &v, boost::false_type, boost::false_type) {
+ //serialize_custom(ar, v, typename has_free_serializer<T>::type());
+ return v.do_serialize(ar);
+ }
+ static void serialize_custom(Archive &ar, T &v, boost::true_type) {
+ }
+};
+
+template <class Archive, class T>
+inline bool do_serialize(Archive &ar, T &v)
+{
+ return ::serializer<Archive, T>::serialize(ar, v);
+}
+
+#ifndef __GNUC__
+#ifndef constexpr
+#define constexpr
+#endif
+#endif
+
+#define BLOB_SERIALIZER(T) \
+ template<> struct is_blob_type<T> { typedef boost::true_type type; }
+#define FREE_SERIALIZER(T) \
+ template<> struct has_free_serializer<T> { typedef boost::true_type type; }
+#define VARIANT_TAG(A, T, Tg) \
+ template <bool W> struct variant_serialization_traits<A<W>, T> { static inline typename A<W>::variant_tag_type get_tag() { return Tg; } }
+#define BEGIN_SERIALIZE() \
+ template <bool W, template <bool> class Archive> bool do_serialize(Archive<W> &ar) {
+#define BEGIN_SERIALIZE_OBJECT() \
+ template <bool W, template <bool> class Archive> bool do_serialize(Archive<W> &ar) { ar.begin_object(); bool r = do_serialize_object(ar); ar.end_object(); return r; } \
+ template <bool W, template <bool> class Archive> bool do_serialize_object(Archive<W> &ar){
+#define PREPARE_CUSTOM_VECTOR_SERIALIZATION(size, vec) ::serialization::detail::prepare_custom_vector_serialization(size, vec, typename Archive<W>::is_saving())
+
+#define END_SERIALIZE() return true;}
+
+
+#define VALUE(f) \
+ do { \
+ ar.tag(#f); \
+ bool r = ::do_serialize(ar, f); \
+ if (!r || !ar.stream().good()) return false; \
+ } while(0);
+#define FIELD_N(t, f) \
+ do { \
+ ar.tag(t); \
+ bool r = ::do_serialize(ar, f); \
+ if (!r || !ar.stream().good()) return false; \
+ } while(0);
+#define FIELDS(f) \
+ bool r = ::do_serialize(ar, f); \
+ if (!r || !ar.stream().good()) return false;
+#define FIELD(f) \
+ do { \
+ ar.tag(#f); \
+ bool r = ::do_serialize(ar, f); \
+ if (!r || !ar.stream().good()) return false; \
+ } while(0);
+#define VARINT_FIELD(f) \
+ do { \
+ ar.tag(#f); \
+ ar.serialize_varint(f); \
+ if (!ar.stream().good()) return false; \
+ } while(0);
+
+namespace serialization {
+ namespace detail
+ {
+ template <typename T>
+ void prepare_custom_vector_serialization(size_t size, std::vector<T>& vec, const boost::mpl::bool_<true>& /*is_saving*/)
+ {
+ }
+
+ template <typename T>
+ void prepare_custom_vector_serialization(size_t size, std::vector<T>& vec, const boost::mpl::bool_<false>& /*is_saving*/)
+ {
+ vec.resize(size);
+ }
+
+ template<class Stream>
+ bool do_check_stream_state(Stream& s, boost::mpl::bool_<true>)
+ {
+ return s.good();
+ }
+
+ template<class Stream>
+ bool do_check_stream_state(Stream& s, boost::mpl::bool_<false>)
+ {
+ bool result = false;
+ if (s.good())
+ {
+ std::ios_base::iostate state = s.rdstate();
+ result = EOF == s.peek();
+ s.setstate(state);
+ }
+ return result;
+ }
+ }
+
+ template<class Archive>
+ bool check_stream_state(Archive& ar)
+ {
+ return detail::do_check_stream_state(ar.stream(), typename Archive::is_saving());
+ }
+
+ template <class Archive, class T>
+ inline bool serialize(Archive &ar, T &v)
+ {
+ bool r = do_serialize(ar, v);
+ return r && check_stream_state(ar);
+ }
+}
+
+#include "string.h"
+#include "vector.h"
diff --git a/src/serialization/string.h b/src/serialization/string.h
new file mode 100644
index 000000000..437cf1c77
--- /dev/null
+++ b/src/serialization/string.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2012-2013 The Cryptonote developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#pragma once
+#include <memory>
+#include "serialization.h"
+
+template <template <bool> class Archive>
+inline bool do_serialize(Archive<false>& ar, std::string& str)
+{
+ size_t size = 0;
+ ar.serialize_varint(size);
+ if (ar.remaining_bytes() < size)
+ {
+ ar.stream().setstate(std::ios::failbit);
+ return false;
+ }
+
+ std::unique_ptr<std::string::value_type[]> buf(new std::string::value_type[size]);
+ ar.serialize_blob(buf.get(), size);
+ str.erase();
+ str.append(buf.get(), size);
+ return true;
+}
+
+
+template <template <bool> class Archive>
+inline bool do_serialize(Archive<true>& ar, std::string& str)
+{
+ size_t size = str.size();
+ ar.serialize_varint(size);
+ ar.serialize_blob(const_cast<std::string::value_type*>(str.c_str()), size);
+ return true;
+}
diff --git a/src/serialization/variant.h b/src/serialization/variant.h
new file mode 100644
index 000000000..3b92fde20
--- /dev/null
+++ b/src/serialization/variant.h
@@ -0,0 +1,110 @@
+// Copyright (c) 2012-2013 The Cryptonote developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#pragma once
+
+#include <boost/variant/variant.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/mpl/empty.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/front.hpp>
+#include <boost/mpl/pop_front.hpp>
+#include "serialization.h"
+
+template <class Archive, class T>
+struct variant_serialization_traits
+{
+};
+
+template <class Archive, class Variant, class TBegin, class TEnd>
+struct variant_reader
+{
+ typedef typename Archive::variant_tag_type variant_tag_type;
+ typedef typename boost::mpl::next<TBegin>::type TNext;
+ typedef typename boost::mpl::deref<TBegin>::type current_type;
+
+ static inline bool read(Archive &ar, Variant &v, variant_tag_type t)
+ {
+ if (variant_serialization_traits<Archive, current_type>::get_tag() == t) {
+ current_type x;
+ if(!::do_serialize(ar, x))
+ {
+ ar.stream().setstate(std::ios::failbit);
+ return false;
+ }
+ v = x;
+ } else {
+ return variant_reader<Archive, Variant, TNext, TEnd>::read(ar, v, t);
+ }
+ return true;
+ }
+};
+
+template <class Archive, class Variant, class TBegin>
+struct variant_reader<Archive, Variant, TBegin, TBegin>
+{
+ typedef typename Archive::variant_tag_type variant_tag_type;
+
+ static inline bool read(Archive &ar, Variant &v, variant_tag_type t)
+ {
+ ar.stream().setstate(std::ios::failbit);
+ return false;
+ }
+
+};
+
+
+template <template <bool> class Archive, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct serializer<Archive<false>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
+{
+ typedef boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> variant_type;
+ typedef typename Archive<false>::variant_tag_type variant_tag_type;
+ typedef typename variant_type::types types;
+
+ static bool serialize(Archive<false> &ar, variant_type &v) {
+ variant_tag_type t;
+ ar.begin_variant();
+ ar.read_variant_tag(t);
+ if(!variant_reader<Archive<false>, variant_type, typename boost::mpl::begin<types>::type, typename boost::mpl::end<types>::type>::read(ar, v, t))
+ {
+ ar.stream().setstate(std::ios::failbit);
+ return false;
+ }
+ ar.end_variant();
+ return true;
+ }
+};
+
+template <template <bool> class Archive, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct serializer<Archive<true>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
+{
+ typedef boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> variant_type;
+ //typedef typename Archive<true>::variant_tag_type variant_tag_type;
+
+ struct visitor : public boost::static_visitor<bool>
+ {
+ Archive<true> &ar;
+
+ visitor(Archive<true> &a) : ar(a) { }
+
+ template <class T>
+ bool operator ()(T &rv) const
+ {
+ ar.begin_variant();
+ ar.write_variant_tag(variant_serialization_traits<Archive<true>, T>::get_tag());
+ if(!::do_serialize(ar, rv))
+ {
+ ar.stream().setstate(std::ios::failbit);
+ return false;
+ }
+ ar.end_variant();
+ return true;
+ }
+ };
+
+ static bool serialize(Archive<true> &ar, variant_type &v) {
+ return boost::apply_visitor(visitor(ar), v);
+ }
+};
diff --git a/src/serialization/vector.h b/src/serialization/vector.h
new file mode 100644
index 000000000..9a0c0ee56
--- /dev/null
+++ b/src/serialization/vector.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2012-2013 The Cryptonote developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#pragma once
+
+#include "serialization.h"
+
+namespace serialization
+{
+ namespace detail
+ {
+ template <typename Archive, class T>
+ bool serialize_vector_element(Archive& ar, T& e)
+ {
+ return ::do_serialize(ar, e);
+ }
+
+ template <typename Archive>
+ bool serialize_vector_element(Archive& ar, uint64_t& e)
+ {
+ ar.serialize_varint(e);
+ return true;
+ }
+ }
+}
+
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<false> &ar, std::vector<T> &v)
+{
+ size_t cnt;
+ ar.begin_array(cnt);
+ if (!ar.stream().good())
+ return false;
+ v.clear();
+
+ // very basic sanity check
+ if (ar.remaining_bytes() < cnt) {
+ ar.stream().setstate(std::ios::failbit);
+ return false;
+ }
+
+ v.reserve(cnt);
+ for (size_t i = 0; i < cnt; i++) {
+ if (i > 0)
+ ar.delimit_array();
+ v.resize(i+1);
+ if (!::serialization::detail::serialize_vector_element(ar, v[i]))
+ return false;
+ if (!ar.stream().good())
+ return false;
+ }
+ ar.end_array();
+ return true;
+}
+
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<true> &ar, std::vector<T> &v)
+{
+ size_t cnt = v.size();
+ ar.begin_array(cnt);
+ for (size_t i = 0; i < cnt; i++) {
+ if (!ar.stream().good())
+ return false;
+ if (i > 0)
+ ar.delimit_array();
+ if(!::serialization::detail::serialize_vector_element(ar, v[i]))
+ return false;
+ if (!ar.stream().good())
+ return false;
+ }
+ ar.end_array();
+ return true;
+}