From 9d32e58f281e6ecefcbde45a897395162395e577 Mon Sep 17 00:00:00 2001 From: Alan Conway Date: Tue, 30 Oct 2007 22:39:46 +0000 Subject: Client API: fix keyword parameter ambiguities for beta client API. Classes: - client::no_keyword::Session_0_10 - plain defaulted signatures - client::Session_0_10 - keyword API. Keyword API changes: - keywords in client::arg namespace, user says: s.bind(arg::queue="x"...) - user can omit with: using namespace client::arg; s.bind(queue="x"...) - No trailing "_" required on session functions. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@590498 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/rubygen/cppgen.rb | 13 +- cpp/rubygen/templates/Session.rb | 333 ++++++++++++++++++--------------------- 2 files changed, 163 insertions(+), 183 deletions(-) (limited to 'cpp/rubygen') diff --git a/cpp/rubygen/cppgen.rb b/cpp/rubygen/cppgen.rb index ceda5e039c..2590d48f7b 100755 --- a/cpp/rubygen/cppgen.rb +++ b/cpp/rubygen/cppgen.rb @@ -97,12 +97,13 @@ 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 end class AmqpMethod def cppname() name.lcaps.cppsafe; end def param_names() fields.map { |f| f.cppname }; end - def signature() fields.map { |f| f.cpptype.param+" "+f.cppname }; end + def signature() fields.map { |f| f.signature }; end def body_name() parent.name.caps+name.caps+"Body"; end end @@ -197,7 +198,7 @@ class CppGen < Generator genl yield genl - genl('}'*names.size+" // "+name) + genl('}'*names.size+" // namespace "+name) genl end @@ -236,3 +237,11 @@ class CppGen < Generator end end +# Fully-qualified class name +class FqClass < Struct.new(:fqname,:namespace,:name,:file) + def initialize(fqclass) + names=fqclass.split "::" + super(fqclass, names[0..-2].join('::'), names[-1], names.join("/")) + end +end + diff --git a/cpp/rubygen/templates/Session.rb b/cpp/rubygen/templates/Session.rb index f351710e7d..c61a217682 100644 --- a/cpp/rubygen/templates/Session.rb +++ b/cpp/rubygen/templates/Session.rb @@ -4,209 +4,180 @@ $: << '..' require 'cppgen' -class SessionGen < CppGen - - def initialize(outdir, amqp) - super(outdir, amqp) - @chassis="server" - @classname="Session_#{@amqp.version.bars}" - end - - def return_type(m) - if (m.result) - return "TypedResult" - elsif (not m.responses().empty?) - return "Response" - else - return "Completion" - end +class CppGen + def session_methods + excludes = ["channel", "connection", "session", "execution"] + gen_methods=@amqp.methods_on(@chassis).reject { |m| + excludes.include? m.parent.name + } end +end - def declare_method (m) - param_unpackers = m.fields.collect { |f| "args[::qpid::client::#{f.cppname}|#{f.cpptype.default_value}]" } - if (m.content()) - param_names = m.param_names + ["content"] - param_unpackers << "args[content|DefaultContent(\"\")]" - params=m.signature + ["const MethodContent& content"] - else - param_names = m.param_names - params=m.signature - end - - if (params.empty?) - gen "#{return_type(m)} #{m.parent.name.lcaps}#{m.name.caps}();\n\n" - else - genl "template #{return_type(m)} #{m.parent.name.lcaps}#{m.name.caps}(ArgumentPack const& args)" - genl "{" - indent { - genl "return #{m.parent.name.lcaps}#{m.name.caps}(#{param_unpackers.join(",\n")});" - } - genl "}" - - #generate the 'real' methods signature - gen "#{return_type(m)} #{m.parent.name.lcaps}#{m.name.caps}(" - indent { gen params.join(",\n") } - gen ");\n\n" - - #generate some overloaded methods to handle keyword args - boost_max_arity = 8 - if param_names.length > boost_max_arity - keywords = param_names[1..boost_max_arity].collect { |p| "keyword::#{p}" } - else - keywords = param_names.collect { |p| "keyword::#{p}" } - end - genl "typedef boost::parameter::parameters< #{keywords.join(",")} > #{m.parent.name.caps}#{m.name.caps}Params;\n" - - j = 1 - while j <= params.length && j <= boost_max_arity - dummy_args = Array.new(j) { |i| "P#{i} const& p#{i}"} - dummy_names = Array.new(j) { |i| "p#{i}"} - dummy_types = Array.new(j) { |i| "class P#{i}"} - - genl "template <#{dummy_types.join(',')}> #{return_type(m)} #{m.parent.name.lcaps}#{m.name.caps}_(#{dummy_args.join(',')})" - genl "{" - indent { - genl "return #{m.parent.name.lcaps}#{m.name.caps}(#{m.parent.name.caps}#{m.name.caps}Params()(#{dummy_names.join(',')}));" - } - genl "}" - j = j + 1 - end - end +class ContentField # For extra content parameters + def cppname() "content" end + def signature() "const MethodContent& content" end + def unpack() "p[arg::content|DefaultContent(std::string())]"; end +end - end +class AmqpField + def unpack() "p[arg::#{cppname}|#{cpptype.default_value}]"; end +end - def define_method (m) - if (m.content()) - params=m.signature + ["const MethodContent& content"] - else - params=m.signature - end - if (params.empty?) - gen "#{return_type(m)} #{@classname}::#{m.parent.name.lcaps}#{m.name.caps}(){\n\n" - else - gen "#{return_type(m)} #{@classname}::#{m.parent.name.lcaps}#{m.name.caps}(" - indent { gen params.join(",\n") } - gen "){\n\n" - end - indent (2) { - gen "return #{return_type(m)}(impl->send(#{m.body_name}(" - params = ["version"] + m.param_names - gen params.join(", ") - other_params=[] - if (m.content()) - gen "), content), impl);\n" - else - gen ")), impl);\n" - end - } - gen "}\n\n" +class AmqpMethod + def fields_c() content ? fields+[ContentField.new] : fields end + def param_names_c() fields_c.map { |f| f.cppname} end + def signature_c() fields_c.map { |f| f.signature }; end + def argpack_name() "#{parent.cppname}#{name.caps}Parameters"; end + def argpack_type() + "boost::parameter::parameters<" + + fields_c.map { |f| "arg::keyword_tags::"+f.cppname }.join(',') + + ">" end - - def declare_keywords(classes) - #need to assemble a listof all the field names - keywords = classes.collect { |c| c.methods_on(@chassis).collect { |m| m.param_names } }.flatten().uniq() - keywords.each { |k| genl "BOOST_PARAMETER_KEYWORD(keyword, #{k})" } - genl "BOOST_PARAMETER_KEYWORD(keyword, content)" + def return_type() + return "TypedResult" if (result) + return "Response" if (not responses().empty?) + return "Completion" end + def session_function() "#{parent.name.lcaps}#{name.caps}"; end +end - def declare_class(c) - c.methods_on(@chassis).each { |m| declare_method(m) } - end +class SessionNoKeywordGen < CppGen - def define_class(c) - c.methods_on(@chassis).each { |m| define_method(m) } + def initialize(outdir, amqp) + super(outdir, amqp) + @chassis="server" + @namespace,@classname,@file= + parse_classname "qpid::client::no_keyword::Session_#{@amqp.version.bars}" end def generate() - excludes = ["channel", "connection", "session", "execution"] - - h_file("qpid/client/#{@classname}.h") { - genl "#define BOOST_PARAMETER_MAX_ARITY 8" - - gen < -#include -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/Uuid.h" -#include "qpid/framing/amqp_structs.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/framing/MethodContent.h" -#include "qpid/framing/TransferContent.h" -#include "qpid/client/Completion.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/Response.h" -#include "qpid/client/SessionCore.h" -#include "qpid/client/TypedResult.h" -#include "qpid/shared_ptr.h" - -namespace qpid { -namespace client { - -using std::string; -using framing::Content; -using framing::FieldTable; -using framing::MethodContent; -using framing::SequenceNumberSet; -using framing::Uuid; - + h_file(@file) { + include "qpid/framing/amqp_framing.h" + include "qpid/framing/Uuid.h" + include "qpid/framing/amqp_structs.h" + include "qpid/framing/ProtocolVersion.h" + include "qpid/framing/MethodContent.h" + include "qpid/framing/TransferContent.h" + include "qpid/client/Completion.h" + include "qpid/client/ConnectionImpl.h" + include "qpid/client/Response.h" + include "qpid/client/SessionCore.h" + include "qpid/client/TypedResult.h" + include "qpid/shared_ptr.h" + include "" + namespace("qpid::client") { + genl "using std::string;" + genl "using framing::Content;" + genl "using framing::FieldTable;" + genl "using framing::MethodContent;" + genl "using framing::SequenceNumberSet;" + genl "using framing::Uuid;" + genl + namespace("no_keyword") { + cpp_class(@classname) { + public + gen <get(); } +Uuid getId() const { return impl->getId(); } +void setSynchronous(bool sync) { impl->setSync(sync); } +void suspend(); +void close(); +Execution& execution() { return impl->getExecution(); } + +typedef framing::TransferContent DefaultContent; EOS - declare_keywords(@amqp.classes.select { |c| !excludes.include?(c.name) }) - genl - gen < impl; - framing::ProtocolVersion version; - friend class Connection; - #{@classname}(shared_ptr); -public: - #{@classname}(); - - framing::FrameSet::shared_ptr get() { return impl->get(); } - Uuid getId() const { return impl->getId(); } - void setSynchronous(bool sync) { impl->setSync(sync); } - void suspend(); - void close(); - Execution& execution() { return impl->getExecution(); } - - typedef framing::TransferContent DefaultContent; -EOS - indent { @amqp.classes.each { |c| declare_class(c) if !excludes.include?(c.name) } } - gen < impl; +framing::ProtocolVersion version; +friend class Connection; +#{@classname}(shared_ptr); EOS -} - - # .cpp file - cpp_file("qpid/client/#{@classname}.cpp") { - gen < core) : impl(core) {} - void #{@classname}::suspend() { impl->suspend(); } void #{@classname}::close() { impl->close(); } - EOS + session_methods.each { |m| + genl + sig=m.signature_c.join(", ") + func="#{@classname}::#{m.session_function}" + scope("#{m.return_type} #{func}(#{sig}) {") { + args=(["ProtocolVersion()"]+m.param_names).join(", ") + body="#{m.body_name}(#{args})" + sendargs=body + sendargs << ", content" if m.content + genl "return #{m.return_type}(impl->send(#{sendargs}), impl);" + }}}} + end +end - @amqp.classes.each { |c| define_class(c) if !excludes.include?(c.name) } - - gen <" + genl + namespace("qpid::client") { + # Generate keyword tag declarations. + namespace("arg") { + keyword_methods.map{ |m| m.param_names_c }.flatten.uniq.each { |k| + genl "BOOST_PARAMETER_KEYWORD(keyword_tags, #{k})" + }} + genl + cpp_class(@classname,"public #{@base}") { + private + genl "#{@classname}(shared_ptr core) : #{ @base}(core) {}" + keyword_methods.each { |m| typedef m.argpack_type, m.argpack_name } + genl "friend class Connection;" + public + genl "#{@classname}() {}" + keyword_methods.each { |m| gen_keyword_decl(m,@base+"::") } + }}} end end +SessionNoKeywordGen.new(ARGV[0], Amqp).generate() SessionGen.new(ARGV[0], Amqp).generate() -- cgit v1.2.1