From 775aa6924e2c432791fafd354751bb068129fe2e Mon Sep 17 00:00:00 2001 From: Alan Conway Date: Wed, 16 Apr 2008 15:33:51 +0000 Subject: Fix encoding for sized structs. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@648724 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/src/qpid/amqp_0_10/Array.h | 12 ++-- cpp/src/qpid/amqp_0_10/Command.h | 62 ++++++++++++++++++ cpp/src/qpid/amqp_0_10/CommmandPacker.h | 60 +++++++++++++++++ cpp/src/qpid/amqp_0_10/Control.h | 70 ++++++++++++++++++++ cpp/src/qpid/amqp_0_10/Header.h | 2 +- cpp/src/qpid/amqp_0_10/Packer.h | 42 ++++++++++-- cpp/src/qpid/amqp_0_10/Struct.h | 60 +++++++++++++++++ cpp/src/qpid/amqp_0_10/Struct32.cpp | 6 ++ cpp/src/qpid/amqp_0_10/Struct32.h | 13 ++-- cpp/src/qpid/amqp_0_10/UnknownStruct.h | 2 +- cpp/src/qpid/amqp_0_10/built_in_types.h | 4 +- cpp/src/qpid/amqp_0_10/complex_types.h | 113 -------------------------------- cpp/src/qpid/framing/SequenceSet.h | 22 ++++--- 13 files changed, 327 insertions(+), 141 deletions(-) create mode 100644 cpp/src/qpid/amqp_0_10/Command.h create mode 100644 cpp/src/qpid/amqp_0_10/CommmandPacker.h create mode 100644 cpp/src/qpid/amqp_0_10/Control.h create mode 100644 cpp/src/qpid/amqp_0_10/Struct.h delete mode 100644 cpp/src/qpid/amqp_0_10/complex_types.h (limited to 'cpp/src/qpid') diff --git a/cpp/src/qpid/amqp_0_10/Array.h b/cpp/src/qpid/amqp_0_10/Array.h index 8061a99b43..6e8a419df7 100644 --- a/cpp/src/qpid/amqp_0_10/Array.h +++ b/cpp/src/qpid/amqp_0_10/Array.h @@ -35,10 +35,11 @@ namespace amqp_0_10 { template class ArrayDomain : public std::vector { public: - template void serialize(S& s) { s.split(*this); s(this->begin(), this->end()); } + template void serialize(S& s) { s.split(*this); } template void encode(S& s) const { s(contentSize())(CodeForType::value)(uint32_t(this->size())); + s(this->begin(), this->end()); } void encode(Codec::Size& s) const { s.raw(0, contentSize() + 4/*size*/); } @@ -46,12 +47,13 @@ template class ArrayDomain : public std::vector { template void decode(S& s) { uint32_t size; uint8_t type; uint32_t count; s(size); - s.setLimit(size); + typename S::ScopedLimit l(s, size); s(type); if (type != CodeForType::value) throw InvalidArgumentException(QPID_MSG("Array domain expected type " << CodeForType::value << " but found " << type)); s(count); this->resize(count); + s(this->begin(), this->end()); } private: @@ -76,10 +78,11 @@ template<> class ArrayDomain : public std::vector { public: ArrayDomain(uint8_t type_=0) : type(type_) {} - template void serialize(S& s) { s.split(*this); s(this->begin(), this->end()); } + template void serialize(S& s) { s.split(*this); } template void encode(S& s) const { s(contentSize())(type)(uint32_t(this->size())); + s(this->begin(), this->end()); } void encode(Codec::Size& s) const { s.raw(0, contentSize() + 4/*size*/); } @@ -87,10 +90,11 @@ template<> class ArrayDomain : public std::vector { template void decode(S& s) { uint32_t size; uint32_t count; s(size); - s.setLimit(size); + typename S::ScopedLimit l(s, size); s(type)(count); this->clear(); this->resize(count, UnknownType(type)); + s(this->begin(), this->end()); } uint8_t getType() const { return type; } diff --git a/cpp/src/qpid/amqp_0_10/Command.h b/cpp/src/qpid/amqp_0_10/Command.h new file mode 100644 index 0000000000..0fe023e520 --- /dev/null +++ b/cpp/src/qpid/amqp_0_10/Command.h @@ -0,0 +1,62 @@ +#ifndef QPID_AMQP_0_10_COMMAND_H +#define QPID_AMQP_0_10_COMMAND_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 "Control.h" +#include "qpid/amqp_0_10/structs.h" + +namespace qpid { +namespace amqp_0_10 { + +struct CommandVisitor; +struct ConstCommandVisitor; +struct CommandHolder; +struct Command + : public Action, + public Visitable +{ + using Action::getCommand; + Command* getCommand() { return this; } + uint8_t getCode() const; + uint8_t getClassCode() const; + const char* getName() const; + const char* getClassName() const; + + session::Header sessionHeader; +}; + +std::ostream& operator<<(std::ostream&, const Command&); + +template +struct CommandPacker : Packer { + CommandPacker(T& t) : Packer(t) {} + + template void serialize(S& s) { + s(this->data.sessionHeader); + Packer::serialize(s); + } +}; + +}} // namespace qpid::amqp_0_10 + +#endif /*!QPID_AMQP_0_10_COMMAND_H*/ diff --git a/cpp/src/qpid/amqp_0_10/CommmandPacker.h b/cpp/src/qpid/amqp_0_10/CommmandPacker.h new file mode 100644 index 0000000000..51ebfe8186 --- /dev/null +++ b/cpp/src/qpid/amqp_0_10/CommmandPacker.h @@ -0,0 +1,60 @@ +#ifndef QPID_AMQP_0_10_COMMMANDPACKER_H +#define QPID_AMQP_0_10_COMMMANDPACKER_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/amqp_0_10/structs.h" + +namespace qpid { +namespace amqp_0_10 { + +/** + * Packer for commands - serialize session.header before pack bits. + */ +template +class CommmandPacker : public Packer +{ + public: + CommmandPacker(T& t) : Packer(t) {} + template void serialize(S& s) { s.split(*this); } + + template void encode(S& s) const { + s.sessionHeader( + Packer::encode(s); + } + + template void decode(S& s) { + Bits bits; + s.littleEnd(bits); + PackedDecoder decode(s, bits); + data.serialize(decode); + } + + + protected: + T& data; + + +}; +}} // namespace qpid::amqp_0_10 + +#endif /*!QPID_AMQP_0_10_COMMMANDPACKER_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Control.h b/cpp/src/qpid/amqp_0_10/Control.h new file mode 100644 index 0000000000..226f6f92a6 --- /dev/null +++ b/cpp/src/qpid/amqp_0_10/Control.h @@ -0,0 +1,70 @@ +#ifndef QPID_AMQP_0_10_CONTROL_H +#define QPID_AMQP_0_10_CONTROL_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 "Struct.h" + +namespace qpid { +namespace amqp_0_10 { + +struct Command; +struct Control; + +struct Action { // Base for commands & controls + virtual ~Action() {} + virtual Command* getCommand() { return 0; } + virtual Control* getControl() { return 0; } + + virtual const Command* getCommand() const { + return const_cast(this)->getCommand(); + } + virtual const Control* getControl() const { + return const_cast(this)->getControl(); + } + static const uint8_t SIZE=0; + static const uint8_t PACK=2; +}; + +struct ControlVisitor; +struct ConstControlVisitor; +struct ControlHolder; +struct Control + : public Action, + public Visitable +{ + using Action::getControl; + Control* getControl() { return this; } + uint8_t getCode() const; + uint8_t getClassCode() const; + const char* getName() const; + const char* getClassName() const; +}; +std::ostream& operator<<(std::ostream&, const Control&); + +template struct ActionType; +template <> struct ActionType { typedef Control type; }; +template <> struct ActionType { typedef Command type; }; + +}} // namespace qpid::amqp_0_10 + +#endif /*!QPID_AMQP_0_10_CONTROL_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Header.h b/cpp/src/qpid/amqp_0_10/Header.h index b3498a1c8c..0ce6ad9135 100644 --- a/cpp/src/qpid/amqp_0_10/Header.h +++ b/cpp/src/qpid/amqp_0_10/Header.h @@ -32,7 +32,7 @@ namespace amqp_0_10 { class Header : public std::vector { public: Header() {} - + template void serialize(S& s) { s.split(*this); } template void encode(S& s) const { s(this->begin(), this->end()); } template void decode(S& s); diff --git a/cpp/src/qpid/amqp_0_10/Packer.h b/cpp/src/qpid/amqp_0_10/Packer.h index 90d72408b5..c38e3a7efa 100644 --- a/cpp/src/qpid/amqp_0_10/Packer.h +++ b/cpp/src/qpid/amqp_0_10/Packer.h @@ -123,10 +123,10 @@ class PackedDecoder { }; /** Metafunction to compute type to contain pack bits. */ -template struct PackBitsType; -template <> struct PackBitsType<1> { typedef uint8_t type; }; -template <> struct PackBitsType<2> { typedef uint16_t type; }; -template <> struct PackBitsType<4> { typedef uint32_t type; }; +template struct UintOfSize; +template <> struct UintOfSize<1> { typedef uint8_t type; }; +template <> struct UintOfSize<2> { typedef uint16_t type; }; +template <> struct UintOfSize<4> { typedef uint32_t type; }; /** * Helper to serialize packed structs. @@ -134,7 +134,7 @@ template <> struct PackBitsType<4> { typedef uint32_t type; }; template class Packer { public: - typedef typename PackBitsType::type Bits; + typedef typename UintOfSize::type Bits; Packer(T& t) : data(t) {} @@ -154,10 +154,40 @@ template class Packer } - private: + protected: T& data; }; +template struct SizedPacker : public Packer { + typedef typename UintOfSize::type Size; + + SizedPacker(T& t) : Packer(t) {} + + template void serialize(S& s) { + s.split(*this); + } + + template void encode(S& s) const { + Codec::Size sizer; + this->data.serialize(sizer); + Size size=size_t(sizer)+T::PACK; // Size with pack bits. + s(size); + Packer::encode(s); + } + + template void decode(S& s) { + Size size; + s(size); + typename S::ScopedLimit l(s, size); + Packer::decode(s); + } + +}; + +template struct SizedPacker : public Packer { + SizedPacker(T& t) : Packer(t) {} +}; + }} // namespace qpid::amqp_0_10 diff --git a/cpp/src/qpid/amqp_0_10/Struct.h b/cpp/src/qpid/amqp_0_10/Struct.h new file mode 100644 index 0000000000..c0cea09c60 --- /dev/null +++ b/cpp/src/qpid/amqp_0_10/Struct.h @@ -0,0 +1,60 @@ +#ifndef QPID_AMQP_0_10_STRUCT_H +#define QPID_AMQP_0_10_STRUCT_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 "built_in_types.h" +#include + +namespace qpid { +namespace amqp_0_10 { + +// Base classes for complex types. + +template struct Visitable { + typedef V Visitor; + typedef CV ConstVisitor; + typedef H Holder; + + virtual ~Visitable() {} + virtual void accept(Visitor&) = 0; + virtual void accept(ConstVisitor&) const = 0; +}; + + +// Note: only coded structs inherit from Struct. +struct StructVisitor; +struct ConstStructVisitor; +struct StructHolder; +struct Struct + : public Visitable +{ + uint8_t getCode() const; + uint8_t getPack() const; + uint8_t getSize() const; + uint8_t getClassCode() const; +}; +std::ostream& operator<<(std::ostream&, const Struct&); + +}} // namespace qpid::amqp_0_10 + +#endif /*!QPID_AMQP_0_10_STRUCT_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Struct32.cpp b/cpp/src/qpid/amqp_0_10/Struct32.cpp index b36b118db3..541f02bcc4 100644 --- a/cpp/src/qpid/amqp_0_10/Struct32.cpp +++ b/cpp/src/qpid/amqp_0_10/Struct32.cpp @@ -23,6 +23,12 @@ namespace qpid { namespace amqp_0_10 { +Struct32::Struct32() { + // FIXME aconway 2008-04-16: this is only here to force a valid + // default-constructed Struct32 for serialize tests, clean up. + *this = in_place(); +} + std::ostream& operator<<(std::ostream& o, const Struct32& s) { return o << static_cast(s); } diff --git a/cpp/src/qpid/amqp_0_10/Struct32.h b/cpp/src/qpid/amqp_0_10/Struct32.h index 1f0c116f91..2ed73e0b4c 100644 --- a/cpp/src/qpid/amqp_0_10/Struct32.h +++ b/cpp/src/qpid/amqp_0_10/Struct32.h @@ -30,23 +30,24 @@ namespace amqp_0_10 { class Struct32 : public StructHolder { public: - Struct32() {} + Struct32(); template explicit Struct32(const T& t) : StructHolder(t) {} - template void serialize(S& s) { - s.split(*this); - StructHolder::serialize(s); - } + template void serialize(S& s) { s.split(*this); } + + using StructHolder::operator=; template void encode(S& s) const { s(contentSize()); + const_cast(this)->StructHolder::serialize(s); } template void decode(S& s) { uint32_t contentSz; s(contentSz); - s.setLimit(contentSz); + typename S::ScopedLimit l(s, contentSz); + StructHolder::serialize(s); } private: diff --git a/cpp/src/qpid/amqp_0_10/UnknownStruct.h b/cpp/src/qpid/amqp_0_10/UnknownStruct.h index 99ba170328..1c66d8e6af 100644 --- a/cpp/src/qpid/amqp_0_10/UnknownStruct.h +++ b/cpp/src/qpid/amqp_0_10/UnknownStruct.h @@ -21,7 +21,7 @@ * under the License. * */ -#include "qpid/amqp_0_10/complex_types.h" +#include "qpid/amqp_0_10/Struct.h" #include namespace qpid { 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 ddd31936fa..157696361d 100644 --- a/cpp/src/qpid/amqp_0_10/built_in_types.h +++ b/cpp/src/qpid/amqp_0_10/built_in_types.h @@ -23,6 +23,7 @@ #include "qpid/Serializer.h" #include "qpid/framing/SequenceNumber.h" +#include "qpid/framing/SequenceSet.h" #include "qpid/framing/Uuid.h" #include "qpid/sys/Time.h" #include "Decimal.h" @@ -135,6 +136,8 @@ typedef SerializableString Str16Utf16; typedef SerializableString Vbin32; +typedef framing::SequenceSet SequenceSet; + // Forward declare class types. class Map; class Struct32; @@ -145,7 +148,6 @@ typedef ArrayDomain Array; // FIXME aconway 2008-04-08: TODO struct ByteRanges { template void serialize(S&) {} }; -struct SequenceSet { template void serialize(S&) {} }; struct List { template void serialize(S&) {} }; // FIXME aconway 2008-03-10: dummy ostream operators diff --git a/cpp/src/qpid/amqp_0_10/complex_types.h b/cpp/src/qpid/amqp_0_10/complex_types.h deleted file mode 100644 index 5d327cc46e..0000000000 --- a/cpp/src/qpid/amqp_0_10/complex_types.h +++ /dev/null @@ -1,113 +0,0 @@ -#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. - * - */ - -#include "built_in_types.h" -#include - -namespace qpid { -namespace amqp_0_10 { - -// Base classes for complex types. - -template 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 Command; -struct Control; - -struct Action { // Base for commands & controls - virtual ~Action() {} - virtual Command* getCommand() { return 0; } - virtual Control* getControl() { return 0; } - - virtual const Command* getCommand() const { - return const_cast(this)->getCommand(); - } - virtual const Control* getControl() const { - return const_cast(this)->getControl(); - } - static const uint8_t SIZE=0; - static const uint8_t PACK=2; -}; - -struct CommandVisitor; -struct ConstCommandVisitor; -struct CommandHolder; -struct Command - : public Action, - public Visitable -{ - using Action::getCommand; - Command* getCommand() { return this; } - uint8_t getCode() const; - uint8_t getClassCode() const; - const char* getName() const; - const char* getClassName() const; -}; -std::ostream& operator<<(std::ostream&, const Command&); - -struct ControlVisitor; -struct ConstControlVisitor; -struct ControlHolder; -struct Control - : public Action, - public Visitable -{ - using Action::getControl; - Control* getControl() { return this; } - uint8_t getCode() const; - uint8_t getClassCode() const; - const char* getName() const; - const char* getClassName() const; -}; -std::ostream& operator<<(std::ostream&, const Control&); - -// Note: only coded structs inherit from Struct. -struct StructVisitor; -struct ConstStructVisitor; -struct StructHolder; -struct Struct - : public Visitable -{ - uint8_t getCode() const; - uint8_t getPack() const; - uint8_t getSize() const; - uint8_t getClassCode() const; -}; -std::ostream& operator<<(std::ostream&, const Struct&); - -template struct ActionType; -template <> struct ActionType { typedef Control type; }; -template <> struct ActionType { typedef Command type; }; - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_COMPLEX_TYPES_H*/ diff --git a/cpp/src/qpid/framing/SequenceSet.h b/cpp/src/qpid/framing/SequenceSet.h index 2f34cb5cba..226062f35d 100644 --- a/cpp/src/qpid/framing/SequenceSet.h +++ b/cpp/src/qpid/framing/SequenceSet.h @@ -21,35 +21,35 @@ #ifndef _framing_SequenceSet_h #define _framing_SequenceSet_h -#include -#include #include "amqp_types.h" #include "Buffer.h" #include "SequenceNumber.h" #include "qpid/framing/reply_exceptions.h" +#include +#include namespace qpid { namespace framing { -class SequenceSet -{ - struct Range - { +class SequenceSet { + struct Range { SequenceNumber start; SequenceNumber end; - Range(SequenceNumber s, SequenceNumber e); + Range(SequenceNumber s=0, SequenceNumber e=0); bool contains(SequenceNumber i) const; bool intersects(const Range& r) const; bool merge(const Range& r); bool mergeable(const SequenceNumber& r) const; void encode(Buffer& buffer) const; + + template void serialize(S& s) { s(start)(end); } }; typedef std::list Ranges; Ranges ranges; -public: + public: SequenceSet() {} SequenceSet(const SequenceNumber& s) { add(s); } @@ -76,7 +76,11 @@ public: } } - friend std::ostream& operator<<(std::ostream&, const SequenceSet&); + template void serialize(S& s) { s.split(*this); s(ranges.begin(), ranges.end()); } + template void encode(S& s) const { s(uint16_t(ranges.size()*sizeof(Range))); } + template void decode(S& s) { uint16_t sz; s(sz); ranges.resize(sz/sizeof(Range)); } + + friend std::ostream& operator<<(std::ostream&, const SequenceSet&); }; -- cgit v1.2.1