diff options
author | Alan Conway <aconway@apache.org> | 2008-04-03 17:23:34 +0000 |
---|---|---|
committer | Alan Conway <aconway@apache.org> | 2008-04-03 17:23:34 +0000 |
commit | 9fb7885893067b5924aac26502433cec7212d6c7 (patch) | |
tree | fe49b09280be5a8e16ca36f81a58f2c903ce9167 /cpp | |
parent | bffa2485f1e33eb1a273d2b74149f0ccb0742c60 (diff) | |
download | qpid-python-9fb7885893067b5924aac26502433cec7212d6c7.tar.gz |
src/qpid/amqp_0_10/Map.h,.cpp: use preview encoding temporarily.
Misc cleanup for 0-10 encoding.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@644413 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp')
-rwxr-xr-x | cpp/rubygen/0-10/specification.rb | 4 | ||||
-rw-r--r-- | cpp/src/qpid/Serializer.h | 131 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/Codec.h | 42 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/Map.cpp | 13 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/Map.h | 23 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/PackedCodec.h | 2 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/Segment.h | 1 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/built_in_types.h | 20 | ||||
-rw-r--r-- | cpp/src/tests/amqp_0_10/Map.cpp | 5 | ||||
-rw-r--r-- | cpp/src/tests/serialize.cpp | 7 |
10 files changed, 131 insertions, 117 deletions
diff --git a/cpp/rubygen/0-10/specification.rb b/cpp/rubygen/0-10/specification.rb index dbb05fb752..95eb8f5f5b 100755 --- a/cpp/rubygen/0-10/specification.rb +++ b/cpp/rubygen/0-10/specification.rb @@ -19,8 +19,8 @@ class Specification < CppGen genl d.enum.choices.map { |c| "#{c.name.constname} = #{c.value}" }.join(",\n") } - scope("inline SerializableEnum<#{typename}, uint8_t> serializable(#{typename}& e) {") { - genl "return SerializableEnum<#{typename}>(e);" + scope("inline SerializeAs<#{typename}, uint8_t> serializable(#{typename}& e) {") { + genl "return SerializeAs<#{typename}, uint8_t>(e);" } else genl "typedef #{d.amqp2cpp} #{typename};" 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*/ diff --git a/cpp/src/qpid/amqp_0_10/Codec.h b/cpp/src/qpid/amqp_0_10/Codec.h index bd0652716f..a819aec845 100644 --- a/cpp/src/qpid/amqp_0_10/Codec.h +++ b/cpp/src/qpid/amqp_0_10/Codec.h @@ -29,6 +29,7 @@ #include <boost/type_traits/is_arithmetic.hpp> #include <boost/detail/endian.hpp> #include <boost/static_assert.hpp> +#include <iterator> namespace qpid { namespace amqp_0_10 { @@ -46,17 +47,14 @@ template <class T> void endianize(T&) {} * AMQP 0-10 encoding and decoding. */ struct Codec { - // FIXME aconway 2008-02-29: drop this wrapper, rename to - // IteratorEncoder, IteratorDecoder? - /** Encode to an output byte iterator */ template <class OutIter> - class Encoder : public serialize::Encoder<Encoder<OutIter> > + class Encoder : public EncoderBase<Encoder<OutIter> > { public: Encoder(OutIter o) : out(o) {} - using serialize::Encoder<Encoder<OutIter> >::operator(); + using EncoderBase<Encoder<OutIter> >::operator(); // FIXME aconway 2008-03-10: wrong encoding, need packing support Encoder& operator()(bool x) { *out++=x; return *this;} @@ -77,14 +75,8 @@ struct Codec { Encoder& operator()(double x) { return endian(x); } - template <class Iter> Encoder& operator()(Iter begin, Iter end) { - std::for_each(begin, end, serialize::ref(*this)); - return *this; - } - void raw(const void* p, size_t n) { - std::copy((const char*)p, (const char*)p+n, out); - out += n; + out = std::copy((const char*)p, (const char*)p+n, out); } OutIter pos() const { return out; } @@ -99,11 +91,13 @@ struct Codec { }; template <class InIter> - class Decoder : public serialize::Decoder<Decoder<InIter> > { + class Decoder : public DecoderBase<Decoder<InIter> > { public: + typedef InIter Iterator; + Decoder(InIter i) : in(i) {} - using serialize::Decoder<Decoder<InIter> >::operator(); + using DecoderBase<Decoder<InIter> >::operator(); // FIXME aconway 2008-03-10: wrong encoding, need packing support Decoder& operator()(bool& x) { x=*in++; return *this; } @@ -123,14 +117,9 @@ struct Codec { Decoder& operator()(float& x) { return endian(x); } Decoder& operator()(double& x) { return endian(x); } - template <class Iter> Decoder& operator()(Iter begin, Iter end) { - std::for_each(begin, end, serialize::ref(*this)); - return *this; - } - void raw(void *p, size_t n) { std::copy(in, in+n, (char*)p); - in += n; + std::advance(in, n); } InIter pos() const { return in; } @@ -145,13 +134,13 @@ struct Codec { }; - class Size : public serialize::Encoder<Size> { + class Size : public EncoderBase<Size> { public: Size() : size(0) {} operator size_t() const { return size; } - using serialize::Encoder<Size>::operator(); + using EncoderBase<Size>::operator(); // FIXME aconway 2008-03-10: wrong encoding, need packing support Size& operator()(bool x) { size += sizeof(x); return *this; } @@ -171,12 +160,9 @@ struct Codec { Size& operator()(float x) { size += sizeof(x); return *this; } Size& operator()(double x) { size += sizeof(x); return *this; } - // FIXME aconway 2008-04-02: enable-if optimized (iter,iter) for - // iter on fixed-size type. - template <class Iter> Size& operator()(Iter begin, Iter end) { - std::for_each(begin, end, serialize::ref(*this)); - return *this; - } + // FIXME aconway 2008-04-03: optimize op()(Iter,Iter) + // for Iter with fixed-size value_type: + // distance(begin,end)*sizeof(value_type) void raw(const void*, size_t n){ size += n; } diff --git a/cpp/src/qpid/amqp_0_10/Map.cpp b/cpp/src/qpid/amqp_0_10/Map.cpp index 1bfc2f6c85..480b439e40 100644 --- a/cpp/src/qpid/amqp_0_10/Map.cpp +++ b/cpp/src/qpid/amqp_0_10/Map.cpp @@ -18,6 +18,7 @@ * under the License. * */ +#include "qpid/amqp_0_10/specification.h" // for error constants. #include "Map.h" #include <ostream> @@ -57,12 +58,12 @@ std::ostream& operator<<(std::ostream& o, const Map& map) { } uint32_t Map::contentSize() const { - uint32_t result=4; // uint32_t count - for (const_iterator i=begin(); i != end(); ++i) { - result += Codec::size(i->first); - result += Codec::size(i->second); - } - return result; + // FIXME aconway 2008-04-03: preview to 0-10 mapping: +4 for count. + return /*4 +*/ Codec::Size()(begin(), end()); +} + +void Map::throwInvalidArg() { + throw SessionException(execution::INVALID_ARGUMENT, "Invalid map encoding"); } }} // namespace qpid::amqp_0_10 diff --git a/cpp/src/qpid/amqp_0_10/Map.h b/cpp/src/qpid/amqp_0_10/Map.h index e9b95ed0f2..c23b4e37db 100644 --- a/cpp/src/qpid/amqp_0_10/Map.h +++ b/cpp/src/qpid/amqp_0_10/Map.h @@ -85,14 +85,13 @@ class Map : public std::map<Str8, MapValue> { public: template <class S> void serialize(S& s) { s.split(*this); } template <class S> void encode(S& s) const; - - // FIXME aconway 2008-04-02: better separation for size calcultion - // support for static size, optimized iterator size calc. + // Shortcut calculation for size. void encode(Codec::Size& s) const { s.raw(0, contentSize() + 4/*size*/); } template <class S> void decode(S& s); private: + static void throwInvalidArg(); uint32_t contentSize() const; }; @@ -157,18 +156,26 @@ template <class V> typename V::result_type MapValue::apply_visitor(const V& v) { } template <class S> void Map::encode(S& s) const { - s(contentSize())(uint32_t(size())); // size, count + // FIXME aconway 2008-04-03: replace preview mapping with 0-10 mapping: + // s(contentSize())(uint32_t(size())); // size, count + s(contentSize()); for (const_iterator i = begin(); i != end(); ++i) s(i->first)(i->second); // key (type value) } template <class S> void Map::decode(S& s) { - uint32_t cSize, count; - // FIXME aconway 2008-04-02: runtime check that we consume exactly cSize. - s(cSize)(count); - for ( ; count > 0; --count) { + uint32_t cSize /*, count*/; + // FIXME aconway 2008-04-03: replace preview mapping with 0-10 mapping: + // s(contentSize())(uint32_t(size())); // size, count + // s(cSize)(count); + s(cSize); + typename S::Iterator start = s.pos(); + // FIXME aconway 2008-04-03: replace preview with 0-10: + // for ( ; count > 0; --count) { + while (uint32_t(std::distance(start, s.pos())) < cSize) { key_type k; MapValue v; s(k)(v); + if (uint32_t(std::distance(start, s.pos())) > cSize) throwInvalidArg(); insert(value_type(k,v)); } } diff --git a/cpp/src/qpid/amqp_0_10/PackedCodec.h b/cpp/src/qpid/amqp_0_10/PackedCodec.h index f6290e76a1..408c20cb0b 100644 --- a/cpp/src/qpid/amqp_0_10/PackedCodec.h +++ b/cpp/src/qpid/amqp_0_10/PackedCodec.h @@ -34,7 +34,7 @@ namespace amqp_0_10 { struct PackedCodec { template <class Bits, class InnerDecoder> class Decoder : - public serialize::Decoder<PackedCodec::Decoder<Bits, InnerDecoder> > + public DecoderBase<PackedCodec::Decoder<Bits, InnerDecoder> > { public: Decoder(Bits b, const InnerDecoder& d) diff --git a/cpp/src/qpid/amqp_0_10/Segment.h b/cpp/src/qpid/amqp_0_10/Segment.h index b779b98dd1..650573802b 100644 --- a/cpp/src/qpid/amqp_0_10/Segment.h +++ b/cpp/src/qpid/amqp_0_10/Segment.h @@ -106,6 +106,7 @@ class Segment::const_iterator : public boost::iterator_facade< p += n; skip_empty(); } + void skip_empty() { invariant(); while (p == i->end() && i != frames->end()) diff --git a/cpp/src/qpid/amqp_0_10/built_in_types.h b/cpp/src/qpid/amqp_0_10/built_in_types.h index 0b9ed4168b..c9ce27bda0 100644 --- a/cpp/src/qpid/amqp_0_10/built_in_types.h +++ b/cpp/src/qpid/amqp_0_10/built_in_types.h @@ -21,11 +21,12 @@ * */ -#include "Decimal.h" -#include "SerializableString.h" +#include "qpid/Serializer.h" #include "qpid/framing/SequenceNumber.h" #include "qpid/framing/Uuid.h" #include "qpid/sys/Time.h" +#include "Decimal.h" +#include "SerializableString.h" #include <boost/array.hpp> #include <boost/range/iterator_range.hpp> #include <string> @@ -153,22 +154,13 @@ inline std::ostream& operator<<(std::ostream& o, const SequenceSet&) { return o; inline std::ostream& operator<<(std::ostream& o, const List&) { return o; } inline std::ostream& operator<<(std::ostream& o, const Struct32&) { return o; } -/** Serialization helper for enums */ -template <class Enum, class Int=uint8_t> -struct SerializableEnum { - Enum& value; - SerializableEnum(Enum & e) : value(e) {} - template <class S> void serialize(S& s) { s.split(*this); } - template <class S> void encode(S& s) const { s(Int(value)); } - template <class S> void decode(S& s) { Int i; s(i); value=Enum(i); } -}; - enum SegmentType { CONTROL, COMMAND, HEADER, BODY }; -inline SerializableEnum<SegmentType> serializable(SegmentType& st) { - return SerializableEnum<SegmentType>(st); +inline SerializeAs<SegmentType, uint8_t> serializable(SegmentType& st) { + return SerializeAs<SegmentType, uint8_t>(st); } + }} // namespace qpid::amqp_0_10 #endif diff --git a/cpp/src/tests/amqp_0_10/Map.cpp b/cpp/src/tests/amqp_0_10/Map.cpp index 0a58a2134a..ad6f38b5d7 100644 --- a/cpp/src/tests/amqp_0_10/Map.cpp +++ b/cpp/src/tests/amqp_0_10/Map.cpp @@ -26,11 +26,6 @@ using namespace qpid::amqp_0_10; using namespace std; -namespace std { -// Dummy += for back inserters so we can use them with the decoder. -template <class C> back_insert_iterator<C>& operator+=(back_insert_iterator<C>& bi, size_t) { return bi; } -} - QPID_AUTO_TEST_SUITE(MapTestSuite) BOOST_AUTO_TEST_CASE(testGetSet) { diff --git a/cpp/src/tests/serialize.cpp b/cpp/src/tests/serialize.cpp index 1f576d6ee1..386f721338 100644 --- a/cpp/src/tests/serialize.cpp +++ b/cpp/src/tests/serialize.cpp @@ -60,15 +60,8 @@ std::ostream& operator<<(std::ostream& out, const AbsTime& t) { } // qpid -namespace std { -// Dummy += for back inserters so we can use them with the decoder. -template <class C> back_insert_iterator<C>& operator+=(back_insert_iterator<C>& bi, size_t) { return bi; } -} - QPID_AUTO_TEST_SUITE(SerializeTestSuite) - - using namespace std; namespace mpl=boost::mpl; using namespace qpid::amqp_0_10; |