diff options
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/Makefile.am | 5 | ||||
-rw-r--r-- | cpp/src/qpid/Serializer.h | 43 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/Codec.h | 42 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/Holder.h | 62 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/apply.h | 29 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/built_in_types.h | 33 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/complex_types.cpp | 65 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/complex_types.h | 79 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/helpers.cpp | 33 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/helpers.h | 81 | ||||
-rw-r--r-- | cpp/src/qpid/framing/AMQBody.h | 3 | ||||
-rw-r--r-- | cpp/src/tests/apply.cpp | 11 | ||||
-rw-r--r-- | cpp/src/tests/serialize.cpp | 56 |
13 files changed, 374 insertions, 168 deletions
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am index 080260be02..f15f8d7a91 100644 --- a/cpp/src/Makefile.am +++ b/cpp/src/Makefile.am @@ -103,8 +103,10 @@ libqpidcommon_la_LIBADD = \ libqpidcommon_la_SOURCES = \ $(rgen_common_cpp) \ $(platform_src) \ - qpid/amqp_0_10/helpers.cpp \ qpid/amqp_0_10/built_in_types.h \ + qpid/amqp_0_10/complex_types.h \ + qpid/amqp_0_10/complex_types.cpp \ + qpid/amqp_0_10/Holder.h \ qpid/amqp_0_10/Codec.h \ qpid/amqp_0_10/Decimal.h \ qpid/Serializer.h \ @@ -254,7 +256,6 @@ libqpidclient_la_SOURCES = \ nobase_include_HEADERS = \ $(platform_hdr) \ - qpid/amqp_0_10/helpers.h \ qpid/amqp_0_10/apply.h \ qpid/assert.h \ qpid/DataDir.h \ diff --git a/cpp/src/qpid/Serializer.h b/cpp/src/qpid/Serializer.h index a7194c5095..34b95d3ffd 100644 --- a/cpp/src/qpid/Serializer.h +++ b/cpp/src/qpid/Serializer.h @@ -22,37 +22,60 @@ * */ -#include <boost/type_traits/remove_const.hpp> #include <boost/utility/enable_if.hpp> -#include <boost/type_traits/is_const.hpp> +#include <boost/static_assert.hpp> #include <boost/type_traits/is_class.hpp> -#include <boost/type_traits/add_const.hpp> #include <algorithm> namespace qpid { -/** - * Base class for serializers. - */ +// FIXME aconway 2008-03-03: Doc - esp decoding template <class Derived> class Serializer { public: + typedef Serializer result_type; // unary functor requirement. + + static const bool IS_DECODER=false; + + /** Generic handler for class objects, call serialize() */ template <class T> typename boost::enable_if<boost::is_class<T>, Derived&>::type operator()(T& t) { - // const_cast so we don't need 2 serialize() members for every class. - const_cast<typename boost::remove_const<T>::type&>(t).serialize(self()); + t.serialize(self()); return self(); } - template <class Iter> Derived& iterate(Iter begin, Iter end) { - std::for_each(begin, end, self()); + /** Generic handler for const class objects, call serialize() */ + template <class T> + typename boost::enable_if<boost::is_class<T>, Derived&>::type + operator()(const T& t) { + assert(!Derived::IS_DECODER); // We won't modify the value. + // const_cast so we don't need 2 serialize() members for every class. + const_cast<T&>(t).serialize(self()); return self(); } + template <class T, bool=false> struct Split { + Split(Derived& s, T& t) { t.encode(s); } + }; + + template <class T> struct Split<T,true> { + Split(Derived& s, T& t) { t.decode(s); } + }; + /** + * Called by classes that want to receive separate + * encode()/decode() calls. + */ + template <class T> + void split(T& t) { Split<T, Derived::IS_DECODER>(self(),t); } + private: Derived& self() { return *static_cast<Derived*>(this); } }; + + + + } // namespace qpid #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 acfc1e9c81..a36004753a 100644 --- a/cpp/src/qpid/amqp_0_10/Codec.h +++ b/cpp/src/qpid/amqp_0_10/Codec.h @@ -28,15 +28,14 @@ #include <boost/type_traits/is_float.hpp> #include <boost/type_traits/is_arithmetic.hpp> #include <boost/detail/endian.hpp> -#include <boost/ref.hpp> namespace qpid { namespace amqp_0_10 { /** * AMQP 0-10 encoding and decoding. */ -class Codec { - public: +struct Codec { // FIXME aconway 2008-02-29: drop this wrapper? + /** Encode to an output byte iterator */ template <class OutIter> class Encode : public Serializer<Encode<OutIter> > { @@ -58,6 +57,11 @@ class Codec { typename boost::enable_if<boost::is_float<T>, Encode&>::type operator()(const T& x) { raw(&x, sizeof(x)); return *this; } + template <class Iter> Encode& operator()(Iter begin, Iter end) { + std::for_each(begin, end, *this); + return *this; + } + void raw(const void* p, size_t n) { std::copy((const char*)p, (const char*)p+n, out); } @@ -70,6 +74,8 @@ class Codec { class Decode : public Serializer<Decode<InIter> > { public: Decode(InIter i) : in(i) {} + + static const bool IS_DECODER=true; using Serializer<Decode<InIter> >::operator(); @@ -94,6 +100,11 @@ class Codec { return *this; } + template <class Iter> Decode& operator()(Iter begin, Iter end) { + std::for_each(begin, end, *this); + return *this; + } + void raw(void *p, size_t n) { // FIXME aconway 2008-02-29: requires random access iterator, // does this optimize to memcpy? Is there a better way? @@ -124,30 +135,27 @@ class Codec { return *this; } + template <class Iter> + Size& operator()(const Iter& a, const Iter& b) { + size += (b-a)*sizeof(*a); + return *this; + } + void raw(const void*, size_t n){ size += n; } private: size_t size; }; - template <class Out, class T> - static void encode(Out o, const T& x) { - Encode<Out> encode(o); - encode(x); + template <class OutIter> static Decode<OutIter> decode(const OutIter &i) { + return Decode<OutIter>(i); } - template <class In, class T> - static void decode(In i, T& x) { - Decode<In> decode(i); - decode(x); + template <class InIter> static Encode<InIter> encode(InIter i) { + return Encode<InIter>(i); } - template <class T> - static size_t size(const T& x) { - Size sz; - sz(x); - return sz; - } + template <class T> static size_t size(const T& x) { return Size()(x); } private: template <class T> static inline void endianize(T& value) { diff --git a/cpp/src/qpid/amqp_0_10/Holder.h b/cpp/src/qpid/amqp_0_10/Holder.h new file mode 100644 index 0000000000..76f8aa52de --- /dev/null +++ b/cpp/src/qpid/amqp_0_10/Holder.h @@ -0,0 +1,62 @@ +#ifndef QPID_AMQP_0_10_HOLDER_H +#define QPID_AMQP_0_10_HOLDER_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 "qpid/framing/Blob.h" +#include "apply.h" + +namespace qpid { +namespace amqp_0_10 { + +template <class DerivedHolder, class BaseHeld, size_t Size> +struct Holder : public framing::Blob<Size, BaseHeld> { + + typedef framing::Blob<Size, BaseHeld> Base; + + Holder() {} + template <class T> Holder(const T& value) : Base(value) {} + + using Base::operator=; + + uint8_t getCode() const { return this->get()->getCode(); } + uint8_t getClassCode() const { return this->get()->getClassCode(); } + + template <class S> void encode(S& s) { + s(getClassCode())(getCode()); + } + + template <class S> void decode(S& s) { + uint8_t code, classCode; + s(classCode)(code); + static_cast<DerivedHolder*>(this)->set(classCode, code); + } + + template <class S> void serialize(S& s) { + s.split(*this); + apply(s, *this->get()); + } +}; + + +}} // namespace qpid::amqp_0_10 + +#endif /*!QPID_AMQP_0_10_HOLDER_H*/ diff --git a/cpp/src/qpid/amqp_0_10/apply.h b/cpp/src/qpid/amqp_0_10/apply.h index e1bd9c3aa6..05b7669322 100644 --- a/cpp/src/qpid/amqp_0_10/apply.h +++ b/cpp/src/qpid/amqp_0_10/apply.h @@ -31,7 +31,8 @@ template <class F, class R=typename F::result_type> struct FunctionAndResult { boost::optional<R> result; FunctionAndResult() : functor(0) {} - template <class T> void invoke(T t) { result=(*functor)(t); } + template <class T> void invoke(T& t) { result=(*functor)(t); } + template <class T> void invoke(const T& t) { result=(*functor)(t); } R getResult() { return *result; } }; @@ -40,17 +41,23 @@ template <class F> struct FunctionAndResult<F, void> { F* functor; FunctionAndResult() : functor(0) {} - template <class T> void invoke(T t) { (*functor)(t); } + template <class T> void invoke(T& t) { (*functor)(t); } void getResult() {} }; -template <class V, class F> -struct ApplyVisitorBase : public V, public FunctionAndResult<F> { - using V::visit; +// Metafunction returning correct abstract visitor for Visitable type. +template <class Visitable> struct VisitorType { + typedef typename Visitable::Visitor type; }; +template <class Visitable> struct VisitorType<const Visitable> { + typedef typename Visitable::ConstVisitor type; +}; + +template <class Visitor, class F> +struct ApplyVisitorBase : public Visitor, public FunctionAndResult<F> {}; // Specialize for each visitor type -template <class V, class F> struct ApplyVisitor; +template <class Visitable, class F> struct ApplyVisitor; /** Apply a functor to a visitable object. * The functor can have operator() overloads for each visitable type @@ -58,7 +65,7 @@ template <class V, class F> struct ApplyVisitor; */ template <class F, class Visitable> typename F::result_type apply(F& functor, Visitable& visitable) { - ApplyVisitor<typename Visitable::Visitor, F> visitor; + ApplyVisitor<typename VisitorType<Visitable>::type, F> visitor; visitor.functor=&functor; visitable.accept(visitor); return visitor.getResult(); @@ -66,12 +73,18 @@ typename F::result_type apply(F& functor, Visitable& visitable) { template <class F, class Visitable> typename F::result_type apply(const F& functor, Visitable& visitable) { - ApplyVisitor<typename Visitable::Visitor, const F> visitor; + ApplyVisitor<typename VisitorType<Visitable>::type, const F> visitor; visitor.functor=&functor; visitable.accept(visitor); return visitor.getResult(); } +template <class R, bool Const=false> struct ApplyFunctor { + typedef R result_type; + static const bool IS_CONST=Const; +}; +template <class R> struct ConstApplyFunctor : public ApplyFunctor<R, true> {}; + }} // namespace qpid::amqp_0_10 #endif /*!QPID_AMQP_0_10_APPLY_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 13bcdf862e..6188e259f0 100644 --- a/cpp/src/qpid/amqp_0_10/built_in_types.h +++ b/cpp/src/qpid/amqp_0_10/built_in_types.h @@ -82,7 +82,7 @@ template <class T, class SizeType> struct SerializableString : public std::basic_string<T> { using std::basic_string<T>::operator=; template <class S> void serialize(S& s) { - s(SizeType(this->size())).iterate(this->begin(), this->end()); + s(SizeType(this->size()))(this->begin(), this->end()); } }; @@ -107,16 +107,29 @@ typedef SerializableString<Uint16, Uint16> Str16Utf16; typedef SerializableString<Uint8, Uint32> Vbin32; // FIXME aconway 2008-02-26: Unimplemented types: -template <class T> struct Array : public std::vector<T> {}; -struct ByteRanges {}; -struct SequenceSet {}; -struct Map {}; -struct List {}; -struct Struct32 {}; +template <class T> struct Array : public std::vector<T> { template <class S> void serialize(S&) {} }; +struct ByteRanges { template <class S> void serialize(S&) {} }; +struct SequenceSet { template <class S> void serialize(S&) {} }; +struct Map { template <class S> void serialize(S&) {} }; +struct List { template <class S> void serialize(S&) {} }; +struct Struct32 { template <class S> void serialize(S&) {} }; + +// Serializable enum support +template <class E, class Store> struct Enum { + Store value; + Enum() {} + Enum(E v) : value(v) {} + Enum(Store v) : value(v) {} + Enum& operator=(E v) { value=v; return *this; } + Enum& operator=(Store v) { value=v; return *this; } + operator E() const { return value; } + operator Store() const { return value; } + template <class S> void serialize(S& s) { s(value); } +}; -// Top level enum definitions. -enum SegmentType { CONTROL, COMMAND, HEADER, BODY }; +enum SegmentTypeEnum { CONTROL, COMMAND, HEADER, BODY }; +typedef Enum<SegmentTypeEnum, uint8_t> SegmentType; }} // namespace qpid::amqp_0_10 -#endif /*!QPID_AMQP_0_10_BUILT_IN_TYPES_H*/ +#endif diff --git a/cpp/src/qpid/amqp_0_10/complex_types.cpp b/cpp/src/qpid/amqp_0_10/complex_types.cpp new file mode 100644 index 0000000000..0960db469d --- /dev/null +++ b/cpp/src/qpid/amqp_0_10/complex_types.cpp @@ -0,0 +1,65 @@ +/* + * + * 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 "qpid/amqp_0_10/ApplyCommand.h" +#include "qpid/amqp_0_10/ApplyControl.h" +// FIXME aconway 2008-03-04: #include "qpid/amqp_0_10/ApplyStruct.h" +#include "qpid/amqp_0_10/apply.h" + +namespace qpid { +namespace amqp_0_10 { +// Functors for getting static values from a visitable base type. + +#define QPID_STATIC_VALUE_GETTER(NAME, TYPE, VALUE) \ + struct NAME : public ConstApplyFunctor<TYPE> { \ + template <class T> TYPE operator()(const T&) const { return T::VALUE; }\ + } + +QPID_STATIC_VALUE_GETTER(GetCode, uint8_t, CODE); +QPID_STATIC_VALUE_GETTER(GetSize, uint8_t, SIZE); +QPID_STATIC_VALUE_GETTER(GetPack, uint8_t, PACK); +QPID_STATIC_VALUE_GETTER(GetClassCode, uint8_t, CLASS_CODE); +QPID_STATIC_VALUE_GETTER(GetName, const char*, NAME); +QPID_STATIC_VALUE_GETTER(GetClassName, const char*, CLASS_NAME); + + +uint8_t Command::getCode() const { return apply(GetCode(), *this); } +uint8_t Command::getClassCode() const { return apply(GetClassCode(), *this); } +const char* Command::getName() const { return apply(GetName(), *this); } +const char* Command::getClassName() const { return apply(GetClassName(), *this); } + +uint8_t Control::getCode() const { return apply(GetCode(), *this); } +uint8_t Control::getClassCode() const { return apply(GetClassCode(), *this); } +const char* Control::getName() const { return apply(GetName(), *this); } +const char* Control::getClassName() const { return apply(GetClassName(), *this); } + +// FIXME aconway 2008-03-04: Struct visitors +// uint8_t Struct::getCode() const { return apply(GetCode(), *this); } +// uint8_t Struct::getPack() const { return apply(GetPack(), *this); } +// uint8_t Struct::getSize() const { return apply(GetSize(), *this); } +// uint8_t Struct::getClassCode() const { return apply(GetClassCode(), *this); } +uint8_t Struct::getCode() const { assert(0); return 0; } +uint8_t Struct::getPack() const { assert(0); return 0; } +uint8_t Struct::getSize() const { assert(0); return 0; } +uint8_t Struct::getClassCode() const { assert(0); return 0; } + +}} // namespace qpid::amqp_0_10 + diff --git a/cpp/src/qpid/amqp_0_10/complex_types.h b/cpp/src/qpid/amqp_0_10/complex_types.h new file mode 100644 index 0000000000..f4810ba2d7 --- /dev/null +++ b/cpp/src/qpid/amqp_0_10/complex_types.h @@ -0,0 +1,79 @@ +#ifndef QPID_AMQP_0_10_COMPLEX_TYPES_H +#define QPID_AMQP_0_10_COMPLEX_TYPES_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. + * + */ + +namespace qpid { +namespace amqp_0_10 { + +// Base classes for complex types. + +template <class V, class CV, class H> struct Visitable { + typedef V Visitor; + typedef CV ConstVisitor; + typedef H Holder; + + virtual ~Visitable() {} + virtual void accept(Visitor&) = 0; + virtual void accept(ConstVisitor&) const = 0; +}; + +struct CommandVisitor; +struct ConstCommandVisitor; +struct CommandHolder; +struct Command + : public Visitable<CommandVisitor, ConstCommandVisitor, CommandHolder> +{ + uint8_t getCode() const; + uint8_t getClassCode() const; + const char* getName() const; + const char* getClassName() const; +}; + +struct ControlVisitor; +struct ConstControlVisitor; +struct ControlHolder; +struct Control + : public Visitable<ControlVisitor, ConstControlVisitor, ControlHolder> +{ + uint8_t getCode() const; + uint8_t getClassCode() const; + const char* getName() const; + const char* getClassName() const; +}; + +struct StructVisitor; +struct ConstStructVisitor; +struct StructHolder; +struct Struct + : public Visitable<StructVisitor, ConstStructVisitor, StructHolder> +{ + uint8_t getCode() const; + uint8_t getPack() const; + uint8_t getSize() const; + uint8_t getClassCode() const; +}; + + +}} // namespace qpid::amqp_0_10 + +#endif /*!QPID_AMQP_0_10_COMPLEX_TYPES_H*/ diff --git a/cpp/src/qpid/amqp_0_10/helpers.cpp b/cpp/src/qpid/amqp_0_10/helpers.cpp deleted file mode 100644 index 457abe2d5f..0000000000 --- a/cpp/src/qpid/amqp_0_10/helpers.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * - * 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 "helpers.h" -#include "qpid/amqp_0_10/CommandVisitor.h" -#include "qpid/amqp_0_10/ControlVisitor.h" -#include "qpid/amqp_0_10/StructVisitor.h" - -namespace qpid { -namespace amqp_0_10 { - -Control::~Control() {} -Command::~Command() {} -Struct::~Struct() {} - -}} // namespace qpid::amqp_0_10 diff --git a/cpp/src/qpid/amqp_0_10/helpers.h b/cpp/src/qpid/amqp_0_10/helpers.h deleted file mode 100644 index b5150cd10f..0000000000 --- a/cpp/src/qpid/amqp_0_10/helpers.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef QPID_AMQP_0_10_HELPERS_H -#define QPID_AMQP_0_10_HELPERS_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 -n * "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 "qpid/amqp_0_10/built_in_types.h" -#include <string> - -namespace qpid { -namespace amqp_0_10 { - -// Look up names by code -const char* getClassName(uint8_t code); -const char* getCommandName(uint8_t classCode, uint8_t code); -const char* getControlName(uint8_t classCode, uint8_t code); -const char* getStructName(uint8_t classCode, uint8_t code); - -struct Command { - static const int SEGMENT_TYPE=COMMAND; - virtual ~Command(); - struct Visitor; - virtual void accept(Visitor&) const = 0; -}; - -struct Control { - static const int SEGMENT_TYPE=CONTROL; - virtual ~Control(); - struct Visitor; - virtual void accept(Visitor&) const = 0; -}; - -// Struct -struct Struct { - virtual ~Struct(); - struct Visitor; - virtual void accept(Visitor&) const = 0; -}; - -template <class SizeType, bool Coded, uint8_t Code, uint8_t Pack> -struct SerializableStruct : public Struct { - static const uint8_t SIZE=sizeof(SizeType); - static const bool CODED=Coded; - static const uint8_t CODE=Code; - static const uint8_t PACK; - // TODO aconway 2008-02-29: handle common encoding/decoding/size - // for structs. Support for packing. -}; - - -/** Base class for generated enum domains. - * Enums map to classes for type safety and to provide separate namespaces - * for clashing values. - */ -struct Enum { - int value; - Enum(int v=0) : value(v) {} - operator int() const { return value; } - template <class S> void serialize(S &s) { s(value); } -}; - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_HELPERS_H*/ diff --git a/cpp/src/qpid/framing/AMQBody.h b/cpp/src/qpid/framing/AMQBody.h index 73c462a427..925f4c46ac 100644 --- a/cpp/src/qpid/framing/AMQBody.h +++ b/cpp/src/qpid/framing/AMQBody.h @@ -22,7 +22,8 @@ * */ #include "qpid/framing/amqp_types.h" -#include "qpid/amqp_0_10/helpers.h" +#include "qpid/amqp_0_10/built_in_types.h" +#include "qpid/amqp_0_10/complex_types.h" #include <ostream> diff --git a/cpp/src/tests/apply.cpp b/cpp/src/tests/apply.cpp index 553026a35c..1b66d8e3b4 100644 --- a/cpp/src/tests/apply.cpp +++ b/cpp/src/tests/apply.cpp @@ -26,11 +26,15 @@ QPID_AUTO_TEST_SUITE(VisitorTestSuite) using namespace qpid::amqp_0_10; -struct GetCode { - typedef uint8_t result_type; +struct GetCode : public ConstApplyFunctor<uint8_t> { template <class T> uint8_t operator()(const T&) const { return T::CODE; } }; +struct SetChannelMax : ApplyFunctor<void> { + template <class T> void operator()(T&) const { BOOST_FAIL(""); } + void operator()(connection::Tune& t) const { t.channelMax=42; } +}; + struct TestFunctor { typedef bool result_type; bool operator()(const connection::Tune& tune) { @@ -57,6 +61,9 @@ BOOST_AUTO_TEST_CASE(testApply) { connection::Start start; p = &start; BOOST_CHECK(!apply(tf, *p)); + + apply(SetChannelMax(), tune); + BOOST_CHECK_EQUAL(tune.channelMax, 42); } struct VoidTestFunctor { diff --git a/cpp/src/tests/serialize.cpp b/cpp/src/tests/serialize.cpp index 8de2d4ca58..9eaf78ab78 100644 --- a/cpp/src/tests/serialize.cpp +++ b/cpp/src/tests/serialize.cpp @@ -22,6 +22,9 @@ #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/specification.h" +#include "qpid/amqp_0_10/ControlHolder.h" + #include <boost/test/test_case_template.hpp> #include <boost/type_traits/is_arithmetic.hpp> #include <boost/utility/enable_if.hpp> @@ -62,6 +65,7 @@ QPID_AUTO_TEST_SUITE(SerializeTestSuite) using namespace std; namespace mpl=boost::mpl; using namespace qpid::amqp_0_10; +using qpid::framing::in_place; template <class A, class B> struct concat2 { typedef typename mpl::copy<B, typename mpl::back_inserter<A> >::type type; }; template <class A, class B, class C> struct concat3 { typedef typename concat2<A, typename concat2<B, C>::type>::type type; }; @@ -82,14 +86,14 @@ BOOST_AUTO_TEST_CASE(testNetworkByteOrder) { string data; uint32_t l = 0x11223344; - Codec::encode(std::back_inserter(data), l); + Codec::encode(std::back_inserter(data))(l); uint32_t enc=reinterpret_cast<const uint32_t&>(*data.data()); uint32_t l2 = ntohl(enc); BOOST_CHECK_EQUAL(l, l2); data.clear(); uint16_t s = 0x1122; - Codec::encode(std::back_inserter(data), s); + Codec::encode(std::back_inserter(data))(s); uint32_t s2 = ntohs(*reinterpret_cast<const uint32_t*>(data.data())); BOOST_CHECK_EQUAL(s, s2); } @@ -116,14 +120,58 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(testEncodeDecode, T, AllTypes) string data; T t; testValue(t); - Codec::encode(std::back_inserter(data), t); + Codec::encode(std::back_inserter(data))(t); BOOST_CHECK_EQUAL(Codec::size(t), data.size()); T t2; - Codec::decode(data.begin(), t2); + Codec::decode(data.begin())(t2); BOOST_CHECK_EQUAL(t,t2); } +struct TestMe { + bool encoded, decoded; + char value; + TestMe(char v) : encoded(), decoded(), value(v) {} + template <class S> void encode(S& s) { encoded=true; s(value); } + template <class S> void decode(S& s) { decoded=true; s(value); } + template <class S> void serialize(S& s) { s.split(*this); } +}; + +BOOST_AUTO_TEST_CASE(testSplit) { + string data; + TestMe t1('x'); + Codec::encode(std::back_inserter(data))(t1); + BOOST_CHECK(t1.encoded); + BOOST_CHECK(!t1.decoded); + BOOST_CHECK_EQUAL(data, "x"); + + TestMe t2('y'); + Codec::decode(data.begin())(t2); + BOOST_CHECK(!t2.encoded); + BOOST_CHECK(t2.decoded); + BOOST_CHECK_EQUAL(t2.value, 'x'); +} + +BOOST_AUTO_TEST_CASE(testControlEncodeDecode) { + string data; + Control::Holder h(in_place<connection::Tune>(1,2,3,4)); + Codec::encode(std::back_inserter(data))(h); + + BOOST_CHECK_EQUAL(data.size(), Codec::size(h)); + + Codec::Decode<string::iterator> decode(data.begin()); + Control::Holder h2; + decode(h2); + + BOOST_REQUIRE(h2.get()); + BOOST_CHECK_EQUAL(h2.get()->getClassCode(), connection::CODE); + BOOST_CHECK_EQUAL(h2.get()->getCode(), uint8_t(connection::Tune::CODE)); + connection::Tune& tune=static_cast<connection::Tune&>(*h2.get()); + BOOST_CHECK_EQUAL(tune.channelMax, 1u); + BOOST_CHECK_EQUAL(tune.maxFrameSize, 2u); + BOOST_CHECK_EQUAL(tune.heartbeatMin, 3u); + BOOST_CHECK_EQUAL(tune.heartbeatMax, 4u); +} QPID_AUTO_TEST_SUITE_END() |