summaryrefslogtreecommitdiff
path: root/cpp/rubygen
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2008-02-29 22:07:40 +0000
committerAlan Conway <aconway@apache.org>2008-02-29 22:07:40 +0000
commit6dd59f62185ab8547cc1eec0a57731e0ab5a8645 (patch)
tree25539ade95b792d9e8228eb5b24d5a65340bc5d6 /cpp/rubygen
parent3fb6c758d2d7d7c1822e216e3c22db4630eb19e0 (diff)
downloadqpid-python-6dd59f62185ab8547cc1eec0a57731e0ab5a8645.tar.gz
Template visitors for amqp_0_10::Command, Control and Struct.
Serialization for all str/vbin types. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@632457 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/rubygen')
-rwxr-xr-xcpp/rubygen/0-10/specification.rb76
-rwxr-xr-xcpp/rubygen/amqpgen.rb9
-rwxr-xr-xcpp/rubygen/cppgen.rb22
3 files changed, 84 insertions, 23 deletions
diff --git a/cpp/rubygen/0-10/specification.rb b/cpp/rubygen/0-10/specification.rb
index d4ecfe98ed..acf9e4e6ed 100755
--- a/cpp/rubygen/0-10/specification.rb
+++ b/cpp/rubygen/0-10/specification.rb
@@ -19,10 +19,8 @@ class Specification < CppGen
genl d.enum.choices.map { |c|
"#{c.name.constname} = #{c.value}" }.join(",\n")
}
- elsif (d.type_ == "array")
- genl "typedef Array<#{ArrayTypes[d.name].amqp2cpp}> #{typename};"
else
- genl "typedef #{d.type_.amqp2cpp} #{typename};"
+ genl "typedef #{d.amqp2cpp} #{typename};"
end
end
@@ -41,7 +39,7 @@ class Specification < CppGen
def action_struct_h(x, base, consts, &block)
genl
struct(x.classname, "public #{base}") {
- x.fields.each { |f| genl "#{f.type_.amqp2cpp} #{f.cppname};" }
+ 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};"}
@@ -58,10 +56,11 @@ class Specification < CppGen
genl
genl "const char* #{x.classname}::NAME=\"#{x.fqname}\";"
genl
- ctor_defn(x.classname) {}
- ctor_defn(x.classname, x.parameters, x.initializers) {} if not x.fields.empty?
- function_defn("void #{x.classname}::accept", ["Visitor&"], "const") {
- genl "// FIXME aconway 2008-02-27: todo"
+ 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);"
}
end
@@ -107,20 +106,21 @@ class Specification < CppGen
# they are used by other definitions:
each_class_ns { |c|
class_h c
- c.domains.each { |d| domain_h d if pregenerate? d }
- c.structs.each { |s| struct_h s if pregenerate? s }
+ c.collect_all(AmqpDomain).each { |d| domain_h d if pregenerate? d }
+ c.collect_all(AmqpStruct).each { |s| struct_h s if pregenerate? s }
}
# Now dependent domains/structs and actions
each_class_ns { |c|
- c.domains.each { |d| domain_h d if not pregenerate? d }
- c.structs.each { |s| struct_h s if not pregenerate? s }
- c.actions.each { |a| action_h a }
+ c.collect_all(AmqpDomain).each { |d| domain_h d unless pregenerate? d}
+ c.collect_all(AmqpStruct).each { |s| struct_h s unless pregenerate? s}
+ c.collect_all(AmqpAction).each { |a| action_h a }
}
}
}
cpp_file("#{@dir}/specification") {
include "#{@dir}/specification"
+ ["Command","Control","Struct"].each { |x| include "#{@dir}/Apply#{x}" }
namespace(@ns) {
each_class_ns { |c|
class_cpp c
@@ -156,10 +156,58 @@ class Specification < CppGen
}
}
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;"
+ }}}}
+
+ 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()
+ end
+
+ def holder(base, derived)
+ name=base.caps+"Holder"
+ h_file("#{@dir}/#{name}") {
+ include "#{@dir}/specification"
+ include "qpid/framing/Blob"
+ namespace(@ns){
+ # TODO aconway 2008-02-29:
+ }
+ }
+ end
+ def gen_holders()
+
+ 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))
end
end
diff --git a/cpp/rubygen/amqpgen.rb b/cpp/rubygen/amqpgen.rb
index 2edc573d00..67b4b1c73c 100755
--- a/cpp/rubygen/amqpgen.rb
+++ b/cpp/rubygen/amqpgen.rb
@@ -131,6 +131,12 @@ class AmqpElement
@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 }
@@ -386,6 +392,7 @@ class AmqpRoot < AmqpElement
def methods_() classes.map { |c| c.methods_ }.flatten; end
+ #preview
# Return all methods on chassis for all classes.
def methods_on(chassis)
@methods_on ||= { }
@@ -394,8 +401,6 @@ class AmqpRoot < AmqpElement
def fqname() nil; end
- # TODO aconway 2008-02-21: methods by role.
-
private
# Merge contents of elements.
diff --git a/cpp/rubygen/cppgen.rb b/cpp/rubygen/cppgen.rb
index 5d2695c77a..df4ba49ca8 100755
--- a/cpp/rubygen/cppgen.rb
+++ b/cpp/rubygen/cppgen.rb
@@ -57,6 +57,7 @@ class String
def cppsafe() CppMangle.include?(self) ? self+"_" : self; end
def amqp2cpp()
+ throw 'Invalid "array".amqp2cpp' if self=="array"
path=split(".")
name=path.pop
return name.typename if path.empty?
@@ -112,21 +113,28 @@ class CppType
def to_s() name; end;
end
+class AmqpElement
+ # convert my amqp type_ attribute to a C++ type.
+ def amqp2cpp()
+ return "Array<#{ArrayTypes[name].amqp2cpp}> " if type_=="array"
+ return type_.amqp2cpp
+ end
+end
+
class AmqpField
def cppname() name.lcaps.cppsafe; end
def cpptype() domain.cpptype; end
def bit?() domain.type_ == "bit"; end
def signature() cpptype.param+" "+cppname; end
- # FIXME aconway 2008-02-27: qualified
- def paramtype()
- fqtype=type_
- unless type_.index(".")
+ 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
- "call_traits<#{fqtype.amqp2cpp}>::param_type";
+ return amqp2cpp
end
+ def paramtype() "call_traits<#{fqtypename}>::param_type"; end
end
class AmqpMethod
@@ -337,8 +345,8 @@ class CppGen < Generator
def ctor_decl(name, params=[]) function_decl(name, params); end
def ctor_defn(name, params=[], inits=[])
- signature(name+"::"+name, params)
- scope(":","") { genl inits.join(",\n")} if not inits.empty?
+ signature(name, params, inits.empty? ? "" : " :")
+ indent { gen inits.join(",\n") } if not inits.empty?
scope() { yield }
end