From b032619a9cb1850dcbb1381b1e77ca1d7c2a00a7 Mon Sep 17 00:00:00 2001 From: jebes Date: Mon, 13 Oct 2014 16:00:09 -0400 Subject: [PATCH] Commented most of src/serialization/ going to read up more on variant's and finish off the job/add last touchs next --- src/serialization/binary_archive.h | 66 ++++++-- src/serialization/binary_utils.h | 39 +++-- src/serialization/json_archive.h | 21 ++- src/serialization/serialization.h | 259 ++++++++++++++++++++++------- src/serialization/variant.h | 27 ++- 5 files changed, 315 insertions(+), 97 deletions(-) diff --git a/src/serialization/binary_archive.h b/src/serialization/binary_archive.h index baa6707d..56c94684 100644 --- a/src/serialization/binary_archive.h +++ b/src/serialization/binary_archive.h @@ -28,7 +28,7 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers -/* binary_archive.h +/*! \file binary_archive.h * * Portable (low-endian) binary archive */ #pragma once @@ -41,11 +41,20 @@ #include "common/varint.h" #include "warnings.h" -PUSH_WARNINGS -DISABLE_VS_WARNINGS(4244) +/* I have no clue what these lines means */ +PUSH_WARNINGS; +DISABLE_VS_WARNINGS(4244); //TODO: fix size_t warning in x32 platform +/*! \struct binary_archive_base + * + * \brief base for the binary archive type + * + * \detailed It isn't used outside of this file, which its only + * purpse is to define the functions used for the binary_archive. Its + * a header, basically. I think it was declared simply to save typing... + */ template struct binary_archive_base { @@ -56,23 +65,39 @@ struct binary_archive_base typedef uint8_t variant_tag_type; explicit binary_archive_base(stream_type &s) : stream_(s) { } - + + /* definition of standard API functions */ void tag(const char *) { } void begin_object() { } void end_object() { } void begin_variant() { } void end_variant() { } - stream_type &stream() { return stream_; } + /* I just want to leave a comment saying how this line really shows + flaws in the ownership model of many OOP languages, that is all. */ + stream_type &stream() { return stream_; } + protected: stream_type &stream_; }; +/* \struct binary_archive + * + * \brief the actualy binary archive type + * + * \detailed The boolean template argument /a W is the is_saving + * parameter for binary_archive_base. + * + * The is_saving parameter says whether the archive is being read from + * (false) or written to (true) + */ template struct binary_archive; + template <> struct binary_archive : public binary_archive_base { + explicit binary_archive(stream_type &s) : base_type(s) { stream_type::streampos pos = stream_.tellg(); stream_.seekg(0, std::ios_base::end); @@ -86,6 +111,10 @@ struct binary_archive : public binary_archive_base serialize_uint(*(typename boost::make_unsigned::type *)&v); } + /*! \fn serialize_uint + * + * \brief serializes an unsigned integer + */ template void serialize_uint(T &v, size_t width = sizeof(T)) { @@ -96,13 +125,17 @@ struct binary_archive : public binary_archive_base char c; stream_.get(c); T b = (unsigned char)c; - ret += (b << shift); + ret += (b << shift); // can this be changed to OR, i think it can. shift += 8; } v = ret; } - void serialize_blob(void *buf, size_t len, const char *delimiter="") { stream_.read((char *)buf, len); } - + + void serialize_blob(void *buf, size_t len, const char *delimiter="") + { + stream_.read((char *)buf, len); + } + template void serialize_varint(T &v) { @@ -115,17 +148,18 @@ struct binary_archive : public binary_archive_base typedef std::istreambuf_iterator it; tools::read_varint(it(stream_), it(), v); // XXX handle failure } + void begin_array(size_t &s) { serialize_varint(s); } - void begin_array() { } + void begin_array() { } void delimit_array() { } void end_array() { } - void begin_string(const char *delimiter="\"") { } - void end_string(const char *delimiter="\"") { } + void begin_string(const char *delimiter /*="\""*/) { } + void end_string(const char *delimiter /*="\""*/) { } void read_variant_tag(variant_tag_type &t) { serialize_int(t); @@ -157,12 +191,14 @@ struct binary_archive : public binary_archive_base { for (size_t i = 0; i < sizeof(T); i++) { stream_.put((char)(v & 0xff)); - if (1 < sizeof(T)) { - v >>= 8; - } + if (1 < sizeof(T)) v >>= 8; } } - void serialize_blob(void *buf, size_t len, const char *delimiter="") { stream_.write((char *)buf, len); } + + void serialize_blob(void *buf, size_t len, const char *delimiter="") + { + stream_.write((char *)buf, len); + } template void serialize_varint(T &v) diff --git a/src/serialization/binary_utils.h b/src/serialization/binary_utils.h index 3b1db3e4..f2cfadd4 100644 --- a/src/serialization/binary_utils.h +++ b/src/serialization/binary_utils.h @@ -34,23 +34,26 @@ #include "binary_archive.h" namespace serialization { + /*! creates a new archive with the passed blob and serializes it into v + */ + template + bool parse_binary(const std::string &blob, T &v) + { + std::istringstream istr(blob); + binary_archive iar(istr); + return ::serialization::serialize(iar, v); + } + + /*! dumps the data in v into the blob string + */ + template + bool dump_binary(T& v, std::string& blob) + { + std::stringstream ostr; + binary_archive oar(ostr); + bool success = ::serialization::serialize(oar, v); + blob = ostr.str(); + return success && ostr.good(); + }; -template -bool parse_binary(const std::string &blob, T &v) -{ - std::istringstream istr(blob); - binary_archive iar(istr); - return ::serialization::serialize(iar, v); } - -template -bool dump_binary(T& v, std::string& blob) -{ - std::stringstream ostr; - binary_archive oar(ostr); - bool success = ::serialization::serialize(oar, v); - blob = ostr.str(); - return success && ostr.good(); -}; - -} // namespace serialization diff --git a/src/serialization/json_archive.h b/src/serialization/json_archive.h index 7a040a12..bd8b1613 100644 --- a/src/serialization/json_archive.h +++ b/src/serialization/json_archive.h @@ -28,9 +28,10 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers -/* json_archive.h +/*! \file json_archive.h * - * JSON archive */ + * \brief JSON archive + */ #pragma once @@ -39,6 +40,12 @@ #include #include +/*! \struct json_archive_base + * + * \brief the base class of json archive type + * + * \detailed contains the basic logic for serializing a json archive + */ template struct json_archive_base { @@ -48,7 +55,8 @@ struct json_archive_base typedef const char *variant_tag_type; - json_archive_base(stream_type &s, bool indent = false) : stream_(s), indent_(indent), object_begin(false), depth_(0) { } + 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) @@ -92,6 +100,13 @@ protected: size_t depth_; }; + +/*! \struct json_archive + * + * \brief a archive using the JSON standard + * + * \detailed only supports being written to + */ template struct json_archive; diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h index eab3c43d..74c66137 100644 --- a/src/serialization/serialization.h +++ b/src/serialization/serialization.h @@ -1,5 +1,5 @@ // Copyright (c) 2014, The Monero Project -// +>// // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are @@ -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 @@ -38,14 +45,35 @@ #include #include +/*! \struct is_blob_type + * + * \brief a descriptor for dispatching serialize + */ template struct is_blob_type { typedef boost::false_type type; }; + +/*! \struct has_free_serializer + * + * \brief a descriptor for dispatching serialize + */ template 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 -struct serializer -{ +struct serializer{ static bool serialize(Archive &ar, T &v) { return serialize(ar, v, typename boost::is_integral::type(), typename is_blob_type::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 inline bool do_serialize(Archive &ar, T &v) { return ::serializer::serialize(ar, v); } -#ifndef __GNUC__ -#ifndef constexpr -#define constexpr -#endif -#endif +// Never used in the code base +// #ifndef __GNUC__ +// #ifndef constexpr +// #define constexpr +// #endif +// #endif -#define BLOB_SERIALIZER(T) \ - template<> struct is_blob_type { typedef boost::true_type type; } -#define FREE_SERIALIZER(T) \ - template<> struct has_free_serializer { typedef boost::true_type type; } -#define VARIANT_TAG(A, T, Tg) \ - template struct variant_serialization_traits, T> { static inline typename A::variant_tag_type get_tag() { return Tg; } } -#define BEGIN_SERIALIZE() \ - template class Archive> bool do_serialize(Archive &ar) { -#define BEGIN_SERIALIZE_OBJECT() \ - template class Archive> bool do_serialize(Archive &ar) { ar.begin_object(); bool r = do_serialize_object(ar); ar.end_object(); return r; } \ - template class Archive> bool do_serialize_object(Archive &ar){ -#define PREPARE_CUSTOM_VECTOR_SERIALIZATION(size, vec) ::serialization::detail::prepare_custom_vector_serialization(size, vec, typename Archive::is_saving()) +/* the following add a trait to a set and define the serialization DSL*/ -#define END_SERIALIZE() return true;} +/*! \macro BLOB_SERIALIZER + * + * \brief makes the type have a blob serializer trait defined + */ +#define BLOB_SERIALIZER(T) \ + template<> \ + struct is_blob_type { \ + 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 { \ + typedef boost::true_type type; \ + } -#define VALUE(f) \ - do { \ - ar.tag(#f); \ - bool r = ::do_serialize(ar, f); \ - if (!r || !ar.stream().good()) return false; \ +/*! \macro VARIANT_TAG + * + * \brief Adds the tag \tag to the \a Archive of \a Type + */ +#define VARIANT_TAG(Archive, Type, Tag) \ + template \ + struct variant_serialization_traits, Type> { \ + static inline typename Archive::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 class Archive> \ + bool do_serialize(Archive &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 class Archive> \ + bool do_serialize(Archive &ar) { \ + ar.begin_object(); \ + bool r = do_serialize_object(ar); \ + ar.end_object(); \ + return r; \ + } \ + template class Archive> \ + bool do_serialize_object(Archive &ar){ + +/*! \macro PREPARE_CUSTON_VECTOR_SERIALIZATION + */ +#define PREPARE_CUSTOM_VECTOR_SERIALIZATION(size, vec) \ + ::serialization::detail::prepare_custom_vector_serialization(size, vec, typename Archive::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 void prepare_custom_vector_serialization(size_t size, std::vector& vec, const boost::mpl::bool_& /*is_saving*/) { @@ -143,32 +269,49 @@ namespace serialization { vec.resize(size); } + /*! \fn do_check_stream_state + * + * \brief self explanatory + */ template bool do_check_stream_state(Stream& s, boost::mpl::bool_) { 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 bool do_check_stream_state(Stream& s, boost::mpl::bool_) { 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 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 inline bool serialize(Archive &ar, T &v) { diff --git a/src/serialization/variant.h b/src/serialization/variant.h index 3b03f1ba..9b5d5423 100644 --- a/src/serialization/variant.h +++ b/src/serialization/variant.h @@ -28,6 +28,12 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +/*! \file variant.h + * + * \brief for dealing with variants + * + * \detailed Variant: OOP Union + */ #pragma once #include @@ -39,11 +45,21 @@ #include #include "serialization.h" +/*! \struct variant_serialization_triats + * + * \brief used internally to contain a variant's traits/possible types + * + * \detailed see the macro VARIANT_TAG in serialization.h:140 + */ template struct variant_serialization_traits { }; +/*! \struct variant_reader + * + * \brief reads a variant + */ template struct variant_reader { @@ -51,9 +67,10 @@ struct variant_reader typedef typename boost::mpl::next::type TNext; typedef typename boost::mpl::deref::type current_type; + // A tail recursive inline function.... okay... static inline bool read(Archive &ar, Variant &v, variant_tag_type t) { - if (variant_serialization_traits::get_tag() == t) { + if(variant_serialization_traits::get_tag() == t) { current_type x; if(!::do_serialize(ar, x)) { @@ -62,12 +79,15 @@ struct variant_reader } v = x; } else { + // Tail recursive.... but no mutation is going on. Why? return variant_reader::read(ar, v, t); } return true; } }; +// This one just fails when you call it.... okay +// So the TEnd parameter must be specified/differnt from TBegin template struct variant_reader { @@ -78,7 +98,6 @@ struct variant_reader ar.stream().setstate(std::ios::failbit); return false; } - }; @@ -93,7 +112,9 @@ struct serializer, boost::variant> variant_tag_type t; ar.begin_variant(); ar.read_variant_tag(t); - if(!variant_reader, variant_type, typename boost::mpl::begin::type, typename boost::mpl::end::type>::read(ar, v, t)) + if(!variant_reader, variant_type, + typename boost::mpl::begin::type, + typename boost::mpl::end::type>::read(ar, v, t)) { ar.stream().setstate(std::ios::failbit); return false;