diff options
author | Alan Conway <aconway@apache.org> | 2008-04-03 13:27:07 +0000 |
---|---|---|
committer | Alan Conway <aconway@apache.org> | 2008-04-03 13:27:07 +0000 |
commit | bffa2485f1e33eb1a273d2b74149f0ccb0742c60 (patch) | |
tree | f116d78d4aab7699806882e2660bf81578b98ea7 /cpp/src | |
parent | 833239ec44ea87a1b619eef3de55afde56c7ee45 (diff) | |
download | qpid-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/src')
-rw-r--r-- | cpp/src/Makefile.am | 1 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/Codec.h | 76 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/PackedCodec.h | 79 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/built_in_types.h | 47 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/complex_types.h | 4 | ||||
-rw-r--r-- | cpp/src/tests/serialize.cpp | 14 |
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() |