summaryrefslogtreecommitdiff
path: root/cpp/rubygen
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2007-10-30 22:39:46 +0000
committerAlan Conway <aconway@apache.org>2007-10-30 22:39:46 +0000
commit9d32e58f281e6ecefcbde45a897395162395e577 (patch)
tree2ef6b1a250dbdf634ef4dec0ac98fd64b26693d2 /cpp/rubygen
parent3667cdd020d46af9c47c1c37998fbed7adae2248 (diff)
downloadqpid-python-9d32e58f281e6ecefcbde45a897395162395e577.tar.gz
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
Diffstat (limited to 'cpp/rubygen')
-rwxr-xr-xcpp/rubygen/cppgen.rb13
-rw-r--r--cpp/rubygen/templates/Session.rb333
2 files changed, 163 insertions, 183 deletions
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<qpid::framing::#{m.result.cpptype.ret}>"
- 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 <class ArgumentPack> #{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<qpid::framing::#{result.cpptype.ret}>" 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 <<EOS
-#include <sstream>
-#include <boost/parameter.hpp>
-#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 "<string>"
+ 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 <<EOS
+#{@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
- declare_keywords(@amqp.classes.select { |c| !excludes.include?(c.name) })
- genl
- gen <<EOS
-class #{@classname} {
- shared_ptr<SessionCore> impl;
- framing::ProtocolVersion version;
- friend class Connection;
- #{@classname}(shared_ptr<SessionCore>);
-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 <<EOS
-}; /* class #{@classname} */
-}
-}
+ session_methods.each { |m|
+ genl
+ args=m.signature_c.join(", ")
+ genl "#{m.return_type} #{m.session_function}(#{args});"
+ }
+ genl
+ protected
+ gen <<EOS
+shared_ptr<SessionCore> impl;
+framing::ProtocolVersion version;
+friend class Connection;
+#{@classname}(shared_ptr<SessionCore>);
EOS
-}
-
- # .cpp file
- cpp_file("qpid/client/#{@classname}.cpp") {
- gen <<EOS
-#include "#{@classname}.h"
-#include "qpid/framing/all_method_bodies.h"
-
-using std::string;
-using namespace qpid::framing;
-
-namespace qpid {
-namespace client {
-
+ }}}}
+
+ cpp_file(@file) {
+ include @classname
+ include "qpid/framing/all_method_bodies.h"
+ namespace(@namespace) {
+ gen <<EOS
+using namespace framing;
#{@classname}::#{@classname}() {}
#{@classname}::#{@classname}(shared_ptr<SessionCore> 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 <<EOS
-}} // namespace qpid::client
-EOS
- }
+class SessionGen < CppGen
+ def initialize(outdir, amqp)
+ super(outdir, amqp)
+ @chassis="server"
+ session="Session_#{@amqp.version.bars}"
+ @base="no_keyword::#{session}"
+ @fqclass=FqClass.new "qpid::client::#{session}"
+ @classname=@fqclass.name
+ @fqbase=FqClass.new("qpid::client::#{@base}")
+ end
+
+ def gen_keyword_decl(m, prefix)
+ return if m.fields_c.empty? # Inherited function will do.
+ scope("BOOST_PARAMETER_MEMFUN(#{m.return_type}, #{m.session_function}, 0, #{m.fields_c.size}, #{m.argpack_name}) {") {
+ scope("return #{prefix}#{m.session_function}(",");") {
+ gen m.fields_c.map { |f| f.unpack() }.join(",\n")
+ }
+ }
+ genl
+ end
+
+ def generate()
+ keyword_methods=session_methods.reject { |m| m.fields_c.empty? }
+ max_arity = keyword_methods.map{ |m| m.fields_c.size }.max
+
+ h_file(@fqclass.file) {
+ include @fqbase.file
+ genl
+ genl "#define BOOST_PARAMETER_MAX_ARITY #{max_arity}"
+ include "<boost/parameter.hpp>"
+ 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<SessionCore> 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()