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/27 17:37:59 UTC

svn commit: r631638 - in /incubator/qpid/trunk/qpid/cpp: ./ rubygen/ rubygen/0-10/ rubygen/99-0/ rubygen/templates/ src/ src/qpid/amqp_0_10/ src/tests/ xml/

Author: aconway
Date: Wed Feb 27 08:37:48 2008
New Revision: 631638

URL: http://svn.apache.org/viewvc?rev=631638&view=rev
Log:
Generate code for both 0-99 preview and 0-10 final specs .
0-10 final: extended code generation and non-generated support classes.

Added:
    incubator/qpid/trunk/qpid/cpp/rubygen/0-10/
    incubator/qpid/trunk/qpid/cpp/rubygen/0-10/amqp_0_10.rb
      - copied, changed from r631476, incubator/qpid/trunk/qpid/cpp/rubygen/templates/amqp_0_10.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/99-0/
      - copied from r631476, incubator/qpid/trunk/qpid/cpp/rubygen/templates/
    incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.cpp   (with props)
Removed:
    incubator/qpid/trunk/qpid/cpp/rubygen/99-0/amqp_0_10.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/templates/
Modified:
    incubator/qpid/trunk/qpid/cpp/configure.ac
    incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodBodyConstVisitor.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodBodyDefaultVisitor.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodHolder.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Operations.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/99-0/OperationsInvoker.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Proxy.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Session.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/99-0/all_method_bodies.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/99-0/constants.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/99-0/frame_body_lists.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/99-0/structs.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/MethodBodyDefaultVisitor.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/amqpgen.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb
    incubator/qpid/trunk/qpid/cpp/rubygen/generate
    incubator/qpid/trunk/qpid/cpp/src/Makefile.am
    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.h
    incubator/qpid/trunk/qpid/cpp/src/tests/serialize.cpp
    incubator/qpid/trunk/qpid/cpp/xml/cluster.xml

Modified: incubator/qpid/trunk/qpid/cpp/configure.ac
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/configure.ac?rev=631638&r1=631637&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/configure.ac (original)
+++ incubator/qpid/trunk/qpid/cpp/configure.ac Wed Feb 27 08:37:48 2008
@@ -122,11 +122,11 @@
 test -z "$RUBY" && AC_MSG_ERROR([Missing ruby installation (try "yum install ruby").])
 
 specdir=`pwd`/$srcdir/../specs  
-AMQP_XML=$specdir/amqp.0-10-preview.xml
-AC_SUBST(AMQP_XML)
-ls $AMQP_XML >/dev/null 2>&1 || generate=no
-
-AM_CONDITIONAL([GENERATE], [test x$generate = xyes])
+AMQP_PREVIEW_XML=$specdir/amqp.0-10-preview.xml
+AMQP_FINAL_XML=$specdir/amqp.0-10.xml
+AC_SUBST(AMQP_PREVIEW_XML)
+AC_SUBST(AMQP_FINAL_XML)
+AM_CONDITIONAL([GENERATE], [ls $AMQP_FINAL_XML >/dev/null])
 
 # URL and download URL for the package.
 URL=http://rhm.et.redhat.com/qpidc

Copied: incubator/qpid/trunk/qpid/cpp/rubygen/0-10/amqp_0_10.rb (from r631476, incubator/qpid/trunk/qpid/cpp/rubygen/templates/amqp_0_10.rb)
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/0-10/amqp_0_10.rb?p2=incubator/qpid/trunk/qpid/cpp/rubygen/0-10/amqp_0_10.rb&p1=incubator/qpid/trunk/qpid/cpp/rubygen/templates/amqp_0_10.rb&r1=631476&r2=631638&rev=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/templates/amqp_0_10.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/0-10/amqp_0_10.rb Wed Feb 27 08:37:48 2008
@@ -3,62 +3,173 @@
 require 'cppgen'
 
 class Amqp_0_10 < CppGen
+  ArrayTypes={
+    "str16-array" => "Str16",
+    "amqp-host-array" => "connection::AmqpHostUrl",
+    "command-fragments" => "session::CommandFragment",
+    "in-doubt" => "dtx::Xid"
+  }
   
   def initialize(outdir, amqp)
     super(outdir, amqp)
-    @namespace="qpid::amqp_0_10"
-    @filename="qpid/amqp_0_10"
+    @ns="qpid::amqp_0_10"
+    @dir="qpid/amqp_0_10"
   end
 
-  def action_h(a, base)
-    struct(a.cppname, "public #{base}") {
-      genl "static const uint8_t CODE=#{a.code};"
-      a.fields.each { |f|
-        genl "#{(f.type_.amqp2cpp)} #{f.cppname};"
+  # domains
+
+  def domain_h(d)
+    typename=d.name.typename
+    if d.enum
+      scope("enum #{typename} {", "};") { 
+        genl d.enum.choices.map { |c| "#{c.name.constname} = #{c.value}" }.join(",\n")
       }
+    elsif d.type_ == "array"
+      @array_domains << "typedef Array<#{ArrayTypes[d.name]}> #{typename};\n"
+    else
+      genl "typedef #{d.type_.amqp2cpp} #{typename};"
+    end
+  end
+
+  # structs
+  
+  # field members and MemberInfo
+  def member_h(m)
+    genl "static const MemberInfo INFO;"    
+    m.fields.each { |f| genl "#{f.type_.amqp2cpp} #{f.cppname};" }
+  end
+
+  # MemberInfo constant definition.
+  def member_cpp(m)
+    infotype=m.is_a?(AmqpStruct) ? "Struct1Info" : "MemberInfo"
+    scope("{infotype} #{m.classname}::INFO = {","};") {
+      inits=[]
+      inits << (m.parent.is_a?(AmqpClass) ? "&CLASS_INFO" : "0")
+      inits << m.name << (m.code or "0");
+      if m.is_a?(AmqpStruct)
+        inits << (m.size or 0) << (m.pack or 0)
+      end
+      genl inits.join(", ")
     }
   end
 
-  def action_cpp(a, base)
-    
+  def struct_h(s) struct(s.classname, "public Struct") { member_h s }; end
+  def struct_cpp(s) member_cpp s; end
+  def gen_structs()
+    file="#{@dir}/structs"
+    h_file(file) {
+      include "#{@dir}/built_in_types.h"
+      include "#{@dir}/helpers.h"
+      include "<boost/call_traits.hpp>"
+      genl "using boost::call_traits;"
+      namespace(@ns) { 
+        @amqp.structs.each { |s| struct_h s }
+        each_class_ns { |c| c.structs.each { |s| struct_h s }}
+      }
+    }
+    cpp_file(file) {
+      include file
+      namespace(@ns) {
+        @amqp.structs.each { |s| struct_h s }
+        each_class_ns { |c| c.structs.each { |s| struct_cpp s }}
+      }
+    }
   end
 
-  def gen_amqp_0_10_h
-    h_file("#{@filename}.h") { 
-      namespace(@namespace) {
-        @amqp.classes.each { |cl|
-          namespace(cl.cppname) { 
-            struct("ClassInfo") {
-              genl "static const uint8_t CODE=#{cl.code};"
-              genl "static const char* NAME;"
-            }
-            cl.commands.each { |c| action_h c, "Command"}
-            cl.controls.each { |c| action_h c, "Control"}
-          }
+  # command and control
+  
+  def action_h(a) 
+    name=a.name.typename
+    struct(name, "public #{a.base}") {
+      genl "#{name}() {}"           
+      scope("#{name}(",");") { genl a.parameters } unless a.fields.empty?
+      scope("template <class T> void invoke(T& target) {","}") {
+        scope("target.#{a.funcname}(", ");") { genl a.values }
+      }
+      scope("template <class S> void serialize(S& s) {","}") {
+        gen "s"
+        a.fields.each { |f| gen "(#{f.cppname})"}
+        genl ";"
+      } unless a.fields.empty?
+      member_h a
+    }
+  end
+  
+  def action_cpp(a)   # command or control
+    # ctor
+    scope("#{a.classname}::#{a.classname}(",") :") { genl a.parameters }
+    indent() { genl a.initializers }
+    genl "{}"
+    # member constants
+    member_cpp a
+  end
+
+  def class_h(c)
+    genl "extern const ClassInfo CLASS_INFO;"
+    @array_domains=""
+    c.domains.each { |d| domain_h d }
+    c.structs.each { |s| struct_h s }
+    gen @array_domains
+  end
+
+  def class_cpp(c)
+    genl "const ClassInfo CLASS_INFO = { #{c.code}, \"#{c.name}\" };"
+    c.structs.each { |s| struct_cpp s }
+  end
+
+  def gen_specification()
+    h_file("#{@dir}/specification") {
+      include "#{@dir}/built_in_types"
+      include "#{@dir}/helpers"
+      include "<boost/call_traits.hpp>"
+      genl "using boost::call_traits;"
+      namespace(@ns) {
+        # We don't generate top-level domains, as they have clashing values.
+        each_class_ns { |c| class_h c }
+        each_class_ns { |c| c.actions.each { |a| action_h a}        
+        }
+      }
+    }
+    cpp_file("#{@dir}/specification") { 
+      include "#{@dir}/specification"
+      namespace(@ns) { 
+        each_class_ns { |c| class_cpp c }
+        each_class_ns { |c| c.actions.each { |a| action_cpp a}
         }
       }
     }
   end
-
-  def gen_amqp_0_10_cpp
-    cpp_file("#{@filename}.cpp") { 
-      include @filename
-
-      namespace(@namespace) {
-        @amqp.classes.each { |cl|
-          namespace(cl.cppname) {
-            genl "static const char* ClassInfo::NAME=\"#{cl.name};"
+  
+  def gen_proxy()
+    h_file("#{@dir}/Proxy.h") { 
+      include "#{@dir}/specification"
+      namespace(@ns) { 
+        genl "template <class F, class R=F::result_type>"
+        cpp_class("ProxyTemplate") {
+          public
+          genl "ProxyTemplate(F f) : functor(f) {}"
+          @amqp.classes.each { |c|
+            c.actions.each { |a|
+              scope("R #{a.funcname}(", ")") {  genl a.parameters }
+              scope() { 
+                var=a.name.funcname
+                scope("#{a.classname} #{var}(",");") { genl a.arguments }
+                genl "return functor(#{var});"
+              }
+            }
           }
+          private
+          genl "F functor;"
         }
       }
     }
   end
-
+  
   def generate
-    gen_amqp_0_10_h
-    gen_amqp_0_10_cpp
+    gen_specification
+    gen_proxy
   end
 end
 
-Amqp_0_10.new(Outdir, Amqp).generate();
+Amqp_0_10.new($outdir, $amqp).generate();
 

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodBodyConstVisitor.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodBodyConstVisitor.rb?rev=631638&r1=631476&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodBodyConstVisitor.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodBodyConstVisitor.rb Wed Feb 27 08:37:48 2008
@@ -23,5 +23,5 @@
   end
 end
 
-MethodBodyConstVisitorGen.new(Outdir, Amqp).generate();
+MethodBodyConstVisitorGen.new($outdir, $amqp).generate();
 

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodBodyDefaultVisitor.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodBodyDefaultVisitor.rb?rev=631638&r1=631476&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodBodyDefaultVisitor.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodBodyDefaultVisitor.rb Wed Feb 27 08:37:48 2008
@@ -31,5 +31,5 @@
   end
 end
 
-MethodBodyDefaultVisitorGen.new(Outdir, Amqp).generate();
+MethodBodyDefaultVisitorGen.new($outdir, $amqp).generate();
 

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodHolder.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodHolder.rb?rev=631638&r1=631476&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodHolder.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/99-0/MethodHolder.rb Wed Feb 27 08:37:48 2008
@@ -96,5 +96,5 @@
   end
 end
 
-MethodHolderGen.new(Outdir, Amqp).generate();
+MethodHolderGen.new($outdir, $amqp).generate();
 

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Operations.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Operations.rb?rev=631638&r1=631476&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Operations.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Operations.rb Wed Feb 27 08:37:48 2008
@@ -91,6 +91,6 @@
   end
 end
 
-OperationsGen.new("client",ARGV[0], Amqp).generate()
-OperationsGen.new("server",ARGV[0], Amqp).generate()
+OperationsGen.new("client",ARGV[0], $amqp).generate()
+OperationsGen.new("server",ARGV[0], $amqp).generate()
 

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/99-0/OperationsInvoker.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/99-0/OperationsInvoker.rb?rev=631638&r1=631476&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/99-0/OperationsInvoker.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/99-0/OperationsInvoker.rb Wed Feb 27 08:37:48 2008
@@ -88,5 +88,5 @@
   end
 end
 
-OperationsInvokerGen.new("client",ARGV[0], Amqp).generate()
-OperationsInvokerGen.new("server",ARGV[0], Amqp).generate()
+OperationsInvokerGen.new("client",ARGV[0], $amqp).generate()
+OperationsInvokerGen.new("server",ARGV[0], $amqp).generate()

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Proxy.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Proxy.rb?rev=631638&r1=631476&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Proxy.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Proxy.rb Wed Feb 27 08:37:48 2008
@@ -62,7 +62,9 @@
       include "<sstream>"
       include "#{@classname}.h"
       include "qpid/framing/amqp_types_full.h"
-      Amqp.methods_on(@chassis).each { |m| include "qpid/framing/"+m.body_name }
+      @amqp.methods_on(@chassis).each {
+        |m| include "qpid/framing/"+m.body_name
+      }
       genl
       namespace("qpid::framing") { 
         genl "#{@classname}::#{@classname}(FrameHandler& f) :"
@@ -75,6 +77,6 @@
 end
 
 
-ProxyGen.new("client", Outdir, Amqp).generate;
-ProxyGen.new("server", Outdir, Amqp).generate;
+ProxyGen.new("client", $outdir, $amqp).generate;
+ProxyGen.new("server", $outdir, $amqp).generate;
     

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Session.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Session.rb?rev=631638&r1=631476&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Session.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/99-0/Session.rb Wed Feb 27 08:37:48 2008
@@ -190,6 +190,6 @@
   end
 end
 
-SessionNoKeywordGen.new(ARGV[0], Amqp).generate()
-SessionGen.new(ARGV[0], Amqp).generate()
+SessionNoKeywordGen.new(ARGV[0], $amqp).generate()
+SessionGen.new(ARGV[0], $amqp).generate()
 

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/99-0/all_method_bodies.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/99-0/all_method_bodies.rb?rev=631638&r1=631476&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/99-0/all_method_bodies.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/99-0/all_method_bodies.rb Wed Feb 27 08:37:48 2008
@@ -17,5 +17,5 @@
   end
 end
 
-AllMethodBodiesGen.new(Outdir, Amqp).generate();
+AllMethodBodiesGen.new($outdir, $amqp).generate();
 

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/99-0/constants.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/99-0/constants.rb?rev=631638&r1=631476&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/99-0/constants.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/99-0/constants.rb Wed Feb 27 08:37:48 2008
@@ -78,5 +78,5 @@
   end
 end
 
-ConstantsGen.new(Outdir, Amqp).generate();
+ConstantsGen.new($outdir, $amqp).generate();
 

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/99-0/frame_body_lists.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/99-0/frame_body_lists.rb?rev=631638&r1=631476&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/99-0/frame_body_lists.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/99-0/frame_body_lists.rb Wed Feb 27 08:37:48 2008
@@ -26,6 +26,6 @@
   end
 end
 
-FrameBodyListsGen.new(ARGV[0], Amqp).generate;
+FrameBodyListsGen.new(ARGV[0], $amqp).generate;
 
     

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/99-0/structs.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/99-0/structs.rb?rev=631638&r1=631476&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/99-0/structs.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/99-0/structs.rb Wed Feb 27 08:37:48 2008
@@ -534,5 +534,5 @@
   end
 end
 
-StructGen.new(ARGV[0], Amqp).generate()
+StructGen.new(ARGV[0], $amqp).generate()
 

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/MethodBodyDefaultVisitor.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/MethodBodyDefaultVisitor.rb?rev=631638&r1=631637&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/MethodBodyDefaultVisitor.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/MethodBodyDefaultVisitor.rb Wed Feb 27 08:37:48 2008
@@ -30,5 +30,5 @@
   end
 end
 
-MethodBodyDefaultVisitorGen.new(Outdir, Amqp).generate();
+MethodBodyDefaultVisitorGen.new($outdir, $amqp).generate();
 

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/amqpgen.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/amqpgen.rb?rev=631638&r1=631637&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/amqpgen.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/amqpgen.rb Wed Feb 27 08:37:48 2008
@@ -119,7 +119,16 @@
   # List of children of type elname, or all children if elname
   # not specified.
   def children(elname=nil)
-    @cache_children[elname] ||= @children.select { |c| elname==c.xml.name }
+    if elname
+      @cache_children[elname] ||= @children.select { |c| elname==c.xml.name }
+    else
+      @children
+    end
+  end
+
+  def each_descendant(&block)
+    yield self
+    @children.each { |c| c.each_descendant(&block) }
   end
 
   # Look up child of type elname with attribute name.
@@ -264,17 +273,21 @@
   amqp_attr_reader :implement
 end
 
-class AmqpControl < AmqpElement
+# Base class for command and control.
+class AmqpAction < AmqpElement
   def initialize(xml,amqp) super; end
   amqp_child_reader :implement, :field, :response
   amqp_attr_reader :code
 end
 
-class AmqpCommand < AmqpElement
+class AmqpControl < AmqpAction
+  def initialize(xml,amqp) super; end
+end
+
+class AmqpCommand < AmqpAction
   def initialize(xml,amqp) super; end
-  amqp_child_reader :implement, :field, :exception, :response
+  amqp_child_reader :exception
   amqp_single_child_reader :result, :segments
-  amqp_attr_reader :code
 end
 
 class AmqpClass < AmqpElement
@@ -295,6 +308,8 @@
   def l4?()                     # preview
     !["connection", "session", "execution"].include?(name)
   end
+
+  def actions() controls+commands;   end
 end
 
 class AmqpType < AmqpElement
@@ -321,6 +336,8 @@
     super(xml, nil)
   end
 
+  def merge(root) xml_merge(xml, root.xml); end
+  
   def version() major + "-" + minor; end
 
   # Find the element corresponding to an amqp dotted name.
@@ -370,25 +387,30 @@
   def initialize (outdir, amqp)
     @amqp=amqp
     @outdir=outdir
-    @prefix=''                  # For indentation or comments.
+    @prefix=['']                # For indentation or comments.
     @indentstr='    '           # One indent level.
     @outdent=2
     Pathname.new(@outdir).mkpath unless @outdir=="-" or File.directory?(@outdir) 
   end
 
   # Create a new file, set @out. 
-  def file(file)
+  def file(file, &block)
     GenFiles.add file
     if (@outdir != "-")         
-      path=Pathname.new "#{@outdir}/#{file}"
-      path.parent.mkpath
+      @path=Pathname.new "#{@outdir}/#{file}"
+      @path.parent.mkpath
       @out=String.new           # Generate in memory first
-      yield                     # Generate to @out
-      if path.exist? and path.read == @out  
-        puts "Skipped #{path} - unchanged" # Dont generate if unchanged
+      if block then yield; endfile; end
+    end
+  end
+
+  def endfile()
+    if @outdir != "-"
+      if @path.exist? and @path.read == @out  
+        puts "Skipped #{@path} - unchanged" # Dont generate if unchanged
       else
-        path.open('w') { |f| f << @out }
-        puts "Generated #{path}"
+        @path.open('w') { |f| f << @out }
+        puts "Generated #{@path}"
       end
     end
   end
@@ -396,7 +418,7 @@
   # Append multi-line string to generated code, prefixing each line.
   def gen (str)
     str.each_line { |line|
-      @out << @prefix unless @midline
+      @out << @prefix.last unless @midline
       @out << line
       @midline = nil
     }
@@ -411,23 +433,25 @@
   end
 
   # Generate code with added prefix.
-  def prefix(add)
-    save=@prefix
-    @prefix+=add
-    yield
-    @prefix=save
+  def prefix(add, &block)
+    @prefix.push @prefix.last+add
+    if block then yield; endprefix; end
+  end
+
+  def endprefix()
+    @prefix.pop
   end
   
   # Generate indented code
   def indent(n=1,&block) prefix(@indentstr * n,&block); end
+  alias :endindent :endprefix
 
   # Generate outdented code
   def outdent(&block)
-    save=@prefix
-    @prefix=@prefix[0...-2]
-    yield
-    @prefix=save
+    @prefix.push @prefix.last[0...-2]
+    if block then yield; endprefix; end
   end
+  alias :endoutdent :endprefix
   
   attr_accessor :out
 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=631638&r1=631637&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb Wed Feb 27 08:37:48 2008
@@ -55,12 +55,20 @@
 
 class String
   def cppsafe() CppMangle.include?(self) ? self+"_" : self; end
+
   def amqp2cpp()
     path=split(".")
     name=path.pop
-    path.map! { |n| n.bars }
-    (path << name.caps).join("::")
+    return name.typename if path.empty?
+    path.map! { |n| n.nsname }
+    return "amqp_0_10::"+(path << name.caps).join("::")
   end
+
+  alias :typename :caps
+  alias :nsname :bars
+  alias :constname :shout
+  alias :funcname :lcaps
+  alias :varname :lcaps
 end
 
 # Hold information about a C++ type.
@@ -119,6 +127,7 @@
   def cpptype() domain.cpptype;  end
   def bit?() domain.type_ == "bit"; end
   def signature() cpptype.param+" "+cppname; end
+  def paramtype() "call_traits<#{type_.amqp2cpp}>::param_type"; end
 end
 
 class AmqpMethod
@@ -128,8 +137,40 @@
   def body_name() parent.name.caps+name.caps+"Body"; end
 end
 
+class AmqpAction
+  def nsname() name.namespace; end
+  def classname() name.typename; end
+  def funcname() parent.name.funcname + name.caps; end
+
+  def parameters()
+    fields.map { |f| "#{f.paramtype} #{f.cppname}_"}.join(",\n")
+  end
+
+  def arguments()
+    fields.map { |f| "#{f.cppname}_"}.join(",\n")
+  end
+
+  def values()
+    fields.map { |f| "#{f.cppname}"}.join(",\n")
+  end
+
+  def initializers()
+    fields.map { |f| "#{f.cppname}(#{f.cppname}_)}"}.join(",\n")
+  end
+
+end
+
+class AmqpCommand
+  def base() "Command";  end
+end
+
+class AmqpControl
+  def base() "Control";  end
+end
+
 class AmqpClass
   def cppname() name.caps; end
+  def nsname() name.nsname; end
 end
 
 class AmqpDomain
@@ -172,17 +213,20 @@
 
 class AmqpStruct
   def cpp_pack_type() AmqpDomain.lookup_type(pack()) or CppType.new("uint16_t"); end
-  def cpptype() parent.cpptype; end
-  def cppname() cpptype.name;  end
+  def cpptype() parent.cpptype; end # preview
+  def cppname() cpptype.name;  end # preview
+  def classname() name.typename; end
 end
 
 class CppGen < Generator
   def initialize(outdir, *specs)
     super(outdir,*specs)
+    # need to sort classes for dependencies
+    @actions=[]                 # Stack of end-scope actions
   end
 
   # Write a header file. 
-  def h_file(path)
+  def h_file(path, &block)
     path = (/\.h$/ === path ? path : path+".h")
     guard=path.upcase.tr('./-','_')
     file(path) { 
@@ -190,12 +234,12 @@
       gen "#define #{guard}\n"
       gen Copyright
       yield
-      gen "#endif  /*!#{guard}*/\n"
+      gen "#endif  /*!#{guard}*/\n" 
     }
   end
 
   # Write a .cpp file.
-  def cpp_file(path)
+  def cpp_file(path, &block)
     path = (/\.cpp$/ === path ? path : path+".cpp")
     file(path) do
       gen Copyright
@@ -209,10 +253,12 @@
     genl "#include #{header}"
   end
 
-  def scope(open="{",close="}", &block) 
-    genl open; indent(&block); genl close
+  def scope(open="{",close="}", &block)
+    genl open
+    indent &block
+    genl close
   end
-
+  
   def namespace(name, &block) 
     genl
     names = name.split("::")
@@ -231,7 +277,7 @@
       indent { gen "#{bases.join(",\n")}" }
     end
     genl
-    scope("{","};") { yield }
+    scope("{","};", &block)
   end
 
   def struct(name, *bases, &block)
@@ -262,6 +308,11 @@
     genl "/**"
     prefix(" * ",&block)
     genl " */"
+  end
+
+  # Generate code in namespace for each class
+  def each_class_ns()
+    @amqp.classes.each { |c| namespace(c.nsname) { yield c } }
   end
 end
 

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/generate
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/generate?rev=631638&r1=631637&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/generate (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/generate Wed Feb 27 08:37:48 2008
@@ -1,5 +1,6 @@
 #!/usr/bin/env ruby
 require 'amqpgen'
+require 'pathname'
 
 #
 # Run a set of code generation templates.
@@ -18,17 +19,39 @@
   exit 1
 end
 
-Outdir=ARGV[0]
-Specs=ARGV.grep(/\.xml$/)
-Amqp=AmqpRoot.new(*Specs)
+# Create array of specs by version
+def parse_specs(specs)
+  roots={ }
+  specs.each { |spec|
+    root=AmqpRoot.new(spec)
+    ver=root.version
+    if (roots[ver])
+      roots[ver].merge(root)
+    else
+      roots[ver]=root
+    end
+  }
+  roots
+end
 
 # Run selected templates
 if ARGV.any? { |arg| arg=="all" }
-  templates=Dir["#{File.dirname __FILE__}/templates/*.rb"]
+  templates=Dir["#{File.dirname __FILE__}/*/*.rb"]
 else
   templates=ARGV.grep(/\.rb$/)
 end
-templates.each { |t| load t }
+
+$outdir=ARGV[0]
+$models=parse_specs(ARGV.grep(/\.xml$/))
+templates.each { |t|
+  ver=Pathname.new(t).dirname.basename.to_s
+  $amqp=$models[ver]
+  if $amqp
+    load t
+  else
+    puts "Warning: skipping #{t}, no spec file for version #{ver}."
+  end
+}
 
 def make_continue(lines) lines.join(" \\\n    "); end
 
@@ -40,7 +63,7 @@
   generator_files=Dir["**/*.rb"] << File.basename(__FILE__)
   Dir.chdir dir
   rgen_generator=generator_files.map{ |f| "$(rgen_dir)/#{f}" }
-  rgen_srcs=GenFiles.get.map{ |f| "#{Outdir}/#{f}" }
+  rgen_srcs=GenFiles.get.map{ |f| "#{$outdir}/#{f}" }
 
   File.open(makefile, 'w') { |out|
     out << <<EOS

Modified: incubator/qpid/trunk/qpid/cpp/src/Makefile.am
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/Makefile.am?rev=631638&r1=631637&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/Makefile.am (original)
+++ incubator/qpid/trunk/qpid/cpp/src/Makefile.am Wed Feb 27 08:37:48 2008
@@ -11,10 +11,12 @@
 # This phony target is needed by generated makefile fragments:
 force:
 
-# AMQP_XML is defined in ../configure.ac
-specs=@AMQP_XML@ $(top_srcdir)/xml/cluster.xml
-
 if GENERATE
+
+# AMQP_PREVIEW_XML and AMQP_FINAL_XML are defined in ../configure.ac
+amqp_99_0_xml=@AMQP_PREVIEW_XML@  $(top_srcdir)/xml/cluster.xml
+amqp_0_10_xml=@AMQP_FINAL_XML@
+specs=$(amqp_99_0_xml) $(amqp_0_10_xml)
 
 # Ruby generator.
 rgen_dir=$(top_srcdir)/rubygen

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=631638&r1=631637&r2=631638&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 Wed Feb 27 08:37:48 2008
@@ -29,6 +29,7 @@
 #include <boost/array.hpp>
 #include <stdint.h>
 #include <string>
+#include <vector>
 
 /**@file Mapping from built-in AMQP types to C++ types */
 
@@ -66,7 +67,7 @@
 typedef float Float;
 typedef framing::SequenceNumber SequenceNo;
 using framing::Uuid;
-typedef sys::AbsTime DateTime;
+typedef sys::AbsTime Datetime;
 
 typedef Decimal<Uint8, Int32> Dec32;
 typedef Decimal<Uint8, Int64> Dec64;
@@ -89,14 +90,18 @@
 
 typedef CodableString<Uint8, Uint32> Vbin32;
 
-/** FIXME aconway 2008-02-20: todo
-byte-ranges       2 byte ranges within a 64-bit payload
-sequence-set      2 ranged set representation
-map          0xa8 4 a mapping of keys to typed values
-list         0xa9 4 a series of consecutive type-value pairs
-array        0xaa 4 a defined length collection of values of a single type
-struct32     0xab 4 a coded struct with a 32-bit size
-*/
+// FIXME aconway 2008-02-26: array encoding
+template <class T> struct Array : public std::vector<T> {};
+
+// FIXME aconway 2008-02-26: Unimplemented types:
+struct ByteRanges {};
+struct SequenceSet {};
+struct Map {};
+struct List {};
+struct Struct32 {};
+
+// Top level enum definitions.
+enum SegmentType { CONTROL, COMMAND, HEADER, BODY };
 
 }} // namespace qpid::amqp_0_10
 

Added: 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=631638&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/amqp_0_10/helpers.cpp Wed Feb 27 08:37:48 2008
@@ -0,0 +1,30 @@
+/*
+ *
+ * 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 "helpers.h"
+
+namespace qpid {
+namespace amqp_0_10 {
+
+Control::~Control() {}
+Command::~Command() {}
+Struct::~Struct() {}
+
+}} // namespace qpid::amqp_0_10

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

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

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=631638&r1=631637&r2=631638&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 Wed Feb 27 08:37:48 2008
@@ -8,7 +8,7 @@
  * 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
+n * "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
@@ -27,43 +27,58 @@
 
 namespace amqp_0_10 {
 
-struct ClassAttributes { uint8_t code; const char* name };
+/** Static information about an AMQP class */
+struct ClassInfo { uint8_t code; const char* name; };
 
-struct MemberAttributes {
-    ClassAttributes class_;
-    const char* name
-    uint8_t code;
+/** Info about a class memeber - command, control or struct */
+struct MemberInfo {
+    ClassInfo* class_;          // 0 for top level struct.
 
+    const char* name;
+    uint8_t code;
     std::string fullName() const {
-        return std::string(class_.name)+"."+name;
+        return std::string(class_->name)+"."+name;
     }
 };
 
-struct StructAttributes : public MemberAttributes { uint8_t size, pack; };
+/** Info about a struct */
+struct StructInfo : public MemberInfo { uint8_t size, pack; };
 
-static const ClassAttributes getClass(uint8_t code);
-static const MemberAttributes getCommand(uint8_t classCode, uint8_t code);
-static const MemberAttributes getControl(uint8_t classCode, uint8_t code);
+// Look up info by code.
+const ClassInfo&  getClassInfo(uint8_t code);
+const MemberInfo& getCommandInfo(uint8_t classCode, uint8_t code);
+const MemberInfo& getControlInfo(uint8_t classCode, uint8_t code);
+const StructInfo& getStructInfo(uint8_t classCode, uint8_t code);
 
-struct Command : public Member {
+struct Command {
+    virtual ~Command();
     class Visitor;
-    virtual const MemberAttributes& attributes() const = 0;
+    virtual const MemberInfo& info() const = 0;
     virtual void accept(Visitor&) const = 0;
 };
 
-struct Control : public Member {
+struct Control {
+    virtual ~Control();
     class Visitor;
-    struct Attributes { uint8_t classCode, code };
-
-    virtual const MemberAttributes& attributes() const = 0;
+    virtual const MemberInfo& info() const = 0;
     virtual void accept(Visitor&) const = 0;
 };
 
-
-struct Struct : public Member {
-    virtual const StructAttributes&  attributes() const = 0;
+struct Struct {
+    virtual ~Struct();
+    virtual const StructInfo&  info() const = 0;
 };
 
+/** Base class for generated enum domains.
+ * Enums map to classes for type safety and to provide separate namespaces
+ * for clashing values.
+ */
+struct Enum {
+    int value;
+    Enum(int v=0) : value(v) {}
+    operator int() const { return value; }
+    template <class S> void serialize(S &s) { s(value); }
+};
 
 }} // namespace qpid::amqp_0_10
 

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=631638&r1=631637&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/tests/serialize.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/tests/serialize.cpp Wed Feb 27 08:37:48 2008
@@ -79,7 +79,7 @@
 typedef mpl::vector<Bit, Boolean, Char, Int32, Int64, Int8, Uint16, CharUtf32, Uint32, Uint64, Bin8, Uint8>::type IntegralTypes;
 typedef mpl::vector<Bin1024, Bin128, Bin16, Bin256, Bin32, Bin40, Bin512, Bin64, Bin72>::type BinTypes;
 typedef mpl::vector<Double, Float>::type FloatTypes;
-typedef mpl::vector<SequenceNo, Uuid, DateTime, Dec32, Dec64> FixedSizeClassTypes;
+typedef mpl::vector<SequenceNo, Uuid, Datetime, Dec32, Dec64> FixedSizeClassTypes;
 typedef mpl::vector<Vbin8, Str8Latin, Str8, Str8Utf16, Vbin16, Str16Latin, Str16, Str16Utf16, Vbin32> VariableSizeTypes;
 
 
@@ -106,7 +106,7 @@
 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(DateTime& dt) { dt = qpid::sys::now(); }
+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; }
 void testValue(SequenceNo& s) { s = 42; }

Modified: incubator/qpid/trunk/qpid/cpp/xml/cluster.xml
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/xml/cluster.xml?rev=631638&r1=631637&r2=631638&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/xml/cluster.xml (original)
+++ incubator/qpid/trunk/qpid/cpp/xml/cluster.xml Wed Feb 27 08:37:48 2008
@@ -20,7 +20,7 @@
  -
  -->
 
-<amqp major="0" minor="10" port="5672">
+<amqp major="99" minor="0" port="5672">
 
 <class name = "cluster" index = "201">