summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2008-04-03 17:23:34 +0000
committerAlan Conway <aconway@apache.org>2008-04-03 17:23:34 +0000
commit9fb7885893067b5924aac26502433cec7212d6c7 (patch)
treefe49b09280be5a8e16ca36f81a58f2c903ce9167 /cpp
parentbffa2485f1e33eb1a273d2b74149f0ccb0742c60 (diff)
downloadqpid-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-xcpp/rubygen/0-10/specification.rb4
-rw-r--r--cpp/src/qpid/Serializer.h131
-rw-r--r--cpp/src/qpid/amqp_0_10/Codec.h42
-rw-r--r--cpp/src/qpid/amqp_0_10/Map.cpp13
-rw-r--r--cpp/src/qpid/amqp_0_10/Map.h23
-rw-r--r--cpp/src/qpid/amqp_0_10/PackedCodec.h2
-rw-r--r--cpp/src/qpid/amqp_0_10/Segment.h1
-rw-r--r--cpp/src/qpid/amqp_0_10/built_in_types.h20
-rw-r--r--cpp/src/tests/amqp_0_10/Map.cpp5
-rw-r--r--cpp/src/tests/serialize.cpp7
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;