Author: aconway
Date: Tue Mar  4 08:34:01 2008
New Revision: 633533

URL: http://svn.apache.org/viewvc?rev=633533&view=rev
Log:
Completed holders, visitors and serialization for 0-10 commands and controls.

Added:
    incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Holder.h   (with props)
    incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp   (with 
props)
    incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/complex_types.h   (with 
props)
Removed:
    incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.h
Modified:
    incubator/qpid/trunk/qpid/cpp/rubygen/0-10/specification.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/apply.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/built_in_types.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQBody.h
    incubator/qpid/trunk/qpid/cpp/src/tests/apply.cpp
    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=633533&r1=633532&r2=633533&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/0-10/specification.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/0-10/specification.rb Tue Mar  4 
08:34:01 2008
@@ -15,10 +15,11 @@
     genl
     typename=d.name.typename
     if d.enum
-      scope("enum #{typename} {", "};") { 
+      scope("enum #{typename}Enum {", "};") { 
         genl d.enum.choices.map { |c|
           "#{c.name.constname} = #{c.value}" }.join(",\n")
       }
+      genl "typedef Enum<#{typename}Enum, uint8_t> #{typename};"
     else
       genl "typedef #{d.amqp2cpp} #{typename};"
     end
@@ -42,11 +43,15 @@
       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};"}
+      consts.each {
+        |c| genl "static const uint8_t #{c.upcase}=#{(x.send c) or 0};"
+      }
       genl "static const uint8_t 
CLASS_CODE=#{x.containing_class.nsname}::CODE;"
+      genl "static const char* CLASS_NAME;"
       ctor_decl(x.classname,[])
       ctor_decl(x.classname, x.parameters) unless x.fields.empty?
-      function_decl("void accept", ["Visitor&"], "const")
+      genl "void accept(Visitor&);" 
+      genl "void accept(ConstVisitor&) const;"
       genl
       yield if block
     }
@@ -55,13 +60,19 @@
   def action_struct_cpp(x)
     genl
     genl "const char* #{x.classname}::NAME=\"#{x.fqname}\";"
+    genl "const char* 
#{x.classname}::CLASS_NAME=#{x.containing_class.nsname}::NAME;"
     genl
     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);"
-    }
+    # FIXME aconway 2008-03-04: struct visitors
+    if x.is_a? AmqpStruct
+      genl "void #{x.classname}::accept(Visitor&) { assert(0); }"
+      genl "void #{x.classname}::accept(ConstVisitor&) const { assert(0); }"
+    else
+      genl "void #{x.classname}::accept(Visitor& v) {  v.visit(*this); }"
+      genl "void #{x.classname}::accept(ConstVisitor& v) const { 
v.visit(*this); }"
+    end
   end
 
   # structs
@@ -76,11 +87,13 @@
       function_defn("template <class T> void invoke", ["T& target"]) {
         genl "target.#{a.funcname}(#{a.values.join(', ')});"
       }
-      function_defn("template <class S> void serialize", ["S& s"]) { 
-        gen "s"
-        a.fields.each { |f| gen "(#{f.cppname})"}
-        genl ";"
-      } unless a.fields.empty?
+      if (a.fields.empty?)
+        genl "template <class S> void serialize(S&) {}"
+      else
+        scope("template <class S> void serialize(S& s) {") {
+          gen "s"; a.fields.each { |f| gen "(#{f.cppname})"}; genl ";"
+        }
+      end
     }
   end
   
@@ -93,7 +106,7 @@
   def gen_specification()
     h_file("[EMAIL PROTECTED]/specification") {
       include "[EMAIL PROTECTED]/built_in_types"
-      include "[EMAIL PROTECTED]/helpers"
+      include "[EMAIL PROTECTED]/complex_types"
       include "<boost/call_traits.hpp>"
       genl "using boost::call_traits;"
       namespace(@ns) {
@@ -120,12 +133,13 @@
 
     cpp_file("[EMAIL PROTECTED]/specification") { 
       include "[EMAIL PROTECTED]/specification"
-      ["Command","Control","Struct"].each { |x| include "[EMAIL 
PROTECTED]/Apply#{x}" }
+      # FIXME aconway 2008-03-04: add Struct visitors.
+      ["Command","Control"].each { |x| include "[EMAIL PROTECTED]/Apply#{x}" }
       namespace(@ns) { 
         each_class_ns { |c|
           class_cpp c
           c.actions.each { |a| action_cpp a}
-          c.structs.each { |s| struct_cpp s }
+          c.collect_all(AmqpStruct).each {  |s| struct_cpp(s) }
         }
       }
     }
@@ -157,57 +171,98 @@
     }
   end
 
+  def visitor_interface_h(base, subs, is_const)
+    name="#{is_const ? 'Const' : ''}#{base}Visitor"
+    const=is_const ? "const " : ""
+    struct(name) {
+      genl "virtual ~#{name}() {}"
+      genl "typedef #{const}#{base} BaseType;"
+      subs.each{ |s|
+        genl "virtual void visit(#{const}#{s.fqclassname}&) = 0;"
+      }}
+  end
+
+  def visitor_impl(base, subs, is_const)
+    name="#{is_const ? 'Const' : ''}#{base}Visitor"
+    const=is_const ? "const " : ""
+    genl "template <class F>"
+    struct("ApplyVisitor<#{name}, F>", "public ApplyVisitorBase<#{name}, F>") {
+      subs.each{ |s|
+        genl "virtual void visit(#{const}#{s.fqclassname}& x) { 
this->invoke(x); }" 
+      }}
+  end
+  
   def gen_visitor(base, subs)
     h_file("[EMAIL PROTECTED]/#{base}Visitor.h") { 
       include "[EMAIL PROTECTED]/specification"
       namespace("[EMAIL PROTECTED]") { 
-        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;"
-          }}}}
-
+        visitor_interface_h(base, subs, false)
+        visitor_interface_h(base, subs, true)
+      }}
+    
     h_file("[EMAIL PROTECTED]/Apply#{base}.h") {
       include "[EMAIL PROTECTED]/#{base}Visitor.h"
       include "[EMAIL PROTECTED]/apply.h"
       namespace("[EMAIL PROTECTED]") { 
-        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()
+        visitor_impl(base, subs, false)
+        visitor_impl(base, subs, true)
+      }
+    }
   end
-
-  def holder(base, derived)
+  
+  def gen_holder(base, subs)
     name=base.caps+"Holder"
     h_file("[EMAIL PROTECTED]/#{name}") {
-      include "[EMAIL PROTECTED]/specification"
-      include "qpid/framing/Blob"
-      namespace(@ns){ 
-        # TODO aconway 2008-02-29: 
-      }
-    }
+      include "[EMAIL PROTECTED]/Apply#{base}"
+      include "[EMAIL PROTECTED]/Holder"
+      namespace(@ns){
+        namespace("#{base.downcase}_max") {
+          gen "template <class M, class X> "
+          struct("Max") {
+            genl "static const size_t max=(M::max > sizeof(X)) ? M::max : 
sizeof(X);"
+          }
+          genl "struct Max000 { static const size_t max=0; };"
+          last="Max000"
+          subs.each { |s|
+            genl "typedef Max<#{last}, #{s.fqclassname}> #{last.succ!};"
+          }
+          genl "static const int MAX=#{last}::max;"
+        }
+        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 "using #{holder_base}::operator=;"
+          genl "void set(uint8_t classCode, uint8_t code);"
+        }}}
+    
+    cpp_file("[EMAIL PROTECTED]/#{name}") {
+      include "[EMAIL PROTECTED]/#{name}"
+      namespace(@ns) {
+        genl "using framing::in_place;"
+        genl
+        scope("void #{name}::set(uint8_t classCode, uint8_t code) {") {
+          genl "uint16_t key=(classCode<<8)+code;"
+          scope ("switch(key) {") {
+            subs.each { |s|
+              genl "case 0x#{s.full_code.to_s(16)}: 
*this=in_place<#{s.fqclassname}>(); break;"
+            }
+            genl "default: assert(0);"
+          }}}}
   end
-  def gen_holders()
 
+  def gen_visitable(base, subs)
+    gen_holder(base, subs)
+    gen_visitor(base, subs)
   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))
+    gen_visitable("Command", @amqp.collect_all(AmqpCommand))
+    gen_visitable("Control", @amqp.collect_all(AmqpControl))
+    # FIXME aconway 2008-03-04: sort out visitable structs.
+    # gen_visitable("Struct", @amqp.collect_all(AmqpStruct))
   end
 end
 

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb?rev=633533&r1=633532&r2=633533&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb Tue Mar  4 08:34:01 2008
@@ -162,7 +162,7 @@
   def classname() name.typename; end
   def funcname() parent.name.funcname + name.caps; end
   def fqclassname() parent.name+"::"+classname; end
-
+  def full_code() (containing_class.code.hex << 8)+code.hex; end
   include AmqpHasFields
 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=633533&r1=633532&r2=633533&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/Makefile.am (original)
+++ incubator/qpid/trunk/qpid/cpp/src/Makefile.am Tue Mar  4 08:34:01 2008
@@ -103,8 +103,10 @@
 libqpidcommon_la_SOURCES = \
   $(rgen_common_cpp) \
   $(platform_src) \
-  qpid/amqp_0_10/helpers.cpp \
   qpid/amqp_0_10/built_in_types.h \
+  qpid/amqp_0_10/complex_types.h \
+  qpid/amqp_0_10/complex_types.cpp \
+  qpid/amqp_0_10/Holder.h \
   qpid/amqp_0_10/Codec.h \
   qpid/amqp_0_10/Decimal.h \
   qpid/Serializer.h \
@@ -254,7 +256,6 @@
 
 nobase_include_HEADERS = \
   $(platform_hdr) \
-  qpid/amqp_0_10/helpers.h \
   qpid/amqp_0_10/apply.h \
   qpid/assert.h \
   qpid/DataDir.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=633533&r1=633532&r2=633533&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/Serializer.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/Serializer.h Tue Mar  4 08:34:01 2008
@@ -22,36 +22,59 @@
  *
  */
 
-#include <boost/type_traits/remove_const.hpp>
 #include <boost/utility/enable_if.hpp>
-#include <boost/type_traits/is_const.hpp>
+#include <boost/static_assert.hpp>
 #include <boost/type_traits/is_class.hpp>
-#include <boost/type_traits/add_const.hpp>
 #include <algorithm>
 
 namespace qpid {
 
-/**
- * Base class for serializers.
- */
+// FIXME aconway 2008-03-03: Doc - esp decoding
 template <class Derived> class Serializer {
   public:
+    typedef Serializer result_type; // unary functor requirement.
+
+    static const bool IS_DECODER=false;
+
+    /** Generic handler for class objects, call serialize() */
     template <class T>
     typename boost::enable_if<boost::is_class<T>, Derived&>::type
     operator()(T& t) {
-        // const_cast so we don't need 2 serialize() members for every class.
-        const_cast<typename 
boost::remove_const<T>::type&>(t).serialize(self());
+        t.serialize(self());
         return self();
     }
 
-    template <class Iter> Derived& iterate(Iter begin, Iter end) {
-        std::for_each(begin, end, self());
+    /** Generic handler for const class objects, call serialize() */
+    template <class T>
+    typename boost::enable_if<boost::is_class<T>, Derived&>::type
+    operator()(const T& t) {
+        assert(!Derived::IS_DECODER); // We won't modify the value.
+        // const_cast so we don't need 2 serialize() members for every class.
+        const_cast<T&>(t).serialize(self());
         return self();
     }
 
+    template <class T, bool=false> struct Split {
+        Split(Derived& s, T& t) { t.encode(s); }
+    };
+    
+    template <class T> struct Split<T,true> {
+        Split(Derived& s, T& t) { t.decode(s); }
+    };
+    /**
+     * Called by classes that want to receive separate
+     * encode()/decode() calls.
+     */
+    template <class T>
+    void split(T& t) { Split<T, Derived::IS_DECODER>(self(),t); }
+
   private:
     Derived& self() { return *static_cast<Derived*>(this); }
 };
+
+
+
+
 
 } // namespace qpid
 

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=633533&r1=633532&r2=633533&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 Tue Mar  4 
08:34:01 2008
@@ -28,15 +28,14 @@
 #include <boost/type_traits/is_float.hpp>
 #include <boost/type_traits/is_arithmetic.hpp>
 #include <boost/detail/endian.hpp>
-#include <boost/ref.hpp>
 
 namespace qpid {
 namespace amqp_0_10 {
 /**
  * AMQP 0-10 encoding and decoding.
  */
-class Codec {
-  public:
+struct Codec {                  // FIXME aconway 2008-02-29: drop this wrapper?
+
     /** Encode to an output byte iterator */
     template <class OutIter>
     class Encode : public Serializer<Encode<OutIter> > {
@@ -58,6 +57,11 @@
         typename boost::enable_if<boost::is_float<T>, Encode&>::type
         operator()(const T& x) { raw(&x, sizeof(x)); return *this; }
 
+        template <class Iter> Encode& operator()(Iter begin, Iter end) {
+            std::for_each(begin, end, *this);
+            return *this;
+        }
+
         void raw(const void* p, size_t n) {
             std::copy((const char*)p, (const char*)p+n, out); 
         }
@@ -70,6 +74,8 @@
     class Decode : public Serializer<Decode<InIter> > {
       public:
         Decode(InIter i) : in(i) {}
+
+        static const bool IS_DECODER=true;
         
         using Serializer<Decode<InIter> >::operator();
         
@@ -94,6 +100,11 @@
             return *this;
         }
 
+        template <class Iter> Decode& operator()(Iter begin, Iter end) {
+            std::for_each(begin, end, *this);
+            return *this;
+        }
+
         void raw(void *p, size_t n) {
             // FIXME aconway 2008-02-29: requires random access iterator,
             // does this optimize to memcpy? Is there a better way?
@@ -124,30 +135,27 @@
             return *this;
         }
 
+        template <class Iter>
+        Size& operator()(const Iter& a, const Iter& b) {
+            size += (b-a)*sizeof(*a);
+            return *this;
+        }
+
         void raw(const void*, size_t n){ size += n; }
 
       private:
         size_t size;
     };
 
-    template <class Out, class T>
-    static void encode(Out o, const T& x) {
-        Encode<Out> encode(o);
-        encode(x);
+    template <class OutIter> static Decode<OutIter> decode(const OutIter &i) {
+        return Decode<OutIter>(i);
     }
 
-    template <class In, class T>
-    static void decode(In i, T& x) {
-        Decode<In> decode(i);
-        decode(x);
+    template <class InIter> static Encode<InIter> encode(InIter i) {
+        return Encode<InIter>(i);
     }
 
-    template <class T>
-    static size_t size(const T& x) {
-        Size sz;
-        sz(x);
-        return sz;
-    }
+    template <class T> static size_t size(const T& x) { return Size()(x); }
 
   private:
     template <class T> static inline void endianize(T& value) {

Added: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Holder.h
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Holder.h?rev=633533&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Holder.h (added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Holder.h Tue Mar  4 
08:34:01 2008
@@ -0,0 +1,62 @@
+#ifndef QPID_AMQP_0_10_HOLDER_H
+#define QPID_AMQP_0_10_HOLDER_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/framing/Blob.h"
+#include "apply.h"
+
+namespace qpid {
+namespace amqp_0_10 {
+
+template <class DerivedHolder, class BaseHeld, size_t Size>
+struct Holder : public framing::Blob<Size, BaseHeld> {
+
+    typedef framing::Blob<Size, BaseHeld> Base;
+    
+    Holder() {}
+    template <class T> Holder(const T& value) : Base(value) {}
+
+    using Base::operator=;
+
+    uint8_t getCode() const { return this->get()->getCode(); }
+    uint8_t getClassCode() const { return this->get()->getClassCode(); }
+    
+    template <class S> void encode(S& s) {
+        s(getClassCode())(getCode());
+    }
+
+    template <class S> void decode(S& s) {
+        uint8_t code, classCode;
+        s(classCode)(code);
+        static_cast<DerivedHolder*>(this)->set(classCode, code);
+    }
+
+    template <class S> void serialize(S& s) {
+        s.split(*this);
+        apply(s, *this->get());
+    }
+};
+
+
+}} // namespace qpid::amqp_0_10
+
+#endif  /*!QPID_AMQP_0_10_HOLDER_H*/

Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Holder.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/Holder.h
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: 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=633533&r1=633532&r2=633533&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/apply.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/apply.h Tue Mar  4 
08:34:01 2008
@@ -31,7 +31,8 @@
     boost::optional<R> result;
 
     FunctionAndResult() : functor(0) {}
-    template <class T> void invoke(T t) { result=(*functor)(t); }
+    template <class T> void invoke(T& t) { result=(*functor)(t); }
+    template <class T> void invoke(const T& t) { result=(*functor)(t); }
     R getResult() { return *result; }
 };
 
@@ -40,17 +41,23 @@
     F* functor;
     
     FunctionAndResult() : functor(0) {}
-    template <class T> void invoke(T t) { (*functor)(t); }
+    template <class T> void invoke(T& t) { (*functor)(t); }
     void getResult() {}
 };
 
-template <class V, class F>
-struct ApplyVisitorBase : public V, public FunctionAndResult<F> {
-    using V::visit;
+// Metafunction returning correct abstract visitor for Visitable type. 
+template <class Visitable> struct VisitorType {
+    typedef typename Visitable::Visitor type;
 };
+template <class Visitable> struct VisitorType<const Visitable> {
+    typedef typename Visitable::ConstVisitor type;
+};
+    
+template <class Visitor, class F>
+struct ApplyVisitorBase : public Visitor, public FunctionAndResult<F> {};
 
 // Specialize for each visitor type
-template <class V, class F> struct ApplyVisitor;
+template <class Visitable, class F> struct ApplyVisitor;
 
 /** Apply a functor to a visitable object.
  * The functor can have operator() overloads for each visitable type
@@ -58,7 +65,7 @@
  */
 template <class F, class Visitable>
 typename F::result_type apply(F& functor, Visitable& visitable) {
-    ApplyVisitor<typename Visitable::Visitor, F> visitor;
+    ApplyVisitor<typename VisitorType<Visitable>::type, F> visitor;
     visitor.functor=&functor;
     visitable.accept(visitor);
     return visitor.getResult();
@@ -66,11 +73,17 @@
 
 template <class F, class Visitable>
 typename F::result_type apply(const F& functor, Visitable& visitable) {
-    ApplyVisitor<typename Visitable::Visitor, const F> visitor;
+    ApplyVisitor<typename VisitorType<Visitable>::type, const F> visitor;
     visitor.functor=&functor;
     visitable.accept(visitor);
     return visitor.getResult();
 }
+
+template <class R, bool Const=false> struct ApplyFunctor {
+    typedef R result_type;
+    static const bool IS_CONST=Const;
+};
+template <class R> struct ConstApplyFunctor : public ApplyFunctor<R, true> {};
 
 }} // namespace qpid::amqp_0_10
 

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=633533&r1=633532&r2=633533&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 Tue Mar  
4 08:34:01 2008
@@ -82,7 +82,7 @@
 struct SerializableString : public std::basic_string<T> {
     using std::basic_string<T>::operator=;
     template <class S> void serialize(S& s) {
-        s(SizeType(this->size())).iterate(this->begin(), this->end());
+        s(SizeType(this->size()))(this->begin(), this->end());
     }
 };
 
@@ -107,16 +107,29 @@
 typedef SerializableString<Uint8, Uint32> Vbin32;
 
 // FIXME aconway 2008-02-26: Unimplemented types:
-template <class T> struct Array : public std::vector<T> {};
-struct ByteRanges {};
-struct SequenceSet {};
-struct Map {};
-struct List {};
-struct Struct32 {};
+template <class T> struct Array : public std::vector<T>  { template <class S> 
void serialize(S&) {} };
+struct ByteRanges { template <class S> void serialize(S&) {} };
+struct SequenceSet  { template <class S> void serialize(S&) {} };
+struct Map  { template <class S> void serialize(S&) {} };
+struct List  { template <class S> void serialize(S&) {} };
+struct Struct32  { template <class S> void serialize(S&) {} };
+
+// Serializable enum support
+template <class E, class Store> struct Enum {
+    Store value;
+    Enum() {}
+    Enum(E v) : value(v) {}
+    Enum(Store v) : value(v) {}
+    Enum& operator=(E v) { value=v; return *this; }
+    Enum& operator=(Store v) { value=v; return *this; }
+    operator E() const { return value; }
+    operator Store() const { return value; }
+    template <class S> void serialize(S& s) { s(value); }
+};
 
-// Top level enum definitions.
-enum SegmentType { CONTROL, COMMAND, HEADER, BODY };
+enum SegmentTypeEnum { CONTROL, COMMAND, HEADER, BODY };
+typedef Enum<SegmentTypeEnum, uint8_t> SegmentType;
 
 }} // namespace qpid::amqp_0_10
 
-#endif  /*!QPID_AMQP_0_10_BUILT_IN_TYPES_H*/
+#endif

Added: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp?rev=633533&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp Tue Mar  
4 08:34:01 2008
@@ -0,0 +1,65 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/amqp_0_10/ApplyCommand.h"
+#include "qpid/amqp_0_10/ApplyControl.h"
+// FIXME aconway 2008-03-04:  #include "qpid/amqp_0_10/ApplyStruct.h"
+#include "qpid/amqp_0_10/apply.h"
+
+namespace qpid {
+namespace amqp_0_10 {
+// Functors for getting static values from a visitable base type.
+
+#define QPID_STATIC_VALUE_GETTER(NAME, TYPE, VALUE) \
+    struct NAME : public ConstApplyFunctor<TYPE> {  \
+        template <class T> TYPE operator()(const T&) const { return T::VALUE; 
}\
+    }
+
+QPID_STATIC_VALUE_GETTER(GetCode, uint8_t, CODE);
+QPID_STATIC_VALUE_GETTER(GetSize, uint8_t, SIZE);
+QPID_STATIC_VALUE_GETTER(GetPack, uint8_t, PACK);
+QPID_STATIC_VALUE_GETTER(GetClassCode, uint8_t, CLASS_CODE);
+QPID_STATIC_VALUE_GETTER(GetName, const char*, NAME);
+QPID_STATIC_VALUE_GETTER(GetClassName, const char*, CLASS_NAME);
+
+
+uint8_t Command::getCode() const { return apply(GetCode(), *this); }
+uint8_t Command::getClassCode() const { return apply(GetClassCode(), *this); }
+const char* Command::getName() const { return apply(GetName(), *this); }
+const char* Command::getClassName() const { return apply(GetClassName(), 
*this); }
+
+uint8_t Control::getCode() const { return apply(GetCode(), *this); }
+uint8_t Control::getClassCode() const { return apply(GetClassCode(), *this); }
+const char* Control::getName() const { return apply(GetName(), *this); }
+const char* Control::getClassName() const { return apply(GetClassName(), 
*this); }
+
+// FIXME aconway 2008-03-04: Struct visitors
+// uint8_t Struct::getCode() const { return apply(GetCode(), *this); }
+// uint8_t Struct::getPack() const { return apply(GetPack(), *this); }
+// uint8_t Struct::getSize() const { return apply(GetSize(), *this); }
+// uint8_t Struct::getClassCode() const { return apply(GetClassCode(), *this); 
}
+uint8_t Struct::getCode() const { assert(0); return 0; }
+uint8_t Struct::getPack() const { assert(0); return 0; }
+uint8_t Struct::getSize() const { assert(0); return 0; }
+uint8_t Struct::getClassCode() const { assert(0); return 0; }
+
+}} // namespace qpid::amqp_0_10
+

Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/complex_types.h
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/complex_types.h?rev=633533&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/complex_types.h (added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/complex_types.h Tue Mar  4 
08:34:01 2008
@@ -0,0 +1,79 @@
+#ifndef QPID_AMQP_0_10_COMPLEX_TYPES_H
+#define QPID_AMQP_0_10_COMPLEX_TYPES_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+namespace qpid {
+namespace amqp_0_10 {
+
+// Base classes for complex types.
+
+template <class V, class CV, class H> struct Visitable {
+    typedef V  Visitor;
+    typedef CV ConstVisitor;
+    typedef H  Holder;
+
+    virtual ~Visitable() {}
+    virtual void accept(Visitor&) = 0;
+    virtual void accept(ConstVisitor&) const = 0;
+};
+
+struct CommandVisitor;
+struct ConstCommandVisitor;
+struct CommandHolder;
+struct Command
+    : public Visitable<CommandVisitor, ConstCommandVisitor, CommandHolder>
+{
+    uint8_t getCode() const;
+    uint8_t getClassCode() const;
+    const char* getName() const;
+    const char* getClassName() const;
+};
+
+struct ControlVisitor;
+struct ConstControlVisitor;
+struct ControlHolder;
+struct Control
+    : public Visitable<ControlVisitor, ConstControlVisitor, ControlHolder>
+{
+    uint8_t getCode() const;
+    uint8_t getClassCode() const;
+    const char* getName() const;
+    const char* getClassName() const;
+};
+
+struct StructVisitor;
+struct ConstStructVisitor;
+struct StructHolder;
+struct Struct
+    : public Visitable<StructVisitor, ConstStructVisitor, StructHolder>
+{
+    uint8_t getCode() const;
+    uint8_t getPack() const;
+    uint8_t getSize() const;
+    uint8_t getClassCode() const;
+};
+
+
+}} // namespace qpid::amqp_0_10
+
+#endif  /*!QPID_AMQP_0_10_COMPLEX_TYPES_H*/

Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/complex_types.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/complex_types.h
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQBody.h
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQBody.h?rev=633533&r1=633532&r2=633533&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQBody.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQBody.h Tue Mar  4 
08:34:01 2008
@@ -22,7 +22,8 @@
  *
  */
 #include "qpid/framing/amqp_types.h"
-#include "qpid/amqp_0_10/helpers.h"
+#include "qpid/amqp_0_10/built_in_types.h"
+#include "qpid/amqp_0_10/complex_types.h"
 
 #include <ostream>
 

Modified: 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=633533&r1=633532&r2=633533&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/tests/apply.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/tests/apply.cpp Tue Mar  4 08:34:01 2008
@@ -26,11 +26,15 @@
 
 using  namespace qpid::amqp_0_10;
 
-struct GetCode {
-    typedef uint8_t result_type;
+struct GetCode : public ConstApplyFunctor<uint8_t> {
     template <class T> uint8_t operator()(const T&) const { return T::CODE; }
 };
 
+struct SetChannelMax : ApplyFunctor<void> {
+    template <class T> void operator()(T&) const { BOOST_FAIL(""); }
+    void operator()(connection::Tune& t) const { t.channelMax=42; }
+};
+    
 struct TestFunctor {
     typedef bool result_type;
     bool operator()(const connection::Tune& tune) {
@@ -57,6 +61,9 @@
     connection::Start start;
     p = &start;
     BOOST_CHECK(!apply(tf, *p));
+
+    apply(SetChannelMax(), tune);
+    BOOST_CHECK_EQUAL(tune.channelMax, 42);
 }
 
 struct VoidTestFunctor {

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=633533&r1=633532&r2=633533&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/tests/serialize.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/tests/serialize.cpp Tue Mar  4 08:34:01 
2008
@@ -22,6 +22,9 @@
 #include "unit_test.h"
 #include "qpid/amqp_0_10/built_in_types.h"
 #include "qpid/amqp_0_10/Codec.h"
+#include "qpid/amqp_0_10/specification.h"
+#include "qpid/amqp_0_10/ControlHolder.h"
+
 #include <boost/test/test_case_template.hpp>
 #include <boost/type_traits/is_arithmetic.hpp>
 #include <boost/utility/enable_if.hpp>
@@ -62,6 +65,7 @@
 using namespace std;
 namespace mpl=boost::mpl;
 using namespace qpid::amqp_0_10;
+using qpid::framing::in_place;
 
 template <class A, class B> struct concat2 { typedef typename mpl::copy<B, 
typename mpl::back_inserter<A> >::type type; };
 template <class A, class B, class C> struct concat3 { typedef typename 
concat2<A, typename concat2<B, C>::type>::type type; };
@@ -82,14 +86,14 @@
     string data;
 
     uint32_t l = 0x11223344;
-    Codec::encode(std::back_inserter(data), l);
+    Codec::encode(std::back_inserter(data))(l);
     uint32_t enc=reinterpret_cast<const uint32_t&>(*data.data());
     uint32_t l2 = ntohl(enc);
     BOOST_CHECK_EQUAL(l, l2);
 
     data.clear();
     uint16_t s = 0x1122;
-    Codec::encode(std::back_inserter(data), s);
+    Codec::encode(std::back_inserter(data))(s);
     uint32_t s2 = ntohs(*reinterpret_cast<const uint32_t*>(data.data()));
     BOOST_CHECK_EQUAL(s, s2);
 }
@@ -116,14 +120,58 @@
     string data;
     T t;
     testValue(t);
-    Codec::encode(std::back_inserter(data), t);
+    Codec::encode(std::back_inserter(data))(t);
 
     BOOST_CHECK_EQUAL(Codec::size(t), data.size());
 
     T t2;
-    Codec::decode(data.begin(), t2);
+    Codec::decode(data.begin())(t2);
     BOOST_CHECK_EQUAL(t,t2);
 }
 
+struct TestMe {
+    bool encoded, decoded;
+    char value;
+    TestMe(char v) : encoded(), decoded(), value(v) {}
+    template <class S> void encode(S& s) { encoded=true; s(value); }
+    template <class S> void decode(S& s) { decoded=true; s(value); }
+    template <class S> void serialize(S& s) { s.split(*this); }
+};
+
+BOOST_AUTO_TEST_CASE(testSplit) {
+    string data;
+    TestMe t1('x');
+    Codec::encode(std::back_inserter(data))(t1);
+    BOOST_CHECK(t1.encoded);
+    BOOST_CHECK(!t1.decoded);
+    BOOST_CHECK_EQUAL(data, "x");
+
+    TestMe t2('y');
+    Codec::decode(data.begin())(t2);
+    BOOST_CHECK(!t2.encoded);
+    BOOST_CHECK(t2.decoded);
+    BOOST_CHECK_EQUAL(t2.value, 'x');
+}
+
+BOOST_AUTO_TEST_CASE(testControlEncodeDecode) {
+    string data;
+    Control::Holder h(in_place<connection::Tune>(1,2,3,4));
+    Codec::encode(std::back_inserter(data))(h);
+    
+    BOOST_CHECK_EQUAL(data.size(), Codec::size(h));
+
+    Codec::Decode<string::iterator> decode(data.begin());
+    Control::Holder h2;
+    decode(h2);
+
+    BOOST_REQUIRE(h2.get());
+    BOOST_CHECK_EQUAL(h2.get()->getClassCode(), connection::CODE);
+    BOOST_CHECK_EQUAL(h2.get()->getCode(), uint8_t(connection::Tune::CODE));
+    connection::Tune& tune=static_cast<connection::Tune&>(*h2.get());
+    BOOST_CHECK_EQUAL(tune.channelMax, 1u);
+    BOOST_CHECK_EQUAL(tune.maxFrameSize, 2u);
+    BOOST_CHECK_EQUAL(tune.heartbeatMin, 3u);
+    BOOST_CHECK_EQUAL(tune.heartbeatMax, 4u);
+}
 
 QPID_AUTO_TEST_SUITE_END()


Reply via email to