mirror of
https://github.com/monero-project/monero.git
synced 2024-12-27 09:09:22 -05:00
Merge pull request #178
b032619
Commented most of src/serialization/ going to read up more on variant's and finish off the job/add last touchs next (jebes)
This commit is contained in:
commit
2de2c52c02
@ -28,7 +28,7 @@
|
|||||||
//
|
//
|
||||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
// 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 */
|
* Portable (low-endian) binary archive */
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -41,11 +41,20 @@
|
|||||||
#include "common/varint.h"
|
#include "common/varint.h"
|
||||||
#include "warnings.h"
|
#include "warnings.h"
|
||||||
|
|
||||||
PUSH_WARNINGS
|
/* I have no clue what these lines means */
|
||||||
DISABLE_VS_WARNINGS(4244)
|
PUSH_WARNINGS;
|
||||||
|
DISABLE_VS_WARNINGS(4244);
|
||||||
|
|
||||||
//TODO: fix size_t warning in x32 platform
|
//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>
|
template <class Stream, bool IsSaving>
|
||||||
struct binary_archive_base
|
struct binary_archive_base
|
||||||
{
|
{
|
||||||
@ -56,23 +65,39 @@ struct binary_archive_base
|
|||||||
typedef uint8_t variant_tag_type;
|
typedef uint8_t variant_tag_type;
|
||||||
|
|
||||||
explicit binary_archive_base(stream_type &s) : stream_(s) { }
|
explicit binary_archive_base(stream_type &s) : stream_(s) { }
|
||||||
|
|
||||||
|
/* definition of standard API functions */
|
||||||
void tag(const char *) { }
|
void tag(const char *) { }
|
||||||
void begin_object() { }
|
void begin_object() { }
|
||||||
void end_object() { }
|
void end_object() { }
|
||||||
void begin_variant() { }
|
void begin_variant() { }
|
||||||
void end_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:
|
protected:
|
||||||
stream_type &stream_;
|
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>
|
template <bool W>
|
||||||
struct binary_archive;
|
struct binary_archive;
|
||||||
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct binary_archive<false> : public binary_archive_base<std::istream, false>
|
struct binary_archive<false> : public binary_archive_base<std::istream, false>
|
||||||
{
|
{
|
||||||
|
|
||||||
explicit binary_archive(stream_type &s) : base_type(s) {
|
explicit binary_archive(stream_type &s) : base_type(s) {
|
||||||
stream_type::streampos pos = stream_.tellg();
|
stream_type::streampos pos = stream_.tellg();
|
||||||
stream_.seekg(0, std::ios_base::end);
|
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);
|
serialize_uint(*(typename boost::make_unsigned<T>::type *)&v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \fn serialize_uint
|
||||||
|
*
|
||||||
|
* \brief serializes an unsigned integer
|
||||||
|
*/
|
||||||
template <class T>
|
template <class T>
|
||||||
void serialize_uint(T &v, size_t width = sizeof(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;
|
char c;
|
||||||
stream_.get(c);
|
stream_.get(c);
|
||||||
T b = (unsigned char)c;
|
T b = (unsigned char)c;
|
||||||
ret += (b << shift);
|
ret += (b << shift); // can this be changed to OR, i think it can.
|
||||||
shift += 8;
|
shift += 8;
|
||||||
}
|
}
|
||||||
v = ret;
|
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>
|
template <class T>
|
||||||
void serialize_varint(T &v)
|
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;
|
typedef std::istreambuf_iterator<char> it;
|
||||||
tools::read_varint(it(stream_), it(), v); // XXX handle failure
|
tools::read_varint(it(stream_), it(), v); // XXX handle failure
|
||||||
}
|
}
|
||||||
|
|
||||||
void begin_array(size_t &s)
|
void begin_array(size_t &s)
|
||||||
{
|
{
|
||||||
serialize_varint(s);
|
serialize_varint(s);
|
||||||
}
|
}
|
||||||
void begin_array() { }
|
|
||||||
|
|
||||||
|
void begin_array() { }
|
||||||
void delimit_array() { }
|
void delimit_array() { }
|
||||||
void end_array() { }
|
void end_array() { }
|
||||||
|
|
||||||
void begin_string(const char *delimiter="\"") { }
|
void begin_string(const char *delimiter /*="\""*/) { }
|
||||||
void end_string(const char *delimiter="\"") { }
|
void end_string(const char *delimiter /*="\""*/) { }
|
||||||
|
|
||||||
void read_variant_tag(variant_tag_type &t) {
|
void read_variant_tag(variant_tag_type &t) {
|
||||||
serialize_int(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++) {
|
for (size_t i = 0; i < sizeof(T); i++) {
|
||||||
stream_.put((char)(v & 0xff));
|
stream_.put((char)(v & 0xff));
|
||||||
if (1 < sizeof(T)) {
|
if (1 < sizeof(T)) v >>= 8;
|
||||||
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>
|
template <class T>
|
||||||
void serialize_varint(T &v)
|
void serialize_varint(T &v)
|
||||||
|
@ -34,23 +34,26 @@
|
|||||||
#include "binary_archive.h"
|
#include "binary_archive.h"
|
||||||
|
|
||||||
namespace serialization {
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! 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();
|
||||||
|
};
|
||||||
|
|
||||||
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
|
|
||||||
|
@ -28,9 +28,10 @@
|
|||||||
//
|
//
|
||||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
// 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
|
#pragma once
|
||||||
|
|
||||||
@ -39,6 +40,12 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#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>
|
template <class Stream, bool IsSaving>
|
||||||
struct json_archive_base
|
struct json_archive_base
|
||||||
{
|
{
|
||||||
@ -48,7 +55,8 @@ struct json_archive_base
|
|||||||
|
|
||||||
typedef const char *variant_tag_type;
|
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) {
|
void tag(const char *tag) {
|
||||||
if (!object_begin)
|
if (!object_begin)
|
||||||
@ -92,6 +100,13 @@ protected:
|
|||||||
size_t depth_;
|
size_t depth_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*! \struct json_archive
|
||||||
|
*
|
||||||
|
* \brief a archive using the JSON standard
|
||||||
|
*
|
||||||
|
* \detailed only supports being written to
|
||||||
|
*/
|
||||||
template <bool W>
|
template <bool W>
|
||||||
struct json_archive;
|
struct json_archive;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Copyright (c) 2014, The Monero Project
|
// Copyright (c) 2014, The Monero Project
|
||||||
//
|
>//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// 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
|
// 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
|
#pragma once
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -38,14 +45,35 @@
|
|||||||
#include <boost/type_traits/is_integral.hpp>
|
#include <boost/type_traits/is_integral.hpp>
|
||||||
#include <boost/type_traits/integral_constant.hpp>
|
#include <boost/type_traits/integral_constant.hpp>
|
||||||
|
|
||||||
|
/*! \struct is_blob_type
|
||||||
|
*
|
||||||
|
* \brief a descriptor for dispatching serialize
|
||||||
|
*/
|
||||||
template <class T>
|
template <class T>
|
||||||
struct is_blob_type { typedef boost::false_type type; };
|
struct is_blob_type { typedef boost::false_type type; };
|
||||||
|
|
||||||
|
/*! \struct has_free_serializer
|
||||||
|
*
|
||||||
|
* \brief a descriptor for dispatching serialize
|
||||||
|
*/
|
||||||
template <class T>
|
template <class T>
|
||||||
struct has_free_serializer { typedef boost::true_type type; };
|
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>
|
template <class Archive, class T>
|
||||||
struct serializer
|
struct serializer{
|
||||||
{
|
|
||||||
static bool serialize(Archive &ar, T &v) {
|
static bool serialize(Archive &ar, T &v) {
|
||||||
return serialize(ar, v, typename boost::is_integral<T>::type(), typename is_blob_type<T>::type());
|
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>
|
template <class Archive, class T>
|
||||||
inline bool do_serialize(Archive &ar, T &v)
|
inline bool do_serialize(Archive &ar, T &v)
|
||||||
{
|
{
|
||||||
return ::serializer<Archive, T>::serialize(ar, v);
|
return ::serializer<Archive, T>::serialize(ar, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __GNUC__
|
// Never used in the code base
|
||||||
#ifndef constexpr
|
// #ifndef __GNUC__
|
||||||
#define constexpr
|
// #ifndef constexpr
|
||||||
#endif
|
// #define constexpr
|
||||||
#endif
|
// #endif
|
||||||
|
// #endif
|
||||||
|
|
||||||
#define BLOB_SERIALIZER(T) \
|
/* the following add a trait to a set and define the serialization DSL*/
|
||||||
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;}
|
/*! \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; \
|
||||||
|
}
|
||||||
|
|
||||||
#define VALUE(f) \
|
/*! \macro VARIANT_TAG
|
||||||
do { \
|
*
|
||||||
ar.tag(#f); \
|
* \brief Adds the tag \tag to the \a Archive of \a Type
|
||||||
bool r = ::do_serialize(ar, f); \
|
*/
|
||||||
if (!r || !ar.stream().good()) return false; \
|
#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);
|
} while(0);
|
||||||
#define FIELD_N(t, f) \
|
|
||||||
do { \
|
/*! \macro FIELD_N(t,f)
|
||||||
ar.tag(t); \
|
*
|
||||||
bool r = ::do_serialize(ar, f); \
|
* \brief serializes a field \a f tagged \a t
|
||||||
if (!r || !ar.stream().good()) return false; \
|
*/
|
||||||
|
#define FIELD_N(t, f) \
|
||||||
|
do { \
|
||||||
|
ar.tag(t); \
|
||||||
|
bool r = ::do_serialize(ar, f); \
|
||||||
|
if (!r || !ar.stream().good()) return false; \
|
||||||
} while(0);
|
} while(0);
|
||||||
#define FIELDS(f) \
|
|
||||||
do { \
|
/*! \macro FIELD(f)
|
||||||
bool r = ::do_serialize(ar, f); \
|
*
|
||||||
if (!r || !ar.stream().good()) return false; \
|
* \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);
|
} while(0);
|
||||||
#define FIELD(f) \
|
|
||||||
do { \
|
/*! \macro FIELDS(f)
|
||||||
ar.tag(#f); \
|
*
|
||||||
bool r = ::do_serialize(ar, f); \
|
* \brief does not add a tag to the serialized value
|
||||||
if (!r || !ar.stream().good()) return false; \
|
*/
|
||||||
|
#define FIELDS(f) \
|
||||||
|
do { \
|
||||||
|
bool r = ::do_serialize(ar, f); \
|
||||||
|
if (!r || !ar.stream().good()) return false; \
|
||||||
} while(0);
|
} while(0);
|
||||||
#define VARINT_FIELD(f) \
|
|
||||||
do { \
|
/*! \macro VARING_FIELD(f)
|
||||||
ar.tag(#f); \
|
* \brief tags and serializes the varint \a f
|
||||||
ar.serialize_varint(f); \
|
*/
|
||||||
if (!ar.stream().good()) return false; \
|
#define VARINT_FIELD(f) \
|
||||||
|
do { \
|
||||||
|
ar.tag(#f); \
|
||||||
|
ar.serialize_varint(f); \
|
||||||
|
if (!ar.stream().good()) return false; \
|
||||||
} while(0);
|
} while(0);
|
||||||
#define VARINT_FIELD_N(t, f) \
|
|
||||||
do { \
|
/*! \macro VARING_FIELD_N(t, f)
|
||||||
ar.tag(t); \
|
*
|
||||||
ar.serialize_varint(f); \
|
* \brief tags (as \a t) and serializes the varint \a f
|
||||||
if (!ar.stream().good()) return false; \
|
*/
|
||||||
|
#define VARINT_FIELD_N(t, f) \
|
||||||
|
do { \
|
||||||
|
ar.tag(t); \
|
||||||
|
ar.serialize_varint(f); \
|
||||||
|
if (!ar.stream().good()) return false; \
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
|
|
||||||
namespace serialization {
|
namespace serialization {
|
||||||
|
/*! \namespace detail
|
||||||
|
*
|
||||||
|
* \brief declaration and default definition for the functions used the API
|
||||||
|
*
|
||||||
|
*/
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
/*! \fn prepare_custom_vector_serialization
|
||||||
|
*
|
||||||
|
* prepares the vector /vec for serialization
|
||||||
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void prepare_custom_vector_serialization(size_t size, std::vector<T>& vec, const boost::mpl::bool_<true>& /*is_saving*/)
|
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);
|
vec.resize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \fn do_check_stream_state
|
||||||
|
*
|
||||||
|
* \brief self explanatory
|
||||||
|
*/
|
||||||
template<class Stream>
|
template<class Stream>
|
||||||
bool do_check_stream_state(Stream& s, boost::mpl::bool_<true>)
|
bool do_check_stream_state(Stream& s, boost::mpl::bool_<true>)
|
||||||
{
|
{
|
||||||
return s.good();
|
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>
|
template<class Stream>
|
||||||
bool do_check_stream_state(Stream& s, boost::mpl::bool_<false>)
|
bool do_check_stream_state(Stream& s, boost::mpl::bool_<false>)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (s.good())
|
if (s.good())
|
||||||
{
|
{
|
||||||
std::ios_base::iostate state = s.rdstate();
|
std::ios_base::iostate state = s.rdstate();
|
||||||
result = EOF == s.peek();
|
result = EOF == s.peek();
|
||||||
s.clear(state);
|
s.clear(state);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \fn check_stream_state
|
||||||
|
*
|
||||||
|
* \brief calls detail::do_check_stream_state for ar
|
||||||
|
*/
|
||||||
template<class Archive>
|
template<class Archive>
|
||||||
bool check_stream_state(Archive& ar)
|
bool check_stream_state(Archive& ar)
|
||||||
{
|
{
|
||||||
return detail::do_check_stream_state(ar.stream(), typename Archive::is_saving());
|
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>
|
template <class Archive, class T>
|
||||||
inline bool serialize(Archive &ar, T &v)
|
inline bool serialize(Archive &ar, T &v)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,12 @@
|
|||||||
//
|
//
|
||||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
// 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
|
#pragma once
|
||||||
|
|
||||||
#include <boost/variant/variant.hpp>
|
#include <boost/variant/variant.hpp>
|
||||||
@ -39,11 +45,21 @@
|
|||||||
#include <boost/mpl/pop_front.hpp>
|
#include <boost/mpl/pop_front.hpp>
|
||||||
#include "serialization.h"
|
#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>
|
template <class Archive, class T>
|
||||||
struct variant_serialization_traits
|
struct variant_serialization_traits
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! \struct variant_reader
|
||||||
|
*
|
||||||
|
* \brief reads a variant
|
||||||
|
*/
|
||||||
template <class Archive, class Variant, class TBegin, class TEnd>
|
template <class Archive, class Variant, class TBegin, class TEnd>
|
||||||
struct variant_reader
|
struct variant_reader
|
||||||
{
|
{
|
||||||
@ -51,9 +67,10 @@ struct variant_reader
|
|||||||
typedef typename boost::mpl::next<TBegin>::type TNext;
|
typedef typename boost::mpl::next<TBegin>::type TNext;
|
||||||
typedef typename boost::mpl::deref<TBegin>::type current_type;
|
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)
|
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;
|
current_type x;
|
||||||
if(!::do_serialize(ar, x))
|
if(!::do_serialize(ar, x))
|
||||||
{
|
{
|
||||||
@ -62,12 +79,15 @@ struct variant_reader
|
|||||||
}
|
}
|
||||||
v = x;
|
v = x;
|
||||||
} else {
|
} else {
|
||||||
|
// Tail recursive.... but no mutation is going on. Why?
|
||||||
return variant_reader<Archive, Variant, TNext, TEnd>::read(ar, v, t);
|
return variant_reader<Archive, Variant, TNext, TEnd>::read(ar, v, t);
|
||||||
}
|
}
|
||||||
return true;
|
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>
|
template <class Archive, class Variant, class TBegin>
|
||||||
struct variant_reader<Archive, Variant, TBegin, 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);
|
ar.stream().setstate(std::ios::failbit);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -93,7 +112,9 @@ struct serializer<Archive<false>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
|
|||||||
variant_tag_type t;
|
variant_tag_type t;
|
||||||
ar.begin_variant();
|
ar.begin_variant();
|
||||||
ar.read_variant_tag(t);
|
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);
|
ar.stream().setstate(std::ios::failbit);
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
Reference in New Issue
Block a user