diff options
| author | Alan Conway <aconway@apache.org> | 2008-02-28 17:53:47 +0000 |
|---|---|---|
| committer | Alan Conway <aconway@apache.org> | 2008-02-28 17:53:47 +0000 |
| commit | 1820dd421a096ed184a08deee9512e809312fed2 (patch) | |
| tree | 3d7ec12c8fbfa3e55b8c6374ce1c73fe0fe4f7f3 /cpp | |
| parent | a9b496076e65aba6b23eea2284c2f3de39a0a79d (diff) | |
| download | qpid-python-1820dd421a096ed184a08deee9512e809312fed2.tar.gz | |
amqp_0_10::ProxyTemplate - tested & functional.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@632075 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp')
| -rwxr-xr-x | cpp/rubygen/0-10/specification.rb | 40 | ||||
| -rwxr-xr-x | cpp/rubygen/amqpgen.rb | 11 | ||||
| -rwxr-xr-x | cpp/rubygen/cppgen.rb | 93 | ||||
| -rwxr-xr-x | cpp/rubygen/generate | 12 | ||||
| -rw-r--r-- | cpp/src/tests/Makefile.am | 3 | ||||
| -rw-r--r-- | cpp/src/tests/ProxyTemplate.cpp | 49 |
6 files changed, 137 insertions, 71 deletions
diff --git a/cpp/rubygen/0-10/specification.rb b/cpp/rubygen/0-10/specification.rb index d88b03c3c6..d4ecfe98ed 100755 --- a/cpp/rubygen/0-10/specification.rb +++ b/cpp/rubygen/0-10/specification.rb @@ -46,11 +46,9 @@ class Specification < CppGen 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 @@ class Specification < CppGen 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 @@ class Specification < CppGen 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 @@ class Specification < CppGen 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});" } } diff --git a/cpp/rubygen/amqpgen.rb b/cpp/rubygen/amqpgen.rb index b95a507b5e..2edc573d00 100755 --- a/cpp/rubygen/amqpgen.rb +++ b/cpp/rubygen/amqpgen.rb @@ -136,9 +136,6 @@ class AmqpElement @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 @@ end 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 @@ class Generator 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 @@ class Generator 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) diff --git a/cpp/rubygen/cppgen.rb b/cpp/rubygen/cppgen.rb index edee72e0bd..5d2695c77a 100755 --- a/cpp/rubygen/cppgen.rb +++ b/cpp/rubygen/cppgen.rb @@ -61,14 +61,14 @@ class String 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 @@ class CppType 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 @@ class AmqpMethod 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 @@ class AmqpDomain 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 @@ class AmqpStruct 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 @@ -320,6 +315,38 @@ class CppGen < Generator 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 # Fully-qualified class name diff --git a/cpp/rubygen/generate b/cpp/rubygen/generate index c370d92897..9f0ddf0f1c 100755 --- a/cpp/rubygen/generate +++ b/cpp/rubygen/generate @@ -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 @@ end # 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 diff --git a/cpp/src/tests/Makefile.am b/cpp/src/tests/Makefile.am index 3ce86b9da1..4a47797350 100644 --- a/cpp/src/tests/Makefile.am +++ b/cpp/src/tests/Makefile.am @@ -38,7 +38,8 @@ unit_test_SOURCES= unit_test.cpp unit_test.h \ 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 diff --git a/cpp/src/tests/ProxyTemplate.cpp b/cpp/src/tests/ProxyTemplate.cpp new file mode 100644 index 0000000000..cab87b6511 --- /dev/null +++ b/cpp/src/tests/ProxyTemplate.cpp @@ -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() |
