summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2008-04-03 13:27:07 +0000
committerAlan Conway <aconway@apache.org>2008-04-03 13:27:07 +0000
commitbffa2485f1e33eb1a273d2b74149f0ccb0742c60 (patch)
treef116d78d4aab7699806882e2660bf81578b98ea7 /cpp
parent833239ec44ea87a1b619eef3de55afde56c7ee45 (diff)
downloadqpid-python-bffa2485f1e33eb1a273d2b74149f0ccb0742c60.tar.gz
amqp_0_10/built_in_types.h
- generic Wrapper template for making distinct types. - added Bit - bool wrapper with empty encode/decode. amqp_0_10/complex_types.h: - Added constants SIZE=0, PACK=2 to Action base class. amqp_0_10/PackedCodec.h: - Decode packed struct fields according to the packing bits. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@644308 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp')
-rw-r--r--cpp/src/Makefile.am1
-rw-r--r--cpp/src/qpid/amqp_0_10/Codec.h76
-rw-r--r--cpp/src/qpid/amqp_0_10/PackedCodec.h79
-rw-r--r--cpp/src/qpid/amqp_0_10/built_in_types.h47
-rw-r--r--cpp/src/qpid/amqp_0_10/complex_types.h4
-rw-r--r--cpp/src/tests/serialize.cpp14
6 files changed, 167 insertions, 54 deletions
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am
index 05efcb2a71..bb3f87f96b 100644
--- a/cpp/src/Makefile.am
+++ b/cpp/src/Makefile.am
@@ -109,6 +109,7 @@ libqpidcommon_la_SOURCES = \
qpid/amqp_0_10/complex_types.cpp \
qpid/amqp_0_10/Holder.h \
qpid/amqp_0_10/Codec.h \
+ qpid/amqp_0_10/PackedCodec.h \
qpid/amqp_0_10/Decimal.h \
qpid/amqp_0_10/Frame.h \
qpid/amqp_0_10/Segment.h \
diff --git a/cpp/src/qpid/amqp_0_10/Codec.h b/cpp/src/qpid/amqp_0_10/Codec.h
index 138de8c96e..bd0652716f 100644
--- a/cpp/src/qpid/amqp_0_10/Codec.h
+++ b/cpp/src/qpid/amqp_0_10/Codec.h
@@ -51,33 +51,33 @@ struct Codec {
/** Encode to an output byte iterator */
template <class OutIter>
- class Encode : public serialize::Encoder<Encode<OutIter> >
+ class Encoder : public serialize::Encoder<Encoder<OutIter> >
{
public:
- Encode(OutIter o) : out(o) {}
+ Encoder(OutIter o) : out(o) {}
- using serialize::Encoder<Encode<OutIter> >::operator();
+ using serialize::Encoder<Encoder<OutIter> >::operator();
// FIXME aconway 2008-03-10: wrong encoding, need packing support
- Encode& operator()(bool x) { *out++=x; return *this;}
+ Encoder& operator()(bool x) { *out++=x; return *this;}
- Encode& operator()(char x) { *out++=x; return *this; }
- Encode& operator()(int8_t x) { *out++=x; return *this; }
- Encode& operator()(uint8_t x) { *out++=x; return *this; }
+ Encoder& operator()(char x) { *out++=x; return *this; }
+ Encoder& operator()(int8_t x) { *out++=x; return *this; }
+ Encoder& operator()(uint8_t x) { *out++=x; return *this; }
- Encode& operator()(int16_t x) { return endian(x); }
- Encode& operator()(int32_t x) { return endian(x); }
- Encode& operator()(int64_t x) { return endian(x); }
+ Encoder& operator()(int16_t x) { return endian(x); }
+ Encoder& operator()(int32_t x) { return endian(x); }
+ Encoder& operator()(int64_t x) { return endian(x); }
- Encode& operator()(uint16_t x) { return endian(x); }
- Encode& operator()(uint32_t x) { return endian(x); }
- Encode& operator()(uint64_t x) { return endian(x); }
+ Encoder& operator()(uint16_t x) { return endian(x); }
+ Encoder& operator()(uint32_t x) { return endian(x); }
+ Encoder& operator()(uint64_t x) { return endian(x); }
- Encode& operator()(float x) { return endian(x); }
- Encode& operator()(double x) { return endian(x); }
+ Encoder& operator()(float x) { return endian(x); }
+ Encoder& operator()(double x) { return endian(x); }
- template <class Iter> Encode& operator()(Iter begin, Iter end) {
+ template <class Iter> Encoder& operator()(Iter begin, Iter end) {
std::for_each(begin, end, serialize::ref(*this));
return *this;
}
@@ -91,7 +91,7 @@ struct Codec {
private:
- template <class T> Encode& endian(T x) {
+ template <class T> Encoder& endian(T x) {
endianize(x); raw(&x, sizeof(x)); return *this;
}
@@ -99,31 +99,31 @@ struct Codec {
};
template <class InIter>
- class Decode : public serialize::Decoder<Decode<InIter> > {
+ class Decoder : public serialize::Decoder<Decoder<InIter> > {
public:
- Decode(InIter i) : in(i) {}
+ Decoder(InIter i) : in(i) {}
- using serialize::Decoder<Decode<InIter> >::operator();
+ using serialize::Decoder<Decoder<InIter> >::operator();
// FIXME aconway 2008-03-10: wrong encoding, need packing support
- Decode& operator()(bool& x) { x=*in++; return *this; }
+ Decoder& operator()(bool& x) { x=*in++; return *this; }
- Decode& operator()(char& x) { x=*in++; return *this; }
- Decode& operator()(int8_t& x) { x=*in++; return *this; }
- Decode& operator()(uint8_t& x) { x=*in++; return *this; }
+ Decoder& operator()(char& x) { x=*in++; return *this; }
+ Decoder& operator()(int8_t& x) { x=*in++; return *this; }
+ Decoder& operator()(uint8_t& x) { x=*in++; return *this; }
- Decode& operator()(int16_t& x) { return endian(x); }
- Decode& operator()(int32_t& x) { return endian(x); }
- Decode& operator()(int64_t& x) { return endian(x); }
+ Decoder& operator()(int16_t& x) { return endian(x); }
+ Decoder& operator()(int32_t& x) { return endian(x); }
+ Decoder& operator()(int64_t& x) { return endian(x); }
- Decode& operator()(uint16_t& x) { return endian(x); }
- Decode& operator()(uint32_t& x) { return endian(x); }
- Decode& operator()(uint64_t& x) { return endian(x); }
+ Decoder& operator()(uint16_t& x) { return endian(x); }
+ Decoder& operator()(uint32_t& x) { return endian(x); }
+ Decoder& operator()(uint64_t& x) { return endian(x); }
- Decode& operator()(float& x) { return endian(x); }
- Decode& operator()(double& x) { return endian(x); }
+ Decoder& operator()(float& x) { return endian(x); }
+ Decoder& operator()(double& x) { return endian(x); }
- template <class Iter> Decode& operator()(Iter begin, Iter end) {
+ template <class Iter> Decoder& operator()(Iter begin, Iter end) {
std::for_each(begin, end, serialize::ref(*this));
return *this;
}
@@ -137,7 +137,7 @@ struct Codec {
private:
- template <class T> Decode& endian(T& x) {
+ template <class T> Decoder& endian(T& x) {
raw(&x, sizeof(x)); endianize(x); return *this;
}
@@ -185,12 +185,12 @@ struct Codec {
};
// FIXME aconway 2008-03-11: rename to encoder(), decoder()
- template <class InIter> static Decode<InIter> decode(const InIter &i) {
- return Decode<InIter>(i);
+ template <class InIter> static Decoder<InIter> decode(const InIter &i) {
+ return Decoder<InIter>(i);
}
- template <class OutIter> static Encode<OutIter> encode(OutIter i) {
- return Encode<OutIter>(i);
+ template <class OutIter> static Encoder<OutIter> encode(OutIter i) {
+ return Encoder<OutIter>(i);
}
template <class T> static size_t size(const T& x) { return Size()(x); }
diff --git a/cpp/src/qpid/amqp_0_10/PackedCodec.h b/cpp/src/qpid/amqp_0_10/PackedCodec.h
new file mode 100644
index 0000000000..f6290e76a1
--- /dev/null
+++ b/cpp/src/qpid/amqp_0_10/PackedCodec.h
@@ -0,0 +1,79 @@
+#ifndef QPID_AMQP_0_10_PACKEDCODEC_H
+#define QPID_AMQP_0_10_PACKEDCODEC_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "Codec.h"
+
+namespace qpid {
+namespace amqp_0_10 {
+
+/**
+ * Packed encoding/decoding. Process or ignore fields based on
+ * packing bits.
+ */
+struct PackedCodec {
+ template <class Bits, class InnerDecoder>
+ class Decoder :
+ public serialize::Decoder<PackedCodec::Decoder<Bits, InnerDecoder> >
+ {
+ public:
+ Decoder(Bits b, const InnerDecoder& d)
+ : bits(b), decode(const_cast<InnerDecoder&>(d)) {}
+
+ // Decode if pack bit is set.
+ template<class T> Decoder& operator()(T& t) {
+ if (bits & 1)
+ decode(t);
+ else
+ t = T(); // FIXME aconway 2008-04-02: see below
+ bits >>= 1;
+ return *this;
+ }
+ Bits bits;
+ InnerDecoder& decode;
+ };
+
+ template <class Bits, class InnerDecoder>
+ static Decoder<Bits, InnerDecoder> decode(Bits b, const InnerDecoder& d) {
+ return Decoder<Bits, InnerDecoder>(b,d);
+ }
+
+ // FIXME aconway 2008-04-02: Incorrect packed semantics.
+ // Current implementation is:
+ // - decode value if packed bit set, else default initialize value.
+ // - encode always encode values
+ // - size count all values.
+ // Correct implementation:
+ // - optional value of type T is mapped to boost::optional<T>
+ // - decode value if packed bit set, else value=boost::none
+ // - PackedCodec::Encoder collect packing bits (1 unless == boost::none)
+ // Codec::Encoder optional skip if none
+ // - size: count only non-none values.
+ // Note we don't encode/decodde the pack bits themselves here, that
+ // happens in the Holder. Holders handle size, count & pack attributes.
+};
+
+
+}} // namespace qpid::amqp_0_10
+
+#endif /*!QPID_AMQP_0_10_PACKEDCODEC_H*/
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 4016302ae8..0b9ed4168b 100644
--- a/cpp/src/qpid/amqp_0_10/built_in_types.h
+++ b/cpp/src/qpid/amqp_0_10/built_in_types.h
@@ -35,16 +35,43 @@
/**@file Mapping from built-in AMQP types to C++ types */
+
namespace qpid {
namespace amqp_0_10 {
-// Fixed size types
-struct EmptyType { template <class S> void serialize(S&) {} };
-inline std::ostream& operator<<(std::ostream& o, const EmptyType&) { return o; }
+/** Wrapper that behaves like type T but is a distinct type for
+ * overloading purposes. Unique allows multiple distinc wrappers.
+ */
+template <class T, int Unique=0> struct Wrapper {
+ T value;
+ Wrapper() {}
+ Wrapper(const T& x) : value(x) {}
+ Wrapper& operator=(const T& x) { value=x; return *this; }
+ operator T&() { return value; }
+ operator const T&() const { return value; }
+ template <class S> void serialize(S& s) { s(value); }
+};
+
+template<class T>
+inline std::ostream& operator<<(std::ostream& o, const Wrapper<T>& w) {
+ return o << w.value;
+}
-struct Void : public EmptyType {};
-struct Bit : public EmptyType {};
+/** Void type */
+struct Void { template <class S> void serialize(S&) {} };
+inline std::ostream& operator<<(std::ostream& o, const Void&) { return o; }
+/** Bit type - bool value with no encoding. */
+struct Bit : Wrapper<bool> {
+ template <class S> void serialize(S& s) { s.split(*this); }
+ template <class S> void encode(S&) const {}
+ template <class S> void decode(S&) { value=true; }
+};
+inline std::ostream& operator<<(std::ostream& o, const Bit& b) {
+ return o << b.value;
+}
+
+// Fixed size types
typedef bool Boolean;
typedef char Char;
typedef int8_t Int8;
@@ -55,15 +82,7 @@ typedef uint8_t Uint8;
typedef uint16_t Uint16;
typedef uint32_t Uint32;
typedef uint64_t Uint64;
-
-// A struct to be distinct from the other 32 bit integrals.
-struct CharUtf32 {
- uint32_t value;
- CharUtf32(uint32_t n=0) : value(n) {}
- operator uint32_t&() { return value; }
- operator const uint32_t&() const { return value; }
- template <class S> void serialize(S& s) { s(value); }
-};
+typedef Wrapper<uint32_t> CharUtf32;
template <size_t N> struct Bin : public boost::array<char, N> {
template <class S> void serialize(S& s) { s.raw(this->begin(), this->size()); }
diff --git a/cpp/src/qpid/amqp_0_10/complex_types.h b/cpp/src/qpid/amqp_0_10/complex_types.h
index 864fed5ae8..d69a2be957 100644
--- a/cpp/src/qpid/amqp_0_10/complex_types.h
+++ b/cpp/src/qpid/amqp_0_10/complex_types.h
@@ -42,7 +42,7 @@ template <class V, class CV, class H> struct Visitable {
struct Command;
struct Control;
-struct Action { // Marker for commands & controls
+struct Action { // Base for commands & controls
virtual ~Action() {}
virtual Command* getCommand() { return 0; }
virtual Control* getControl() { return 0; }
@@ -53,6 +53,8 @@ struct Action { // Marker for commands & controls
virtual const Control* getControl() const {
return const_cast<Action*>(this)->getControl();
}
+ static const uint8_t SIZE=0;
+ static const uint8_t PACK=2;
};
struct CommandVisitor;
diff --git a/cpp/src/tests/serialize.cpp b/cpp/src/tests/serialize.cpp
index da71917cbd..1f576d6ee1 100644
--- a/cpp/src/tests/serialize.cpp
+++ b/cpp/src/tests/serialize.cpp
@@ -22,6 +22,7 @@
#include "unit_test.h"
#include "qpid/amqp_0_10/built_in_types.h"
#include "qpid/amqp_0_10/Codec.h"
+#include "qpid/amqp_0_10/PackedCodec.h"
#include "qpid/amqp_0_10/specification.h"
#include "qpid/amqp_0_10/ControlHolder.h"
#include "qpid/amqp_0_10/Frame.h"
@@ -170,7 +171,7 @@ BOOST_AUTO_TEST_CASE(testControlEncodeDecode) {
BOOST_CHECK_EQUAL(data.size(), Codec::size(h));
- Codec::Decode<string::iterator> decode(data.begin());
+ Codec::Decoder<string::iterator> decode(data.begin());
Control::Holder h2;
decode(h2);
@@ -226,4 +227,15 @@ BOOST_AUTO_TEST_CASE(testFrameEncodeDecode) {
}
+BOOST_AUTO_TEST_CASE(testPackedCodec) {
+ int i=-1, j=-1, k=-1, l=-1;
+ std::string data;
+ Codec::encode(std::back_inserter(data))(1)(3);
+ PackedCodec::decode(0x5, Codec::decode(data.begin()))(i)(j)(k)(l);
+ BOOST_CHECK_EQUAL(i, 1);
+ BOOST_CHECK_EQUAL(j, 0);
+ BOOST_CHECK_EQUAL(k, 3);
+ BOOST_CHECK_EQUAL(l, 0);
+}
+
QPID_AUTO_TEST_SUITE_END()