diff options
Diffstat (limited to 'cpp/src/qpid/Serializer.h')
-rw-r--r-- | cpp/src/qpid/Serializer.h | 131 |
1 files changed, 85 insertions, 46 deletions
diff --git a/cpp/src/qpid/Serializer.h b/cpp/src/qpid/Serializer.h index 12bcded0f7..6ff701f346 100644 --- a/cpp/src/qpid/Serializer.h +++ b/cpp/src/qpid/Serializer.h @@ -22,82 +22,121 @@ * */ -#include <boost/utility/enable_if.hpp> -#include <boost/type_traits/is_base_and_derived.hpp> +#include <algorithm> namespace qpid { -namespace serialize { - -/** Wrapper to pass serializer functors by reference. */ -template <class S> struct SRef { - S& s; - SRef(S& ss) : s(ss) {} - template <class T> typename S::result_type operator()(T& x) { return s(x); } - template <class T> typename S::result_type operator()(const T& x) { return s(x); } -}; - -template <class S> SRef<S> ref(S& s) { return SRef<S>(s); } -// FIXME aconway 2008-03-03: Document. -// Encoder/Decoder concept: add op() for primitive types, raw(), -// op()(Iter, Iter). Note split, encode, decode. -// +/** + * Overload for types that do not provide a serialize() member. + * It should retrun a wrapper holding a reference to t that implements + * serialize() + */ +template <class T> T& serializable(T& t) { return t; } -// FIXME aconway 2008-03-09: document - non-intrusive serialzation. -// Default rule calls member. Enums must provide an override rule. +/** Serialize std::pair */ +template <class T, class U> struct SerializablePair { + std::pair<T,U>& value; + SerializablePair(std::pair<T,U>& x) : value(x) {} + template <class S> void serialize(S& s) { s(value.first)(value.second); } +}; -/** Overload for types that do not provide a serialize() member.*/ -template <class T> T& serializable(T& t) { return t; } +template <class T, class U> +SerializablePair<T,U> serializable(std::pair<T,U>& p) { + return SerializablePair<T,U>(p); +} -template <class Derived> class Encoder { +/** + * Base class for all serializers. + * Derived serializers inherit from either Encoder or Decoder. + * Serializers can be used as functors or static_visitors. + */ +template <class Derived> class Serializer { public: typedef Derived& result_type; // unary functor requirement. - /** Default op() calls serializable() free function */ - template <class T> - Derived& operator()(const T& t) { + /** Wrapper functor to pass serializer functors by reference. */ + template <class S> struct Ref { + typedef typename S::result_type result_type; + S& s; + Ref(S& ss) : s(ss) {} + template <class T> result_type operator()(T& x) { return s(x); } + template <class T> result_type operator()(const T& x) { return s(x); } + }; + + /** Reference wrapper to pass serializers by reference, + * e.g. to std:: functions that take functors. + */ + template <class S> static Ref<S> ref(S& s) { return Ref<S>(s); } + + /** Generic rule to serialize an iterator range */ + template <class Iter> Derived& operator()(Iter begin, Iter end) { + std::for_each(begin, end, ref(this->self())); + return self(); + } + + protected: + Derived& self() { return *static_cast<Derived*>(this); } +}; + +/** + * Base class for encoders, provides generic encode functions. + * + * A derived encoder must provide operator(const T&) to encode all + * primitive types T. + */ +template <class Derived> class EncoderBase : public Serializer<Derived> { + public: + using Serializer<Derived>::operator(); + using Serializer<Derived>::self; + + /** Default op() for non-primitive types. */ + template <class T> Derived& operator()(const T& t) { serializable(const_cast<T&>(t)).serialize(self()); return self(); } /** Split serialize() into encode()/decode() */ - template <class T> - Derived& split(const T& t) { t.encode(self()); return self(); } - - private: - Derived& self() { return *static_cast<Derived*>(this); } + template <class T> Derived& split(const T& t) { + t.encode(self()); return self(); + } }; -template <class Derived> class Decoder { +/** + * Base class for decoders, provides generic decode functions. + * + * A derived encoder must provide operator(T&) to encode all + * primitive types T. + */ +template <class Derived> class DecoderBase : public Serializer<Derived> { public: - typedef Derived& result_type; // unary functor requirement. + using Serializer<Derived>::operator(); + using Serializer<Derived>::self; - /** Default op() calls serializable() free function */ - template <class T> - Derived& operator()(T& t) { + /** Default op() for non-primitive types. */ + template <class T> Derived& operator()(T& t) { serializable(t).serialize(self()); return self(); } /** Split serialize() into encode()/decode() */ - template <class T> - Derived& split(T& t) { t.decode(self()); return self(); } - - - private: - Derived& self() { return *static_cast<Derived*>(this); } + template <class T> Derived& split(T& t) { + t.decode(self()); return self(); + } }; -/** Serialize a type by converting it to/from another type */ +/** Serialize a type by converting it to/from another type. + * To serialize type Foo by converting to/from type Bar create + * a serializable() overload like this: + * + * SerializeAs<Foo,Bar> serializable(Foo& t) { return SerializeAs<Foo,Bar>(t); } + */ template <class Type, class AsType> struct SerializeAs { Type& value; SerializeAs(Type & t) : value(t) {} template <class S> void serialize(S& s) { s.split(*this); } template <class S> void encode(S& s) const { s(AsType(value)); } - template <class S> void decode(S& s) { AsType x; s(x); value=x; } + template <class S> void decode(S& s) { AsType x; s(x); value=Type(x); } }; -}} // namespace qpid::serialize +} // namespace qpid -// FIXME aconway 2008-03-09: rename to serialize.h -// #endif /*!QPID_SERIALIZER_H*/ |