From cc55340d5d7cf74d045f5f7608aa03c5fa7a4675 Mon Sep 17 00:00:00 2001 From: Alan Conway Date: Thu, 21 Feb 2008 02:58:37 +0000 Subject: AMQP 0-10 type system: - new lightweight templated serialization framework - all fixed-size built-in types tested and working - all vbin & str types implemented, tests disabled need to fix encoding. The following types remain to be implemented: byte-ranges 2 byte ranges within a 64-bit payload sequence-set 2 ranged set representation map 0xa8 4 a mapping of keys to typed values list 0xa9 4 a series of consecutive type-value pairs array 0xaa 4 a defined length collection of values of a single type struct32 0xab 4 a coded struct with a 32-bit size git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@629679 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/src/qpid/Serializer.h | 109 +++++++++++++++++++ cpp/src/qpid/amqp_0_10/Codec.h | 187 ++++++++++++++++++++++++++++++++ cpp/src/qpid/amqp_0_10/Decimal.h | 52 +++++++++ cpp/src/qpid/amqp_0_10/built_in_types.h | 103 ++++++++++++++++++ cpp/src/qpid/framing/SequenceNumber.h | 2 + cpp/src/qpid/framing/Uuid.h | 4 + cpp/src/qpid/sys/Time.h | 3 + 7 files changed, 460 insertions(+) create mode 100644 cpp/src/qpid/Serializer.h create mode 100644 cpp/src/qpid/amqp_0_10/Codec.h create mode 100644 cpp/src/qpid/amqp_0_10/Decimal.h create mode 100644 cpp/src/qpid/amqp_0_10/built_in_types.h (limited to 'cpp/src/qpid') diff --git a/cpp/src/qpid/Serializer.h b/cpp/src/qpid/Serializer.h new file mode 100644 index 0000000000..a2fbf944ae --- /dev/null +++ b/cpp/src/qpid/Serializer.h @@ -0,0 +1,109 @@ +#ifndef QPID_SERIALIZERBASE_H +#define QPID_SERIALIZERBASE_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 +#include +#include +#include + +namespace qpid { + +/** + * Base template for serializers, provides generic serialization for + * conmpound types and common encode/decode/size functions. + * + * Derived template must provide + * - Derived& op()(T) for primitive types. + * - Derived& raw(void*, size_t) for raw binary data + * - Derived& byte(char) for single bytes. + * + * Derived templatse may override any of the functions provided by + * this base class. + * + * This class provides templates to break down compound types + * into primitive types and delegate to the derived class. + * + */ +template class Serializer { + public: + + /** Call T::serialize() for classes that have their own serialize function */ + template + typename boost::enable_if, Derived>::type + operator()(T& t) { t.serialize(self()); return self(); } + + template + Derived& operator()(boost::array& a) { + std::for_each(a.begin(), a.end(), self()); + return self(); + } + + Derived& operator()(char& x) { return self().byte((char&)x); } + Derived& operator()(int8_t& x) { return self().byte((char&)x); } + Derived& operator()(uint8_t& x) { return self().byte((char&)x); } + + protected: + template Derived& raw(T& t) { + return self().raw(&t, sizeof(T)); + } + + private: + Derived& self() { return *static_cast(this); } +}; + +/** Like Serializer but does not modify the values passed to it. */ +template class ConstSerializer { + public: + template + typename boost::enable_if, Derived>::type + operator()(const T& t) { + // Const cast so we don't have to write 2 serialize() functions + // for every class. + const_cast(t).serialize(self()); + return self(); + } + + template + Derived& operator()(const boost::array& a) { + std::for_each(a.begin(), a.end(), self()); + return self(); + } + + Derived& operator()(char x) { return self().byte(x); } + Derived& operator()(int8_t x) { return self().byte(x); } + Derived& operator()(uint8_t x) { return self().byte(x); } + + protected: + template Derived& raw(const T& t) { + return self().raw(&t, sizeof(T)); + } + + private: + Derived& self() { return *static_cast(this); } +}; + + +} // namespace qpid + +#endif /*!QPID_SERIALIZERBASE_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Codec.h b/cpp/src/qpid/amqp_0_10/Codec.h new file mode 100644 index 0000000000..e7f35e9288 --- /dev/null +++ b/cpp/src/qpid/amqp_0_10/Codec.h @@ -0,0 +1,187 @@ +#ifndef QPID_AMQP_0_10_CODEC_H +#define QPID_AMQP_0_10_CODEC_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 "qpid/Serializer.h" +#include +#include +#include +#include +#include + +namespace qpid { +namespace amqp_0_10 { + +/** + * AMQP 0-10 encoding and decoding. + */ +struct Codec +{ + template + static inline void endianize(T& value) { + +#ifdef BOOST_LITTLE_ENDIAN + std::reverse((char*)&value, (char*)&value+sizeof(value)); +#else + (void)value; // Avoid unused var warnings. +#endif + } + static inline void endianize(char&) {} + static inline void endianize(uint8_t&) {} + static inline void endianize(int8_t&) {} + + + template struct Encode : public ConstSerializer > { + Out out; + + Encode(Out o) : out(o) {} + + using ConstSerializer >::operator(); + using ConstSerializer >::raw; + + template + typename boost::enable_if, Encode&>::type + operator()(const T& x) { T xx(x); endianize(xx); return raw(xx); } + + // FIXME aconway 2008-02-20: correct float encoading + template + typename boost::enable_if, Encode&>::type + operator()(const T& x) { return raw(x); } + + + template + Encode& operator()(const CodableString& str) { + (*this)(SizeType(str.size())); + std::for_each(str.begin(), str.end(), *this); + return *this; + } + + private: + friend class ConstSerializer >; + + Encode& raw(const void* vp, size_t s) { + char* p = (char*) vp; + std::copy(p, p+s, out); + return *this; + } + + Encode& byte(char x) { out++ = x; return *this; } + }; + + template struct Decode : public Serializer > { + In in; + Decode(In i) : in(i) {} + + using Serializer >::operator(); + using Serializer >::raw; + + template + typename boost::enable_if, Decode&>::type + operator()(T& x) { + raw(&x, sizeof(x)); + endianize(x); + return *this; + } + + template + typename boost::enable_if, Decode&>::type + operator()(T& x) { return raw(&x, sizeof(x)); } + + template + Decode& operator()(CodableString& str) { + SizeType n; + (*this)(n); + str.resize(n); + std::for_each(str.begin(), str.end(), *this); + return *this; + } + + private: + friend class Serializer >; + + Decode& raw(void* vp, size_t s) { + char* p=(char*)vp; + std::copy(in, in+s, p); + return *this; + } + + Decode& byte(char& x) { x = *in++; return *this; } + }; + + struct Size : public ConstSerializer { + Size() : size(0) {} + size_t size; + operator size_t() const { return size; } + + using ConstSerializer::operator(); + using ConstSerializer::raw; + + template + typename boost::enable_if, Size&>::type + operator()(const T&) { size += sizeof(T); return *this; } + + template + Size& operator()(const boost::array&) { + size += sizeof(boost::array); + return *this; + } + + template + Size& operator()(const CodableString& str) { + size += sizeof(SizeType) + str.size()*sizeof(T); + return *this; + } + + + private: + friend class ConstSerializer; + + Size& raw(void*, size_t s) { size += s; return *this; } + + Size& byte(char) { ++size; return *this; } + }; + + template + static void encode(Out o, const T& x) { + Encodeencode(o); + encode(x); + } + + template + static void decode(In i, T& x) { + Decode decode(i); + decode(x); + } + + template + static size_t size(const T& x) { + Size sz; + sz(x); + return sz; + } +}; + +}} // namespace qpid::amqp_0_10 + +#endif /*!QPID_AMQP_0_10_CODEC_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Decimal.h b/cpp/src/qpid/amqp_0_10/Decimal.h new file mode 100644 index 0000000000..75cde94559 --- /dev/null +++ b/cpp/src/qpid/amqp_0_10/Decimal.h @@ -0,0 +1,52 @@ +#ifndef TESTS_DECIMAL_H +#define TESTS_DECIMAL_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 + +namespace qpid { +namespace amqp_0_10 { + +template struct Decimal { + E exponent; + M mantissa; + + Decimal() : exponent(0), mantissa(0) {} + + bool operator==(const Decimal& d) const { + return exponent == d.exponent && mantissa == d.mantissa; + } + + // TODO aconway 2008-02-20: We could provide arithmetic operators + // if anybody really cares about this type. + + template void serialize(S& s) { s(exponent)(mantissa); } +}; + +template +inline std::ostream& operator<<(std::ostream& o, const Decimal& d) { + M pow10=10^d.exponent; + return o << d.mantissa/pow10 << "." << d.mantissa%pow10; +} +}} + +#endif /*!TESTS_DECIMAL_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 new file mode 100644 index 0000000000..6cd9c72367 --- /dev/null +++ b/cpp/src/qpid/amqp_0_10/built_in_types.h @@ -0,0 +1,103 @@ +#ifndef QPID_AMQP_0_10_BUILT_IN_TYPES_H +#define QPID_AMQP_0_10_BUILT_IN_TYPES_H +// FIXME aconway 2008-02-20: separate _fwd.h from full include. +/* + * + * 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 "Decimal.h" +#include "qpid/framing/SequenceNumber.h" +#include "qpid/framing/Uuid.h" +#include "qpid/sys/Time.h" +#include +#include +#include + +/**@file Mapping from built-in AMQP types to C++ types */ + +namespace qpid { +namespace amqp_0_10 { + +// Fixed size types +typedef void Void; + +typedef bool Bit; +typedef bool Boolean; +typedef char Char; +typedef int16_t Int16; +typedef int32_t Int32; +typedef int64_t Int64; +typedef int8_t Int8; +typedef uint16_t Uint16; +typedef uint32_t CharUtf32 ; +typedef uint32_t Uint32; +typedef uint64_t Uint64; +typedef uint8_t Bin8; +typedef uint8_t Uint8; + +typedef boost::array Bin1024; +typedef boost::array Bin128; +typedef boost::array Bin16; +typedef boost::array Bin256; +typedef boost::array Bin32; +typedef boost::array Bin40; +typedef boost::array Bin512; +typedef boost::array Bin64; +typedef boost::array Bin72; + +typedef double Double; +typedef float Float; +typedef framing::SequenceNumber SequenceNo; +using framing::Uuid; +typedef sys::AbsTime DateTime; + +typedef Decimal Dec32; +typedef Decimal Dec64; + + +/** Template for length-prefixed strings/arrays. */ +template +struct CodableString : public std::basic_string {}; + +// Variable width types +typedef CodableString Vbin8; +typedef CodableString Str8Latin; +typedef CodableString Str8; +typedef CodableString Str8Utf16; + +typedef CodableString Vbin16; +typedef CodableString Str16Latin; +typedef CodableString Str16; +typedef CodableString Str16Utf16; + +typedef CodableString Vbin32; + +/** FIXME aconway 2008-02-20: todo +byte-ranges 2 byte ranges within a 64-bit payload +sequence-set 2 ranged set representation +map 0xa8 4 a mapping of keys to typed values +list 0xa9 4 a series of consecutive type-value pairs +array 0xaa 4 a defined length collection of values of a single type +struct32 0xab 4 a coded struct with a 32-bit size +*/ + +}} // namespace qpid::amqp_0_10 + +#endif /*!QPID_AMQP_0_10_BUILT_IN_TYPES_H*/ diff --git a/cpp/src/qpid/framing/SequenceNumber.h b/cpp/src/qpid/framing/SequenceNumber.h index 3aee04a4ce..b2594452d0 100644 --- a/cpp/src/qpid/framing/SequenceNumber.h +++ b/cpp/src/qpid/framing/SequenceNumber.h @@ -50,6 +50,8 @@ class SequenceNumber operator uint32_t() const { return (uint32_t) value; } friend int32_t operator-(const SequenceNumber& a, const SequenceNumber& b); + + template void serialize(S& s) { s(value); } }; struct Window diff --git a/cpp/src/qpid/framing/Uuid.h b/cpp/src/qpid/framing/Uuid.h index 9bde67ad8e..278a60c439 100644 --- a/cpp/src/qpid/framing/Uuid.h +++ b/cpp/src/qpid/framing/Uuid.h @@ -65,6 +65,10 @@ struct Uuid : public boost::array { /** String value in format 1b4e28ba-2fa1-11d2-883f-b9a761bde3fb */ std::string str() const; + + template void serialize(S& s) { + s(static_cast&>(*this)); + } }; /** Print in format 1b4e28ba-2fa1-11d2-883f-b9a761bde3fb */ diff --git a/cpp/src/qpid/sys/Time.h b/cpp/src/qpid/sys/Time.h index 9c9b3de5c2..c87bd6f05b 100644 --- a/cpp/src/qpid/sys/Time.h +++ b/cpp/src/qpid/sys/Time.h @@ -46,6 +46,9 @@ class AbsTime { static AbsTime now(); inline static AbsTime FarFuture(); + int64_t timeValue() const { return time_ns; } + bool operator==(const AbsTime& t) const { return t.time_ns == time_ns; } + template void serialize(S& s) { s(time_ns); } friend bool operator<(const AbsTime& a, const AbsTime& b); friend bool operator>(const AbsTime& a, const AbsTime& b); -- cgit v1.2.1