You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2008/02/29 23:07:45 UTC
svn commit: r632457 - in /incubator/qpid/trunk/qpid/cpp: rubygen/
rubygen/0-10/ src/ src/qpid/ src/qpid/amqp_0_10/ src/qpid/framing/ src/tests/
Author: aconway
Date: Fri Feb 29 14:07:40 2008
New Revision: 632457
URL: http://svn.apache.org/viewvc?rev=632457&view=rev
Log:
Template visitors for amqp_0_10::Command, Control and Struct.
Serialization for all str/vbin types.
Added:
incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/apply.h (with props)
incubator/qpid/trunk/qpid/cpp/src/tests/apply.cpp (with props)
Removed:
incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/visitors.h
Modified:
incubator/qpid/trunk/qpid/cpp/rubygen/0-10/specification.rb
incubator/qpid/trunk/qpid/cpp/rubygen/amqpgen.rb
incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb
incubator/qpid/trunk/qpid/cpp/src/Makefile.am
incubator/qpid/trunk/qpid/cpp/src/qpid/Serializer.h
incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Codec.h
incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Decimal.h
incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/built_in_types.h
incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.cpp
incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.h
incubator/qpid/trunk/qpid/cpp/src/qpid/framing/Uuid.h
incubator/qpid/trunk/qpid/cpp/src/tests/Makefile.am
incubator/qpid/trunk/qpid/cpp/src/tests/serialize.cpp
Modified: incubator/qpid/trunk/qpid/cpp/rubygen/0-10/specification.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/0-10/specification.rb?rev=632457&r1=632456&r2=632457&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/0-10/specification.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/0-10/specification.rb Fri Feb 29 14:07:40 2008
@@ -19,10 +19,8 @@
genl d.enum.choices.map { |c|
"#{c.name.constname} = #{c.value}" }.join(",\n")
}
- elsif (d.type_ == "array")
- genl "typedef Array<#{ArrayTypes[d.name].amqp2cpp}> #{typename};"
else
- genl "typedef #{d.type_.amqp2cpp} #{typename};"
+ genl "typedef #{d.amqp2cpp} #{typename};"
end
end
@@ -41,7 +39,7 @@
def action_struct_h(x, base, consts, &block)
genl
struct(x.classname, "public #{base}") {
- x.fields.each { |f| genl "#{f.type_.amqp2cpp} #{f.cppname};" }
+ x.fields.each { |f| genl "#{f.amqp2cpp} #{f.cppname};" }
genl
genl "static const char* NAME;"
consts.each { |c| genl "static const uint8_t #{c.upcase}=#{x.send c or 0};"}
@@ -58,10 +56,11 @@
genl
genl "const char* #{x.classname}::NAME=\"#{x.fqname}\";"
genl
- ctor_defn(x.classname) {}
- ctor_defn(x.classname, x.parameters, x.initializers) {} if not x.fields.empty?
- function_defn("void #{x.classname}::accept", ["Visitor&"], "const") {
- genl "// FIXME aconway 2008-02-27: todo"
+ ctor=x.classname+"::"+x.classname
+ ctor_defn(ctor) {}
+ ctor_defn(ctor, x.parameters, x.initializers) {} if not x.fields.empty?
+ function_defn("void #{x.classname}::accept", ["Visitor& v"], "const") {
+ genl "v.visit(*this);"
}
end
@@ -107,20 +106,21 @@
# they are used by other definitions:
each_class_ns { |c|
class_h c
- c.domains.each { |d| domain_h d if pregenerate? d }
- c.structs.each { |s| struct_h s if pregenerate? s }
+ c.collect_all(AmqpDomain).each { |d| domain_h d if pregenerate? d }
+ c.collect_all(AmqpStruct).each { |s| struct_h s if pregenerate? s }
}
# Now dependent domains/structs and actions
each_class_ns { |c|
- c.domains.each { |d| domain_h d if not pregenerate? d }
- c.structs.each { |s| struct_h s if not pregenerate? s }
- c.actions.each { |a| action_h a }
+ c.collect_all(AmqpDomain).each { |d| domain_h d unless pregenerate? d}
+ c.collect_all(AmqpStruct).each { |s| struct_h s unless pregenerate? s}
+ c.collect_all(AmqpAction).each { |a| action_h a }
}
}
}
cpp_file("#{@dir}/specification") {
include "#{@dir}/specification"
+ ["Command","Control","Struct"].each { |x| include "#{@dir}/Apply#{x}" }
namespace(@ns) {
each_class_ns { |c|
class_cpp c
@@ -156,10 +156,58 @@
}
}
end
-
+
+ def gen_visitor(base, subs)
+ h_file("#{@dir}/#{base}Visitor.h") {
+ include "#{@dir}/specification"
+ namespace("#{@ns}") {
+ genl
+ genl "/** Visitor interface for #{base} subclasses. */"
+ struct("#{base}::Visitor") {
+ genl "virtual ~Visitor() {}"
+ genl "typedef #{base} BaseType;"
+ subs.each{ |s|
+ genl "virtual void visit(const #{s.fqclassname}&) = 0;"
+ }}}}
+
+ h_file("#{@dir}/Apply#{base}.h") {
+ include "#{@dir}/#{base}Visitor.h"
+ include "#{@dir}/apply.h"
+ namespace("#{@ns}") {
+ genl
+ genl "/** apply() support for #{base} subclasses */"
+ genl "template <class F>"
+ struct("ApplyVisitor<#{base}::Visitor, F>",
+ ["public FunctionAndResult<F>", "public #{base}::Visitor"]) {
+ subs.each{ |s|
+ function_defn("virtual void visit", ["const #{s.fqclassname}& x"]) {
+ genl "this->invoke(x);"
+ }}}}}
+ end
+
+ def gen_visitors()
+ end
+
+ def holder(base, derived)
+ name=base.caps+"Holder"
+ h_file("#{@dir}/#{name}") {
+ include "#{@dir}/specification"
+ include "qpid/framing/Blob"
+ namespace(@ns){
+ # TODO aconway 2008-02-29:
+ }
+ }
+ end
+ def gen_holders()
+
+ end
+
def generate
gen_specification
gen_proxy
+ gen_visitor("Command", @amqp.collect_all(AmqpCommand))
+ gen_visitor("Control", @amqp.collect_all(AmqpControl))
+ gen_visitor("Struct", @amqp.collect_all(AmqpStruct))
end
end
Modified: incubator/qpid/trunk/qpid/cpp/rubygen/amqpgen.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/amqpgen.rb?rev=632457&r1=632456&r2=632457&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/amqpgen.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/amqpgen.rb Fri Feb 29 14:07:40 2008
@@ -131,6 +131,12 @@
@children.each { |c| c.each_descendant(&block) }
end
+ def collect_all(amqp_type)
+ collect=[]
+ each_descendant { |d| collect << d if d.is_a? amqp_type }
+ collect
+ end
+
# Look up child of type elname with attribute name.
def child(elname, name)
@cache_child[[elname,name]] ||= children(elname).find { |c| c.name==name }
@@ -386,6 +392,7 @@
def methods_() classes.map { |c| c.methods_ }.flatten; end
+ #preview
# Return all methods on chassis for all classes.
def methods_on(chassis)
@methods_on ||= { }
@@ -394,8 +401,6 @@
def fqname() nil; end
- # TODO aconway 2008-02-21: methods by role.
-
private
# Merge contents of elements.
Modified: incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb?rev=632457&r1=632456&r2=632457&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb Fri Feb 29 14:07:40 2008
@@ -57,6 +57,7 @@
def cppsafe() CppMangle.include?(self) ? self+"_" : self; end
def amqp2cpp()
+ throw 'Invalid "array".amqp2cpp' if self=="array"
path=split(".")
name=path.pop
return name.typename if path.empty?
@@ -112,21 +113,28 @@
def to_s() name; end;
end
+class AmqpElement
+ # convert my amqp type_ attribute to a C++ type.
+ def amqp2cpp()
+ return "Array<#{ArrayTypes[name].amqp2cpp}> " if type_=="array"
+ return type_.amqp2cpp
+ end
+end
+
class AmqpField
def cppname() name.lcaps.cppsafe; end
def cpptype() domain.cpptype; end
def bit?() domain.type_ == "bit"; end
def signature() cpptype.param+" "+cppname; end
- # FIXME aconway 2008-02-27: qualified
- def paramtype()
- fqtype=type_
- unless type_.index(".")
+ def fqtypename()
+ unless type_.index(".")
c=containing_class
return c.domain(type_).fqtypename if c.domain(type_)
return c.struct(type_).fqclassname if c.struct(type_)
end
- "call_traits<#{fqtype.amqp2cpp}>::param_type";
+ return amqp2cpp
end
+ def paramtype() "call_traits<#{fqtypename}>::param_type"; end
end
class AmqpMethod
@@ -337,8 +345,8 @@
def ctor_decl(name, params=[]) function_decl(name, params); end
def ctor_defn(name, params=[], inits=[])
- signature(name+"::"+name, params)
- scope(":","") { genl inits.join(",\n")} if not inits.empty?
+ signature(name, params, inits.empty? ? "" : " :")
+ indent { gen inits.join(",\n") } if not inits.empty?
scope() { yield }
end
Modified: incubator/qpid/trunk/qpid/cpp/src/Makefile.am
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/Makefile.am?rev=632457&r1=632456&r2=632457&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/Makefile.am (original)
+++ incubator/qpid/trunk/qpid/cpp/src/Makefile.am Fri Feb 29 14:07:40 2008
@@ -104,10 +104,10 @@
$(rgen_common_cpp) \
$(platform_src) \
qpid/amqp_0_10/helpers.cpp \
- qpid/Serializer.h \
qpid/amqp_0_10/built_in_types.h \
qpid/amqp_0_10/Codec.h \
qpid/amqp_0_10/Decimal.h \
+ qpid/Serializer.h \
qpid/framing/AccumulatedAck.cpp \
qpid/framing/AMQBody.cpp \
qpid/framing/AMQMethodBody.cpp \
@@ -254,6 +254,7 @@
nobase_include_HEADERS = \
$(platform_hdr) \
qpid/amqp_0_10/helpers.h \
+ qpid/amqp_0_10/apply.h \
qpid/assert.h \
qpid/DataDir.h \
qpid/Exception.h \
Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/Serializer.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/Serializer.h?rev=632457&r1=632456&r2=632457&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/Serializer.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/Serializer.h Fri Feb 29 14:07:40 2008
@@ -1,5 +1,5 @@
-#ifndef QPID_SERIALIZERBASE_H
-#define QPID_SERIALIZERBASE_H
+#ifndef QPID_SERIALIZER_H
+#define QPID_SERIALIZER_H
/*
*
@@ -22,88 +22,36 @@
*
*/
-#include <boost/cast.hpp>
-#include <boost/array.hpp>
+#include <boost/type_traits/remove_const.hpp>
#include <boost/utility/enable_if.hpp>
-#include <boost/type_traits/is_class.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/add_const.hpp>
+#include <algorithm>
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.
- *
+ * Base class for serializers.
*/
template <class Derived> class Serializer {
public:
-
- /** Call T::serialize() for classes that have their own serialize function */
- template <class T>
- typename boost::enable_if<boost::is_class<T>, Derived>::type
- operator()(T& t) { t.serialize(self()); return self(); }
-
- template <class T, size_t N>
- Derived& operator()(boost::array<T,N>& 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 <class T> Derived& raw(T& t) {
- return self().raw(&t, sizeof(T));
- }
-
- private:
- Derived& self() { return *static_cast<Derived*>(this); }
-};
-
-/** Like Serializer but does not modify the values passed to it. */
-template <class Derived> class ConstSerializer {
- public:
template <class T>
- typename boost::enable_if<boost::is_class<T>, Derived>::type
- operator()(const T& t) {
- // Const cast so we don't have to write 2 serialize() functions
- // for every class.
- const_cast<T&>(t).serialize(self());
+ 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());
return self();
}
- template <class T, size_t N>
- Derived& operator()(const boost::array<T,N>& a) {
- std::for_each(a.begin(), a.end(), self());
+ template <class Iter> Derived& iterate(Iter begin, Iter end) {
+ std::for_each(begin, 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 <class T> Derived& raw(const T& t) {
- return self().raw(&t, sizeof(T));
- }
-
private:
Derived& self() { return *static_cast<Derived*>(this); }
};
-
} // namespace qpid
-#endif /*!QPID_SERIALIZERBASE_H*/
+#endif /*!QPID_SERIALIZER_H*/
Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Codec.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Codec.h?rev=632457&r1=632456&r2=632457&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Codec.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Codec.h Fri Feb 29 14:07:40 2008
@@ -32,70 +32,47 @@
namespace qpid {
namespace amqp_0_10 {
-
/**
* AMQP 0-10 encoding and decoding.
*/
-struct Codec
-{
- template <class T>
- 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 <class Out> struct Encode : public ConstSerializer<Encode<Out> > {
- Out out;
+class Codec {
+ public:
+ /** Encode to an output byte iterator */
+ template <class OutIter>
+ class Encode : public Serializer<Encode<OutIter> > {
+ public:
+ Encode(OutIter o) : out(o) {}
- Encode(Out o) : out(o) {}
+ using Serializer<Encode<OutIter> >::operator();
- using ConstSerializer<Encode<Out> >::operator();
- using ConstSerializer<Encode<Out> >::raw;
-
- template <class T>
+ template <class T>
typename boost::enable_if<boost::is_integral<T>, Encode&>::type
- operator()(const T& x) { T xx(x); endianize(xx); return raw(xx); }
+ operator()(T x) {
+ endianize(x);
+ raw(&x, sizeof(x));
+ return *this;
+ }
- // FIXME aconway 2008-02-20: correct float encoading
+ // FIXME aconway 2008-02-20: correct float encoading?
template <class T>
typename boost::enable_if<boost::is_float<T>, Encode&>::type
- operator()(const T& x) { return raw(x); }
-
+ operator()(const T& x) { raw(&x, sizeof(x)); return *this; }
- template<class T, class SizeType>
- Encode& operator()(const CodableString<T,SizeType>& str) {
- (*this)(SizeType(str.size()));
- std::for_each(str.begin(), str.end(), *this);
- return *this;
+ void raw(const void* p, size_t n) {
+ std::copy((const char*)p, (const char*)p+n, out);
}
-
+
private:
- friend class ConstSerializer<Encode<Out> >;
-
- 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; }
+ OutIter out;
};
- template <class In> struct Decode : public Serializer<Decode<In> > {
- In in;
- Decode(In i) : in(i) {}
-
- using Serializer<Decode<In> >::operator();
- using Serializer<Decode<In> >::raw;
-
+ template <class InIter>
+ class Decode : public Serializer<Decode<InIter> > {
+ public:
+ Decode(InIter i) : in(i) {}
+
+ using Serializer<Decode<InIter> >::operator();
+
template <class T>
typename boost::enable_if<boost::is_integral<T>, Decode&>::type
operator()(T& x) {
@@ -106,10 +83,10 @@
template <class T>
typename boost::enable_if<boost::is_float<T>, Decode&>::type
- operator()(T& x) { return raw(&x, sizeof(x)); }
+ operator()(T& x) { raw(&x, sizeof(x)); return *this; }
template<class T, class SizeType>
- Decode& operator()(CodableString<T,SizeType>& str) {
+ Decode& operator()(SerializableString<T,SizeType>& str) {
SizeType n;
(*this)(n);
str.resize(n);
@@ -117,54 +94,45 @@
return *this;
}
- private:
- friend class Serializer<Decode<In> >;
-
- Decode& raw(void* vp, size_t s) {
- char* p=(char*)vp;
- std::copy(in, in+s, p);
- 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?
+ std::copy(in, in+n, (char*)p);
+ in += n;
}
- Decode& byte(char& x) { x = *in++; return *this; }
+ private:
+ InIter in;
};
- struct Size : public ConstSerializer<Size> {
+
+ class Size : public Serializer<Size> {
+ public:
Size() : size(0) {}
- size_t size;
+
operator size_t() const { return size; }
- using ConstSerializer<Size>::operator();
- using ConstSerializer<Size>::raw;
+ using Serializer<Size>::operator();
template <class T>
typename boost::enable_if<boost::is_arithmetic<T>, Size&>::type
operator()(const T&) { size += sizeof(T); return *this; }
- template <class T, size_t N>
- Size& operator()(const boost::array<T,N>&) {
- size += sizeof(boost::array<T,N>);
- return *this;
- }
-
template<class T, class SizeType>
- Size& operator()(const CodableString<T,SizeType>& str) {
+ Size& operator()(const SerializableString<T,SizeType>& str) {
size += sizeof(SizeType) + str.size()*sizeof(T);
return *this;
}
+ void raw(const void*, size_t n){ size += n; }
private:
- friend class ConstSerializer<Size>;
-
- Size& raw(void*, size_t s) { size += s; return *this; }
-
- Size& byte(char) { ++size; return *this; }
+ size_t size;
};
template <class Out, class T>
static void encode(Out o, const T& x) {
- Encode<Out>encode(o);
+ Encode<Out> encode(o);
encode(x);
}
@@ -180,6 +148,18 @@
sz(x);
return sz;
}
+
+ private:
+ template <class T> 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&) {}
};
}} // namespace qpid::amqp_0_10
Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Decimal.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Decimal.h?rev=632457&r1=632456&r2=632457&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Decimal.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Decimal.h Fri Feb 29 14:07:40 2008
@@ -30,7 +30,7 @@
E exponent;
M mantissa;
- Decimal() : exponent(0), mantissa(0) {}
+ Decimal(E exp=0, M man=0) : exponent(exp), mantissa(man) {}
bool operator==(const Decimal& d) const {
return exponent == d.exponent && mantissa == d.mantissa;
@@ -44,8 +44,7 @@
template<class E, class M>
inline std::ostream& operator<<(std::ostream& o, const Decimal<E,M>& d) {
- M pow10=10^d.exponent;
- return o << d.mantissa/pow10 << "." << d.mantissa%pow10;
+ return o << "Decimal{" << d.mantissa << "/10^" << (int)d.exponent << "}";
}
}}
Added: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/apply.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/apply.h?rev=632457&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/apply.h (added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/apply.h Fri Feb 29 14:07:40 2008
@@ -0,0 +1,77 @@
+#ifndef QPID_AMQP_0_10_APPLY_H
+#define QPID_AMQP_0_10_APPLY_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 <boost/optional.hpp>
+
+namespace qpid {
+namespace amqp_0_10 {
+
+template <class F, class R=typename F::result_type> struct FunctionAndResult {
+ F* functor;
+ boost::optional<R> result;
+
+ FunctionAndResult() : functor(0) {}
+ template <class T> void invoke(T t) { result=(*functor)(t); }
+ R getResult() { return *result; }
+};
+
+// void result is special case.
+template <class F> struct FunctionAndResult<F, void> {
+ F* functor;
+
+ FunctionAndResult() : functor(0) {}
+ 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;
+};
+
+// Specialize for each visitor type
+template <class V, class F> struct ApplyVisitor;
+
+/** Apply a functor to a visitable object.
+ * The functor can have operator() overloads for each visitable type
+ * and/or templated operator().
+ */
+template <class F, class Visitable>
+typename F::result_type apply(F& functor, Visitable& visitable) {
+ ApplyVisitor<typename Visitable::Visitor, F> visitor;
+ visitor.functor=&functor;
+ visitable.accept(visitor);
+ return visitor.getResult();
+}
+
+template <class F, class Visitable>
+typename F::result_type apply(const F& functor, Visitable& visitable) {
+ ApplyVisitor<typename Visitable::Visitor, const F> visitor;
+ visitor.functor=&functor;
+ visitable.accept(visitor);
+ return visitor.getResult();
+}
+
+}} // namespace qpid::amqp_0_10
+
+#endif /*!QPID_AMQP_0_10_APPLY_H*/
Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/apply.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/apply.h
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/built_in_types.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/built_in_types.h?rev=632457&r1=632456&r2=632457&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/built_in_types.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/built_in_types.h Fri Feb 29 14:07:40 2008
@@ -1,6 +1,5 @@
#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
@@ -29,6 +28,7 @@
#include <boost/array.hpp>
#include <stdint.h>
#include <string>
+#include <ostream>
#include <vector>
/**@file Mapping from built-in AMQP types to C++ types */
@@ -53,15 +53,19 @@
typedef uint8_t Bin8;
typedef uint8_t Uint8;
-typedef boost::array<uint8_t,128> Bin1024;
-typedef boost::array<uint8_t,16> Bin128;
-typedef boost::array<uint8_t,2> Bin16;
-typedef boost::array<uint8_t,32> Bin256;
-typedef boost::array<uint8_t,4> Bin32;
-typedef boost::array<uint8_t,5> Bin40;
-typedef boost::array<uint8_t,64> Bin512;
-typedef boost::array<uint8_t,8> Bin64;
-typedef boost::array<uint8_t,9> Bin72;
+template <size_t N> struct Bin : public boost::array<char, N> {
+ template <class S> void serialize(S& s) { s.raw(this->begin(), this->size()); }
+};
+
+typedef Bin<128> Bin1024;
+typedef Bin<16> Bin128;
+typedef Bin<2> Bin16;
+typedef Bin<32> Bin256;
+typedef Bin<4> Bin32;
+typedef Bin<5> Bin40;
+typedef Bin<64> Bin512;
+typedef Bin<8> Bin64;
+typedef Bin<9> Bin72;
typedef double Double;
typedef float Float;
@@ -75,25 +79,35 @@
/** Template for length-prefixed strings/arrays. */
template <class T, class SizeType>
-struct CodableString : public std::basic_string<T> {};
+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());
+ }
+};
+
+// TODO aconway 2008-02-29: separate ostream ops
+template <class T, class SizeType>
+std::ostream& operator<<(std::ostream& o, const SerializableString<T,SizeType>& s) {
+ const std::basic_string<T> str(s);
+ return o << str.c_str(); // TODO aconway 2008-02-29: why doesn't o<<str work?
+}
// Variable width types
-typedef CodableString<Uint8, Uint8> Vbin8;
-typedef CodableString<char, Uint8> Str8Latin;
-typedef CodableString<char, Uint8> Str8;
-typedef CodableString<Uint16, Uint8> Str8Utf16;
-
-typedef CodableString<Uint8, Uint16> Vbin16;
-typedef CodableString<char, Uint16> Str16Latin;
-typedef CodableString<char, Uint16> Str16;
-typedef CodableString<Uint16, Uint16> Str16Utf16;
+typedef SerializableString<Uint8, Uint8> Vbin8;
+typedef SerializableString<char, Uint8> Str8Latin;
+typedef SerializableString<char, Uint8> Str8;
+typedef SerializableString<Uint16, Uint8> Str8Utf16;
+
+typedef SerializableString<Uint8, Uint16> Vbin16;
+typedef SerializableString<char, Uint16> Str16Latin;
+typedef SerializableString<char, Uint16> Str16;
+typedef SerializableString<Uint16, Uint16> Str16Utf16;
-typedef CodableString<Uint8, Uint32> Vbin32;
-
-// FIXME aconway 2008-02-26: array encoding
-template <class T> struct Array : public std::vector<T> {};
+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 {};
Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.cpp?rev=632457&r1=632456&r2=632457&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.cpp Fri Feb 29 14:07:40 2008
@@ -19,6 +19,9 @@
*
*/
#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 {
Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.h?rev=632457&r1=632456&r2=632457&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.h Fri Feb 29 14:07:40 2008
@@ -24,7 +24,6 @@
#include <string>
namespace qpid {
-
namespace amqp_0_10 {
// Look up names by code
@@ -35,19 +34,19 @@
struct Command {
virtual ~Command();
- class Visitor;
+ struct Visitor;
virtual void accept(Visitor&) const = 0;
};
struct Control {
virtual ~Control();
- class Visitor;
+ struct Visitor;
virtual void accept(Visitor&) const = 0;
};
struct Struct {
virtual ~Struct();
- class Visitor;
+ struct Visitor;
virtual void accept(Visitor&) const = 0;
};
Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/framing/Uuid.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/framing/Uuid.h?rev=632457&r1=632456&r2=632457&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/framing/Uuid.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/framing/Uuid.h Fri Feb 29 14:07:40 2008
@@ -67,7 +67,7 @@
std::string str() const;
template <class S> void serialize(S& s) {
- s(static_cast<boost::array<uint8_t, 16>&>(*this));
+ s.raw(begin(), size());
}
};
Modified: incubator/qpid/trunk/qpid/cpp/src/tests/Makefile.am
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/tests/Makefile.am?rev=632457&r1=632456&r2=632457&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/tests/Makefile.am (original)
+++ incubator/qpid/trunk/qpid/cpp/src/tests/Makefile.am Fri Feb 29 14:07:40 2008
@@ -39,7 +39,7 @@
ISList.cpp IList.cpp \
ClientSessionTest.cpp \
serialize.cpp \
- ProxyTemplate.cpp
+ ProxyTemplate.cpp apply.cpp
# FIXME aconway 2008-02-20: removed RefCountedMap.cpp due to valgrind error.
check_LTLIBRARIES += libshlibtest.la
Added: incubator/qpid/trunk/qpid/cpp/src/tests/apply.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/tests/apply.cpp?rev=632457&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/tests/apply.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/src/tests/apply.cpp Fri Feb 29 14:07:40 2008
@@ -0,0 +1,92 @@
+/*
+ *
+ * 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 "unit_test.h"
+#include "qpid/amqp_0_10/specification.h"
+#include "qpid/amqp_0_10/ApplyControl.h"
+
+QPID_AUTO_TEST_SUITE(VisitorTestSuite)
+
+using namespace qpid::amqp_0_10;
+
+struct GetCode {
+ typedef uint8_t result_type;
+ template <class T> uint8_t operator()(const T&) const { return T::CODE; }
+};
+
+struct TestFunctor {
+ typedef bool result_type;
+ bool operator()(const connection::Tune& tune) {
+ BOOST_CHECK_EQUAL(tune.channelMax, 1u);
+ BOOST_CHECK_EQUAL(tune.maxFrameSize, 2u);
+ BOOST_CHECK_EQUAL(tune.heartbeatMin, 3u);
+ BOOST_CHECK_EQUAL(tune.heartbeatMax, 4u);
+ return true;
+ }
+ template <class T>
+ bool operator()(const T&) { return false; }
+};
+
+BOOST_AUTO_TEST_CASE(testApply) {
+ connection::Tune tune(1,2,3,4);
+ Control* p = &tune;
+
+ // boost oddity - without the cast we get undefined symbol errors.
+ BOOST_CHECK_EQUAL(apply(GetCode(), *p), (uint8_t)connection::Tune::CODE);
+
+ TestFunctor tf;
+ BOOST_CHECK(apply(tf, *p));
+
+ connection::Start start;
+ p = &start;
+ BOOST_CHECK(!apply(tf, *p));
+}
+
+struct VoidTestFunctor {
+ typedef void result_type;
+
+ int code;
+ VoidTestFunctor() : code() {}
+
+ void operator()(const connection::Tune& tune) {
+ BOOST_CHECK_EQUAL(tune.channelMax, 1u);
+ BOOST_CHECK_EQUAL(tune.maxFrameSize, 2u);
+ BOOST_CHECK_EQUAL(tune.heartbeatMin, 3u);
+ BOOST_CHECK_EQUAL(tune.heartbeatMax, 4u);
+ code=connection::Tune::CODE;
+ }
+ template <class T>
+ void operator()(const T&) { code=0xFF; }
+};
+
+BOOST_AUTO_TEST_CASE(testApplyVoid) {
+ connection::Tune tune(1,2,3,4);
+ Control* p = &tune;
+ VoidTestFunctor tf;
+ apply(tf, *p);
+ BOOST_CHECK_EQUAL(uint8_t(connection::Tune::CODE), tf.code);
+
+ connection::Start start;
+ p = &start;
+ apply(tf, *p);
+ BOOST_CHECK_EQUAL(0xFF, tf.code);
+}
+
+QPID_AUTO_TEST_SUITE_END()
Propchange: incubator/qpid/trunk/qpid/cpp/src/tests/apply.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/qpid/trunk/qpid/cpp/src/tests/apply.cpp
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: incubator/qpid/trunk/qpid/cpp/src/tests/serialize.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/tests/serialize.cpp?rev=632457&r1=632456&r2=632457&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/tests/serialize.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/tests/serialize.cpp Fri Feb 29 14:07:40 2008
@@ -31,7 +31,7 @@
#include <boost/mpl/empty_sequence.hpp>
#include <iterator>
#include <string>
-#include <ostream>
+#include <iostream>
#include <netinet/in.h>
// Missing operators needed for tests.
@@ -52,15 +52,6 @@
}
}
-namespace amqp_0_10 {
-template <class T, class SizeType>
-std::ostream& operator<<(std::ostream& out, const CodableString<T,SizeType>& str) {
- std::ostream_iterator<T> o(out, " ");
- std::copy(str.begin(), str.end(), o);
- return out;
-}
-}
-
} // qpid
@@ -90,34 +81,37 @@
BOOST_AUTO_TEST_CASE(testNetworkByteOrder) {
string data;
- uint32_t l = 1234567890;
+ uint32_t l = 0x11223344;
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 = 12345;
+ uint16_t s = 0x1122;
Codec::encode(std::back_inserter(data), s);
uint32_t s2 = ntohs(*reinterpret_cast<const uint32_t*>(data.data()));
BOOST_CHECK_EQUAL(s, s2);
}
+// Assign test values to the various types.
void testValue(bool& b) { b = true; }
template <class T> typename boost::enable_if<boost::is_arithmetic<T> >::type testValue(T& n) { n=42; }
-void testValue(long long& l) { l = 12345; }
+void testValue(long long& l) { l = 0x012345; }
void testValue(Datetime& dt) { dt = qpid::sys::now(); }
void testValue(Uuid& uuid) { uuid=Uuid(true); }
-template <class E, class M> void testValue(Decimal<E,M>& d) { d.exponent=2; d.mantissa=1234; }
+template <class E, class M> void testValue(Decimal<E,M>& d) { d.exponent=2; d.mantissa=0x1122; }
void testValue(SequenceNo& s) { s = 42; }
-template <class T, size_t N> void testValue(boost::array<T,N>& a) { a.assign(42); }
-template <class T, class SizeType> void testValue(CodableString<T, SizeType>& s) {
+template <size_t N> void testValue(Bin<N>& a) { a.assign(42); }
+template <class T, class S> void testValue(SerializableString<T, S>& s) {
char msg[]="foobar";
s.assign(msg, msg+sizeof(msg));
}
+void testValue(Str16& s) { s = "the quick brown fox jumped over the lazy dog"; }
+void testValue(Str8& s) { s = "foobar"; }
-// FIXME aconway 2008-02-20: test AllTypes
-BOOST_AUTO_TEST_CASE_TEMPLATE(testEncodeDecode, T, FixedSizeTypes)
+//typedef mpl::vector<Str8, Str16>::type TestTypes;
+BOOST_AUTO_TEST_CASE_TEMPLATE(testEncodeDecode, T, AllTypes)
{
string data;
T t;