summaryrefslogtreecommitdiff
path: root/qpid/cpp/rubygen
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/cpp/rubygen')
-rwxr-xr-xqpid/cpp/rubygen/0-10/specification.rb149
-rwxr-xr-xqpid/cpp/rubygen/cppgen.rb2
2 files changed, 103 insertions, 48 deletions
diff --git a/qpid/cpp/rubygen/0-10/specification.rb b/qpid/cpp/rubygen/0-10/specification.rb
index acf9e4e6ed..c159d9f08b 100755
--- a/qpid/cpp/rubygen/0-10/specification.rb
+++ b/qpid/cpp/rubygen/0-10/specification.rb
@@ -15,10 +15,11 @@ class Specification < CppGen
genl
typename=d.name.typename
if d.enum
- scope("enum #{typename} {", "};") {
+ scope("enum #{typename}Enum {", "};") {
genl d.enum.choices.map { |c|
"#{c.name.constname} = #{c.value}" }.join(",\n")
}
+ genl "typedef Enum<#{typename}Enum, uint8_t> #{typename};"
else
genl "typedef #{d.amqp2cpp} #{typename};"
end
@@ -42,11 +43,15 @@ class Specification < CppGen
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};"}
+ 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(x.classname,[])
ctor_decl(x.classname, x.parameters) unless x.fields.empty?
- function_decl("void accept", ["Visitor&"], "const")
+ genl "void accept(Visitor&);"
+ genl "void accept(ConstVisitor&) const;"
genl
yield if block
}
@@ -55,13 +60,19 @@ class Specification < CppGen
def action_struct_cpp(x)
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) {}
ctor_defn(ctor, x.parameters, x.initializers) {} if not x.fields.empty?
- function_defn("void #{x.classname}::accept", ["Visitor& v"], "const") {
- genl "v.visit(*this);"
- }
+ # FIXME aconway 2008-03-04: struct visitors
+ if x.is_a? AmqpStruct
+ genl "void #{x.classname}::accept(Visitor&) { assert(0); }"
+ genl "void #{x.classname}::accept(ConstVisitor&) const { assert(0); }"
+ else
+ genl "void #{x.classname}::accept(Visitor& v) { v.visit(*this); }"
+ genl "void #{x.classname}::accept(ConstVisitor& v) const { v.visit(*this); }"
+ end
end
# structs
@@ -76,11 +87,13 @@ class Specification < CppGen
function_defn("template <class T> void invoke", ["T& target"]) {
genl "target.#{a.funcname}(#{a.values.join(', ')});"
}
- function_defn("template <class S> void serialize", ["S& s"]) {
- gen "s"
- a.fields.each { |f| gen "(#{f.cppname})"}
- genl ";"
- } unless a.fields.empty?
+ if (a.fields.empty?)
+ genl "template <class S> void serialize(S&) {}"
+ else
+ scope("template <class S> void serialize(S& s) {") {
+ gen "s"; a.fields.each { |f| gen "(#{f.cppname})"}; genl ";"
+ }
+ end
}
end
@@ -93,7 +106,7 @@ class Specification < CppGen
def gen_specification()
h_file("#{@dir}/specification") {
include "#{@dir}/built_in_types"
- include "#{@dir}/helpers"
+ include "#{@dir}/complex_types"
include "<boost/call_traits.hpp>"
genl "using boost::call_traits;"
namespace(@ns) {
@@ -120,12 +133,13 @@ class Specification < CppGen
cpp_file("#{@dir}/specification") {
include "#{@dir}/specification"
- ["Command","Control","Struct"].each { |x| include "#{@dir}/Apply#{x}" }
+ # FIXME aconway 2008-03-04: add Struct visitors.
+ ["Command","Control"].each { |x| include "#{@dir}/Apply#{x}" }
namespace(@ns) {
each_class_ns { |c|
class_cpp c
c.actions.each { |a| action_cpp a}
- c.structs.each { |s| struct_cpp s }
+ c.collect_all(AmqpStruct).each { |s| struct_cpp(s) }
}
}
}
@@ -157,57 +171,98 @@ class Specification < CppGen
}
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 "#{@dir}/specification"
namespace("#{@ns}") {
- genl
- genl "/** Visitor interface for #{base} subclasses. */"
- struct("#{base}::Visitor") {
- genl "virtual ~Visitor() {}"
- genl "typedef #{base} BaseType;"
- subs.each{ |s|
- genl "virtual void visit(const #{s.fqclassname}&) = 0;"
- }}}}
-
+ 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}") {
- genl
- genl "/** apply() support for #{base} subclasses */"
- genl "template <class F>"
- struct("ApplyVisitor<#{base}::Visitor, F>",
- ["public FunctionAndResult<F>", "public #{base}::Visitor"]) {
- subs.each{ |s|
- function_defn("virtual void visit", ["const #{s.fqclassname}& x"]) {
- genl "this->invoke(x);"
- }}}}}
- end
-
- def gen_visitors()
+ visitor_impl(base, subs, false)
+ visitor_impl(base, subs, true)
+ }
+ }
end
-
- def holder(base, derived)
+
+ def gen_holder(base, subs)
name=base.caps+"Holder"
h_file("#{@dir}/#{name}") {
- include "#{@dir}/specification"
- include "qpid/framing/Blob"
- namespace(@ns){
- # TODO aconway 2008-02-29:
- }
- }
+ include "#{@dir}/Apply#{base}"
+ include "#{@dir}/Holder"
+ namespace(@ns){
+ namespace("#{base.downcase}_max") {
+ gen "template <class M, class X> "
+ struct("Max") {
+ genl "static const size_t max=(M::max > sizeof(X)) ? M::max : sizeof(X);"
+ }
+ genl "struct Max000 { static const size_t max=0; };"
+ last="Max000"
+ subs.each { |s|
+ genl "typedef Max<#{last}, #{s.fqclassname}> #{last.succ!};"
+ }
+ genl "static const int MAX=#{last}::max;"
+ }
+ holder_base="amqp_0_10::Holder<#{base}Holder, #{base}, #{base.downcase}_max::MAX>"
+ struct("#{name}", "public #{holder_base}") {
+ genl "#{name}() {}"
+ genl "template <class T> #{name}(const T& t) : #{holder_base}(t) {}"
+ genl "using #{holder_base}::operator=;"
+ genl "void set(uint8_t classCode, uint8_t code);"
+ }}}
+
+ cpp_file("#{@dir}/#{name}") {
+ include "#{@dir}/#{name}"
+ 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;"
+ }
+ genl "default: assert(0);"
+ }}}}
end
- def gen_holders()
+ def gen_visitable(base, subs)
+ gen_holder(base, subs)
+ gen_visitor(base, subs)
end
def generate
gen_specification
gen_proxy
- gen_visitor("Command", @amqp.collect_all(AmqpCommand))
- gen_visitor("Control", @amqp.collect_all(AmqpControl))
- gen_visitor("Struct", @amqp.collect_all(AmqpStruct))
+ gen_visitable("Command", @amqp.collect_all(AmqpCommand))
+ gen_visitable("Control", @amqp.collect_all(AmqpControl))
+ # FIXME aconway 2008-03-04: sort out visitable structs.
+ # gen_visitable("Struct", @amqp.collect_all(AmqpStruct))
end
end
diff --git a/qpid/cpp/rubygen/cppgen.rb b/qpid/cpp/rubygen/cppgen.rb
index 8e64b06208..63a2e6857e 100755
--- a/qpid/cpp/rubygen/cppgen.rb
+++ b/qpid/cpp/rubygen/cppgen.rb
@@ -162,7 +162,7 @@ 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