summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2008-04-08 19:53:07 +0000
committerAlan Conway <aconway@apache.org>2008-04-08 19:53:07 +0000
commite72e25abd1272c4e9489f7efd5bc02c4ecf0b5cd (patch)
tree2d32b5153aefb4059ec410118ffd80f37d64b6bd
parent43aaed1c309c8c7ff95695109cf49b5b9157f4b6 (diff)
downloadqpid-python-e72e25abd1272c4e9489f7efd5bc02c4ecf0b5cd.tar.gz
Summary: added 0-10 Array encoding and decoding.
rubygen/0-10/allsegmenttypes.rb: test header,body and each command and control type. rubygen/0-10/specification.rb: enable packed encoding. src/qpid/amqp_0_10/Array.h: Implemented array and array domains. src/qpid/amqp_0_10/Codec.h: enable litte-endian encoding for pack bits src/qpid/amqp_0_10/Packer.h: use litte-endian encoding for pack bits src/qpid/amqp_0_10/Unit.cpp, .h: setting flags, fix op <<. src/qpid/amqp_0_10/complex_types.cpp, .h: added op << src/qpid/framing/Blob.h: copy-object template constructor. src/tests/amqp_0_10/serialize.cpp: - test Array Minor adjustments for new Array.h: src/qpid/amqp_0_10/Map.cpp src/qpid/amqp_0_10/Map.h src/qpid/amqp_0_10/UnknownType.h src/qpid/amqp_0_10/built_in_types.h src/qpid/amqp_0_10/Body.h git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@646054 13f79535-47bb-0310-9956-ffa450edef68
-rwxr-xr-xcpp/rubygen/0-10/allsegmenttypes.rb34
-rwxr-xr-xcpp/rubygen/0-10/specification.rb15
-rwxr-xr-xcpp/rubygen/0-10/typecode.rb20
-rw-r--r--cpp/src/Makefile.am3
-rw-r--r--cpp/src/qpid/amqp_0_10/Array.cpp34
-rw-r--r--cpp/src/qpid/amqp_0_10/Array.h120
-rw-r--r--cpp/src/qpid/amqp_0_10/Body.h4
-rw-r--r--cpp/src/qpid/amqp_0_10/Codec.h61
-rw-r--r--cpp/src/qpid/amqp_0_10/Map.cpp2
-rw-r--r--cpp/src/qpid/amqp_0_10/Map.h2
-rw-r--r--cpp/src/qpid/amqp_0_10/Packer.h4
-rw-r--r--cpp/src/qpid/amqp_0_10/Unit.cpp16
-rw-r--r--cpp/src/qpid/amqp_0_10/Unit.h21
-rw-r--r--cpp/src/qpid/amqp_0_10/UnknownType.h3
-rw-r--r--cpp/src/qpid/amqp_0_10/all_built_in_types.h31
-rw-r--r--cpp/src/qpid/amqp_0_10/built_in_types.h12
-rw-r--r--cpp/src/qpid/amqp_0_10/complex_types.cpp13
-rw-r--r--cpp/src/qpid/amqp_0_10/complex_types.h5
-rw-r--r--cpp/src/qpid/framing/Blob.h12
-rw-r--r--cpp/src/tests/amqp_0_10/Map.cpp3
-rw-r--r--cpp/src/tests/amqp_0_10/serialize.cpp85
-rwxr-xr-xcpp/src/tests/python_tests3
22 files changed, 419 insertions, 84 deletions
diff --git a/cpp/rubygen/0-10/allsegmenttypes.rb b/cpp/rubygen/0-10/allsegmenttypes.rb
new file mode 100755
index 0000000000..c4c4095e02
--- /dev/null
+++ b/cpp/rubygen/0-10/allsegmenttypes.rb
@@ -0,0 +1,34 @@
+#!/usr/bin/env ruby
+$: << ".." # Include .. in load path
+require 'cppgen'
+
+class GenAllSegmentTypes < CppGen
+ def initialize(outdir, amqp)
+ super(outdir, amqp)
+ end
+
+ def generate
+ h_file("tests/allSegmentTypes.h") {
+ include "qpid/amqp_0_10/specification.h"
+ include "qpid/amqp_0_10/Header.h"
+ include "qpid/amqp_0_10/Body.h"
+ genl
+ genl "using namespace qpid::amqp_0_10;"
+ genl
+ scope("template <class Op> size_t allSegmentTypes(Op& op) {"){
+ genl "op(Header());"
+ genl "op(Body());"
+ n = 2;
+ @amqp.classes.each { |c|
+ c.commands.each { |s| genl "op(CommandHolder(#{c.nsname}::#{s.classname}()));" }
+ c.controls.each { |s| genl "op(ControlHolder(#{c.nsname}::#{s.classname}()));" }
+ n += 2
+ }
+ genl "return #{n};"
+ }
+ }
+ end
+end
+
+GenAllSegmentTypes.new($outdir, $amqp).generate();
+
diff --git a/cpp/rubygen/0-10/specification.rb b/cpp/rubygen/0-10/specification.rb
index d8c5378538..54d39de9b4 100755
--- a/cpp/rubygen/0-10/specification.rb
+++ b/cpp/rubygen/0-10/specification.rb
@@ -64,11 +64,11 @@ class Specification < CppGen
genl
yield if block
}
+ genl "inline Packer<#{x.classname}> serializable(#{x.classname}& x) { return Packer<#{x.classname}>(x); }" unless x.respond_to? :pack and x.pack == "0"
genl "std::ostream& operator << (std::ostream&, const #{x.classname}&);"
genl "bool operator==(const #{x.classname}&, const #{x.classname}&);"
end
- # FIXME aconway 2008-03-10: packing, coding
def action_struct_cpp(x)
genl
genl "const char* #{x.classname}::NAME=\"#{x.fqname}\";"
@@ -89,7 +89,7 @@ class Specification < CppGen
scope("std::ostream& operator << (std::ostream& o, const #{x.classname}&#{"x" unless x.fields.empty?}) {") {
genl "o << \"[#{x.fqname}\";";
x.fields.each{ |f| genl "o << \" #{f.name}=\" << x.#{f.cppname};" }
- genl "o << \"];\";"
+ genl "o << \"]\";"
genl "return o;"
}
end
@@ -151,8 +151,8 @@ class Specification < CppGen
def gen_specification()
h_file("#{@dir}/specification") {
include "#{@dir}/specification_fwd"
- include "#{@dir}/complex_types"
- include "#{@dir}/Map.h"
+ include "#{@dir}/all_built_in_types"
+ include "#{@dir}/Packer.h"
include "<boost/call_traits.hpp>"
include "<iosfwd>"
genl "using boost::call_traits;"
@@ -271,7 +271,7 @@ class Specification < CppGen
holder_base="amqp_0_10::Holder<#{base}Holder, #{base}, #{base.downcase}_max::MAX>"
struct("#{name}", "public #{holder_base}") {
genl "#{name}() {}"
- genl "template <class T> #{name}(const T& t) : #{holder_base}(t) {}"
+ genl "template <class T> explicit #{name}(const T& t) : #{holder_base}(t) {}"
genl "using #{holder_base}::operator=;"
genl "void set(uint8_t classCode, uint8_t code);"
}
@@ -281,7 +281,8 @@ class Specification < CppGen
}
cpp_file("#{@dir}/#{name}") {
- include "#{@dir}/#{name}"
+ include "#{name}"
+ include "exceptions.h"
namespace(@ns) {
genl "using framing::in_place;"
genl
@@ -291,7 +292,7 @@ class Specification < CppGen
subs.each { |s|
genl "case 0x#{s.full_code.to_s(16)}: *this=in_place<#{s.fqclassname}>(); break;"
}
- genl "default: assert(0);"
+ genl "default: throw CommandInvalidException(QPID_MSG(\"Invalid class-#{base.downcase} key \" << std::hex << key));"
}}
genl
genl "std::ostream& operator<<(std::ostream& o, const #{name}& h) { return h.get() ? (o << *h.get()) : (o << \"<empty #{name}>\"); }"
diff --git a/cpp/rubygen/0-10/typecode.rb b/cpp/rubygen/0-10/typecode.rb
index 459516e51c..e36b92c07c 100755
--- a/cpp/rubygen/0-10/typecode.rb
+++ b/cpp/rubygen/0-10/typecode.rb
@@ -13,6 +13,7 @@ class TypeCode < CppGen
def type_for_code_h()
h_file("#{@dir}/TypeForCode") {
+ include "#{@dir}/built_in_types.h"
include "#{@dir}/UnknownType.h"
namespace(@ns) {
genl
@@ -61,17 +62,30 @@ class TypeCode < CppGen
end
def code_for_type_h()
- h_file("#{@dir}/CodeForType") {
+ name="#{@dir}/CodeForType"
+ h_file(name) {
+ include "#{@dir}/built_in_types.h"
+
namespace(@ns) {
genl
genl "template <class T> struct CodeForType;"
genl
@types.each { |t|
- genl "template <> struct CodeForType<#{t.typename}> { static const uint8_t value=#{t.code}; };"
+ genl "template <> struct CodeForType<#{t.typename}> { static const uint8_t value; };"
}
genl
genl "template <class T> uint8_t codeFor(const T&) { return CodeForType<T>::value; }"
- }}
+ }
+ }
+
+ cpp_file(name) {
+ include name
+ namespace(@ns) {
+ @types.each { |t|
+ genl "const uint8_t CodeForType<#{t.typename}>::value=#{t.code};"
+ }
+ }
+ }
end
def generate
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am
index 991d9bc4c5..eaf8119405 100644
--- a/cpp/src/Makefile.am
+++ b/cpp/src/Makefile.am
@@ -104,9 +104,12 @@ libqpidcommon_la_SOURCES = \
$(rgen_common_cpp) \
$(platform_src) \
qpid/amqp_0_10/apply.h \
+ qpid/amqp_0_10/all_built_in_types.h \
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/Array.h \
+ qpid/amqp_0_10/Array.cpp \
qpid/amqp_0_10/Body.h \
qpid/amqp_0_10/Header.h \
qpid/amqp_0_10/FrameHeader.h \
diff --git a/cpp/src/qpid/amqp_0_10/Array.cpp b/cpp/src/qpid/amqp_0_10/Array.cpp
new file mode 100644
index 0000000000..380e0f1f36
--- /dev/null
+++ b/cpp/src/qpid/amqp_0_10/Array.cpp
@@ -0,0 +1,34 @@
+/*
+ *
+ * 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 "Array.h"
+
+namespace qpid {
+namespace amqp_0_10 {
+
+std::ostream& operator<<(std::ostream& o, const Array& a) {
+ std::ostream_iterator<UnknownType> i(o, " ");
+ o << "Array<" << typeName(a.getType()) << "[";
+ std::copy(a.begin(), a.end(), i);
+ o << "]";
+ return o;
+}
+
+}} // namespace qpid::amqp_0_10
diff --git a/cpp/src/qpid/amqp_0_10/Array.h b/cpp/src/qpid/amqp_0_10/Array.h
new file mode 100644
index 0000000000..8061a99b43
--- /dev/null
+++ b/cpp/src/qpid/amqp_0_10/Array.h
@@ -0,0 +1,120 @@
+#ifndef QPID_AMQP_0_10_ARRAY_H
+#define QPID_AMQP_0_10_ARRAY_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/TypeForCode.h"
+#include "qpid/amqp_0_10/CodeForType.h"
+#include "qpid/amqp_0_10/UnknownType.h"
+#include "qpid/amqp_0_10/exceptions.h"
+#include "qpid/amqp_0_10/Codec.h"
+#include <vector>
+#include <ostream>
+
+namespace qpid {
+namespace amqp_0_10 {
+
+template <class T> class ArrayDomain : public std::vector<T> {
+ public:
+ template <class S> void serialize(S& s) { s.split(*this); s(this->begin(), this->end()); }
+
+ template <class S> void encode(S& s) const {
+ s(contentSize())(CodeForType<T>::value)(uint32_t(this->size()));
+ }
+
+ void encode(Codec::Size& s) const { s.raw(0, contentSize() + 4/*size*/); }
+
+ template <class S> void decode(S& s) {
+ uint32_t size; uint8_t type; uint32_t count;
+ s(size);
+ s.setLimit(size);
+ s(type);
+ if (type != CodeForType<T>::value)
+ throw InvalidArgumentException(QPID_MSG("Array domain expected type " << CodeForType<T>::value << " but found " << type));
+ s(count);
+ this->resize(count);
+ }
+
+ private:
+ uint32_t contentSize() const {
+ return Codec::size(this->begin(), this->end()) + sizeof(uint32_t) /*count*/ + sizeof(uint8_t) /*type*/;
+ }
+};
+
+template <class T>
+std::ostream& operator<<(std::ostream& o, const ArrayDomain<T>& ad) {
+ std::ostream_iterator<T> i(o, " ");
+ o << "Array<" << typeName(CodeForType<T>::value) << ">[";
+ std::copy(ad.begin(), ad.end(), i);
+ o << "]";
+ return o;
+}
+
+/** A non-domain array is represented as and array of UnknownType.
+ * Special case templat.
+ */
+template<> class ArrayDomain<UnknownType> : public std::vector<UnknownType> {
+ public:
+ ArrayDomain(uint8_t type_=0) : type(type_) {}
+
+ template <class S> void serialize(S& s) { s.split(*this); s(this->begin(), this->end()); }
+
+ template <class S> void encode(S& s) const {
+ s(contentSize())(type)(uint32_t(this->size()));
+ }
+
+ void encode(Codec::Size& s) const { s.raw(0, contentSize() + 4/*size*/); }
+
+ template <class S> void decode(S& s) {
+ uint32_t size; uint32_t count;
+ s(size);
+ s.setLimit(size);
+ s(type)(count);
+ this->clear();
+ this->resize(count, UnknownType(type));
+ }
+
+ uint8_t getType() const { return type; }
+
+ private:
+ uint32_t contentSize() const {
+ return Codec::size(this->begin(), this->end()) + sizeof(uint32_t) /*count*/ + sizeof(uint8_t) /*type*/;
+ }
+ uint8_t type;
+};
+
+std::ostream& operator<<(std::ostream& o, const Array& a);
+
+// FIXME aconway 2008-04-08: hack to supress encoding of
+// command-fragments and in-doubt as there is a problem with the spec
+// (command-fragments does not have a one byte type code.)
+namespace session { class CommandFragment; }
+namespace dtx { class Xid; }
+
+template <> struct ArrayDomain<session::CommandFragment> : public Void {};
+template <> struct ArrayDomain<dtx::Xid> : public Void {};
+inline std::ostream& operator<<(std::ostream& o, const ArrayDomain<session::CommandFragment>&) { return o; }
+inline std::ostream& operator<<(std::ostream& o, const ArrayDomain<dtx::Xid>&) { return o; }
+
+}} // namespace qpid::amqp_0_10
+
+#endif /*!QPID_AMQP_0_10_ARRAY_H*/
diff --git a/cpp/src/qpid/amqp_0_10/Body.h b/cpp/src/qpid/amqp_0_10/Body.h
index a2192503b8..c96931551c 100644
--- a/cpp/src/qpid/amqp_0_10/Body.h
+++ b/cpp/src/qpid/amqp_0_10/Body.h
@@ -31,7 +31,7 @@ namespace amqp_0_10 {
class Body {
public:
Body() {}
- Body(size_t size_) : str('\0', size_) {}
+ Body(size_t size_) : str(size_, '\0') {}
Body(const char* data_, size_t size_) : str(data_, size_) {}
size_t size() const { return str.size(); };
@@ -47,7 +47,7 @@ class Body {
};
inline std::ostream& operator<<(std::ostream& o, const Body& b) {
- return o << b.str.substr(16) << "... (" << b.size() << ")";
+ return o << b.str.substr(0, 16) << "... (" << b.size() << ")";
}
}} // namespace qpid::amqp_0_10
diff --git a/cpp/src/qpid/amqp_0_10/Codec.h b/cpp/src/qpid/amqp_0_10/Codec.h
index c4909e7cbd..5cad5cf4ed 100644
--- a/cpp/src/qpid/amqp_0_10/Codec.h
+++ b/cpp/src/qpid/amqp_0_10/Codec.h
@@ -34,13 +34,17 @@
namespace qpid {
namespace amqp_0_10 {
-#ifdef BOOST_LITTLE_ENDIAN
-template <class T> void endianize(T& t) {
+template <class T> void reverse(T& t) {
char*p =reinterpret_cast<char*>(&t);
std::reverse(p, p+sizeof(T));
}
+
+#ifdef BOOST_LITTLE_ENDIAN
+template <class T> void bigEndian(T& t) { reverse(t); }
+template <class T> void littleEndian(T&) {}
#else
-template <class T> void endianize(T&) {}
+template <class T> void littleEndian(T& t) { reverse(t); }
+template <class T> void bigEndian(T&) {}
#endif
/**
@@ -66,16 +70,16 @@ struct Codec {
Encoder& operator()(int8_t x) { raw(x); return *this; }
Encoder& operator()(uint8_t x) { raw(x); return *this; }
- Encoder& operator()(int16_t x) { return endian(x); }
- Encoder& operator()(int32_t x) { return endian(x); }
- Encoder& operator()(int64_t x) { return endian(x); }
+ Encoder& operator()(int16_t x) { return networkByteOrder(x); }
+ Encoder& operator()(int32_t x) { return networkByteOrder(x); }
+ Encoder& operator()(int64_t x) { return networkByteOrder(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); }
+ Encoder& operator()(uint16_t x) { return networkByteOrder(x); }
+ Encoder& operator()(uint32_t x) { return networkByteOrder(x); }
+ Encoder& operator()(uint64_t x) { return networkByteOrder(x); }
- Encoder& operator()(float x) { return endian(x); }
- Encoder& operator()(double x) { return endian(x); }
+ Encoder& operator()(float x) { return networkByteOrder(x); }
+ Encoder& operator()(double x) { return networkByteOrder(x); }
void raw(const void* p, size_t n) {
this->addBytes(n);
@@ -84,12 +88,16 @@ struct Codec {
void raw(char b) { this->addBytes(1); *out++=b; }
+ template <class T> Encoder& littleEnd(T x) {
+ littleEndian(x); raw(&x, sizeof(x)); return *this;
+ }
+
OutIter pos() const { return out; }
private:
- template <class T> Encoder& endian(T x) {
- endianize(x); raw(&x, sizeof(x)); return *this;
+ template <class T> Encoder& networkByteOrder(T x) {
+ bigEndian(x); raw(&x, sizeof(x)); return *this;
}
OutIter out;
@@ -114,16 +122,16 @@ struct Codec {
Decoder& operator()(int8_t& x) { raw((char&)x); return *this; }
Decoder& operator()(uint8_t& x) { raw((char&)x); return *this; }
- Decoder& operator()(int16_t& x) { return endian(x); }
- Decoder& operator()(int32_t& x) { return endian(x); }
- Decoder& operator()(int64_t& x) { return endian(x); }
+ Decoder& operator()(int16_t& x) { return networkByteOrder(x); }
+ Decoder& operator()(int32_t& x) { return networkByteOrder(x); }
+ Decoder& operator()(int64_t& x) { return networkByteOrder(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); }
+ Decoder& operator()(uint16_t& x) { return networkByteOrder(x); }
+ Decoder& operator()(uint32_t& x) { return networkByteOrder(x); }
+ Decoder& operator()(uint64_t& x) { return networkByteOrder(x); }
- Decoder& operator()(float& x) { return endian(x); }
- Decoder& operator()(double& x) { return endian(x); }
+ Decoder& operator()(float& x) { return networkByteOrder(x); }
+ Decoder& operator()(double& x) { return networkByteOrder(x); }
void raw(void *p, size_t n) {
this->addBytes(n);
@@ -133,12 +141,16 @@ struct Codec {
void raw(char &b) { this->addBytes(1); b=*in++; }
+ template <class T> Decoder& littleEnd(T& x) {
+ raw(&x, sizeof(x)); littleEndian(x); return *this;
+ }
+
InIter pos() const { return in; }
private:
- template <class T> Decoder& endian(T& x) {
- raw(&x, sizeof(x)); endianize(x); return *this;
+ template <class T> Decoder& networkByteOrder(T& x) {
+ raw(&x, sizeof(x)); bigEndian(x); return *this;
}
InIter in;
@@ -177,6 +189,8 @@ struct Codec {
void raw(const void*, size_t n){ size += n; }
+ template <class T> Size& littleEnd(T) { size+= sizeof(T); return *this; }
+
private:
size_t size;
};
@@ -191,6 +205,7 @@ struct Codec {
}
template <class T> static size_t size(const T& x) { return Size()(x); }
+ template <class Iter> static size_t size(const Iter& a, const Iter& z) { return Size()(a,z); }
};
}} // namespace qpid::amqp_0_10
diff --git a/cpp/src/qpid/amqp_0_10/Map.cpp b/cpp/src/qpid/amqp_0_10/Map.cpp
index 308e280e45..2d32466c3f 100644
--- a/cpp/src/qpid/amqp_0_10/Map.cpp
+++ b/cpp/src/qpid/amqp_0_10/Map.cpp
@@ -18,7 +18,7 @@
* under the License.
*
*/
-#include "Map.h"
+#include "all_built_in_types.h"
#include <ostream>
namespace qpid {
diff --git a/cpp/src/qpid/amqp_0_10/Map.h b/cpp/src/qpid/amqp_0_10/Map.h
index c1580bf4f3..d63eb0cc4e 100644
--- a/cpp/src/qpid/amqp_0_10/Map.h
+++ b/cpp/src/qpid/amqp_0_10/Map.h
@@ -14,7 +14,7 @@
* 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
+ * software distributed under the License is distributed on ang
* "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
diff --git a/cpp/src/qpid/amqp_0_10/Packer.h b/cpp/src/qpid/amqp_0_10/Packer.h
index ebb0488525..8943dc4c51 100644
--- a/cpp/src/qpid/amqp_0_10/Packer.h
+++ b/cpp/src/qpid/amqp_0_10/Packer.h
@@ -126,13 +126,13 @@ template <class T> class Packer
template <class S> void encode(S& s) const {
Bits bits = packBits(data);
- s(bits);
+ s.littleEnd(bits);
data.serialize(s);
}
template <class S> void decode(S& s) {
Bits bits;
- s(bits);
+ s.littleEnd(bits);
PackedDecoder<S, Bits> decode(s, bits);
data.serialize(decode);
}
diff --git a/cpp/src/qpid/amqp_0_10/Unit.cpp b/cpp/src/qpid/amqp_0_10/Unit.cpp
index 6b0a2e542d..1fa6b2e085 100644
--- a/cpp/src/qpid/amqp_0_10/Unit.cpp
+++ b/cpp/src/qpid/amqp_0_10/Unit.cpp
@@ -24,7 +24,7 @@
namespace qpid {
namespace amqp_0_10 {
-void Unit::setVariant() {
+void Unit::updateVariant() {
switch (header.getType()) {
case CONTROL: variant=ControlHolder(); break;
case COMMAND: variant=CommandHolder();
@@ -40,8 +40,16 @@ struct GetTypeVisitor : public boost::static_visitor<SegmentType> {
SegmentType operator()(const Body&) const { return BODY; }
};
-void Unit::setHeader(uint8_t flags) {
- header.setFlags(flags);
+struct GetFlagsVisitor : public boost::static_visitor<uint8_t> {
+ uint8_t operator()(const CommandHolder& ) const { return FIRST_FRAME|LAST_FRAME|FIRST_SEGMENT; }
+ uint8_t operator()(const ControlHolder& ) const { return FIRST_FRAME|LAST_FRAME|FIRST_SEGMENT; }
+ uint8_t operator()(const Header& ) const { return FIRST_FRAME|LAST_FRAME; }
+ uint8_t operator()(const Body&) const { return 0; }
+};
+
+void Unit::updateHeader(uint8_t flags) {
+ GetFlagsVisitor flagger;
+ header.setFlags(flags | variant.apply_visitor(flagger));
GetTypeVisitor getter;
header.setType(variant.apply_visitor(getter));
header.setDataSize(Codec::size(*this));
@@ -50,7 +58,7 @@ void Unit::setHeader(uint8_t flags) {
}
std::ostream& operator<<(std::ostream& o, const Unit& u) {
- return o << u.getHeader() << " " << u.getVariant();
+ return o << u.getHeader() << " " << u.variant.type().name() << "[" << u.variant << "]";
}
}} // namespace qpid::amqp_0_10
diff --git a/cpp/src/qpid/amqp_0_10/Unit.h b/cpp/src/qpid/amqp_0_10/Unit.h
index dad34fef01..bcba36e35a 100644
--- a/cpp/src/qpid/amqp_0_10/Unit.h
+++ b/cpp/src/qpid/amqp_0_10/Unit.h
@@ -43,30 +43,33 @@ class Unit {
public:
typedef boost::variant<ControlHolder, CommandHolder, Header, Body> Variant;
- Unit(const FrameHeader& h=FrameHeader()) : header(h) { setVariant(); }
+ explicit Unit(const FrameHeader& h=FrameHeader()) : header(h) { updateVariant(); }
+ /**
+ *@param flags: is ORed with the required flags for type T.
+ */
template <class T>
- Unit(const T& t, uint8_t flags) : variant(t) { setHeader(flags); }
+ explicit Unit(const T& t, uint8_t flags=0) : variant(t) { updateHeader(flags); }
+ void setHeader(FrameHeader& h) { header = h; updateVariant(); }
const FrameHeader& getHeader() const { return header; }
template<class T> const T* get() const { return boost::get<T>(&variant); }
template<class T> T* get() { return boost::get<T>(&variant); }
- template<class T> Unit& operator==(const T& t) { variant=t; return *this; }
+ template<class T> Unit& operator=(const T& t) { variant=t; return *this; }
template <class S> void serialize(S& s) { variant.apply_visitor(s); s.split(*this); }
template <class S> void encode(S&) const {}
- template <class S> void decode(S&) { setHeader(header.getFlags()); }
+ template <class S> void decode(S&) { updateHeader(header.getFlags()); }
- const Variant& getVariant() const { return variant; }
- Variant& getVariant() { return variant; }
-
private:
- void setHeader(uint8_t flags);
- void setVariant();
+ void updateHeader(uint8_t flags);
+ void updateVariant();
Variant variant;
FrameHeader header;
+
+ friend std::ostream& operator<<(std::ostream& o, const Unit& u);
};
std::ostream& operator<<(std::ostream& o, const Unit& u);
diff --git a/cpp/src/qpid/amqp_0_10/UnknownType.h b/cpp/src/qpid/amqp_0_10/UnknownType.h
index 0b4ec550d1..1e4aa04bf4 100644
--- a/cpp/src/qpid/amqp_0_10/UnknownType.h
+++ b/cpp/src/qpid/amqp_0_10/UnknownType.h
@@ -35,12 +35,13 @@ class UnknownType {
uint8_t getCode() const { return code; }
/** Size of fixed type or 0 if not fixed/0-length. -1 invalid */
int fixed() const;
- /** Bytes in size tyep for variable width. -1 invalid */
+ /** Bytes in size type for variable width. -1 invalid */
int variable() const;
typedef std::vector<char>::const_iterator const_iterator;
const_iterator begin() const { return data.begin(); }
const_iterator end() const { return data.end(); }
+ size_t size() const { return data.size(); }
template <class S> void serialize(S& s) { s.split(*this); }
template <class S> void encode(S& s) const;
diff --git a/cpp/src/qpid/amqp_0_10/all_built_in_types.h b/cpp/src/qpid/amqp_0_10/all_built_in_types.h
new file mode 100644
index 0000000000..1568465004
--- /dev/null
+++ b/cpp/src/qpid/amqp_0_10/all_built_in_types.h
@@ -0,0 +1,31 @@
+#ifndef QPID_AMQP_0_10_ALL_BUILT_IN_TYPES_H
+#define QPID_AMQP_0_10_ALL_BUILT_IN_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 "Map.h"
+#include "Array.h"
+#include "UnknownType.h"
+#include "complex_types.h"
+
+#endif /*!QPID_AMQP_0_10_ALL_BUILT_IN_TYPES_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 c9ce27bda0..5b79faef36 100644
--- a/cpp/src/qpid/amqp_0_10/built_in_types.h
+++ b/cpp/src/qpid/amqp_0_10/built_in_types.h
@@ -36,7 +36,6 @@
/**@file Mapping from built-in AMQP types to C++ types */
-
namespace qpid {
namespace amqp_0_10 {
@@ -135,20 +134,17 @@ typedef SerializableString<Uint8, Uint32> Vbin32;
// Forward declare class types.
class Map;
+class UnknownType;
+template <class T> struct ArrayDomain;
+typedef ArrayDomain<UnknownType> Array;
-// FIXME aconway 2008-02-26: Unimplemented types:
-template <class T> struct ArrayDomain : public std::vector<T> {
- template <class S> void serialize(S&) {}
-};
-struct Array { template <class S> void serialize(S&) {} };
+// FIXME aconway 2008-04-08: TODO
struct ByteRanges { template <class S> void serialize(S&) {} };
struct SequenceSet { template <class S> void serialize(S&) {} };
struct List { template <class S> void serialize(S&) {} };
struct Struct32 { template <class S> void serialize(S&) {} };
// FIXME aconway 2008-03-10: dummy ostream operators
-template <class T> std::ostream& operator<<(std::ostream& o, const ArrayDomain<T>&) { return o; }
-inline std::ostream& operator<<(std::ostream& o, const Array&) { return o; }
inline std::ostream& operator<<(std::ostream& o, const ByteRanges&) { return o; }
inline std::ostream& operator<<(std::ostream& o, const SequenceSet&) { return o; }
inline std::ostream& operator<<(std::ostream& o, const List&) { return o; }
diff --git a/cpp/src/qpid/amqp_0_10/complex_types.cpp b/cpp/src/qpid/amqp_0_10/complex_types.cpp
index 39cbb0a2cd..93550b9c20 100644
--- a/cpp/src/qpid/amqp_0_10/complex_types.cpp
+++ b/cpp/src/qpid/amqp_0_10/complex_types.cpp
@@ -23,6 +23,7 @@
#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"
+#include <iostream>
namespace qpid {
namespace amqp_0_10 {
@@ -61,5 +62,17 @@ 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; }
+struct PrintVisitor {
+ typedef std::ostream& result_type;
+ std::ostream& out;
+ PrintVisitor(std::ostream& o) : out(o) {}
+ template <class T> result_type operator()(const T& t) const { return out << t; }
+};
+
+std::ostream& operator<<(std::ostream& o, const Command& x) { return apply(PrintVisitor(o), x); }
+std::ostream& operator<<(std::ostream& o, const Control& x) { return apply(PrintVisitor(o), x); }
+// FIXME aconway 2008-04-07:
+// std::ostream& operator<<(std::ostream& o, const Struct& x) { apply(PrintVisitor(o), x); }
+
}} // 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
index d69a2be957..c8080b867d 100644
--- a/cpp/src/qpid/amqp_0_10/complex_types.h
+++ b/cpp/src/qpid/amqp_0_10/complex_types.h
@@ -23,6 +23,7 @@
*/
#include "built_in_types.h"
+#include <iosfwd>
namespace qpid {
namespace amqp_0_10 {
@@ -71,6 +72,7 @@ struct Command
const char* getName() const;
const char* getClassName() const;
};
+std::ostream& operator<<(std::ostream&, const Command&);
struct ControlVisitor;
struct ConstControlVisitor;
@@ -86,6 +88,7 @@ struct Control
const char* getName() const;
const char* getClassName() const;
};
+std::ostream& operator<<(std::ostream&, const Control&);
struct StructVisitor;
struct ConstStructVisitor;
@@ -98,7 +101,7 @@ struct Struct
uint8_t getSize() const;
uint8_t getClassCode() const;
};
-
+std::ostream& operator<<(std::ostream&, const Struct&);
template <SegmentType E> struct ActionType;
template <> struct ActionType<CONTROL> { typedef Control type; };
diff --git a/cpp/src/qpid/framing/Blob.h b/cpp/src/qpid/framing/Blob.h
index 344e4ac4db..cf81f693b0 100644
--- a/cpp/src/qpid/framing/Blob.h
+++ b/cpp/src/qpid/framing/Blob.h
@@ -85,10 +85,6 @@ template <> struct BlobHelper<void> {
* In particular the user must ensure the blob is big enough for its
* contents and must know the type of object in the blob to cast get().
*
- * Objects can be allocated directly in place using
- * construct(in_place<T>(...)) or copied using operator=.
- * Constructing a new object in the blob destroys the old one.
- *
* If BaseType is specified then only object that can be
* safely static_cast to BaseType may be stored in the Blob.
*/
@@ -140,12 +136,18 @@ class Blob
/** Copy a blob. */
Blob(const Blob& b) { initialize(); assign(b); }
- /** @see construct() */
+ /** Construct from in_place constructor */
template<class InPlace>
Blob(const InPlace & expr, typename EnableInPlace<InPlace>::type* =0) {
initialize(); apply(expr);
}
+ /** Construct by copying an objecct constructor */
+ template<class T>
+ Blob(const T & t, typename DisableInPlace<T>::type* =0) {
+ initialize(); apply(in_place<T>(t));
+ }
+
~Blob() { clear(); }
/** Assign from another blob. */
diff --git a/cpp/src/tests/amqp_0_10/Map.cpp b/cpp/src/tests/amqp_0_10/Map.cpp
index ad6f38b5d7..dcba6e38c2 100644
--- a/cpp/src/tests/amqp_0_10/Map.cpp
+++ b/cpp/src/tests/amqp_0_10/Map.cpp
@@ -19,7 +19,8 @@
*
*/
#include "unit_test.h"
-#include "qpid/amqp_0_10/Map.h"
+#include "qpid/amqp_0_10/all_built_in_types.h"
+//FIXME aconway 2008-04-08: #include "qpid/amqp_0_10/allSegmentTypes.h"
#include "qpid/amqp_0_10/Codec.h"
#include <iostream>
diff --git a/cpp/src/tests/amqp_0_10/serialize.cpp b/cpp/src/tests/amqp_0_10/serialize.cpp
index 16559b3516..e479151ec0 100644
--- a/cpp/src/tests/amqp_0_10/serialize.cpp
+++ b/cpp/src/tests/amqp_0_10/serialize.cpp
@@ -20,6 +20,10 @@
*/
#include "unit_test.h"
+
+#include "qpid/framing/AMQFrame.h"
+#include "qpid/framing/Buffer.h"
+
#include "qpid/amqp_0_10/Packer.h"
#include "qpid/amqp_0_10/built_in_types.h"
#include "qpid/amqp_0_10/Codec.h"
@@ -28,6 +32,7 @@
#include "qpid/amqp_0_10/FrameHeader.h"
#include "qpid/amqp_0_10/Map.h"
#include "qpid/amqp_0_10/Unit.h"
+#include "tests/allSegmentTypes.h"
#include <boost/test/test_case_template.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
@@ -266,21 +271,71 @@ BOOST_AUTO_TEST_CASE(testUnit) {
BOOST_CHECK_EQUAL(data, data2);
}
-// FIXME aconway 2008-04-07: TODO
-// BOOST_AUTO_TEST_CASE(testAllSegmentTypes) {
-// string data;
-// int n = allSegmentTypes(Codec::encode(data));
-
-// string data2;
-// Codec::Decoder<string::iterator> decode(data.begin(), data.size());
-// while (decode.pos() != data.end()) {
-// Unit unit;
-// decode(unit);
-// Codec::encode(back_insert(data));
-// --n;
-// }
-// BOOST_CHECK_EQUAL(n, 0);
-// BOOST_CHECK_EQUAL(data, data2);
+BOOST_AUTO_TEST_CASE(testArray) {
+ ArrayDomain<char> a;
+ a.resize(3, 'x');
+ string data;
+ Codec::encode(back_inserter(data))(a);
+
+ ArrayDomain<char> b;
+ Codec::decode(data.begin())(b);
+ BOOST_CHECK_EQUAL(b.size(), 3u);
+ string data3;
+ Codec::encode(back_inserter(data3))(a);
+ BOOST_CHECK_EQUAL(data, data3);
+
+ Array x;
+ Codec::decode(data.begin())(x);
+ BOOST_CHECK_EQUAL(x.size(), 3u);
+ BOOST_CHECK_EQUAL(x[0].size(), 1u);
+ BOOST_CHECK_EQUAL(*x[0].begin(), 'x');
+ BOOST_CHECK_EQUAL(*x[2].begin(), 'x');
+
+ string data2;
+ Codec::encode(back_inserter(data2))(x);
+ BOOST_CHECK_EQUAL(data,data2);
+}
+
+struct RecodeUnit {
+ template <class T>
+ void operator() (const T& t) {
+ using qpid::framing::Buffer;
+ using qpid::framing::AMQFrame;
+
+ Unit u(t);
+ connection::Start s;
+
+ string data;
+ Codec::encode(back_inserter(data))(u.getHeader())(u);
+ data.push_back(char(0xCE)); // Preview end-of-frame
+
+ Buffer buf(&data[0], data.size());
+ AMQFrame f;
+ f.decode(buf);
+
+ string data2(f.size(), ' ');
+ Buffer buf2(&data2[0], data.size());
+ f.encode(buf2);
+
+ BOOST_CHECK_EQUAL(data, data2);
+
+ Codec::Decoder<string::iterator> decode(data2.begin());
+ FrameHeader h;
+ decode(h);
+ Unit u2(h);
+ decode(u2);
+
+ string data3;
+ Codec::encode(back_inserter(data3))(u.getHeader())(u);
+
+ BOOST_CHECK_EQUAL(data3, data2);
+ }
+};
+
+// FIXME aconway 2008-04-08: TODO
+// BOOST_AUTO_TEST_CASE(testSerializeAllSegmentTypes) {
+// RecodeUnit recode;
+// allSegmentTypes(recode);
// }
QPID_AUTO_TEST_SUITE_END()
diff --git a/cpp/src/tests/python_tests b/cpp/src/tests/python_tests
index a3478eac1c..f35cb16480 100755
--- a/cpp/src/tests/python_tests
+++ b/cpp/src/tests/python_tests
@@ -3,10 +3,11 @@
QPID_PORT=${QPID_PORT:-5672}
PYTHON_TESTS=${PYTHON_TESTS:-$*}
+
run() {
SPEC=$1
FAILING=$2
- ./run-tests --skip-self-test -v -s $SPEC -I $FAILING -b localhost:$QPID_PORT $PYTHON_TESTS || exit 1
+ ./run-tests --skip-self-test -v -s $SPEC -I $FAILING -b localhost:$QPID_PORT $PYTHON_TESTS || { echo "FAIL python tests for $SPEC"; exit 1; }
}
if test -d ../../../python ; then