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/28 18:53:53 UTC

svn commit: r632075 - in /incubator/qpid/trunk/qpid/cpp: rubygen/0-10/specification.rb rubygen/amqpgen.rb rubygen/cppgen.rb rubygen/generate src/tests/Makefile.am src/tests/ProxyTemplate.cpp

Author: aconway
Date: Thu Feb 28 09:53:47 2008
New Revision: 632075

URL: http://svn.apache.org/viewvc?rev=632075&view=rev
Log:
amqp_0_10::ProxyTemplate - tested & functional.

Added:
    incubator/qpid/trunk/qpid/cpp/src/tests/ProxyTemplate.cpp   (with props)
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/rubygen/generate
    incubator/qpid/trunk/qpid/cpp/src/tests/Makefile.am

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=632075&r1=632074&r2=632075&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/0-10/specification.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/0-10/specification.rb Thu Feb 28 09:53:47 2008
@@ -46,11 +46,9 @@
       genl "static const char* NAME;"
       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
-      genl "#{x.classname}();"           
-      scope("#{x.classname}(",");") { genl x.parameters } unless x.fields.empty?
-      genl
-      genl "void accept(Visitor&) const;"
+      ctor_decl(x.classname,[])
+      ctor_decl(x.classname, x.parameters) unless x.fields.empty?
+      function_decl("void accept", ["Visitor&"], "const")
       genl
       yield if block
     }
@@ -60,15 +58,9 @@
     genl
     genl "const char* #{x.classname}::NAME=\"#{x.fqname}\";"
     genl
-    genl "#{x.classname}::#{x.classname}() {}"; 
-    genl
-    if not x.fields.empty?
-      scope("#{x.classname}::#{x.classname}(",") :") { genl x.parameters }
-      indent() { genl x.initializers }
-      genl "{}"
-      genl
-    end
-    scope("void #{x.classname}::accept(Visitor&) const {","}") {
+    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"
     }
   end
@@ -82,11 +74,10 @@
   
   def action_h(a)
     action_struct_h(a, a.base, ["code"]) {
-      scope("template <class T> void invoke(T& target) {","}") {
-        scope("target.#{a.funcname}(", ");") { genl a.values }
+      function_defn("template <class T> void invoke", ["T& target"]) {
+        genl "target.#{a.funcname}(#{a.values.join(', ')});"
       }
-      genl
-      scope("template <class S> void serialize(S& s) {","}") {
+      function_defn("template <class S> void serialize", ["S& s"]) { 
         gen "s"
         a.fields.each { |f| gen "(#{f.cppname})"}
         genl ";"
@@ -141,19 +132,20 @@
   end
   
   def gen_proxy()
-    h_file("#{@dir}/Proxy.h") { 
+    h_file("#{@dir}/ProxyTemplate.h") { 
       include "#{@dir}/specification"
       namespace(@ns) { 
-        genl "template <class F, class R=F::result_type>"
+        genl "template <class F, class R=typename F::result_type>"
         cpp_class("ProxyTemplate") {
           public
-          genl "ProxyTemplate(F f) : functor(f) {}"
+          genl "ProxyTemplate(F f=F()) : functor(f) {}"
           @amqp.classes.each { |c|
             c.actions.each { |a|
-              scope("R #{a.funcname}(", ")") {  genl a.parameters }
-              scope() { 
+              genl
+              function_defn("R #{a.funcname}", a.parameters) { 
                 var=a.name.funcname
-                scope("#{a.classname} #{var}(",");") { genl a.arguments }
+                args = a.arguments.empty? ? "" : "("+a.arguments.join(", ")+")"
+                genl("#{a.fqclassname} #{var}#{args};")
                 genl "return functor(#{var});"
               }
             }

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/amqpgen.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/amqpgen.rb?rev=632075&r1=632074&r2=632075&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/amqpgen.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/amqpgen.rb Thu Feb 28 09:53:47 2008
@@ -136,9 +136,6 @@
     @cache_child[[elname,name]] ||= children(elname).find { |c| c.name==name }
   end
 
-  # Fully qualified amqp dotted name of this element
-  def dotted_name() (parent ? parent.dotted_name+"." : "") + name; end
-
   # The root <amqp> element.
   def root() @root ||=parent ? parent.root : self; end
 
@@ -167,6 +164,7 @@
 
 class AmqpResponse < AmqpElement
   def initialize(xml, parent) super; end
+  def fqname() (parent ? parent.dotted_name+"." : "") + "response"; end  
 end
 
 class AmqpDoc < AmqpElement
@@ -454,7 +452,7 @@
   end
 
   # Append multi-line string to generated code, prefixing each line.
-  def gen (str)
+  def gen(str)
     str.each_line { |line|
       @out << @prefix.last unless @midline
       @out << line
@@ -465,10 +463,7 @@
   end
 
   # Append str + '\n' to generated code.
-  def genl(str="")
-    gen str
-    gen "\n"
-  end
+  def genl(str="") gen str+"\n"; end
 
   # Generate code with added prefix.
   def prefix(add, &block)

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb?rev=632075&r1=632074&r2=632075&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/cppgen.rb Thu Feb 28 09:53:47 2008
@@ -61,14 +61,14 @@
     name=path.pop
     return name.typename if path.empty?
     path.map! { |n| n.nsname }
-    return (path << name.caps).join("::")
+    return (path << name.caps.cppsafe).join("::")
   end
 
-  alias :typename :caps
-  alias :nsname :bars
-  alias :constname :shout
-  alias :funcname :lcaps
-  alias :varname :lcaps
+  def typename() caps.cppsafe; end
+  def nsname() bars.cppsafe; end
+  def constname() shout.cppsafe; end
+  def funcname() lcaps.cppsafe; end
+  def varname() lcaps.cppsafe; end
 end
 
 # Hold information about a C++ type.
@@ -112,22 +112,21 @@
   def to_s() name; end;
 end
 
-class AmqpElement
-  def cppfqname()
-    names=parent.dotted_name.split(".")
-    # Field children are moved up to method in C++b
-    prefix.pop if parent.is_a? AmqpField
-    prefix.push cppname
-    prefix.join("::")
-  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
-  def paramtype() "call_traits<#{type_.amqp2cpp}>::param_type"; end
+  # FIXME aconway 2008-02-27: qualified
+  def paramtype()
+    fqtype=type_
+    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";
+  end
 end
 
 class AmqpMethod
@@ -138,26 +137,17 @@
 end
 
 module AmqpHasFields
-    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
+  def parameters() fields.map { |f| "#{f.paramtype} #{f.cppname}_"} end
+  def arguments() fields.map { |f| "#{f.cppname}_"} end
+  def values() fields.map { |f| "#{f.cppname}"} end
+  def initializers() fields.map { |f| "#{f.cppname}(#{f.cppname}_)"}  end
 end
 
 class AmqpAction
   def classname() name.typename; end
   def funcname() parent.name.funcname + name.caps; end
+  def fqclassname() parent.name+"::"+classname; end
+
   include AmqpHasFields
 end
 
@@ -194,6 +184,11 @@
 
   def cppname() name.caps; end
 
+  def fqtypename()
+    return containing_class.nsname+"::"+name.typename if containing_class
+    name.typename
+  end
+  
   def cpptype()
     d=unalias
     @cpptype ||= @@typemap[d.type_] or
@@ -220,7 +215,7 @@
   end 
   def cpptype() parent.cpptype; end # preview
   def cppname() cpptype.name;  end # preview
-
+  def fqclassname() containing_class.nsname+"::"+name.typename;  end
   def classname() name.typename; end
 end
 
@@ -319,6 +314,38 @@
   # Generate code in namespace for each class
   def each_class_ns()
     @amqp.classes.each { |c| namespace(c.nsname) { yield c } }
+  end
+
+  def signature(ret_name, params, trailer="")
+    if params.size <= 1
+      genl ret_name+"(#{params})"+trailer
+    else
+      scope(ret_name+"(",")"+trailer) { genl params.join(",\n") }
+    end
+  end
+  
+  def function_decl(ret_name, params=[], trailer="")
+    signature(ret_name, params, trailer+";")
+  end
+
+  def function_defn(ret_name, params=[], trailer="")
+    genl
+    signature(ret_name, params, trailer)
+    scope() { yield }
+  end
+
+  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?
+    scope() { yield }
+  end
+
+  def function_call(name, params=[], trailer="")
+    gen name
+    list "(",params, ")"
+    gen trailer
   end
 end
 

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/generate
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/generate?rev=632075&r1=632074&r2=632075&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/generate (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/generate Thu Feb 28 09:53:47 2008
@@ -1,6 +1,6 @@
 #!/usr/bin/env ruby
-require 'amqpgen'
 require 'pathname'
+require 'amqpgen'
 
 #
 # Run a set of code generation templates.
@@ -21,14 +21,16 @@
 
 # Create array of specs by version
 def parse_specs(files)
-  specs=Hash.new { |h,k| h[k]=[] }
+  lists=Hash.new { |h,k| h[k]=[] }
   files.each { |f|
     spec=AmqpRoot.new(File.new(f))
-    specs[spec.version] << spec
+    lists[spec.version] << spec
   }
-  specs.each_pair { |k,v|
-    specs[k] = v.size==1 ? v.first : AmqpRoot.new(*v.map { |s| s.xml})
+  specs={}
+  lists.each_pair { |k,l|
+    specs[k] = l.size==1 ? l.first : AmqpRoot.new(*l.map { |s| s.xml})
   }
+  return specs
 end
 
 # Run selected templates

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=632075&r1=632074&r2=632075&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/tests/Makefile.am (original)
+++ incubator/qpid/trunk/qpid/cpp/src/tests/Makefile.am Thu Feb 28 09:53:47 2008
@@ -38,7 +38,8 @@
 	InlineVector.cpp \
 	ISList.cpp IList.cpp \
 	ClientSessionTest.cpp \
-	serialize.cpp
+	serialize.cpp \
+	ProxyTemplate.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/ProxyTemplate.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/tests/ProxyTemplate.cpp?rev=632075&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/tests/ProxyTemplate.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/src/tests/ProxyTemplate.cpp Thu Feb 28 09:53:47 2008
@@ -0,0 +1,49 @@
+/*
+ *
+ * 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/ProxyTemplate.h"
+#include <boost/any.hpp>
+
+QPID_AUTO_TEST_SUITE(ProxyTemplateTestSuite)
+
+using  namespace qpid::amqp_0_10;
+
+struct ToAny {
+    template <class T> 
+    boost::any operator()(const T& t) { return boost::any(t); }
+};
+
+struct AnyProxy : public ProxyTemplate<ToAny, boost::any> {};
+
+BOOST_AUTO_TEST_CASE(testAnyProxy) {
+    AnyProxy p;
+    boost::any a=p.connectionTune(1,2,3,4);
+    BOOST_CHECK_EQUAL(a.type().name(), typeid(connection::Tune).name());
+    connection::Tune* tune=boost::any_cast<connection::Tune>(&a);
+    BOOST_REQUIRE(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);
+}
+
+QPID_AUTO_TEST_SUITE_END()

Propchange: incubator/qpid/trunk/qpid/cpp/src/tests/ProxyTemplate.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/src/tests/ProxyTemplate.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date