diff options
author | Antonio Juarez <antonio.maria.juarez@live.com> | 2014-03-03 22:07:58 +0000 |
---|---|---|
committer | Antonio Juarez <antonio.maria.juarez@live.com> | 2014-03-03 22:07:58 +0000 |
commit | 296ae46ed8f8f6e5f986f978febad302e3df231a (patch) | |
tree | 1629164454a239308f33c9e12afb22e7f3cd8eeb /src/serialization | |
parent | changed name (diff) | |
download | monero-296ae46ed8f8f6e5f986f978febad302e3df231a.tar.xz |
moved all stuff to github
Diffstat (limited to 'src/serialization')
-rw-r--r-- | src/serialization/binary_archive.h | 169 | ||||
-rw-r--r-- | src/serialization/binary_utils.h | 28 | ||||
-rw-r--r-- | src/serialization/crypto.h | 62 | ||||
-rw-r--r-- | src/serialization/debug_archive.h | 28 | ||||
-rw-r--r-- | src/serialization/json_archive.h | 145 | ||||
-rw-r--r-- | src/serialization/json_utils.h | 19 | ||||
-rw-r--r-- | src/serialization/serialization.h | 146 | ||||
-rw-r--r-- | src/serialization/string.h | 35 | ||||
-rw-r--r-- | src/serialization/variant.h | 110 | ||||
-rw-r--r-- | src/serialization/vector.h | 74 |
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; +} |