diff options
Diffstat (limited to 'src/serialization/serialization.h')
-rw-r--r-- | src/serialization/serialization.h | 265 |
1 files changed, 204 insertions, 61 deletions
diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h index eab3c43d4..9e534cbc6 100644 --- a/src/serialization/serialization.h +++ b/src/serialization/serialization.h @@ -28,9 +28,16 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers -/* serialization.h +/*! \file serialization.h + * \breif Simple DSL AAPI based on * - * Simple templated serialization API */ + * \detailed is_blob_type and has_free_serializer are + * both descriptors for dispatching on to the serailize function. + * + * The API itself defines a domain specific language via dirty macro + * hacks. Greenspun's tenth rule is very much in action throughout + * this entire code base. + */ #pragma once #include <vector> @@ -38,14 +45,35 @@ #include <boost/type_traits/is_integral.hpp> #include <boost/type_traits/integral_constant.hpp> +/*! \struct is_blob_type + * + * \brief a descriptor for dispatching serialize + */ template <class T> struct is_blob_type { typedef boost::false_type type; }; + +/*! \struct has_free_serializer + * + * \brief a descriptor for dispatching serialize + */ template <class T> struct has_free_serializer { typedef boost::true_type type; }; +/*! \struct serializer + * + * \brief ... wouldn't a class be better? + * + * \detailed The logic behind serializing data. Places the archive + * data into the supplied parameter. This dispatches based on the + * supplied \a T template parameter's traits of is_blob_type or it is + * an integral (as defined by the is_integral trait). Depends on the + * \a Archive parameter to have overloaded the serialize_blob(T v, + * size_t size) and serialize_int(T v) base on which trait it + * applied. When the class has neither types, it falls to the + * overloaded method do_serialize(Archive ar) in T to do the work. + */ template <class Archive, class T> -struct serializer -{ +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()); } @@ -65,73 +93,171 @@ struct serializer } }; +/*! \fn do_serialize(Archive &ar, T &v) + * + * \brief just calls the serialize function defined for ar and v... + */ 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; \ +// Never used in the code base +// #ifndef __GNUC__ +// #ifndef constexpr +// #define constexpr +// #endif +// #endif + +/* the following add a trait to a set and define the serialization DSL*/ + +/*! \macro BLOB_SERIALIZER + * + * \brief makes the type have a blob serializer trait defined + */ +#define BLOB_SERIALIZER(T) \ + template<> \ + struct is_blob_type<T> { \ + typedef boost::true_type type; \ + } + +/*! \macro FREE_SERIALIZER + * + * \brief adds the has_free_serializer to the type + */ +#define FREE_SERIALIZER(T) \ + template<> \ + struct has_free_serializer<T> { \ + typedef boost::true_type type; \ + } + +/*! \macro VARIANT_TAG + * + * \brief Adds the tag \tag to the \a Archive of \a Type + */ +#define VARIANT_TAG(Archive, Type, Tag) \ + template <bool W> \ + struct variant_serialization_traits<Archive<W>, Type> { \ + static inline typename Archive<W>::variant_tag_type get_tag() { \ + return Tag; \ + } \ + } + +/*! \macro BEGIN_SERIALIZE + * + * \brief Begins the environment of the DSL + * \detailed for describing how to + * serialize an of an archive type + */ +#define BEGIN_SERIALIZE() \ + template <bool W, template <bool> class Archive> \ + bool do_serialize(Archive<W> &ar) { + +/*! \macro BEGIN_SERIALIZE_OBJECT + * + * \brief begins the environment of the DSL + * \detailed for described the serialization of an object + */ +#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){ + +/*! \macro PREPARE_CUSTON_VECTOR_SERIALIZATION + */ +#define PREPARE_CUSTOM_VECTOR_SERIALIZATION(size, vec) \ + ::serialization::detail::prepare_custom_vector_serialization(size, vec, typename Archive<W>::is_saving()) + +/*! \macro END_SERIALIZE + * \brief self-explanatory + */ +#define END_SERIALIZE() \ + return true; \ + } + +/*! \macro VALUE(f) + * \brief the same as FIELD(f) + */ +#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; \ + +/*! \macro FIELD_N(t,f) + * + * \brief serializes a field \a f tagged \a t + */ +#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) \ - do { \ - bool r = ::do_serialize(ar, f); \ - if (!r || !ar.stream().good()) return false; \ + +/*! \macro FIELD(f) + * + * \brief tags the field with the variable name and then serializes it + */ +#define FIELD(f) \ + do { \ + ar.tag(#f); \ + bool r = ::do_serialize(ar, f); \ + if (!r || !ar.stream().good()) return false; \ } while(0); -#define FIELD(f) \ - do { \ - ar.tag(#f); \ - bool r = ::do_serialize(ar, f); \ - if (!r || !ar.stream().good()) return false; \ + +/*! \macro FIELDS(f) + * + * \brief does not add a tag to the serialized value + */ +#define FIELDS(f) \ + do { \ + 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; \ + +/*! \macro VARING_FIELD(f) + * \brief tags and serializes the varint \a f + */ +#define VARINT_FIELD(f) \ + do { \ + ar.tag(#f); \ + ar.serialize_varint(f); \ + if (!ar.stream().good()) return false; \ } while(0); -#define VARINT_FIELD_N(t, f) \ - do { \ - ar.tag(t); \ - ar.serialize_varint(f); \ - if (!ar.stream().good()) return false; \ + +/*! \macro VARING_FIELD_N(t, f) + * + * \brief tags (as \a t) and serializes the varint \a f + */ +#define VARINT_FIELD_N(t, f) \ + do { \ + ar.tag(t); \ + ar.serialize_varint(f); \ + if (!ar.stream().good()) return false; \ } while(0); + namespace serialization { + /*! \namespace detail + * + * \brief declaration and default definition for the functions used the API + * + */ namespace detail { + /*! \fn prepare_custom_vector_serialization + * + * prepares the vector /vec for serialization + */ template <typename T> void prepare_custom_vector_serialization(size_t size, std::vector<T>& vec, const boost::mpl::bool_<true>& /*is_saving*/) { @@ -143,32 +269,49 @@ namespace serialization { vec.resize(size); } + /*! \fn do_check_stream_state + * + * \brief self explanatory + */ template<class Stream> bool do_check_stream_state(Stream& s, boost::mpl::bool_<true>) { return s.good(); } - + /*! \fn do_check_stream_state + * + * \brief self explanatory + * + * \detailed Also checks to make sure that the stream is not at EOF + */ 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.clear(state); - } + { + std::ios_base::iostate state = s.rdstate(); + result = EOF == s.peek(); + s.clear(state); + } return result; } } + /*! \fn check_stream_state + * + * \brief calls detail::do_check_stream_state for ar + */ template<class Archive> bool check_stream_state(Archive& ar) { return detail::do_check_stream_state(ar.stream(), typename Archive::is_saving()); } + /*! \fn serialize + * + * \brief serializes \a v into \a ar + */ template <class Archive, class T> inline bool serialize(Archive &ar, T &v) { |