aboutsummaryrefslogtreecommitdiff
path: root/src/serialization
diff options
context:
space:
mode:
authorjebes <psteidelprogramming@gmail.com>2014-10-13 16:00:09 -0400
committerjebes <psteidelprogramming@gmail.com>2014-10-13 16:00:09 -0400
commitb032619a9cb1850dcbb1381b1e77ca1d7c2a00a7 (patch)
tree5e13ac793a68ab974ff173b4d9892386f40267c2 /src/serialization
parentMerge pull request #175 (diff)
downloadmonero-b032619a9cb1850dcbb1381b1e77ca1d7c2a00a7.tar.xz
Commented most of src/serialization/ going to read up more on variant's and finish off the job/add last touchs next
Diffstat (limited to 'src/serialization')
-rw-r--r--src/serialization/binary_archive.h66
-rw-r--r--src/serialization/binary_utils.h39
-rw-r--r--src/serialization/json_archive.h21
-rw-r--r--src/serialization/serialization.h267
-rw-r--r--src/serialization/variant.h27
5 files changed, 319 insertions, 101 deletions
diff --git a/src/serialization/binary_archive.h b/src/serialization/binary_archive.h
index baa6707db..56c94684e 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 <class Stream, bool IsSaving>
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 <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);
@@ -86,6 +111,10 @@ struct binary_archive<false> : public binary_archive_base<std::istream, false>
serialize_uint(*(typename boost::make_unsigned<T>::type *)&v);
}
+ /*! \fn serialize_uint
+ *
+ * \brief serializes an unsigned integer
+ */
template <class T>
void serialize_uint(T &v, size_t width = sizeof(T))
{
@@ -96,13 +125,17 @@ struct binary_archive<false> : public binary_archive_base<std::istream, false>
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 <class T>
void serialize_varint(T &v)
{
@@ -115,17 +148,18 @@ struct binary_archive<false> : public binary_archive_base<std::istream, false>
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 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<true> : public binary_archive_base<std::ostream, true>
{
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 <class T>
void serialize_varint(T &v)
diff --git a/src/serialization/binary_utils.h b/src/serialization/binary_utils.h
index 3b1db3e48..f2cfadd4e 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 <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 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();
-};
+ /*! dumps the data in v into the blob string
+ */
+ 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/json_archive.h b/src/serialization/json_archive.h
index 7a040a126..bd8b16130 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 <iostream>
#include <iomanip>
+/*! \struct json_archive_base
+ *
+ * \brief the base class of json archive type
+ *
+ * \detailed contains the basic logic for serializing a json archive
+ */
template <class Stream, bool IsSaving>
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 <bool W>
struct json_archive;
diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h
index eab3c43d4..74c661371 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
+ *
+ * \detailed is_blob_type and has_free_serializer are
+ * both descriptors for dispatching on to the serailize function.
*
- * Simple templated serialization API */
+ * 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)
{
diff --git a/src/serialization/variant.h b/src/serialization/variant.h
index 3b03f1ba5..9b5d54237 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 <boost/variant/variant.hpp>
@@ -39,11 +45,21 @@
#include <boost/mpl/pop_front.hpp>
#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 <class Archive, class T>
struct variant_serialization_traits
{
};
+/*! \struct variant_reader
+ *
+ * \brief reads a variant
+ */
template <class Archive, class Variant, class TBegin, class TEnd>
struct variant_reader
{
@@ -51,9 +67,10 @@ struct variant_reader
typedef typename boost::mpl::next<TBegin>::type TNext;
typedef typename boost::mpl::deref<TBegin>::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<Archive, current_type>::get_tag() == t) {
+ if(variant_serialization_traits<Archive, current_type>::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<Archive, Variant, TNext, TEnd>::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 <class Archive, class Variant, class TBegin>
struct variant_reader<Archive, Variant, TBegin, TBegin>
{
@@ -78,7 +98,6 @@ struct variant_reader<Archive, Variant, TBegin, TBegin>
ar.stream().setstate(std::ios::failbit);
return false;
}
-
};
@@ -93,7 +112,9 @@ struct serializer<Archive<false>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
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))
+ 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;