diff options
author | Rajith Muditha Attapattu <rajith@apache.org> | 2011-05-27 15:44:23 +0000 |
---|---|---|
committer | Rajith Muditha Attapattu <rajith@apache.org> | 2011-05-27 15:44:23 +0000 |
commit | 66765100f4257159622cefe57bed50125a5ad017 (patch) | |
tree | a88ee23bb194eb91f0ebb2d9b23ff423e3ea8e37 /cpp/rubygen | |
parent | 1aeaa7b16e5ce54f10c901d75c4d40f9f88b9db6 (diff) | |
parent | 88b98b2f4152ef59a671fad55a0d08338b6b78ca (diff) | |
download | qpid-python-rajith_jms_client.tar.gz |
Creating a branch for experimenting with some ideas for JMS client.rajith_jms_client
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/rajith_jms_client@1128369 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/rubygen')
21 files changed, 0 insertions, 3743 deletions
diff --git a/cpp/rubygen/0-10/allsegmenttypes.rb b/cpp/rubygen/0-10/allsegmenttypes.rb deleted file mode 100755 index 26363d6a1f..0000000000 --- a/cpp/rubygen/0-10/allsegmenttypes.rb +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env ruby -# -# 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 .. in load path -require 'cppgen' - -class GenAllSegmentTypes < CppGen - def initialize(outdir, amqp) - super(outdir, amqp) - end - - def generate - h_file("tests/allSegmentTypes.h") { - include "qpid/amqp_0_10/specification.h" - include "qpid/amqp_0_10/Header.h" - include "qpid/amqp_0_10/Body.h" - genl - genl "using namespace qpid::amqp_0_10;" - genl - scope("template <class Op> size_t allSegmentTypes(Op& op) {"){ - genl "op(Header());" - genl "op(Body());" - n = 2; - @amqp.classes.each { |c| - c.commands.each { |s| genl "op(CommandHolder(#{c.nsname}::#{s.classname}()));" } - c.controls.each { |s| genl "op(ControlHolder(#{c.nsname}::#{s.classname}()));" } - n += 2 - } - genl "return #{n};" - } - } - end -end - -GenAllSegmentTypes.new($outdir, $amqp).generate(); - diff --git a/cpp/rubygen/0-10/exceptions.rb b/cpp/rubygen/0-10/exceptions.rb deleted file mode 100755 index 02e3a5d547..0000000000 --- a/cpp/rubygen/0-10/exceptions.rb +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env ruby -# -# 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 .. in load path -require 'cppgen' - -class GenExceptions < CppGen - - def initialize(outdir, amqp) - super(outdir, amqp) - @ns="qpid::amqp_#{@amqp.version.bars}" - @dir="qpid/amqp_#{@amqp.version.bars}" - end - - def exceptions_for_enum(enum, base, ns, suffix="") - enum.choices.each { |c| - name=c.name.typename+suffix+"Exception" - genl - doxygen_comment { genl c.doc } - struct(name, "public #{base}") { - genl "#{name}(const std::string& msg=std::string())" - genl " : #{base}(#{ns}::#{c.name.shout}, msg) {}" - protected - genl "std::string getPrefix() const { return \"#{name}\"; }" - } - } - end - - def gen_exceptions() - h_file("#{@dir}/exceptions") { - include "qpid/amqp_0_10/Exception" - namespace("#{@ns}") { - error_code = @amqp.class_("execution").domain("error-code").enum - exceptions_for_enum(error_code, "SessionAbortedException", "execution") - genl - - detach_code = @amqp.class_("session").domain("detach-code").enum - exceptions_for_enum(detach_code, "SessionDetachedException", "session", "Detached") - - genl - exceptions_for_enum(detach_code, "SessionExpiredException", "session", "Expired") - genl - - close_code = @amqp.class_("connection").domain("close-code").enum - exceptions_for_enum(close_code, "ConnectionException", "connection") - } - } - end - - def generate() - gen_exceptions - end -end - -GenExceptions.new($outdir, $amqp).generate(); - - diff --git a/cpp/rubygen/0-10/handlers.rb b/cpp/rubygen/0-10/handlers.rb deleted file mode 100755 index 981ea890e6..0000000000 --- a/cpp/rubygen/0-10/handlers.rb +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env ruby -# -# 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 .. in load path -require 'cppgen' - -class GenHandlers < CppGen - def initialize(outdir, amqp) - super(outdir, amqp) - @ns="qpid::amqp_#{@amqp.version.bars}" - @dir="qpid/amqp_#{@amqp.version.bars}" - end - - def action_handler(type, actions) - genl - bases=actions.map { |a| "public #{a.fqclassname}::Handler" } - struct("#{type}Handler", *bases) { } - end - - def generate() - h_file("#{@dir}/handlers.h") { - include "#{@dir}/specification" - namespace("#{@ns}") { - action_handler "Command", @amqp.collect_all(AmqpCommand) - action_handler "Control", @amqp.collect_all(AmqpControl) - } - } - end -end - -GenHandlers.new($outdir, $amqp).generate() diff --git a/cpp/rubygen/0-10/specification.rb b/cpp/rubygen/0-10/specification.rb deleted file mode 100755 index ef193f5fd0..0000000000 --- a/cpp/rubygen/0-10/specification.rb +++ /dev/null @@ -1,389 +0,0 @@ -#!/usr/bin/env ruby -# -# 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 .. in load path -require 'cppgen' - - -# Dummy element representing an unknown struct type. -class UnknownStruct - def visitable?() true end - def fqclassname() "UnknownStruct" end -end - -# Dummy element representing a session.header field -class SessionHeaderField - def amqp2cpp() "session::Header" end - def cppname() "sessionHeader" end - def name() "session-header" end -end - -class Specification < CppGen - def initialize(outdir, amqp) - super(outdir, amqp) - @ns="qpid::amqp_#{@amqp.version.bars}" - @dir="qpid/amqp_#{@amqp.version.bars}" - end - - # domains - - def domain_h(d) - genl - typename=d.name.typename - if d.enum - scope("enum #{typename} {", "};") { - genl d.enum.choices.map { |c| - "#{c.name.constname} = #{c.value}" }.join(",\n") - } - scope("inline SerializeAs<#{typename}, uint8_t> serializable(#{typename}& e) {") { - genl "return SerializeAs<#{typename}, uint8_t>(e);" - } - else - genl "typedef #{d.amqp2cpp} #{typename};" - end - end - - def visitable?(x) x.code and x.size=="4" end - - # Used by structs, commands and controls. - def action_struct_h(x, base, consts, &block) - genl - base = visitable?(x) ? ["public #{base}"] : [] - struct(x.classname, *base) { - x.fields.each { |f| genl "#{f.amqp2cpp} #{f.cppname};" } - genl - 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 "static const char* CLASS_NAME;" - ctor_decl("explicit #{x.classname}", x.parameters(true)) - - if visitable? x - genl "void accept(Visitor&);" - genl "void accept(ConstVisitor&) const;" - end - - if (x.fields.empty?) - genl "template <class S> void serialize(S&) {}" - else - scope("template <class S> void serialize(S& s) {") { - gen "s"; x.fields.each { |f| gen "(#{f.cppname})"}; genl ";" - } - end - genl - yield if block - } - case x - when AmqpCommand then packer = "CommandPacker" - when AmqpControl then packer = "Packer" - when AmqpStruct then packer = "SizedPacker" - end - genl "inline #{packer}<#{x.classname}> serializable(#{x.classname}& x) { return #{packer}<#{x.classname}>(x); }" unless x.respond_to? :pack and x.pack == "0" - genl "std::ostream& operator << (std::ostream&, const #{x.classname}&);" - genl "bool operator==(const #{x.classname}&, const #{x.classname}&);" - end - - def action_struct_cpp(x, &block) - genl - genl "const char* #{x.classname}::NAME=\"#{x.fqname}\";" - genl "const char* #{x.classname}::CLASS_NAME=#{x.containing_class.nsname}::NAME;" - genl - ctor=x.classname+"::"+x.classname - ctor_defn(ctor, x.parameters, x.initializers) {} - - if visitable? x - genl "void #{x.classname}::accept(Visitor& v) { v.visit(*this); }" - genl "void #{x.classname}::accept(ConstVisitor& v) const { v.visit(*this); }" - end - genl - scope("std::ostream& operator << (std::ostream& o, const #{x.classname}&#{"x" unless x.fields.empty?}) {") { - genl "o << \"#{x.fqname}[\";"; - x.fields.each{ |f| genl "o << \" #{f.name}=\" << x.#{f.cppname};" } - genl "o << \"]\";" - genl "return o;" - } - yield if block - end - - # structs - - def struct_h(s) action_struct_h(s, "Struct", ["size","pack","code"]); end - def struct_cpp(s) action_struct_cpp(s) end - - # command and control - - def action_h(a) - action_struct_h(a, a.base, ["code"]) { - struct("Handler") { - scope("void #{a.funcname}(", ");") { - genl a.parameters.join(",\n") - } - } - function_defn("template <class T> void invoke", ["T& target"], "const") { - genl "target.#{a.funcname}(#{a.values.join(', ')} );" - } - } - end - - def action_cpp(a) - action_struct_cpp(a) { - scope("void #{a.classname}::Handler::#{a.funcname}(", ")") { - genl a.unused_parameters.join(",\n") - } - scope { - genl "assert(0);" - genl "throw NotImplementedException(QPID_MSG(\"#{a.fqname} not implemented.\"));" - } - } - end - - # Types that must be generated early because they are used by other types. - def pregenerate?(x) not @amqp.used_by[x.fqname].empty?; end - - def pregenerate_class?(c) - c.children.select{ |t| (t.is_a? AmqpStruct or t.is_a? AmqpDomain) and pregenerate? t} - end - - # Typedefs, enums and forward declarations for classes. - def gen_specification_fwd() - h_file("#{@dir}/specification_fwd") { - include "#{@dir}/built_in_types" - namespace(@ns) { - # Top level - @amqp.domains.each { |d| - # segment-type and track are are built in - domain_h d unless ["track","segment-type"].include?(d.name) - } - each_class_ns { |c| - genl "const uint8_t CODE=#{c.code};" # class code - genl "extern const char* NAME;" - c.each_descendant { |x| - case x - when AmqpDomain then domain_h x - when AmqpStruct then genl "class #{x.classname};" - when AmqpAction then genl "class #{x.classname};" - end - } - } - } - } - end - - # Generate struct definitions into a separate header file so the - # can be included by StructHolder.h without circularity. - def gen_structs() - h_file("#{@dir}/structs") { - include "#{@dir}/specification_fwd" - include "#{@dir}/Map.h" - include "#{@dir}/Array.h" - include "#{@dir}/Struct.h" - include "#{@dir}/UnknownStruct.h" - include "#{@dir}/Packer.h" - namespace(@ns) { - each_class_ns { |c| - c.collect_all(AmqpStruct).each { |s| struct_h s } - } - } - } - - cpp_file("#{@dir}/structs") { - include "#{@dir}/structs" - include "#{@dir}/StructHolder" - namespace(@ns) { - each_class_ns { |c| - c.collect_all(AmqpStruct).each { |s| struct_cpp(s) } - } - } - } - end - - # Generate the specification files - def gen_specification() - h_file("#{@dir}/specification") { - include "#{@dir}/specification_fwd.h" - include "#{@dir}/Map.h" - include "#{@dir}/Array.h" - include "#{@dir}/UnknownType.h" - include "#{@dir}/Struct32" - include "#{@dir}/Control.h" - include "#{@dir}/Command.h" - include "#{@dir}/Packer.h" - include "<iosfwd>" - namespace(@ns) { - each_class_ns { |c| - c.collect_all(AmqpAction).each { |a| action_h a } - } - }} - - cpp_file("#{@dir}/specification") { - include "#{@dir}/specification" - include "#{@dir}/exceptions" - include "<iostream>" - ["Command","Control", "Struct"].each { |x| include "#{@dir}/Apply#{x}" } - namespace(@ns) { - each_class_ns { |c| - genl "const char* NAME=\"#{c.fqname}\";" - c.actions.each { |a| action_cpp a} - } - } - } - end - - def gen_proxy() - h_file("#{@dir}/ProxyTemplate.h") { - include "#{@dir}/specification" - namespace(@ns) { - genl "template <class F, class R=typename F::result_type>" - cpp_extern_class("QPID_COMMON_CLASS_EXTERN", "ProxyTemplate") { - public - genl "ProxyTemplate(F f=F()) : functor(f) {}" - @amqp.classes.each { |c| - c.actions.each { |a| - genl - function_defn("R #{a.funcname}", a.parameters) { - var=a.name.funcname - args = a.arguments.empty? ? "" : "("+a.arguments.join(", ")+")" - genl("#{a.fqclassname} #{var}#{args};") - genl "return functor(#{var});" - } - } - } - private - genl "F functor;" - } - } - } - end - - def visitor_interface_h(base, subs, is_const) - name="#{is_const ? 'Const' : ''}#{base}Visitor" - const=is_const ? "const " : "" - struct(name) { - genl "virtual ~#{name}() {}" - genl "typedef #{const}#{base} BaseType;" - subs.each{ |s| - genl "virtual void visit(#{const}#{s.fqclassname}&) = 0;" - }} - end - - def visitor_impl(base, subs, is_const) - name="#{is_const ? 'Const' : ''}#{base}Visitor" - const=is_const ? "const " : "" - genl "template <class F>" - struct("ApplyVisitor<#{name}, F>", "public ApplyVisitorBase<#{name}, F>") { - subs.each{ |s| - genl "virtual void visit(#{const}#{s.fqclassname}& x) { this->invoke(x); }" - }} - end - - def gen_visitor(base, subs) - h_file("#{@dir}/#{base}Visitor.h") { - include base=="Struct" ? "#{@dir}/structs" : "#{@dir}/specification" - namespace("#{@ns}") { - visitor_interface_h(base, subs, false) - visitor_interface_h(base, subs, true) - }} - - h_file("#{@dir}/Apply#{base}.h") { - include "#{@dir}/#{base}Visitor.h" - include "#{@dir}/apply.h" - namespace("#{@ns}") { - visitor_impl(base, subs, false) - visitor_impl(base, subs, true) - } - } - end - - def gen_holder(base, subs) - name=base+"Holder" - h_file("#{@dir}/#{name}") { - include "#{@dir}/Apply#{base}" - include "#{@dir}/Holder" - include base=="Struct" ? "#{@dir}/structs" : "#{@dir}/specification" - namespace(@ns){ - namespace("#{base.downcase}_max") { - genl "static const size_t MAX000=0;" - last="MAX000" - subs.each { |s| - sizeof="sizeof(#{s.fqclassname})" - genl "static const size_t #{last.succ} = #{sizeof} > #{last} ? #{sizeof} : #{last};" - last.succ! - } - genl "static const int MAX=#{last};" - } - holder_base="amqp_0_10::Holder<#{name}, #{base}, #{base.downcase}_max::MAX>" - struct("#{name}", "public #{holder_base}") { - genl "#{name}() {}" - genl "template <class T> explicit #{name}(const T& t) : #{holder_base}(t) {}" - genl "using #{holder_base}::operator=;" - genl "void set(uint8_t classCode, uint8_t code);" - } - genl - genl "std::ostream& operator<<(std::ostream& o, const #{name}& h);" - } - } - - cpp_file("#{@dir}/#{name}") { - include "#{@dir}/#{name}" - include "#{@dir}/exceptions.h" - namespace(@ns) { - genl "using framing::in_place;" - genl - scope("void #{name}::set(uint8_t classCode, uint8_t code) {") { - genl "uint16_t key=(classCode<<8)+code;" - scope ("switch(key) {") { - subs.each { |s| - genl "case 0x#{s.full_code.to_s(16)}: *this=in_place<#{s.fqclassname}>(); break;" unless (s.is_a? UnknownStruct) - } - genl "default: " - indent { - if (base=="Struct") - genl "*this=in_place<UnknownStruct>(classCode, code);" - else - genl "throw CommandInvalidException(QPID_MSG(\"Invalid class-#{base.downcase} key \" << std::hex << key));" - end - } - } - } - genl - genl "std::ostream& operator<<(std::ostream& o, const #{name}& h) { return h.get() ? (o << *h.get()) : (o << \"<empty #{name}>\"); }" - } - } - end - - def gen_visitable(base, subs) - subs << UnknownStruct.new if base=="Struct" # Extra case for unknown structs. - gen_holder(base, subs) - gen_visitor(base, subs) - end - - def generate - gen_specification_fwd - gen_specification - gen_proxy - gen_structs - gen_visitable("Command", @amqp.collect_all(AmqpCommand)) - gen_visitable("Control", @amqp.collect_all(AmqpControl)) - gen_visitable("Struct", @amqp.collect_all(AmqpStruct).select { |s| s.code}) - end -end - -Specification.new($outdir, $amqp).generate(); diff --git a/cpp/rubygen/0-10/typecode.rb b/cpp/rubygen/0-10/typecode.rb deleted file mode 100755 index 0ab9c4be5d..0000000000 --- a/cpp/rubygen/0-10/typecode.rb +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env ruby -# -# 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 .. in load path -require 'cppgen' - -class TypeCode < CppGen - def initialize(outdir, amqp) - super(outdir, amqp) - @ns="qpid::amqp_#{@amqp.version.bars}" - @dir="qpid/amqp_#{@amqp.version.bars}" - @types = @amqp.collect_all(AmqpType).select { |t| t.code } - - end - - def type_for_code_h() - h_file("#{@dir}/TypeForCode") { - include "#{@dir}/built_in_types.h" - include "#{@dir}/UnknownType.h" - namespace(@ns) { - genl - genl "template <uint8_t Code> struct TypeForCode;" - genl - @types.each { |t| - genl "template <> struct TypeForCode<#{t.code}> { typedef #{t.typename} type; };" - } - genl - genl "template <class V> typename V::result_type" - scope("apply_visitor(V& visitor, uint8_t code) {") { - scope("switch (code) {", "}") { - @types.each { |t| - genl "case #{t.code}: return visitor((#{t.typename}*)0);" - } - genl "default: return visitor((UnknownType*)0);" - } - } - genl - genl "std::string typeName(uint8_t code);" - } - } - end - - def type_for_code_cpp() - cpp_file("#{@dir}/TypeForCode") { - include "<string>" - include "<sstream>" - namespace(@ns) { - namespace("") { - struct("Names") { - scope("Names() {") { - scope("for (int i =0; i < 256; ++i) {") { - genl "std::ostringstream os;" - genl "os << \"UnknownType<\" << i << \">\";" - genl "names[i] = os.str();" - } - @types.each { |t| genl "names[#{t.code}] = \"#{t.name}\";" } - } - genl "std::string names[256];" - } - genl "Names names;" - } - genl "std::string typeName(uint8_t code) { return names.names[code]; }" - }} - end - - def code_for_type_h() - name="#{@dir}/CodeForType" - h_file(name) { - include "#{@dir}/built_in_types.h" - - namespace(@ns) { - genl - genl "template <class T> struct CodeForType;" - genl - @types.each { |t| - genl "template <> struct CodeForType<#{t.typename}> { static const uint8_t value; };" - } - genl - genl "template <class T> uint8_t codeFor(const T&) { return CodeForType<T>::value; }" - } - } - - cpp_file(name) { - include name - namespace(@ns) { - @types.each { |t| - genl "const uint8_t CodeForType<#{t.typename}>::value=#{t.code};" - } - } - } - end - - def generate - type_for_code_h - type_for_code_cpp - code_for_type_h - end -end - -TypeCode.new($outdir, $amqp).generate(); - diff --git a/cpp/rubygen/MethodBodyDefaultVisitor.rb b/cpp/rubygen/MethodBodyDefaultVisitor.rb deleted file mode 100755 index 11dbcb8f83..0000000000 --- a/cpp/rubygen/MethodBodyDefaultVisitor.rb +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env ruby -# -# 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 .. in load path -require 'cppgen' - -class MethodBodyDefaultVisitorGen < CppGen - - def initialize(outdir, amqp) - super(outdir, amqp) - set_classname("qpid::framing::MethodBodyDefaultVisitor") - end - - def generate() - h_file(@filename) { - include "qpid/framing/MethodBodyConstVisitor" - namespace(@namespace) { - genl - cpp_extern_class("QPID_COMMON_CLASS_EXTERN", @classname, "public MethodBodyConstVisitor") { - genl "public:" - genl "virtual void defaultVisit() = 0;" - @amqp.methods_.each { |m| - genl "virtual void visit(const #{m.body_name}&);" } - }}} - - cpp_file(@filename) { - include(@filename) - namespace(@namespace) { - @amqp.methods_.each { |m| - genl "void #{@classname}::visit(const #{m.body_name}&) { defaultVisit(); }" - }}} - end -end - -MethodBodyDefaultVisitorGen.new($outdir, $amqp).generate(); - diff --git a/cpp/rubygen/README.txt b/cpp/rubygen/README.txt deleted file mode 100644 index a1fd6cfec8..0000000000 --- a/cpp/rubygen/README.txt +++ /dev/null @@ -1,17 +0,0 @@ -RUBY CODE GENERATOR - -Run ./generate for usage. -Examples in samples/ - -For example: - ./generate . ../../specs/amqp.0-9.xml samples/Proxy.rb -will generate - - - - - - - - - diff --git a/cpp/rubygen/amqpgen.rb b/cpp/rubygen/amqpgen.rb deleted file mode 100755 index 20aac35194..0000000000 --- a/cpp/rubygen/amqpgen.rb +++ /dev/null @@ -1,550 +0,0 @@ -# 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. -# -# Generic AMQP code generation library. -# -# TODO aconway 2008-02-21: -# -# The amqp_attr_reader and amqp_child_reader for each Amqp* class -# should correspond exactly to ampq.dtd. Currently they are more -# permissive so we can parse 0-10 preview and 0-10 final XML. -# -# Code marked with "# preview" should be removed/modified when final 0-10 -# is complete and we are ready to remove preview-related code. -# - -require 'delegate' -require 'rexml/document' -require 'pathname' -require 'set' -include REXML - -# Handy String functions for converting names. -class String - # Convert to CapitalizedForm. - def caps() gsub( /(^|\W)(\w)/ ) { |m| $2.upcase } end - - # Convert to underbar_separated_form. - def bars() tr('- .','_'); end - - # Convert to ALL_UPPERCASE_FORM - def shout() bars.upcase; end - - # Convert to lowerCaseCapitalizedForm - def lcaps() gsub( /\W(\w)/ ) { |m| $1.upcase } end - - def plural() self + (/[xs]$/ === self ? 'es' : 's'); end -end - -# Sort an array by name. -module Enumerable - def sort_by_name() sort { |a,b| a.name <=> b.name }; end -end - -# Add functions similar to attr_reader for AMQP attributes/children. -# Symbols that are ruby Object function names (e.g. class) get -# an "_" suffix. -class Module - # Add trailing _ to avoid conflict with Object methods. - def mangle(sym) - sym = (sym.to_s+"_").to_sym if (Object.method_defined?(sym) or sym == :type) - sym - end - - # Add attribute reader for XML attribute. - def amqp_attr_reader(*attrs) - attrs.each { |a| - case a - when Symbol - define_method(mangle(a)) { - @amqp_attr_reader||={ } - @amqp_attr_reader[a] ||= xml.attributes[a.to_s] - } - when Hash - a.each { |attr, default| - define_method(mangle(attr)) { - @amqp_attr_reader||={ } - value = xml.attributes[attr.to_s] - if value - @amqp_attr_reader[attr] ||= value - else - @amqp_attr_reader[attr] ||= default - end - } - } - end - } - end - - # Add 2 child readers: - # elname(name) == child('elname',name) - # elnames() == children('elname') - def amqp_child_reader(*element_names) - element_names.each { |e| - define_method(mangle(e)) { |name| child(e.to_s, name) } - define_method(mangle(e.to_s.plural)) { children(e.to_s) } } - end - - # When there can only be one child instance - def amqp_single_child_reader(*element_names) - element_names.each { |e| - define_method(mangle(e)) { children(e.to_s)[0] } } - end -end - -# An AmqpElement contains an XML element and provides a convenient -# API to access AMQP data. -# -# NB: AmqpElements cache values from XML, they assume that -# the XML model does not change after the AmqpElement has -# been created. -class AmqpElement - - def wrap(xml) - return nil if ["assert","rule"].include? xml.name - eval("Amqp"+xml.name.caps).new(xml, self) or raise "nil wrapper" - end - - public - - def initialize(xml, parent) - @xml, @parent=xml, parent - @children=xml.elements.map { |e| wrap e }.compact - @cache_child={} - @cache_child_named={} - @cache_children={} - @cache_children[nil]=@children - end - - attr_reader :parent, :xml, :children, :doc - amqp_attr_reader :name, :label - - # List of children of type elname, or all children if elname - # not specified. - def children(elname=nil) - 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 - - def collect_all(amqp_type) - collect=[] - each_descendant { |d| collect << d if d.is_a? amqp_type } - collect - end - - # Look up child of type elname with attribute name. - def child(elname, name) - @cache_child[[elname,name]] ||= children(elname).find { |c| c.name==name } - end - - # Look up any child with name - def child_named(name) - @cache_child_named[name] ||= @children.find { |c| c.name==name } - end - - # The root <amqp> element. - def root() @root ||=parent ? parent.root : self; end - - def to_s() "#<#{self.class}(#{fqname})>"; end - def inspect() to_s; end - - # Text of doc child if there is one. - def doc() d=xml.elements["doc"]; d and d.text; end - - def fqname() - throw "fqname: #{self} #{parent.fqname} has no name" unless name - p=parent && parent.fqname - p ? p+"."+name : name; - end - - def containing_class() - return self if is_a? AmqpClass - return parent && parent.containing_class - end - - # 0-10 array domains are missing element type information, add it here. - ArrayTypes={ - "str16-array" => "str-16", - "amqp-host-array" => "connection.amqp-host-url", - "command-fragments" => "session.command-fragment", - "in-doubt" => "dtx.xid", - "tx-publish" => "str-8", - "queues" => "str-8" - } - - def array_type(name) - return ArrayTypes[name] if ArrayTypes[name] - raise "Missing ArrayType entry for " + name - end - -end - -class AmqpResponse < AmqpElement - def initialize(xml, parent) super; end - def fqname() (parent ? parent.dotted_name+"." : "") + "response"; end -end - -class AmqpDoc < AmqpElement - def initialize(xml,parent) super; end - def text() @xml.text end -end - -class AmqpChoice < AmqpElement - def initialize(xml,parent) super; end - amqp_attr_reader :name, :value -end - -class AmqpEnum < AmqpElement - def initialize(xml,parent) super; end - amqp_child_reader :choice -end - -class AmqpDomain < AmqpElement - def initialize(xml, parent) - super - root.used_by[uses].push(fqname) if uses and uses.index('.') - end - - amqp_attr_reader :type - amqp_single_child_reader :struct # preview - amqp_single_child_reader :enum - - def uses() type_=="array" ? ArrayTypes[name] : type_; end -end - -class AmqpException < AmqpElement - def initialize(xml, amqp) super; end; - amqp_attr_reader :error_code -end - -class AmqpField < AmqpElement - def initialize(xml, amqp) - super; - root.used_by[type_].push(parent.fqname) if type_ and type_.index('.') - end - amqp_single_child_reader :struct # preview - amqp_child_reader :exception - amqp_attr_reader :type, :default, :code, :required -end - -class AmqpChassis < AmqpElement # preview - def initialize(xml, parent) super; end - amqp_attr_reader :implement -end - -class AmqpConstant < AmqpElement - def initialize(xml, parent) super; end - amqp_attr_reader :value, :class -end - -class AmqpResult < AmqpElement - def initialize(xml, parent) super; end - amqp_single_child_reader :struct # preview - amqp_attr_reader :type - def name() "result"; end -end - -class AmqpEntry < AmqpElement - def initialize(xml,parent) super; end - amqp_attr_reader :type -end - -class AmqpHeader < AmqpElement - def initialize(xml,parent) super; end - amqp_child_reader :entry - amqp_attr_reader :required -end - -class AmqpBody < AmqpElement - def initialize(xml,parent) super; end - amqp_attr_reader :required -end - -class AmqpSegments < AmqpElement - def initialize(xml,parent) super; end - amqp_child_reader :header, :body -end - -class AmqpStruct < AmqpElement - def initialize(xml, parent) super; end - amqp_attr_reader :type # preview - amqp_attr_reader :size, :code, :pack - amqp_child_reader :field - - def result?() parent.xml.name == "result"; end - def domain?() parent.xml.name == "domain"; end -end - -class AmqpMethod < AmqpElement - def initialize(xml, parent) super; end - - amqp_attr_reader :content, :index, :synchronous - amqp_child_reader :field, :chassis,:response - amqp_single_child_reader :result - - def on_chassis?(chassis) child("chassis", chassis); end - def on_client?() on_chassis? "client"; end - def on_server?() on_chassis? "server"; end -end - -# preview: Map command/control to preview method. -class AmqpFakeMethod < AmqpMethod - def initialize(action) - super(action.xml, action.parent); - @action=action - end - - def content() return "1" if @action.is_a? AmqpCommand and @action.segments end - def index() @action.code end - def code() @action.code end - def synchronous() end - def on_chassis?(chassis) - @action.received_by?(chassis) - end - def pack() "2" end # Encode pack=2, size=4 struct - def size() "4" end -end - -class AmqpImplement < AmqpElement - def initialize(xml,amqp) super; end - amqp_attr_reader :handle, :send -end - -class AmqpRole < AmqpElement - def initialize(xml,amqp) super; end - amqp_attr_reader :implement -end - -# 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 - def implement?(role) - # we can't use xpath for this because it triggers a bug in some - # versions of ruby, including version 1.8.6.110 - xml.elements.each {|el| - return true if el.name == "implement" and el.attributes["role"] == role - } - return false - end - def received_by?(client_or_server) - return (implement?(client_or_server) or implement?("sender") or implement?("receiver")) - end - def pack() "2" end - def size() "4" end # Encoded as a size 4 Struct -end - -class AmqpControl < AmqpAction - def initialize(xml,amqp) super; end -end - -class AmqpCommand < AmqpAction - def initialize(xml,amqp) super; end - amqp_child_reader :exception - amqp_single_child_reader :result, :segments -end - -class AmqpClass < AmqpElement - def initialize(xml,amqp) super; end - - amqp_attr_reader :index # preview - - amqp_child_reader :struct, :domain, :control, :command, :role, :method - amqp_attr_reader :code - - def actions() controls+commands; end - - # preview - command/control as methods - def methods_() - return (controls + commands).map { |a| AmqpFakeMethod.new(a) } - end - - def method(name) - a = (command(name) or control(name)) - return AmqpFakeMethod.new(a) - end - - # chassis should be "client" or "server" - def methods_on(chassis) # preview - @methods_on ||= { } - @methods_on[chassis] ||= methods_.select { |m| m.on_chassis? chassis } - end - - # FIXME aconway 2008-04-11: - def l4?() # preview - !["connection", "session", "execution"].include?(name) && !control? - end - - # FIXME aconway 2008-04-11: - def control?() - ["connection", "session"].include?(name) - end -end - -class AmqpType < AmqpElement - def initialize(xml,amqp) super; end - amqp_attr_reader :code, :fixed_width, :variable_width -end - -class AmqpXref < AmqpElement - def initialize(xml,amqp) super; end -end - -# AMQP root element. -class AmqpRoot < AmqpElement - amqp_attr_reader :major, :minor, :port, :comment - amqp_child_reader :doc, :type, :struct, :domain, :constant, :class - - def get_root(x) - case x - when Element then x - when Document then x.root - else Document.new(x).root - end - end - - # Initialize with output directory and spec files from ARGV. - def initialize(*specs) - raise "No XML spec files." if specs.empty? - xml=get_root(specs.shift) - specs.each { |s| xml_merge(xml, get_root(s)) } - @used_by=Hash.new{ |h,k| h[k]=[] } - super(xml, nil) - end - - attr_reader :used_by - - def merge(root) xml_merge(xml, root.xml); end - - def version() major + "-" + minor; end - - def methods_() classes.map { |c| c.methods_ }.flatten; end - - #preview - # Return all methods on chassis for all classes. - def methods_on(chassis) - @methods_on ||= { } - @methods_on[chassis] ||= classes.map { |c| c.methods_on(chassis) }.flatten - end - - def fqname() nil; end - - private - - # Merge contents of elements. - def xml_merge(to,from) - from.elements.each { |from_child| - tag,name = from_child.name, from_child.attributes["name"] - to_child=to.elements["./#{tag}[@name='#{name}']"] - to_child ? xml_merge(to_child, from_child) : to.add(from_child.deep_clone) } - end -end - -# Collect information about generated files. -class GenFiles - @@files = Set.new - @@public_api = [] - def GenFiles.add(f) @@files.add(f); end - def GenFiles.get() @@files; end - def GenFiles.public_api(file) @@public_api << file; end - def GenFiles.public_api?(file) @@public_api.find { |f| f == file }; end -end - -# Base class for code generators. -# Supports setting a per-line prefix, useful for e.g. indenting code. -# -class Generator - # Takes directory for output or "-", meaning print file names that - # would be generated. - def initialize (outdir, amqp) - @outdir=outdir[0] - @apidir=outdir[1] - @amqp=amqp - raise "outdir is not an array" unless outdir.class == Array - @prefix=[''] # For indentation or comments. - @indentstr=' ' # One indent level. - @outdent=2 - end - - # Declare next file to be public API - def public_api(file) GenFiles.public_api(file); end - - # Create a new file, set @out. - def file(file, &block) - GenFiles.add(file) - dir = GenFiles.public_api?(file) ? @apidir : @outdir - if (dir != "-") - @path=Pathname.new "#{dir}/#{file}" - @path.parent.mkpath - @out=String.new # Generate in memory first - yield if block - 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}" - end - end - end - - # Append multi-line string to generated code, prefixing each line. - def gen(str) - str.each_line { |line| - @out << @prefix.last unless @midline - @out << line - @midline = nil - } - # Note if we stopped mid-line - @midline = /[^\n]\z/ === str - end - - # Append str + '\n' to generated code. - def genl(str="") gen str+"\n"; end - - # Generate code with added prefix. - 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) - @prefix.push @prefix.last[0...-2] - if block then yield; endprefix; end - end - alias :endoutdent :endprefix - - attr_accessor :out -end - diff --git a/cpp/rubygen/cppgen.rb b/cpp/rubygen/cppgen.rb deleted file mode 100755 index 7dc21fe1bc..0000000000 --- a/cpp/rubygen/cppgen.rb +++ /dev/null @@ -1,452 +0,0 @@ -#!/usr/bin/ruby -# -# General purpose C++ code generation. -# -require 'amqpgen' -require 'set' - -Copyright=<<EOS -/* - * - * 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. - * - */ - -/// -/// This file was automatically generated from the AMQP specification. -/// Do not edit. -/// - - -EOS - -CppKeywords = Set.new(["and", "and_eq", "asm", "auto", "bitand", - "bitor", "bool", "break", "case", "catch", "char", - "class", "compl", "const", "const_cast", "continue", - "default", "delete", "do", "DomainInfo", "double", - "dynamic_cast", "else", "enum", "explicit", "extern", - "false", "float", "for", "friend", "goto", "if", - "inline", "int", "long", "mutable", "namespace", "new", - "not", "not_eq", "operator", "or", "or_eq", "private", - "protected", "public", "register", "reinterpret_cast", - "return", "short", "signed", "sizeof", "static", - "static_cast", "struct", "switch", "template", "this", - "throw", "true", "try", "typedef", "typeid", - "typename", "union", "unsigned", "using", "virtual", - "void", "volatile", "wchar_t", "while", "xor", - "xor_eq"]) -# Names that need a trailing "_" to avoid clashes. -CppMangle = CppKeywords+Set.new(["std::string"]) - -class String - def cppsafe() CppMangle.include?(self) ? self+"_" : self; end - - def amqp2cpp() - path=split(".") - name=path.pop - return name.typename if path.empty? - path.map! { |n| n.nsname } - return (path << name.caps.cppsafe).join("::") - end - - 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 - -# preview: Hold information about a C++ type. -# -# new mapping does not use CppType, -# Each amqp type corresponds exactly by dotted name -# to a type, domain or struct, which in turns -# corresponds by name to a C++ type or typedef. -# (see String.amqp2cpp) -# -class CppType - def initialize(name) @name=@param=@ret=name; end - attr_reader :name, :param, :ret, :code - - def retref() @ret="#{name}&"; self; end - def retcref() @ret="const #{name}&"; self; end - def passcref() @param="const #{name}&"; self; end - def code(str) @code=str; self; end - def defval(str) @defval=str; self; end - def encoded() @code end - def ret_by_val() @name; end - - def encode(value, buffer) - @code ? "#{buffer}.put#{@code}(#{value});" : "#{value}.encode(#{buffer});" - end - - def decode(value,buffer) - if @code - if /&$/===param then - "#{buffer}.get#{@code}(#{value});" - else - "#{value} = #{buffer}.get#{@code}();" - end - else - "#{value}.decode(#{buffer});" - end - end - - def default_value() - return @defval ||= "#{name}()" - end - - def to_s() name; end; -end - -class AmqpRoot - # preview; map 0-10 types to preview code generator types - @@typemap = { - "bit"=> CppType.new("bool").code("Octet").defval("false"), - "boolean"=> CppType.new("bool").code("Octet").defval("false"), - "uint8"=>CppType.new("uint8_t").code("Octet").defval("0"), - "uint16"=>CppType.new("uint16_t").code("Short").defval("0"), - "uint32"=>CppType.new("uint32_t").code("Long").defval("0"), - "uint64"=>CppType.new("uint64_t").code("LongLong").defval("0"), - "datetime"=>CppType.new("uint64_t").code("LongLong").defval("0"), - "str8"=>CppType.new("std::string").passcref.retcref.code("ShortString"), - "str16"=>CppType.new("std::string").passcref.retcref.code("MediumString"), - "str32"=>CppType.new("std::string").passcref.retcref.code("LongString"), - "vbin8"=>CppType.new("std::string").passcref.retcref.code("ShortString"), - "vbin16"=>CppType.new("std::string").passcref.retcref.code("MediumString"), - "vbin32"=>CppType.new("std::string").passcref.retcref.code("LongString"), - "map"=>CppType.new("FieldTable").passcref.retcref, - "array"=>CppType.new("Array").passcref.retcref, - "sequence-no"=>CppType.new("SequenceNumber").passcref, - "sequence-set"=>CppType.new("SequenceSet").passcref.retcref, - "struct32"=>CppType.new("std::string").passcref.retcref.code("LongString"), - "uuid"=>CppType.new("Uuid").passcref.retcref, - "byte-ranges"=>CppType.new("ByteRanges").passcref.retcref - } - - # preview: map amqp types to preview cpp types. - def lookup_cpptype(t) t = @@typemap[t] and return t end -end - - -class AmqpElement - # convert my amqp type_ attribute to a C++ type. - def amqp2cpp() - return "ArrayDomain<#{array_type(name).amqp2cpp}> " if type_=="array" - return type_.amqp2cpp - end - - # Does this object have a type-like child named name? - def typechild(name) - child = domain(name) if respond_to? :domain - child = struct(name) if not child and respond_to? :struct - child = type_(name) if not child and respond_to? :type_ - child - end - - # dotted name to a type object - def dotted_typechild(name) - names=name.split('.') - context = self - while context and names.size > 1 - context = context.child_named(names.shift) - end - return context.typechild(names[0]) if context - end - - # preview mapping - type_ attribute to C++ type - def lookup_cpptype(name) - if t = root.lookup_cpptype(name) then return t - elsif c = containing_class.typechild(name) then return c.cpptype - elsif c= root.dotted_typechild(name) then return c.cpptype - else raise "Cannot resolve type-name #{name} from #{self}" - end - end - - def containing_class() - return self if is_a? AmqpClass - return parent && parent.containing_class - end -end - - -class AmqpField - def struct?() - c=containing_class - c.struct(type_) - end - def cpptype() lookup_cpptype(type_) or raise "no cpptype #{type_} for field #{self}" end - def cppname() name.lcaps.cppsafe; end - def bit?() type_ == "bit"; end - def signature() cpptype.param+" "+cppname; end - - def fqtypename() - 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 - return amqp2cpp - end - def paramtype() - /^(int|uint|char|boolean|bit)/ === type_ ? fqtypename : "const #{fqtypename}&" - end - def param_default() "=#{fqtypename}()" end - - # Default value is normally the C++ default but over-ridden in specific cases - def default_value() - defval = cpptype.default_value; - if name == "accept-mode" and parent.name == "transfer" then defval = "1"; end - return defval - 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.signature }; end - def classname() parent.name; end - def body_name() - classname().caps+name.caps+"Body" - end - def cpp_pack_type() root.lookup_cpptype("uint16") end -end - -module AmqpHasFields - def parameters(with_default=nil) - fields.map { |f| - "#{f.paramtype} #{f.cppname}_#{f.param_default if with_default}" - } - end - def unused_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 - def full_code() (containing_class.code.hex << 8)+code.hex; end - include AmqpHasFields -end - -class AmqpType - def cpptype() root.lookup_cpptype(name) end # preview - def typename() name.typename; end # new mapping - def fixed?() fixed_width; end -end - -class AmqpCommand < AmqpAction - def base() "Command"; end -end - -class AmqpControl < AmqpAction - def base() "Control"; end -end - -class AmqpClass - def cppname() name.caps; end # preview - def nsname() name.nsname; end -end - -class AmqpDomain - # preview - def cpptype() lookup_cpptype(type_) end - def cppname() name.caps; end - - # new mapping - def fqtypename() - return containing_class.nsname+"::"+name.typename if containing_class - name.typename - end -end - -class AmqpResult - # preview - def cpptype() - if type_ then lookup_cpptype(type_) - else CppType.new(parent.parent.name.caps+parent.name.caps+"Result").passcref - end - end -end - -class AmqpStruct - include AmqpHasFields - - @@pack_types={ "1"=>"uint8", "2"=>"uint16", "4"=>"uint32"} - def cpp_pack_type() # preview - root.lookup_cpptype(@@pack_types[pack]) - end - def cpptype() CppType.new(cppname).passcref.retcref end - #def cppname() containing_class.cppname+name.caps; end - def cppname() - if parent.kind_of? AmqpResult - parent.parent.parent.name.caps+parent.parent.name.caps+"Result" - else - name.caps - end - end - def fqclassname() containing_class.nsname+"::"+name.typename; end - def classname() name.typename; end - def full_code() (containing_class.code.hex << 8)+code.hex; 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, &block) - path = (/\.h$/ === path ? path : path+".h") - guard=path.upcase.tr('./-','_') - file(path) { - gen "#ifndef #{guard}\n" - gen "#define #{guard}\n" - gen Copyright - yield - gen "#endif /*!#{guard}*/\n" - } - end - - # Write a .cpp file. - def cpp_file(path, &block) - path = (/\.cpp$/ === path ? path : path+".cpp") - file(path) do - gen Copyright - yield - end - end - - def include(header) - header+=".h" unless /(\.h|[">])$/===header - header="\"#{header}\"" unless /(^<.*>$)|(^".*"$)/===header - genl "#include #{header}" - end - - def scope(open="{",close="}", &block) - genl open - indent &block - genl close - end - - def namespace(name, &block) - genl - names = name.split("::") - names.each { |n| genl "namespace #{n} {" } - genl "namespace {" if (names.empty?) - genl - yield - genl - genl('}'*([names.size, 1].max)+" // namespace "+name) - genl - end - - def struct_class(type, name, bases, &block) - gen "#{type} #{name}" - if (!bases.empty?) - genl ":" - indent { gen "#{bases.join(",\n")}" } - end - genl - scope("{","};", &block) - end - - def struct(name, *bases, &block) - struct_class("struct", name, bases, &block); - end - def cpp_class(name, *bases, &block) - struct_class("class", name, bases, &block); - end - def cpp_extern_class(scope, name, *bases, &block) - struct_class("class "+scope, name, bases, &block); - end - - def typedef(type, name) genl "typedef #{type} #{name};\n"; end - - def variant(types) "boost::variant<#{types.join(", ")}>"; end - def variantl(types) "boost::variant<#{types.join(", \n")}>"; end - def blank_variant(types) variant(["boost::blank"]+types); end - def tuple(types) "boost::tuple<#{types.join(', ')}>"; end - - def public() outdent { genl "public:" } end - def private() outdent { genl "private:" } end - def protected() outdent { genl "protected:" } end - - # Returns [namespace, classname, filename] - def parse_classname(full_cname) - names=full_cname.split("::") - return names[0..-2].join('::'), names[-1], names.join("/") - end - - def doxygen_comment(&block) - 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 - - 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, params, inits.empty? ? "" : " :") - indent { gen 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 -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/framing.0-10/MethodBodyConstVisitor.rb b/cpp/rubygen/framing.0-10/MethodBodyConstVisitor.rb deleted file mode 100755 index d784e589df..0000000000 --- a/cpp/rubygen/framing.0-10/MethodBodyConstVisitor.rb +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env ruby -# -# 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 .. in load path -require 'cppgen' - -class MethodBodyConstVisitorGen < CppGen - - def initialize(outdir, amqp) - super(outdir, amqp) - @namespace="qpid::framing" - @classname="MethodBodyConstVisitor" - @filename="qpid/framing/MethodBodyConstVisitor" - end - - def generate() - h_file("#{@filename}") { - namespace(@namespace) { - @amqp.methods_.each { |m| genl "class #{m.body_name};" } - cpp_class("MethodBodyConstVisitor") { - genl "public:" - genl "virtual ~MethodBodyConstVisitor() {}" - @amqp.methods_.each { |m| genl "virtual void visit(const #{m.body_name}&) = 0;" } - }}} - end -end - -MethodBodyConstVisitorGen.new($outdir, $amqp).generate(); - diff --git a/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb b/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb deleted file mode 100755 index 4c58ff2bbb..0000000000 --- a/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env ruby -# -# 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 .. in load path -require 'cppgen' - -class MethodBodyDefaultVisitorGen < CppGen - - def initialize(outdir, amqp) - super(outdir, amqp) - @namespace, @classname, @filename = parse_classname("qpid::framing::MethodBodyDefaultVisitor") - end - - def generate() - h_file(@filename) { - include "qpid/framing/MethodBodyConstVisitor" - include "qpid/CommonImportExport.h" - namespace(@namespace) { - genl "class AMQMethodBody;" - cpp_extern_class("QPID_COMMON_CLASS_EXTERN", @classname, "public MethodBodyConstVisitor") { - genl "public:" - genl "virtual void defaultVisit(const AMQMethodBody&) = 0;" - @amqp.methods_.each { |m| - genl "QPID_COMMON_EXTERN virtual void visit(const #{m.body_name}&);" } - }}} - - cpp_file(@filename) { - include(@filename) - include("qpid/framing/all_method_bodies.h") - namespace(@namespace) { - @amqp.methods_.each { |m| - genl "void #{@classname}::visit(const #{m.body_name}& b) { defaultVisit(b); }" - }}} - end -end - -MethodBodyDefaultVisitorGen.new($outdir, $amqp).generate(); - diff --git a/cpp/rubygen/framing.0-10/MethodBodyFactory.rb b/cpp/rubygen/framing.0-10/MethodBodyFactory.rb deleted file mode 100644 index 28a5d94e32..0000000000 --- a/cpp/rubygen/framing.0-10/MethodBodyFactory.rb +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env ruby -# -# 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 .. in load path -require 'cppgen' - -class MethodBodyFactoryGen < CppGen - - def initialize(outdir, amqp) - super(outdir, amqp) - @namespace="qpid::framing" - @classname="MethodBodyFactory" - @filename="qpid/framing/MethodBodyFactory" - end - - def generate() - cpp_file(@filename) { - include @filename - include "qpid/framing/BodyFactory" - @amqp.methods_.each { |m| include "qpid/framing/#{m.body_name}" } - include "qpid/Exception.h" - include "qpid/Msg.h" - genl - namespace(@namespace) { - scope("boost::intrusive_ptr<AMQMethodBody> #{@classname}::create(ClassId c, MethodId m) {") { - scope("switch (c) {") { - @amqp.classes.each { |c| - scope("case #{c.code}: switch(m) {") { - c.methods_.each { |m| - genl "case #{m.code}: return BodyFactory::create<#{m.body_name}>();" - } - genl "default: throw Exception(QPID_MSG(\"Invalid method id \" << int(m) << \" for class #{c.name} \"));" - } - genl "break;" - } - genl "default: throw Exception(QPID_MSG(\"Invalid class id \" << int(c)));" - } - } - }} - end -end - -MethodBodyFactoryGen.new($outdir, $amqp).generate(); diff --git a/cpp/rubygen/framing.0-10/Operations.rb b/cpp/rubygen/framing.0-10/Operations.rb deleted file mode 100755 index cd6a363c56..0000000000 --- a/cpp/rubygen/framing.0-10/Operations.rb +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env ruby -# -# 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. -# -# Usage: output_directory xml_spec_file [xml_spec_file...] -# -$: << '..' -require 'cppgen' -require 'fileutils' -require 'etc' -require 'pathname' - -class OperationsGen < CppGen - - def initialize(chassis, outdir, amqp) - super(outdir, amqp) - @chassis=chassis - @classname="AMQP_#{@chassis.caps}Operations" - end - - def handler_method (m) - return_type = m.result ? m.result.cpptype.ret_by_val : "void" - gen "\nvirtual #{return_type} #{m.cppname}(" - gen m.signature.join(",\n") - gen ") = 0;\n" - end - - def handler_classname(c) c.name.caps+"Handler"; end - - def methods_on(parent, chassis) - chassis == "all" ? parent.methods_ : parent.methods_on(chassis) - end - - def handler_class(c) - m = methods_on(c,@chassis) - if (not m.empty?) - handlerclass=handler_classname c - gen <<EOS -// ==================== class #{handlerclass} ==================== -class #{handlerclass} { - // Constructors and destructors - public: - class Invoker; // Declared in #{@chassis.caps}Invoker - - #{handlerclass}(){}; - virtual ~#{handlerclass}() {} - // Protocol methods -EOS - m.each { |m| handler_method(m) if !m.content() } - gen <<EOS -}; // class #{handlerclass} - - -EOS - end - end - - def handler_get(c) - m = methods_on(c,@chassis) - if (not m.empty?) - handlerclass=handler_classname c - gen "virtual #{handlerclass}* get#{handlerclass}() = 0;\n" - end - end - - def generate() - h_file("qpid/framing/#{@classname}.h") { - gen <<EOS -#include <sstream> -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/framing/amqp_structs.h" - -namespace qpid { -namespace framing { - -class AMQMethodBody; - -class #{@classname} { - public: - class Invoker; // Declared in #{@chassis.caps}Invoker - - virtual ~#{@classname}() {} - - virtual ProtocolVersion getVersion() const = 0; - - // Inner classes -EOS - indent { @amqp.classes.each { |c| handler_class(c) } } - gen <<EOS - - // Method handler get methods - -EOS - indent { @amqp.classes.each { |c| handler_get(c) } } - gen <<EOS -}; /* class #{@classname} */ -}} -EOS -} - end -end - -OperationsGen.new("client",$outdir, $amqp).generate() -OperationsGen.new("server",$outdir, $amqp).generate() -OperationsGen.new("all",$outdir, $amqp).generate() - diff --git a/cpp/rubygen/framing.0-10/OperationsInvoker.rb b/cpp/rubygen/framing.0-10/OperationsInvoker.rb deleted file mode 100755 index f9b5ce58d8..0000000000 --- a/cpp/rubygen/framing.0-10/OperationsInvoker.rb +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env ruby -# -# 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. -# -# Usage: output_directory xml_spec_file [xml_spec_file...] -# -$: << '..' -require 'cppgen' - -class OperationsInvokerGen < CppGen - def initialize(chassis, outdir, amqp) - super(outdir, amqp) - @chassis=chassis - @ops="AMQP_#{@chassis.caps}Operations" - @classname="#{@ops}::Invoker" - @filename="qpid/framing/#{@chassis.caps}Invoker" - end - - def methods_on(parent, chassis) - chassis == "all" ? parent.methods_ : parent.methods_on(chassis) - end - - def handler(c) "#{@ops}::#{c.cppname}Handler"; end - def getter(c) "get#{c.cppname}Handler"; end - def invoker(c) "#{handler(c)}::Invoker"; end - def visit_methods(c) methods_on(c, @chassis).select { |m| !m.content } end - - - def handler_visits_cpp(c) - visit_methods(c).each { |m| - scope("void #{invoker(c)}::visit(const #{m.body_name}& body) {") { - if (m.result) - genl "this->encode(body.invoke(target), result.result);" - else - genl "body.invoke(target);" - end - genl "result.handled=true;" - } - } - end - - def ops_visits_cpp() - @amqp.classes.each { |c| - visit_methods(c).each { |m| - scope("void #{@classname}::visit(const #{m.body_name}& body) {") { - genl "#{handler(c)}::Invoker invoker(*target.#{getter(c)}());" - genl "body.accept(invoker);" - genl "result=invoker.getResult();" - } - } - } - end - - def invoker_h(invoker, target, methods) - return if methods.empty? - genl - cpp_extern_class("QPID_COMMON_CLASS_EXTERN", invoker, "public qpid::framing::Invoker") { - genl "#{target}& target;" - public - genl("Invoker(#{target}& target_) : target(target_) {}") - genl "using MethodBodyDefaultVisitor::visit;" - methods.each { |m| genl "QPID_COMMON_EXTERN void visit(const #{m.body_name}& body);" } - } - end - - def generate() - h_file(@filename) { - include "qpid/framing/#{@ops}" - include "qpid/framing/Invoker.h" - include "qpid/CommonImportExport.h" - namespace("qpid::framing") { - # AMQP_*Operations invoker. - methods=@amqp.classes.map { |c| visit_methods(c).to_a }.flatten - invoker_h(@classname, @ops, methods) - - # AMQP_*Operations::*Handler invokers. - @amqp.classes.each { |c| - invoker_h(invoker(c), handler(c), visit_methods(c)) - } - } - } - - cpp_file(@filename) { - include @filename - @amqp.classes.each { |c| - visit_methods(c).each { |m| - include "qpid/framing/#{m.body_name}" - }} - namespace("qpid::framing") { - ops_visits_cpp - @amqp.classes.each { |c| - next if visit_methods(c).empty? - handler_visits_cpp(c) - } - } - } - end -end - -OperationsInvokerGen.new("client",$outdir, $amqp).generate() -OperationsInvokerGen.new("server",$outdir, $amqp).generate() -OperationsInvokerGen.new("all",$outdir, $amqp).generate() diff --git a/cpp/rubygen/framing.0-10/Proxy.rb b/cpp/rubygen/framing.0-10/Proxy.rb deleted file mode 100755 index 3325616754..0000000000 --- a/cpp/rubygen/framing.0-10/Proxy.rb +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env ruby -# -# 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 .. in load path -require 'cppgen' - -class ProxyGen < CppGen - - def initialize(chassis, outdir, amqp) - super(outdir, amqp) - @chassis=chassis - @classname="AMQP_#{@chassis.caps}Proxy" - @filename="qpid/framing/#{@classname}" - end - - def methods_on(parent, chassis) - chassis == "all" ? parent.methods_ : parent.methods_on(chassis) - end - - def proxy_member(c) c.name.lcaps+"Proxy"; end - - def inner_class_decl(c) - cname=c.name.caps - cpp_extern_class("QPID_COMMON_CLASS_EXTERN", cname, "public Proxy") { - gen <<EOS -public: -#{cname}(FrameHandler& f) : Proxy(f) {} -static #{cname}& get(#{@classname}& proxy) { return proxy.get#{cname}(); } -EOS - methods_on(c, @chassis).each { |m| - genl "QPID_COMMON_EXTERN virtual void #{m.cppname}(#{m.signature.join(",\n ")});" - genl - }} - end - - def inner_class_defn(c) - cname=c.cppname - methods_on(c, @chassis).each { |m| - genl "void #{@classname}::#{cname}::#{m.cppname}(#{m.signature.join(", ")})" - scope { - params=(["getVersion()"]+m.param_names).join(", ") - genl "send(#{m.body_name}(#{params}));" - }} - end - - def generate - # .h file - h_file(@filename) { - include "qpid/framing/Proxy.h" - include "qpid/framing/Array.h" - include "qpid/framing/amqp_types.h" - include "qpid/framing/amqp_structs.h" - include "qpid/CommonImportExport.h" - - namespace("qpid::framing") { - cpp_extern_class("QPID_COMMON_CLASS_EXTERN", @classname, "public Proxy") { - public - genl "QPID_COMMON_EXTERN #{@classname}(FrameHandler& out);" - genl - @amqp.classes.each { |c| - inner_class_decl(c) - genl - genl "#{c.cppname}& get#{c.cppname}() { return #{proxy_member(c)}; }" - genl - } - private - @amqp.classes.each{ |c| gen c.cppname+" "+proxy_member(c)+";\n" } - }}} - - # .cpp file - cpp_file(@filename) { - include "<sstream>" - include "qpid/framing/#{@classname}.h" - include "qpid/framing/amqp_types_full.h" - methods_on(@amqp, @chassis).each { - |m| include "qpid/framing/"+m.body_name - } - genl - namespace("qpid::framing") { - genl "#{@classname}::#{@classname}(FrameHandler& f) :" - gen " Proxy(f)" - @amqp.classes.each { |c| gen ",\n "+proxy_member(c)+"(f)" } - genl "{}\n" - @amqp.classes.each { |c| inner_class_defn(c) } - }} - end -end - - -ProxyGen.new("client", $outdir, $amqp).generate; -ProxyGen.new("server", $outdir, $amqp).generate; -ProxyGen.new("all", $outdir, $amqp).generate; - diff --git a/cpp/rubygen/framing.0-10/Session.rb b/cpp/rubygen/framing.0-10/Session.rb deleted file mode 100755 index e800df9b2e..0000000000 --- a/cpp/rubygen/framing.0-10/Session.rb +++ /dev/null @@ -1,417 +0,0 @@ -#!/usr/bin/env ruby -# -# 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. -# -# Usage: output_directory xml_spec_file [xml_spec_file...] -# -$: << '..' -require 'cppgen' - -class CppGen - def session_methods(sync_default) - excludes = ["connection", "session", "file", "stream"] - gen_methods=@amqp.methods_on(@chassis).reject { |m| - excludes.include? m.parent.name or m.body_name.include?("010") - } - gen_methods.each { |m| m.set_sync_default(sync_default) } - end - - - # Generates a doxygen comment for AmqpMethod m. - def doxygen(m) - doxygen_comment { - genl m.doc - genl - m.fields_c.each { |f| - genl "@param #{f.cppname}" - genl f.doc if f.doc - genl - } - } - end -end - -# Sync vs. async APIs -module SyncAsync - def sync_prefix() @async ? "Async" : "" end - def sync_adjective() @async ? "asynchronous" : "synchronous" end - def sync_convert() @async ? "async" : "sync" end - - - def decl_ctor_opeq() - genl - genl "QPID_CLIENT_EXTERN #{@classname}();" - genl "QPID_CLIENT_INLINE_EXTERN #{@classname}(const #{@version_base}& other);" - genl "QPID_CLIENT_INLINE_EXTERN #{@classname}& operator=(const #{@version_base}& other);" - end - - def defn_ctor_opeq(inline="") - genl - genl "#{inline} #{@classname}::#{@classname}() {}" - scope("#{inline} #{@classname}::#{@classname}(const #{@version_base}& other) {") { - genl "*this = other;" - } - scope("#{inline} #{@classname}& #{@classname}::operator=(const #{@version_base}& other) {") { - genl "impl = static_cast<const #{@classname}&>(other).impl;" - genl "return *this;" - } - end - - def sync_default() !@async end -end - -class ContentField # For extra content parameters - def cppname() "content" end - def signature() "const Message& content" end - def sig_default() signature+"="+"Message(std::string())" end - def unpack() "p[arg::content|Message(std::string())]"; end - def doc() "Message content"; end -end - -class SyncField # For extra sync parameters - def initialize(default_value) @default_value=default_value ? "true" : "false" end - def cppname() "sync" end - def signature() "bool sync" end - def sig_default() signature+"="+@default_value end - def unpack() "p[arg::sync|#{@default_value}]"; end - def doc() "If true the broker will respond with completion status as soon as possible."; end -end - -class AmqpField - def unpack() "p[arg::#{cppname}|#{default_value}]"; end - def sig_default() signature+"="+default_value; end -end - -class AmqpMethod - def set_sync_default(sync_default) @sync_default=sync_default end - def fields_c() result = fields + (content ? [ContentField.new] : []) + [SyncField.new(@sync_default)] end - def param_names_c() fields_c.map { |f| f.cppname} end - def signature_c() fields_c.map { |f| f.signature }; end - def sig_c_default() fields_c.map { |f| f.sig_default }; 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 return_type(async) - if (async) - return "TypedResult<qpid::framing::#{result.cpptype.ret_by_val}>" if (result) - return "Completion" - else - return "qpid::framing::#{result.cpptype.ret_by_val}" if (result) - return "void" - end - end - - def session_function() "#{parent.name.lcaps}#{name.caps}"; end -end - -class SessionNoKeywordGen < CppGen - include SyncAsync - - def initialize(outdir, amqp, async) - super(outdir, amqp) - @async=async - @chassis="server" - @namespace,@classname,@file= - parse_classname "qpid::client::no_keyword::#{sync_prefix}Session_#{@amqp.version.bars}" - @version_base="SessionBase_#{@amqp.major}_#{@amqp.minor}" - end - - def generate() - public_api("#{@file}.h") - h_file(@file) { - include "qpid/client/#{@version_base}.h" - include "qpid/client/ClientImportExport.h" - namespace(@namespace) { - doxygen_comment { - genl "AMQP #{@amqp.version} #{sync_adjective} session API." - genl @amqp.class_("session").doc - # FIXME aconway 2008-05-23: additional doc on sync/async use. - } - cpp_class(@classname, "public #{@version_base}") { - public - decl_ctor_opeq() - session_methods(sync_default).each { |m| - genl - doxygen(m) - args=m.sig_c_default.join(", ") - genl "QPID_CLIENT_EXTERN #{m.return_type(@async)} #{m.session_function}(#{args});" - } - } - }} - - cpp_file(@file) { - include "qpid/client/#{@classname}" - include "qpid/framing/all_method_bodies.h" - include "qpid/client/SessionImpl.h" - include "qpid/client/MessageImpl.h" - include "qpid/client/PrivateImplRef.h" - include "qpid/client/CompletionImpl.h" - include "<boost/intrusive_ptr.hpp>" - namespace(@namespace) { - genl "using namespace framing;" - session_methods(sync_default).each { |m| - genl - sig=m.signature_c.join(", ") - func="#{@classname}::#{m.session_function}" - scope("#{m.return_type(@async)} #{func}(#{sig}) {") { - args=(["ProtocolVersion(#{@amqp.major},#{@amqp.minor})"]+m.param_names).join(", ") - genl "#{m.body_name} body(#{args});"; - genl "body.setSync(sync);" - sendargs="body" - sendargs << ", *MessageImpl::get(content)" if m.content - async_retval="#{m.return_type(true)}(new CompletionImpl(impl->send(#{sendargs}), impl))" - if @async then - genl "return #{async_retval};" - else - if m.result - genl "return #{async_retval}.get();" - else - genl "#{async_retval}.wait();" - end - end - }} - defn_ctor_opeq() - }} - end -end - -class SessionGen < CppGen - include SyncAsync - - def initialize(outdir, amqp, async) - super(outdir, amqp) - @async=async - @chassis="server" - session="#{sync_prefix}Session_#{@amqp.version.bars}" - @base="no_keyword::#{session}" - @fqclass=FqClass.new "qpid::client::#{session}" - @classname=@fqclass.name - @fqbase=FqClass.new("qpid::client::#{@base}") - @version_base="SessionBase_#{@amqp.major}_#{@amqp.minor}" - end - - def gen_keyword_decl(m) - return if m.fields_c.empty? # Inherited function will do. - scope("BOOST_PARAMETER_MEMFUN(#{m.return_type(@async)}, #{m.session_function}, 0, #{m.fields_c.size}, #{m.argpack_name}) {") { - scope("return #{@base}::#{m.session_function}(",");") { - gen m.fields_c.map { |f| f.unpack() }.join(",\n") - } - } - genl - end - - def generate() - keyword_methods=session_methods(sync_default).reject { |m| m.fields_c.empty? } - max_arity = keyword_methods.map{ |m| m.fields_c.size }.max - - public_api("qpid/client/arg.h") - h_file("qpid/client/arg.h") { - # Generate keyword tag declarations. - genl "#define BOOST_PARAMETER_MAX_ARITY #{max_arity}" - include "<boost/parameter.hpp>" - namespace("qpid::client::arg") { - keyword_methods.map{ |m| m.param_names_c }.flatten.uniq.each { |k| - genl "BOOST_PARAMETER_KEYWORD(keyword_tags, #{k})" - }} - } - public_api("#{@fqclass.file}.h") - h_file(@fqclass.file) { - include @fqbase.file - include "qpid/client/arg" - include "qpid/client/ClientImportExport" - namespace("qpid::client") { - # Doxygen comment. - doxygen_comment { - genl "AMQP #{@amqp.version} session API with keyword arguments." - genl <<EOS -This class provides the same set of functions as #{@base}, but also -allows parameters be passed using keywords. The keyword is the -parameter name in the namespace "arg". - -For example given the normal function "foo(int x=0, int y=0, int z=0)" -you could call it in either of the following ways: - -@code -session.foo(1,2,3); // Normal no keywords -session.foo(arg::z=3, arg::x=1); // Keywords and a default -@endcode - -The keyword functions are easy to use but their declarations are hard -to read. You may find it easier to read the documentation for #{@base} -which provides the same set of functions using normal non-keyword -declarations. - -\\ingroup clientapi - - -\\details - -<h2>Publishing Messages</h2> -<ul> -<li><p>messageTransfer()</p> -<pre>session.messageTransfer(arg::content=message, arg::destination="amq.topic");</pre></li> -<li><p>messageTransfer() — asynchronous</p> -<pre>#include <qpid/client/AsyncSession.h> - -for (int i=0; i<10; i++) { - message.setData(message_data.str()); - async(session).messageTransfer(arg::content=message, arg::destination="amq.direct"); -} - -session.sync(); -</pre> -</li> -</ul> - -<h2>Exchanges</h2> -<ul> -<li><p>exchangeBind()</p> -<pre>session.exchangeBind(arg::exchange="amq.topic", arg::queue=queue, arg::bindingKey=routing_key);</pre> -</li> -<li><p>exchangeUnbind()</p> -<pre>session.exchangeUnBind(arg::exchange="amq.topic", arg::queue=queue, arg::bindingKey=routing_key);</pre></li> -<li><p>exchangeBound()</p> -<pre>if (session.exchangeBound(arg::exchange="amq.topic", arg::queue=queue, arg::bindingKey=rk)){...}</pre> -<pre>if (session.exchangeBound(arg::exchange="amq.topic", arg::queue=queue)){...}</pre> -</li> -<li><p>exchangeDeclare()</p> -<pre>session.exchangeDeclare(arg::exchange="my.topic", arg::type="topic");</pre> -<pre>session.exchangeDeclare(arg::exchange="xml", arg::type="xml");</pre> -</li> -<li><p>exchangeDelete()</p> -<pre>session.exchangeDeclare(arg::exchange="my.topic");</pre> -<pre>session.exchangeDeclare(arg::exchange="xml", arg::ifUnused=true);</pre> -</li> -<li><p>exchangeQuery()</p> -<pre>ExchangeQueryResult eqr = session.exchangeQuery(arg::exchange="my.topic");</pre></li> -</ul> - - -<h2>Configuring exchanges in session.exchangeDeclare</h2> - -<pre>arg::durable=true</pre> -<p>Default: false.</p> -<p>If durable=true, an exchange remains active even if the server is restarted. If durable=false, an exchange is purged when a server restarts.</p> - -<pre>arg::autoDelete=true</pre> -<p>Default: false.</p> -<p>If autoDelete=true, deleting the last binding for an exchange also deletes the exchange.</p> - -<pre>arg::alternatExchange="my.exchange"</pre> -<p>Default: none.</p> -<p>If an alternate exchange is specified, messages that can not be delivered to any queue are sent to the alternate exchange.</p> - -<h2>Queues</h2> -<ul> -<li><p>queueDeclare()</p> -<pre>session.queueDeclare(arg::queue="message_queue");</pre> -</li> -<li><p>queueDelete()</p> -<pre>session.queueDelete(arg::queue="message_queue");</pre></li> -<li><p>queuePurge()</p> -<pre>session.queuePurge(arg::queue="message_queue");</pre></li> -<li><p>queueQuery()</p> -<pre>QueueQueryResult qqr = session.queueQuery(arg::queue="message_queue");</pre></li> -</ul> - - -<h2>Configuring queues with session.queueDeclare</h2> -<pre>arg::durable=true</pre> -<p>Default: false.</p> -<p>If durable=true, a queue remains active if the server is restarted. If durable=false, a queue and its contents are lost when a server restarts.</p> -<br/> - -<pre>arg::autoDelete=true</pre> -<p>Default: false.</p> -<p>If autoDelete=true, the queue is deleted when the last active Subscription to the Queue is canceled.</p> -<br/> - -<pre>arg::exclusive=true</pre> -<p>Default: false.</p> -<p>If exclusive=true, only the Session that created a queue can access it.</p> -<br/> - -<pre>arg::alternateExchange="my.exchange"</pre> -<p>Default: none. </p> -<p>If an alternate exchange is specified, messages are routed to it if (1) they are rejected by a client, or (2) they remain on the queue when it is deleted.</p> -<br/> - - -<h2>Accepting, Acquiring, Rejecting, or Releasing Messages</h2> -<ul> -<li><p>messageAccept() — acknowledges messages</p> -<pre>SequenceSet tobeAccepted; -toAccepted.add(msg.getId()); -session.messageAccept(toBeAccepted);</pre> -</li> -<li><p>messageAcquire()</p> -<pre>SequenceSet tobeAcquired; -toBeAcquired.add(msg.getId()); -session.messageAcquire(toBeAcquired);</pre> -</li> -<li><p>messageReject()</p> -<pre>SequenceSet tobeRejected; -toRejected.add(msg.getId()); -session.messageReject(toBeRejected);</pre> -</li> -<li><p>messageRelease()</p> -<pre>SequenceSet tobeReleased; -toReleased.add(msg.getId()); -session.messageRelease(toBeReleased);</pre></li> -</ul> - -<h2>Transactions</h2> -<ul> -<li><p>txSelect()</p> -<pre>session.txSelect();</pre> -</li> -<li><p>txCommit()</p> -<pre>session.txSelect();</pre></li> -<li><p>txRollback()</p> -<pre>session.txRollback();</pre></li> -</ul> - - -EOS - } - # Session class. - cpp_class(@classname,"public #{@base}") { - public - decl_ctor_opeq() - private - keyword_methods.each { |m| typedef m.argpack_type, m.argpack_name } - genl "friend class Connection;" - public - keyword_methods.each { |m| gen_keyword_decl(m) } - } - genl "/** Conversion to #{@classname} from another session type */" - genl "inline #{@classname} #{sync_convert}(const #{@version_base}& other) { return #{@clasname}(other); }" - defn_ctor_opeq("inline") - }} - end -end - -SessionNoKeywordGen.new($outdir, $amqp, true).generate() -SessionNoKeywordGen.new($outdir, $amqp, false).generate() -SessionGen.new($outdir, $amqp, true).generate() -SessionGen.new($outdir, $amqp, false).generate() - diff --git a/cpp/rubygen/framing.0-10/all_method_bodies.rb b/cpp/rubygen/framing.0-10/all_method_bodies.rb deleted file mode 100755 index 4c7fccfff5..0000000000 --- a/cpp/rubygen/framing.0-10/all_method_bodies.rb +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env ruby -# -# 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 .. in load path -require 'cppgen' - -class AllMethodBodiesGen < CppGen - - def initialize(outdir, amqp) - super(outdir, amqp) - @namespace="qpid::framing" - @filename="qpid/framing/all_method_bodies" - end - - def generate() - h_file(@filename) { - @amqp.methods_.each { |m| include "qpid/framing/"+m.body_name } - } - end -end - -AllMethodBodiesGen.new($outdir, $amqp).generate(); - diff --git a/cpp/rubygen/framing.0-10/constants.rb b/cpp/rubygen/framing.0-10/constants.rb deleted file mode 100755 index 85bfb96ac0..0000000000 --- a/cpp/rubygen/framing.0-10/constants.rb +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/env ruby -# -# 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 .. in load path -require 'cppgen' - -class ConstantsGen < CppGen - - def initialize(outdir, amqp) - super(outdir, amqp) - @namespace="qpid::framing" - @dir="qpid/framing" - end - - def constants_h() - public_api("#{@dir}/constants.h") - h_file("#{@dir}/constants.h") { - namespace(@namespace) { - # Constants for class/method names. - scope("enum AmqpConstant {","};") { - l=[] - l.concat @amqp.constants.map { |c| "#{c.name.shout}=#{c.value}" } - @amqp.classes.each { |c| - l << "#{c.name.shout}_CLASS_ID=#{c.code}" - l.concat c.methods_.map { |m| - "#{c.name.shout}_#{m.name.shout}_METHOD_ID=#{m.code}" } - } - genl l.join(",\n") - } - } - } - end - - def typecode_enum(t) "TYPE_CODE_#{t.name.shout}" end - - def typecode_h_cpp - path="#{@dir}/TypeCode" - public_api(path+".h") - h_file(path) { - include("<iosfwd>") - include("\"qpid/sys/IntegerTypes.h\"") - namespace(@namespace) { - scope("enum TypeCode {", "};") { - genl @amqp.types.map { |t| "#{typecode_enum t} = #{t.code}" if t.code }.compact.join(",\n") - } - genl <<EOS - -/** True if t is a valid TypeCode value */ -bool isTypeCode(uint8_t t); - -/** Throw exception if not a valid TypeCode */ -TypeCode typeCode(uint8_t); - -/**@return 0 if t is not a valid enum TypeCode value. */ -const char* typeName(TypeCode t); - -std::ostream& operator<<(std::ostream&, TypeCode); -EOS - } - } - - cpp_file(path) { - include(path); - include("qpid/Exception.h") - include("qpid/Msg.h") - include("<ostream>") - namespace(@namespace) { - scope("const char* typeName(TypeCode t) {") { - scope("switch (t) {") { - @amqp.types.each { |t| genl "case #{typecode_enum t}: return \"#{t.name}\";" if t.code } - genl "default: break;" - } - genl "return 0;"; - } - genl <<EOS - -bool isTypeCode(uint8_t t) { return typeName(TypeCode(t)); } - -TypeCode typeCode(uint8_t t) { - if (!isTypeCode(t)) throw Exception(QPID_MSG("Invalid TypeCode " << t)); - return TypeCode(t); -} - -std::ostream& operator<<(std::ostream& o, TypeCode t) { - if (isTypeCode(t)) return o << typeName(t); - else return o << "Invalid TypeCode " << t; -} -EOS - } - } - end - - def enum_h() - public_api("#{@dir}/enum.h") - h_file("#{@dir}/enum.h") { - # Constants for enum domains. - namespace(@namespace) { - @amqp.domains.each { |d| declare_enum(d.enum) if d.enum } - @amqp.classes.each { |c| - enums=c.collect_all(AmqpEnum) - if !enums.empty? then - namespace(c.nsname) { enums.each { |e| declare_enum(e) } } - end - } - } - } - end - - def declare_enum(enum) - # Generated like this: enum containing_class::Foo { FOO_X, FOO_Y; } - name="#{enum.parent.name.caps}" - prefix=enum.parent.name.shout+"_" - scope("enum #{name} {","};") { - genl enum.choices.collect { |c| "#{prefix}#{c.name.shout}=#{c.value}" }.join(",\n") - } - end - - def declare_exception(c, base, package, enum) - name=c.name.caps+"Exception" - value="#{package}::#{enum.parent.name.shout}_#{c.name.shout}" - genl - doxygen_comment { genl c.doc } - struct(c.name.caps+"Exception", base) { - genl "std::string getPrefix() const { return \"#{c.name}\"; }" - genl "#{c.name.caps}Exception(const std::string& msg=std::string()) : #{base}(#{value}, \"\"+msg) {}" - } - end - - def declare_exceptions(class_name, domain_name, base) - enum = @amqp.class_(class_name).domain(domain_name).enum - enum.choices.each { |c| declare_exception(c, base, class_name, enum) unless c.name == "normal" } - genl - genl "QPID_COMMON_EXTERN sys::ExceptionHolder create#{base}(int code, const std::string& text);" - end - - def create_exception(class_name, domain_name, base, invalid) - scope("sys::ExceptionHolder create#{base}(int code, const std::string& text) {") { - genl "sys::ExceptionHolder holder;" - scope("switch (code) {") { - enum = @amqp.class_(class_name).domain(domain_name).enum - enum.choices.each { |c| - assign = "holder = new #{c.name.caps}Exception(text); " unless c.name == "normal" - genl "case #{c.value}: #{assign}break;" - } - genl "default: holder = new #{invalid}(QPID_MSG(\"Bad #{enum.parent.name}: \" << code << \": \" << text));" - } - genl "return holder;" - } - end - - def reply_exceptions_h() - public_api("#{@dir}/reply_exceptions.h") - h_file("#{@dir}/reply_exceptions.h") { - include "qpid/Exception" - include "qpid/sys/ExceptionHolder" - include "qpid/framing/enum" - include "qpid/CommonImportExport.h" - namespace(@namespace) { - declare_exceptions("execution", "error-code", "SessionException") - declare_exceptions("connection", "close-code", "ConnectionException") - declare_exceptions("session", "detach-code", "ChannelException") - } - } - end - - def reply_exceptions_cpp() - cpp_file("#{@dir}/reply_exceptions") { - include "#{@dir}/reply_exceptions" - include "qpid/Msg.h" - include "<sstream>" - include "<assert.h>" - namespace("qpid::framing") { - create_exception("execution", "error-code", "SessionException", "InvalidArgumentException") - # FIXME aconway 2008-10-07: there are no good exception codes in 0-10 for an invalid code. - # The following choices are arbitrary. - create_exception("connection", "close-code", "ConnectionException", "FramingErrorException") - create_exception("session", "detach-code", "ChannelException", "NotAttachedException") - } - } - end - - def generate() - constants_h - enum_h - reply_exceptions_h - reply_exceptions_cpp - typecode_h_cpp - end -end - -ConstantsGen.new($outdir, $amqp).generate(); - diff --git a/cpp/rubygen/framing.0-10/frame_body_lists.rb b/cpp/rubygen/framing.0-10/frame_body_lists.rb deleted file mode 100644 index 4f1b976032..0000000000 --- a/cpp/rubygen/framing.0-10/frame_body_lists.rb +++ /dev/null @@ -1,49 +0,0 @@ -# -# 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 .. in load path -require 'cppgen' - -class FrameBodyListsGen < CppGen - - def initialize(outdir, amqp) - super(outdir, amqp); - end - - def generate - h_file("qpid/framing/frame_body_lists.h") { - gen <<EOS -/**@file - * Macro lists of frame body classes, used to generate Visitors - */ -EOS - gen "#define METHOD_BODIES() " - @amqp.methods_.each { |m| gen "\\\n (#{m.body_name}) " } - gen <<EOS - - -#define OTHER_BODIES() (AMQContentBody)(AMQHeaderBody)(AMQHeartbeatBody)) - -EOS - } - end -end - -FrameBodyListsGen.new($outdir, $amqp).generate; - - diff --git a/cpp/rubygen/framing.0-10/structs.rb b/cpp/rubygen/framing.0-10/structs.rb deleted file mode 100755 index 62b33ce773..0000000000 --- a/cpp/rubygen/framing.0-10/structs.rb +++ /dev/null @@ -1,615 +0,0 @@ -#!/usr/bin/env ruby -# -# 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. -# -# Usage: output_directory xml_spec_file [xml_spec_file...] -# -$: << '..' -require 'cppgen' - -class StructGen < CppGen - - def initialize(outdir, amqp) - super(outdir, amqp) - end - - SizeMap={ - "Octet"=>1, - "Short"=>2, - "Long"=>4, - "LongLong"=>8, - "int8"=>1, - "int16"=>2, - "int32"=>4, - "int64"=>8, - "uint8"=>1, - "uint16"=>2, - "uint32"=>4, - "uint64"=>8, - "timestamp"=>8 - } - - StringSizeMap={ - "LongString"=>4, - "MediumString"=>2, - "ShortString"=>1 - } - - SizeType={ - 1=>"Octet", - 2=>"Short", - 4=>"Long", - 8=>"LongLong" - } - - ValueTypes=["uint8_t", "uint16_t", "uint32_t", "uint64_t"] - - def is_packed(s) s.pack and s.pack != "0" end - - def execution_header?(s) - s.is_a? AmqpMethod and not s.parent.control? - # s.kind_of? AmqpMethod and s.parent.name.include?("010") and not s.parent.control? - end - - def has_bitfields_only(s) - s.fields.select {|f| f.type_ != "bit"}.empty? - end - - def default_initialisation(s) - params = s.fields.select {|f| ValueTypes.include?(f.cpptype.name) || (!is_packed(s) && f.type_ == "bit")} - strings = params.collect {|f| "#{f.cppname}(#{f.default_value})"} - strings << "flags(0)" if (is_packed(s)) - if strings.empty? - return "" - else - return " : " + strings.join(", ") - end - end - - def printable_form(f) - if (f.cpptype.name == "uint8_t") - return "(int) " + f.cppname - elsif (f.type_ == "bit") - return "get#{f.name.caps}()" - else - return f.cppname - end - end - - def flag_mask(s, i) - pos = s.pack.to_i*8 - 8 - (i/8)*8 + (i % 8) - return "(1 << #{pos})" - end - - def encode_packed_struct(s) - genl s.cpp_pack_type.encode('flags', 'buffer') - process_packed_fields(s) { |f, i| encode_packed_field(s, f, i) unless f.type_ == "bit" } - end - - def decode_packed_struct(s) - genl "#{s.cpp_pack_type.decode('flags', 'buffer')}" - process_packed_fields(s) { |f, i| decode_packed_field(s, f, i) unless f.type_ == "bit" } - end - - def size_packed_struct(s) - genl "total += #{s.pack};" - process_packed_fields(s) { |f, i| size_packed_field(s, f, i) unless f.type_ == "bit" } - end - - def print_packed_struct(s) - process_packed_fields(s) { |f, i| print_packed_field(s, f, i) } - end - - def encode_packed_field(s, f, i) - genl "if (flags & #{flag_mask(s, i)})" - indent { genl f.cpptype.encode(f.cppname,"buffer") } - end - - def decode_packed_field(s, f, i) - genl "if (flags & #{flag_mask(s, i)})" - indent { genl f.cpptype.decode(f.cppname,"buffer") } - end - - def size_packed_field(s, f, i) - genl "if (flags & #{flag_mask(s, i)})" - indent { generate_size(f, []) } - end - - def print_packed_field(s, f, i) - classname = s.cppname - if (s.kind_of? AmqpMethod) - classname = s.body_name - end - genl "if (flags & #{flag_mask(s, i)})" - indent { - unless (classname == "ConnectionStartOkBody" && f.name == "response") - genl "out << \"#{f.name}=\" << #{printable_form(f)} << \"; \";" - else - genl "out << \"response=\" << \"xxxxxx\" << \"; \";" - end - } - end - - def generate_encode(f, combined) - if (f.type_ == "bit") - genl "uint8_t #{f.cppname}_bits = #{f.cppname};" - count = 0 - combined.each { |c| genl "#{f.cppname}_bits |= #{c.cppname} << #{count += 1};" } - genl "buffer.putOctet(#{f.cppname}_bits);" - else - genl f.cpptype.encode(f.cppname,"buffer") - end - end - - def generate_decode(f, combined) - if (f.type_ == "bit") - genl "uint8_t #{f.cppname}_bits = buffer.getOctet();" - genl "#{f.cppname} = 1 & #{f.cppname}_bits;" - count = 0 - combined.each { |c| genl "#{c.cppname} = (1 << #{count += 1}) & #{f.cppname}_bits;" } - else - genl f.cpptype.decode(f.cppname,"buffer") - end - end - - def generate_size(f, combined) - if (f.type_ == "bit") - names = ([f] + combined).collect {|g| g.cppname} - genl "total += 1;//#{names.join(", ")}" - else - size = SizeMap[f.cpptype.encoded] - if (size) - genl "total += #{size};//#{f.cppname}" - elsif (f.cpptype.name == "SequenceNumberSet") - genl "total += #{f.cppname}.encodedSize();" - elsif (size = StringSizeMap[f.cpptype.encoded]) - genl "total += #{size} + #{f.cppname}.size();" - else - genl "total += #{f.cppname}.encodedSize();" - end - end - end - - def process_packed_fields(s) - s.fields.each { |f| yield f, s.fields.index(f) } - end - - def process_fields(s) - last = nil - count = 0 - bits = [] - s.fields.each { - |f| if (last and last.bit? and f.bit? and count < 7) - count += 1 - bits << f - else - if (last and last.bit?) - yield last, bits - count = 0 - bits = [] - end - if (not f.bit?) - yield f - end - last = f - end - } - if (last and last.bit?) - yield last, bits - end - end - - def all_fields_via_accessors(s) - s.fields.collect { |f| "get#{f.name.caps}()" }.join(", ") - end - - def methodbody_extra_defs(s) - if (s.parent.control?) - genl "virtual uint8_t type() const { return 0;/*control segment*/ }" - end - - - gen <<EOS - typedef #{s.result ? s.result.cpptype.name : 'void'} ResultType; - - template <class T> ResultType invoke(T& invocable) const { - return invocable.#{s.cppname}(#{all_fields_via_accessors(s)}); - } - - using AMQMethodBody::accept; - void accept(MethodBodyConstVisitor& v) const { v.visit(*this); } - boost::intrusive_ptr<AMQBody> clone() const { return BodyFactory::copy(*this); } - - ClassId amqpClassId() const { return CLASS_ID; } - MethodId amqpMethodId() const { return METHOD_ID; } - bool isContentBearing() const { return #{s.content ? "true" : "false" }; } - bool resultExpected() const { return #{s.result ? "true" : "false"}; } - bool responseExpected() const { return #{s.responses().empty? ? "false" : "true"}; } -EOS - end - - def define_constructor(name, s) - if (s.fields.size > 0) - genl "#{name}(" - if (s.kind_of? AmqpMethod) - indent {gen "ProtocolVersion, "} - end - indent { gen s.fields.collect { |f| "#{f.cpptype.param} _#{f.cppname}" }.join(",\n") } - genl ") : " - if (is_packed(s)) - initialisers = s.fields.select { |f| f.type_ != "bit"}.collect { |f| "#{f.cppname}(_#{f.cppname})"} - - initialisers << "flags(0)" - indent { gen initialisers.join(",\n") } - genl "{" - indent { - process_packed_fields(s) { |f, i| genl "set#{f.name.caps}(_#{f.cppname});" if f.type_ == "bit"} - process_packed_fields(s) { |f, i| genl "flags |= #{flag_mask(s, i)};" unless f.type_ == "bit"} - } - genl "}" - else - indent { gen s.fields.collect { |f| " #{f.cppname}(_#{f.cppname})" }.join(",\n") } - genl "{}" - end - end - #default constructors: - if (s.kind_of? AmqpMethod) - genl "#{name}(ProtocolVersion=ProtocolVersion()) #{default_initialisation(s)} {}" - end - if (s.kind_of? AmqpStruct) - genl "#{name}() #{default_initialisation(s)} {}" - end - end - - def define_packed_field_accessors(s, f, i) - if (s.kind_of? AmqpMethod) - define_packed_field_accessors_for_method(s, f, i) - else - define_packed_field_accessors_for_struct(s, f, i) - end - end - - def define_packed_field_accessors_for_struct(s, f, i) - if (f.type_ == "bit") - genl "void #{s.cppname}::set#{f.name.caps}(#{f.cpptype.param} _#{f.cppname}) {" - indent { - genl "if (_#{f.cppname}) flags |= #{flag_mask(s, i)};" - genl "else flags &= ~#{flag_mask(s, i)};" - } - genl "}" - genl "#{f.cpptype.ret} #{s.cppname}::get#{f.name.caps}() const { return flags & #{flag_mask(s, i)}; }" - else - genl "void #{s.cppname}::set#{f.name.caps}(#{f.cpptype.param} _#{f.cppname}) {" - indent { - genl "#{f.cppname} = _#{f.cppname};" - genl "flags |= #{flag_mask(s, i)};" - } - genl "}" - genl "#{f.cpptype.ret} #{s.cppname}::get#{f.name.caps}() const { return #{f.cppname}; }" - if (f.cpptype.name == "FieldTable") - genl "#{f.cpptype.name}& #{s.cppname}::get#{f.name.caps}() {" - indent { - genl "flags |= #{flag_mask(s, i)};"#treat the field table as having been 'set' - genl "return #{f.cppname};" - } - genl "}" - end - genl "bool #{s.cppname}::has#{f.name.caps}() const { return flags & #{flag_mask(s, i)}; }" - genl "void #{s.cppname}::clear#{f.name.caps}Flag() { flags &= ~#{flag_mask(s, i)}; }" - end - genl "" - end - - def define_packed_field_accessors_for_method(s, f, i) - if (f.type_ == "bit") - genl "void #{s.body_name}::set#{f.name.caps}(#{f.cpptype.param} _#{f.cppname}) {" - indent { - genl "if (_#{f.cppname}) flags |= #{flag_mask(s, i)};" - genl "else flags &= ~#{flag_mask(s, i)};" - } - genl "}" - genl "#{f.cpptype.ret} #{s.body_name}::get#{f.name.caps}() const { return flags & #{flag_mask(s, i)}; }" - else - genl "void #{s.body_name}::set#{f.name.caps}(#{f.cpptype.param} _#{f.cppname}) {" - indent { - genl "#{f.cppname} = _#{f.cppname};" - genl "flags |= #{flag_mask(s, i)};" - } - genl "}" - genl "#{f.cpptype.ret} #{s.body_name}::get#{f.name.caps}() const { return #{f.cppname}; }" - if (f.cpptype.name == "FieldTable") - genl "#{f.cpptype.name}& #{s.body_name}::get#{f.name.caps}() {" - indent { - genl "flags |= #{flag_mask(s, i)};"#treat the field table as having been 'set' - genl "return #{f.cppname};" - } - genl "}" - end - genl "bool #{s.body_name}::has#{f.name.caps}() const { return flags & #{flag_mask(s, i)}; }" - genl "void #{s.body_name}::clear#{f.name.caps}Flag() { flags &= ~#{flag_mask(s, i)}; }" - end - genl "" - end - - def define_packed_accessors(s) - process_packed_fields(s) { |f, i| define_packed_field_accessors(s, f, i) } - end - - def declare_packed_accessors(f) - genl "QPID_COMMON_EXTERN void set#{f.name.caps}(#{f.cpptype.param} _#{f.cppname});"; - genl "QPID_COMMON_EXTERN #{f.cpptype.ret} get#{f.name.caps}() const;" - if (f.cpptype.name == "FieldTable") - genl "QPID_COMMON_EXTERN #{f.cpptype.name}& get#{f.name.caps}();" - end - if (f.type_ != "bit") - #extra 'accessors' for packed fields: - genl "QPID_COMMON_EXTERN bool has#{f.name.caps}() const;" - genl "QPID_COMMON_EXTERN void clear#{f.name.caps}Flag();" - end - end - - def define_accessors(f) - genl "void set#{f.name.caps}(#{f.cpptype.param} _#{f.cppname}) { #{f.cppname} = _#{f.cppname}; }" - genl "#{f.cpptype.ret} get#{f.name.caps}() const { return #{f.cppname}; }" - if (f.cpptype.name == "FieldTable") - genl "#{f.cpptype.name}& get#{f.name.caps}() { return #{f.cppname}; }" - end - end - - def define_struct(s) - classname = s.cppname - inheritance = "" - if (s.kind_of? AmqpMethod) - classname = s.body_name - if (execution_header?(s)) - inheritance = ": public ModelMethod" - else - inheritance = ": public AMQMethodBody" - end - else - public_api("qpid/framing/#{classname}.h") # Non-method structs are public - end - - h_file("qpid/framing/#{classname}.h") { - if (s.kind_of? AmqpMethod) - gen <<EOS -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/AMQP_ServerOperations.h" -#include "qpid/framing/MethodBodyConstVisitor.h" -EOS - end - include "qpid/framing/ModelMethod.h" if (execution_header?(s)) - - s.fields.each { |f| include "qpid/framing/#{f.cpptype.name}" if f.struct?} - - gen <<EOS - -#include <ostream> -#include "qpid/framing/amqp_types_full.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -class QPID_COMMON_CLASS_EXTERN #{classname} #{inheritance} { -EOS - if (is_packed(s)) - indent { s.fields.each { |f| genl "#{f.cpptype.name} #{f.cppname};" unless f.type_ == "bit"} } - indent { - genl "#{s.cpp_pack_type.name} flags;" - } - else - indent { s.fields.each { |f| genl "#{f.cpptype.name} #{f.cppname};" } } - end - genl "public:" - if (s.kind_of? AmqpMethod) - indent { genl "static const ClassId CLASS_ID = #{s.parent.code};" } - indent { genl "static const MethodId METHOD_ID = #{s.code};" } - end - - if (s.kind_of? AmqpStruct) - if (s.code) - indent { genl "static const uint16_t TYPE = #{s.full_code};" } - end - end - - indent { - define_constructor(classname, s) - genl "" - if (is_packed(s)) - s.fields.each { |f| declare_packed_accessors(f) } - else - s.fields.each { |f| define_accessors(f) } - end - } - if (s.kind_of? AmqpMethod) - methodbody_extra_defs(s) - end - if (s.kind_of? AmqpStruct) - indent {genl "QPID_COMMON_EXTERN friend std::ostream& operator<<(std::ostream&, const #{classname}&);" } - end - - gen <<EOS - QPID_COMMON_EXTERN void encode(Buffer&) const; - QPID_COMMON_EXTERN void decode(Buffer&, uint32_t=0); - QPID_COMMON_EXTERN void encodeStructBody(Buffer&) const; - QPID_COMMON_EXTERN void decodeStructBody(Buffer&, uint32_t=0); - QPID_COMMON_EXTERN uint32_t encodedSize() const; - QPID_COMMON_EXTERN uint32_t bodySize() const; - QPID_COMMON_EXTERN void print(std::ostream& out) const; -}; /* class #{classname} */ - -}} -EOS - } - cpp_file("qpid/framing/#{classname}.cpp") { - if (is_packed(s) || s.fields.size > 0 || execution_header?(s)) - buffer = "buffer" - else - buffer = "/*buffer*/" - end - gen <<EOS -#include "qpid/framing/#{classname}.h" -#include "qpid/framing/reply_exceptions.h" - -using namespace qpid::framing; - -EOS - - if (is_packed(s)) - define_packed_accessors(s) - end - gen <<EOS -void #{classname}::encodeStructBody(Buffer& #{buffer}) const -{ -EOS - if (execution_header?(s)) - genl "encodeHeader(buffer);" - end - - if (is_packed(s)) - indent {encode_packed_struct(s)} - else - indent { process_fields(s) { |f, combined| generate_encode(f, combined) } } - end - gen <<EOS -} - -void #{classname}::encode(Buffer& buffer) const -{ -EOS - indent { - if (s.kind_of? AmqpStruct) - if (s.code) - genl "buffer.put#{SizeType[s.size.to_i]}(bodySize() + 2/*typecode*/);" if s.size and s.size.to_i != 0 - genl "buffer.putShort(TYPE);" - else - genl "buffer.put#{SizeType[s.size.to_i]}(bodySize());" if s.size and s.size.to_i != 0 - end - end - genl "encodeStructBody(buffer);" - } - gen <<EOS -} - -void #{classname}::decodeStructBody(Buffer& #{buffer}, uint32_t /*size*/) -{ -EOS - if (execution_header?(s)) - genl "decodeHeader(buffer);" - end - - if (is_packed(s)) - indent {decode_packed_struct(s)} - else - indent { process_fields(s) { |f, combined| generate_decode(f, combined) } } - end - gen <<EOS -} - -void #{classname}::decode(Buffer& buffer, uint32_t /*size*/) -{ -EOS - indent { - if (s.kind_of? AmqpStruct) - genl "buffer.get#{SizeType[s.size.to_i]}();" if s.size and s.size.to_i != 0 - genl "if (TYPE != buffer.getShort()) throw FramingErrorException(\"Bad type code for struct\");" if s.code - end - genl "decodeStructBody(buffer);" - } - gen <<EOS -} - -uint32_t #{classname}::bodySize() const -{ - uint32_t total = 0; -EOS - if (execution_header?(s)) - genl "total += headerSize();" - end - - if (is_packed(s)) - indent {size_packed_struct(s)} - else - indent { process_fields(s) { |f, combined| generate_size(f, combined) } } - end - gen <<EOS - return total; -} - -uint32_t #{classname}::encodedSize() const { - uint32_t total = bodySize(); -EOS - if (s.kind_of? AmqpStruct) - genl "total += #{s.size}/*size field*/;" if s.size - genl "total += 2/*typecode*/;" if s.code - end - gen <<EOS - return total; -} - -void #{classname}::print(std::ostream& out) const -{ - out << "{#{classname}: "; -EOS - if (is_packed(s)) - indent {print_packed_struct(s)} - else - copy = Array.new(s.fields) - f = copy.shift - - indent { - genl "out << \"#{f.name}=\" << #{printable_form(f)};" if f - copy.each { |f| genl "out << \"; #{f.name}=\" << #{printable_form(f)};" } - } - end - gen <<EOS - out << "}"; -} -EOS - - if (s.kind_of? AmqpStruct) - gen <<EOS -namespace qpid{ -namespace framing{ - - std::ostream& operator<<(std::ostream& out, const #{classname}& s) - { - s.print(out); - return out; - } - -} -} -EOS - end -} - end - - def generate() - structs = @amqp.collect_all(AmqpStruct).select { |s| not ["command-fragment"].include?(s.name) } - structs.each { |s| define_struct(s) } - @amqp.methods_.each { |m| define_struct(m) } - #generate a single include file containing the list of structs for convenience - public_api("qpid/framing/amqp_structs.h") - h_file("qpid/framing/amqp_structs.h") { structs.each { |s| genl "#include \"qpid/framing/#{s.cppname}.h\"" } } - end -end - -StructGen.new($outdir, $amqp).generate() - diff --git a/cpp/rubygen/generate b/cpp/rubygen/generate deleted file mode 100755 index 89b9b99520..0000000000 --- a/cpp/rubygen/generate +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env ruby -# -# 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. -# -require 'pathname' -require 'amqpgen' - -# -# Run a set of code generation templates. -# -if ARGV.size < 3 - puts <<EOS -Usage: #{ARGV[0]} SRCDIR APIDIR SPEC.xml [ ... ] TEMPLATE.rb [ ... ] -or: #{ARGV[0]} SRCDIR APIDIR SPEC.xml [ ... ] all [ makefragment.mk | makefragment.cmake ] - -Parse all SPEC.xml files to create an AMQP model, run each TEMPLATE -putting the resulting files under SRCDIR, public API files in APIdir. -Prints a list of files generated to standard output. - -If SRCDIR and APIDIR are '-' then just prints file list without generating files. -EOS - exit 1 -end - -# Create array of specs by version -def parse_specs(files) - lists=Hash.new { |h,k| h[k]=[] } - files.each { |f| - spec=AmqpRoot.new(File.new(f)) - lists[spec.version] << spec - } - specs={} - lists.each_pair { |k,l| - specs[k] = l.size==1 ? l.first : AmqpRoot.new(*l.map { |s| s.xml}) - } - return specs -end - -gendir=File.dirname(__FILE__) - -# Run selected templates -if ARGV.any? { |arg| arg=="all" } - templates=Dir["#{gendir}/*/*.rb"] -else -templates=ARGV.grep(/\.rb$/) - ARGV.each { |arg| - d=File.join gendir,arg - templates += Dir["#{d}/*.rb"] if File.directory? d - } -end - -$outdir=[ ARGV[0], ARGV[1] ] -$models=parse_specs(ARGV.grep(/\.xml$/)) - -templates.each { |t| - ver=Pathname.new(t).dirname.basename.to_s.split('.')[-1] - $amqp=$models[ver] - if $amqp - load t - else - puts "Warning: skipping #{t}, no spec file for version #{ver}." - end -} - -def cmake_continue(lines) lines.join(" \n "); end -def make_continue(lines) lines.join(" \\\n "); end - -# Generate makefile -makefile=ARGV.grep(/.mk$/)[0] -cmakefile=ARGV.grep(/.cmake$/)[0] -if cmakefile || makefile - srcdir,apidir=$outdir - dir=Dir.getwd - Dir.chdir File.dirname(__FILE__) - generator_files=Dir["**/*.rb"] << File.basename(__FILE__) - Dir.chdir dir - rgen_generator=generator_files.map{ |f| "$(rgen_dir)/#{f}" } - cmake_rgen_generator=generator_files.map{ |f| "${rgen_dir}/#{f}" } - rgen_srcs=GenFiles.get.map{ |f| "#{GenFiles.public_api?(f) ? apidir : srcdir}/#{f}" } - rgen_subdirs={} - rgen_srcs.each { |src| - if src.match(%r{(#{srcdir}|#{apidir})/qpid/([^/]+)/}) - subdir=$2 - rgen_subdirs[subdir] ||= [] - rgen_subdirs[subdir] << src - end - } - if (makefile) - File.open(makefile, 'w') { |out| - out << <<EOS -# Generated makefile fragment. -# Including makefile defines $(rgen_dir) $(rgen_cmd) and $(specs). - -rgen_generator=#{make_continue rgen_generator} -EOS - rgen_subdirs.each_key { |subdir| - out << "\nrgen_#{subdir}_srcs = #{make_continue(rgen_subdirs[subdir])}\n" - } - out << <<EOS -rgen_srcs=#{make_continue rgen_srcs} - -# Header file install rules. -EOS - ["amqp_0_10", "framing", "client/no_keyword","client", "broker"].each { |ns| - dir="qpid/#{ns}" - dir_ = dir.tr("/", "_") - regex=%r|#{dir}/[^/]+\.h$| - out << <<EOS -#{dir_}dir = $(includedir)/#{dir} -dist_#{dir_}_HEADERS = #{make_continue rgen_srcs.grep(regex)} - -EOS - } # each - } # File makefile - end # if (makefile) - - if (cmakefile) - File.open(cmakefile, 'w') { |out| - out << <<EOS -# Generated makefile fragment. -# Including makefile defines ${rgen_dir} ${rgen_cmd} and ${specs}. - -set(rgen_generator #{cmake_continue cmake_rgen_generator}) -EOS - rgen_subdirs.each_key { |subdir| - out << "\nset(rgen_#{subdir}_srcs #{cmake_continue(rgen_subdirs[subdir])})\n" - } - out << <<EOS -set(rgen_srcs #{cmake_continue rgen_srcs}) - -# Header file install rules. -EOS - ["amqp_0_10", "framing", "client/no_keyword","client", "broker"].each { |ns| - dir="qpid/#{ns}" - dir_ = dir.tr("/", "_") - regex=%r|#{dir}/[^/]+\.h$| - out << <<EOS -set(#{dir_}dir \${includedir}/#{dir}) -set(dist_#{dir_}_HEADERS #{cmake_continue rgen_srcs.grep(regex)}) - -EOS - } # each - } # File makefile - end # if (makefile) -end |