diff options
Diffstat (limited to 'cpp/rubygen')
-rwxr-xr-x | cpp/rubygen/amqpgen.rb | 296 | ||||
-rwxr-xr-x | cpp/rubygen/cppgen.rb | 166 | ||||
-rwxr-xr-x | cpp/rubygen/generate | 4 | ||||
-rw-r--r-- | cpp/rubygen/templates/InvocationVisitor.rb | 18 | ||||
-rwxr-xr-x | cpp/rubygen/templates/MethodBodyConstVisitor.rb | 4 | ||||
-rwxr-xr-x | cpp/rubygen/templates/MethodHolder.rb | 12 | ||||
-rwxr-xr-x | cpp/rubygen/templates/Operations.rb | 23 | ||||
-rwxr-xr-x | cpp/rubygen/templates/Proxy.rb | 14 | ||||
-rw-r--r-- | cpp/rubygen/templates/Session.rb | 12 | ||||
-rwxr-xr-x | cpp/rubygen/templates/all_method_bodies.rb | 2 | ||||
-rw-r--r-- | cpp/rubygen/templates/frame_body_lists.rb | 2 | ||||
-rw-r--r-- | cpp/rubygen/templates/structs.rb | 60 |
12 files changed, 301 insertions, 312 deletions
diff --git a/cpp/rubygen/amqpgen.rb b/cpp/rubygen/amqpgen.rb index ceaf04090b..068ecf7aae 100755 --- a/cpp/rubygen/amqpgen.rb +++ b/cpp/rubygen/amqpgen.rb @@ -17,220 +17,216 @@ class String # 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. -class Array - def sort_by_name() - sort() { |a,b| a.name <=> b.name } - end +module Enumerable + def sort_by_name() sort { |a,b| a.name <=> b.name }; end end -# Add collect to Elements -class Elements - def collect(xpath, &block) - result=[] - each(xpath) { |el| result << yield(el) } - result +# 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) + (Object.method_defined? sym) ? (sym.to_s+"_").intern : sym + end + + # Add attribute reader for XML attribute. + def amqp_attr_reader(*attrs) + attrs.each { |a| + define_method(mangle(a)) { + @amqp_attr_reader||={ } + @amqp_attr_reader[a] ||= xml.attributes[a.to_s] + } + } end -end - -# An AmqpElement extends (delegates to) a REXML::Element -# -# NB: AmqpElements cache various values, they assume that -# the XML model does not change after the AmqpElement has -# been created. -# -class AmqpElement < DelegateClass(Element) - def initialize(xml, amqp) super(xml); @amqp_parent=amqp; end - attr_reader :amqp_parent - - # Return the name attribute, not the element name. - def name() attributes["name"]; 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 - def amqp_root() - amqp_parent ? amqp_parent.amqp_root : self; + # 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 -# AMQP field element -class AmqpField < AmqpElement - def initialize(xml, amqp) super; end; - # Get AMQP type for a domain name. - def domain_type(name) - @cache_domain_type ||= domain_type_impl(name) - 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 - # Get the AMQP type of this field. - def field_type() - d=attributes["domain"] - dt=domain_type d if d - (dt or attributes["type"]) + def wrap(xml) + return nil if ["doc","assert","rule"].include? xml.name + eval("Amqp"+xml.name.caps).new(xml, self) or raise "nil wrapper" end - # determine whether this type is defined as a struct in the spec - def defined_as_struct() - @cache_defined_as_struct ||= defined_as_struct_impl() + public + + def initialize(xml, parent) + @xml, @parent=xml, parent + @children=xml.elements.map { |e| wrap e }.compact + @cache_child={} + @cache_children={} + @cache_children[nil]=@children end -private - def domain_type_impl(name) - domain=elements["/amqp/domain[@name='#{name}']"] - (domain and domain.attributes["type"] or name) - end + attr_reader :parent, :xml, :children + amqp_attr_reader :name, :label - def defined_as_struct_impl() - domain_name = attributes["domain"] - elements["/amqp/domain[@name='#{domain_name}']/struct"] + # List of children of type elname, or all children if elname + # not specified. + def children(elname=nil) + @cache_children[elname] ||= @children.select { |c| elname==c.xml.name } end -end - -# AMQP method element -class AmqpMethod < AmqpElement - def initialize(xml, amqp) super; end - def content() - attributes["content"] + # 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 - def index() attributes["index"]; end + # The root <amqp> element. + def root() @root ||=parent ? parent.root : self; end - def fields() - @cache_fields ||= elements.collect("field") { |f| AmqpField.new(f,self); } - end + def to_s() "#<#{self.class}(#{name})>"; end + def inspect() to_s; end +end - # Responses to this method (0-9) - def responses() - @cache_responses ||= elements.collect("response") { |el| AmqpMethod.new(el,self) } - end +AmqpResponse = AmqpElement - # Methods this method responds to (0-9) - def responds_to() - @cache_responds_to ||= elements.collect("../method/response[@name='#{attributes['name']}']") { |el| - AmqpMethod.new(el.parent, amqp_parent) - } - end +class AmqpDomain < AmqpElement + def initialize(xml, parent) super; end + amqp_attr_reader :type + amqp_single_child_reader :struct - def has_result?() - @cache_has_result ||= elements["result/struct"] + def unalias() + d=self + while (d.type_ != d.name and root.domain(d.type_)) + d=root.domain(d.type_) + end + return d end +end - def result_struct() - @cache_result_struct ||= has_result? ? AmqpStruct.new(elements["result/struct"], self) : nil - end +class AmqpField < AmqpElement + def initialize(xml, amqp) super; end; + def domain() root.domain(xml.attributes["domain"]); end + amqp_single_child_reader :struct +end - def is_server_method?() - @cache_is_server_method ||= elements["chassis[@name='server']"] - end +class AmqpChassis < AmqpElement + def initialize(xml, parent) super; end + amqp_attr_reader :implement +end - def request?() responds_to().empty?; end - def response?() not request?; end +class AmqpConstant < AmqpElement + def initialize(xml, parent) super; end + amqp_attr_reader :value, :datatype end -# AMQP class element. -class AmqpClass < AmqpElement - def initialize(xml,amqp) super; end - def index() attributes["index"]; end - def amqp_methods() - @cache_amqp_methods ||= elements.collect("method") { |el| - AmqpMethod.new(el,self) - }.sort_by_name - end +class AmqpResult < AmqpElement + def initialize(xml, parent) super; end + amqp_single_child_reader :struct +end - # chassis should be "client" or "server" - def amqp_methods_on(chassis) - @cache_amqp_methods_on ||= { } - @cache_amqp_methods_on[chassis] ||= elements.collect("method/chassis[@name='#{chassis}']/..") { |m| AmqpMethod.new(m,self) }.sort_by_name - end +class AmqpStruct < AmqpElement + def initialize(xml, parent) super; end + amqp_attr_reader :size, :type + 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 struct element. -class AmqpStruct < AmqpElement - def initialize(xml,amqp) super; end + amqp_attr_reader :content, :index, :synchronous + amqp_child_reader :field, :chassis,:response + amqp_single_child_reader :result - def type() attributes["type"]; end + def on_chassis?(chassis) child("chassis", chassis); end + def on_client?() on_chassis? "client"; end + def on_server?() on_chassis? "server"; end +end - def size() attributes["size"]; end +class AmqpClass < AmqpElement + def initialize(xml,amqp) super; end + amqp_attr_reader :index - def result?() parent.name == "result"; end + amqp_child_reader :method - def domain?() parent.name == "domain"; end + # FIXME aconway 2007-08-27: REMOVE + def methods_() children("method").sort_by_name; end - def fields() - @cache_fields ||= elements.collect("field") { |f| AmqpField.new(f,self); } + # chassis should be "client" or "server" + def methods_on(chassis) + @methods_on ||= { } + @methods_on[chassis] ||= methods_.select { |m| m.on_chassis? chassis } end end + + # AMQP root element. class AmqpRoot < AmqpElement - - # FIXME aconway - something namespace-related in ruby 1.8.6 - # breaks all the xpath expressions with [@attr] tests. - # Not clear if this is a ruby bug or error in my xpath, - # current workaround is to simply delete the namespace node. - def newDoc(xmlFile) - root=Document.new(File.new(xmlFile)).root - root.delete_namespace - throw "Internal error, FIXME comment in aqmpgen.rb." unless (root.namespaces.empty?) - root - end + def parse(filename) Document.new(File.new(filename)).root; end # Initialize with output directory and spec files from ARGV. def initialize(*specs) - specs.size or raise "No XML spec files." - specs.each { |f| File.exists?(f) or raise "Invalid XML file: #{f}"} - super newDoc(specs.shift), nil - specs.each { |s| # Merge in additional specs - root=newDoc s - merge(self,root) - } + raise "No XML spec files." if specs.empty? + xml=parse(specs.shift) + specs.each { |s| xml_merge(xml, parse(s)) } + super(xml, nil) end - def version() - attributes["major"]+"-"+attributes["minor"] - end + amqp_attr_reader :major, :minor + amqp_child_reader :class, :domain - def amqp_classes() - @cache_amqp_classes ||= elements.collect("class") { |c| - AmqpClass.new(c,self) }.sort_by_name - end + # FIXME aconway 2007-08-27: REMOVE + def classes() children("class").sort_by_name; end + + def version() major + "-" + minor; end - def amqp_structs() - @cache_amqp_structs ||= amqp_result_structs + amqp_domain_structs - end + def domain_structs() domains.map{ |d| d.struct }.compact; end - def amqp_domain_structs() - @cache_amqp_domain_structs ||= elements.collect("domain/struct") { |s| AmqpStruct.new(s, self) } + def result_structs() + methods_.map { |m| m.result and m.result.struct }.compact end - def amqp_result_structs() - @cache_amqp_result_structs ||= amqp_methods.collect { |m| m.result_struct }.compact - end - - # Return all methods on all classes. - def amqp_methods() - @cache_amqp_methods ||= amqp_classes.collect { |c| c.amqp_methods }.flatten; - end + def structs() result_structs+domain_structs; end + def methods_() classes.map { |c| c.methods_ }.flatten; end + # Return all methods on chassis for all classes. - def amqp_methods_on(chassis) - @cache_amqp_methods_on ||= { } - @cache_amqp_methods_on[chassis] ||= amqp_classes.collect { |c| c.amqp_methods_on(chassis) }.flatten + def methods_on(chassis) + @methods_on ||= { } + @methods_on[chassis] ||= classes.map { |c| c.methods_on(chassis) }.flatten end + private + # Merge contents of elements. - def merge(to,from) + 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 ? merge(to_child, from_child) : to.add(from_child.deep_clone) } + to_child ? xml_merge(to_child, from_child) : to.add(from_child.deep_clone) } end - - private :merge - end # Collect information about generated files. @@ -304,5 +300,3 @@ class Generator attr_accessor :out end - - diff --git a/cpp/rubygen/cppgen.rb b/cpp/rubygen/cppgen.rb index 109005e743..99d80b0b4e 100755 --- a/cpp/rubygen/cppgen.rb +++ b/cpp/rubygen/cppgen.rb @@ -36,20 +36,20 @@ Copyright=<<EOS 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"]) + "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(["string"]) @@ -59,83 +59,89 @@ class String end end -# Additional methods for AmqpField. +# Hold information about a C++ type. +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 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 to_s() name; end; +end + class AmqpField - def cppname() @cache_cppname ||= name.lcaps.cppsafe; end - def cpptype() @cache_cpptype ||= defined_as_struct ? "const " + field_type.caps + "&" : amqp_root.param_type(field_type); end - def cpp_member_type() @cache_cpp_member_type ||= defined_as_struct ? field_type.caps : amqp_root.member_type(field_type); end - def cppret_type() @cache_cpptype ||= amqp_root.return_type(field_type); end - def type_name () @type_name ||= cpptype+" "+cppname; end - def bit?() field_type == "bit" end + def cppname() name.lcaps.cppsafe; end + def cpptype() domain.cpptype; end + def bit?() domain.type_ == "bit"; end end -# Additional methods for AmqpMethod class AmqpMethod def cppname() name.lcaps.cppsafe; end - def param_names() @param_names ||= fields.collect { |f| f.cppname }; end - def signature() @signature ||= fields.collect { |f| f.cpptype+" "+f.cppname }; end - def body_name() amqp_parent.name.caps+name.caps+"Body"; end + def param_names() fields.map { |f| f.cppname }; end + def signature() fields.map { |f| f.cpptype.param+" "+f.cppname }; end + def body_name() parent.name.caps+name.caps+"Body"; end end -# Additional methods for AmqpClass class AmqpClass def cppname() name.caps; end - def body_name() cppname+"Body" - end end -class AmqpStruct - def cppname() - @cache_cppname ||= cppname_impl() - end - -private - - def cppname_impl() - #The name of the struct comes from the context it appears in: - #structs defined in a domain get their name from the domain - #element, structs defined in a result element get their name by - #appending 'Result' to the enclosing method name. - if (domain?) - parent.attributes["name"].caps - else - if (result?) - method = parent.parent - method.parent.attributes["name"].caps + method.attributes["name"].caps + "Result" - else - raise "Bad struct context: expected struct to be child of <domain> or <result>" - end - end +class AmqpDomain + @@typemap = { + "bit"=> CppType.new("bool").code("Octet"), + "octet"=>CppType.new("u_int8_t").code("Octet"), # FIXME aconway 2007-08-25: uint + "short"=>CppType.new("u_int16_t").code("Short"), + "long"=>CppType.new("u_int32_t").code("Long"), + "longlong"=>CppType.new("u_int64_t").code("LongLong"), + "timestamp"=>CppType.new("u_int64_t").code("LongLong"), + "longstr"=>CppType.new("string").passcref.retcref.code("LongString"), + "shortstr"=>CppType.new("string").passcref.retcref.code("ShortString"), + "table"=>CppType.new("FieldTable").passcref.retcref.code("FieldTable"), + "content"=>CppType.new("Content").passcref.retcref.code("Content"), + "rfc1982-long-set"=>CppType.new("SequenceNumberSet").passcref.retcref, + "long-struct"=>CppType.new("string").passcref.retcref.code("LongString"), + "uuid"=>CppType.new("string").passcref.retcref.code("ShortString") # FIXME aconway 2007-08-25: Remove, +# "uuid"=>CppType.new("Uuid").passcref.retcref.code, + } + + def cppname() name.caps; end + def cpptype() + d=unalias + @cpptype ||= @@typemap[d.type_] or + CppType.new(d.cppname).passcref.retcref or + raise "Invalid type #{self}" end end -# Additional methos for AmqpRoot -class AmqpRoot - # FIXME aconway 2007-06-20: fix u_int types, should be uint - CppTypeMap={ - "bit"=> ["bool"], - "octet"=>["u_int8_t"], - "short"=>["u_int16_t"], - "long"=>["u_int32_t"], - "longlong"=>["u_int64_t"], - "timestamp"=>["u_int64_t"], - "longstr"=>["string", "const string&"], - "shortstr"=>["string", "const string&"], - "table"=>["FieldTable", "const FieldTable&", "const FieldTable&"], - "content"=>["Content", "const Content&", "const Content&"], - "rfc1982-long-set"=>["SequenceNumberSet", "const SequenceNumberSet&", "const SequenceNumberSet&"], - "long-struct"=>["string", "const string&"], - "uuid"=>["string", "const string&"] # FIXME should be: ["Uuid", "const Uuid&", "const Uuid&"] - } - - def lookup(amqptype) - CppTypeMap[amqptype] or raise "No cpp type for #{amqptype}"; +class AmqpResult + def cpptype() + @cpptype=CppType.new(parent.parent.name.caps+parent.name.caps+"Result").passcref end - - def member_type(amqptype) lookup(amqptype)[0]; end - def param_type(amqptype) t=lookup(amqptype); t[1] or t[0]; end - def return_type(amqptype) t=lookup(amqptype); t[2] or t[0]; end +end + +class AmqpStruct + def cpptype() parent.cpptype; end + def cppname() cpptype.name; end end class CppGen < Generator @@ -197,10 +203,14 @@ class CppGen < Generator scope("{","};") { yield } 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 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 typedef(type, name) genl "typedef #{type} #{name};\n" 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 diff --git a/cpp/rubygen/generate b/cpp/rubygen/generate index 52313186ed..e35a5458ea 100755 --- a/cpp/rubygen/generate +++ b/cpp/rubygen/generate @@ -23,12 +23,12 @@ Specs=ARGV.grep(/\.xml$/) Amqp=AmqpRoot.new(*Specs) # Run selected templates -if ARGV.grep("^all$") +if ARGV.any? { |arg| arg=="all" } templates=Dir["#{File.dirname __FILE__}/templates/*.rb"] else templates=ARGV.grep(/\.rb$/) end -templates.each { |t| require t } +templates.each { |t| load t } # Generate makefile makefile=ARGV.grep(/.mk$/)[0] diff --git a/cpp/rubygen/templates/InvocationVisitor.rb b/cpp/rubygen/templates/InvocationVisitor.rb index 7017872176..befbdd53c7 100644 --- a/cpp/rubygen/templates/InvocationVisitor.rb +++ b/cpp/rubygen/templates/InvocationVisitor.rb @@ -12,7 +12,7 @@ class InvocationVisitor < CppGen end def invocation_args(m) - if (m.amqp_parent.name == "message" && (m.name == "transfer" || m.name == "append")) + if (m.parent.name == "message" && (m.name == "transfer" || m.name == "append")) "body" else m.param_names.collect {|p| "body.get" + p.caps + "()" }.join(",\n") @@ -32,17 +32,17 @@ class InvocationVisitor < CppGen gen <<EOS void InvocationVisitor::visit(const #{m.body_name}& #{body}) { - AMQP_ServerOperations::#{m.amqp_parent.cppname}Handler* ptr(0); + AMQP_ServerOperations::#{m.parent.cppname}Handler* ptr(0); if (invocable) { - ptr = dynamic_cast<AMQP_ServerOperations::#{m.amqp_parent.cppname}Handler*>(invocable); + ptr = dynamic_cast<AMQP_ServerOperations::#{m.parent.cppname}Handler*>(invocable); } else { - ptr = ops->get#{m.amqp_parent.cppname}Handler(); + ptr = ops->get#{m.parent.cppname}Handler(); } if (ptr) { EOS - if (m.has_result?) - indent(2) { genl "encode<#{m.result_struct.cppname.caps}>(ptr->#{m.cppname}(#{invocation_args(m)}), result);" } + if (m.result) + indent(2) { genl "encode<#{m.result.struct.cpptype.name}>(ptr->#{m.cppname}(#{invocation_args(m)}), result);" } else indent(2) { genl "ptr->#{m.cppname}(#{invocation_args(m)});" } end @@ -79,14 +79,14 @@ EOS genl "void clear();" genl "virtual ~InvocationVisitor() {}" } - @amqp.amqp_methods.each { |m| genl "void visit(const #{m.body_name}&);" } + @amqp.methods_.each { |m| genl "void visit(const #{m.body_name}&);" } } } } cpp_file("#{@filename}") { include "InvocationVisitor.h" - @amqp.amqp_methods.each { |m| include m.body_name } + @amqp.methods_.each { |m| include m.body_name } namespace(@namespace) { genl "void InvocationVisitor::clear() {" indent { @@ -95,7 +95,7 @@ EOS } genl "}" genl - @amqp.amqp_methods.each { |m| m.is_server_method? ? define_visit(m) : null_visit(m) } + @amqp.methods_.each { |m| m.on_server? ? define_visit(m) : null_visit(m) } } } end diff --git a/cpp/rubygen/templates/MethodBodyConstVisitor.rb b/cpp/rubygen/templates/MethodBodyConstVisitor.rb index 6fd7fe8ead..18f74a2e41 100755 --- a/cpp/rubygen/templates/MethodBodyConstVisitor.rb +++ b/cpp/rubygen/templates/MethodBodyConstVisitor.rb @@ -14,11 +14,11 @@ class MethodBodyConstVisitorGen < CppGen def generate() h_file("#{@filename}") { namespace(@namespace) { - @amqp.amqp_methods.each { |m| genl "class #{m.body_name};" } + @amqp.methods_.each { |m| genl "class #{m.body_name};" } cpp_class("MethodBodyConstVisitor") { genl "public:" genl "virtual ~MethodBodyConstVisitor() {}" - @amqp.amqp_methods.each { |m| genl "virtual void visit(const #{m.body_name}&) = 0;" } + @amqp.methods_.each { |m| genl "virtual void visit(const #{m.body_name}&) = 0;" } }}} end end diff --git a/cpp/rubygen/templates/MethodHolder.rb b/cpp/rubygen/templates/MethodHolder.rb index 39a570c982..95c60f5727 100755 --- a/cpp/rubygen/templates/MethodHolder.rb +++ b/cpp/rubygen/templates/MethodHolder.rb @@ -14,7 +14,7 @@ class MethodHolderGen < CppGen def gen_max_size() # Generate program to generate MaxSize.h cpp_file("generate_#{@classname}MaxSize_h") { - @amqp.amqp_methods.each { |m| include "qpid/framing/#{m.body_name}" } + @amqp.methods_.each { |m| include "qpid/framing/#{m.body_name}" } genl include "<algorithm>" include "<fstream>" @@ -24,7 +24,7 @@ class MethodHolderGen < CppGen genl scope("int main(int, char** argv) {") { genl "size_t maxSize=0;" - @amqp.amqp_methods.each { |m| + @amqp.methods_.each { |m| genl "maxSize=max(maxSize, sizeof(#{m.body_name}));" } gen <<EOS ofstream out("#{@filename}MaxSize.h"); @@ -41,7 +41,7 @@ EOS cpp_file(@filename+"_construct") { include @filename include "qpid/framing/MethodBodyConstVisitor.h" - @amqp.amqp_methods.each { |m| include "qpid/framing/#{m.body_name}" } + @amqp.methods_.each { |m| include "qpid/framing/#{m.body_name}" } genl include "qpid/Exception.h" genl @@ -49,9 +49,9 @@ EOS # construct function scope("void #{@classname}::construct(ClassId c, MethodId m) {") { scope("switch (c) {") { - @amqp.amqp_classes.each { |c| + @amqp.classes.each { |c| scope("case #{c.index}: switch(m) {") { - c.amqp_methods.each { |m| + c.methods_.each { |m| genl "case #{m.index}: blob.construct(in_place<#{m.body_name}>()); break;" } genl "default: throw Exception(QPID_MSG(\"Invalid method id \" << m << \" for class #{c.name} \"));" @@ -64,7 +64,7 @@ EOS # CopyVisitor struct("#{@classname}::CopyVisitor", "public MethodBodyConstVisitor") { genl "MethodHolder& holder;" genl "CopyVisitor(MethodHolder& h) : holder(h) {}" - @amqp.amqp_methods.each { |m| + @amqp.methods_.each { |m| genl "void visit(const #{m.body_name}& x) { holder.blob=x; }" } } diff --git a/cpp/rubygen/templates/Operations.rb b/cpp/rubygen/templates/Operations.rb index 79b82a9d59..9f242f5910 100755 --- a/cpp/rubygen/templates/Operations.rb +++ b/cpp/rubygen/templates/Operations.rb @@ -3,6 +3,9 @@ # $: << '..' require 'cppgen' +require 'fileutils' +require 'etc' +require 'pathname' class OperationsGen < CppGen @@ -13,12 +16,8 @@ class OperationsGen < CppGen end def handler_method (m) - if (m.has_result?) - return_type = "#{m.amqp_parent.name.caps}#{m.cppname.caps}Result" - else - return_type = "void" - end - if (m.amqp_parent.name == "message" && (m.name == "transfer" || m.name == "append")) + return_type = m.result ? m.result.cpptype.ret : "void" + if (m.parent.name == "message" && (m.name == "transfer" || m.name == "append")) gen "\nvirtual #{return_type} #{m.cppname}(const framing::AMQMethodBody& context) = 0;\n" else gen "\nvirtual #{return_type} #{m.cppname}(" @@ -30,7 +29,7 @@ class OperationsGen < CppGen def handler_classname(c) c.name.caps+"Handler"; end def handler_class(c) - if (!c.amqp_methods_on(@chassis).empty?) + if (!c.methods_on(@chassis).empty?) handlerclass=handler_classname c gen <<EOS // ==================== class #{handlerclass} ==================== @@ -41,7 +40,7 @@ class #{handlerclass} : public virtual Invocable { virtual ~#{handlerclass}() {} // Protocol methods EOS - c.amqp_methods_on(@chassis).each { |m| handler_method(m) } + c.methods_on(@chassis).each { |m| handler_method(m) } gen <<EOS }; // class #{handlerclass} @@ -51,14 +50,14 @@ EOS end def handler_get(c) - if (!c.amqp_methods_on(@chassis).empty?) + if (!c.methods_on(@chassis).empty?) handlerclass=handler_classname c gen "virtual #{handlerclass}* get#{handlerclass}() = 0;\n" end end def generate() - h_file("qpid/framing/#{@classname}.h") { + h_file("qpid/framing/#{@classname}.h") { gen <<EOS #include <sstream> #include "qpid/framing/ProtocolVersion.h" @@ -88,13 +87,13 @@ class #{@classname} { // Inner classes EOS - indent { @amqp.amqp_classes.each { |c| handler_class(c) } } + indent { @amqp.classes.each { |c| handler_class(c) } } gen <<EOS // Method handler get methods EOS - indent { @amqp.amqp_classes.each { |c| handler_get(c) } } + indent { @amqp.classes.each { |c| handler_get(c) } } gen <<EOS }; /* class #{@classname} */ }} diff --git a/cpp/rubygen/templates/Proxy.rb b/cpp/rubygen/templates/Proxy.rb index a6c0763a8a..41e0cc1882 100755 --- a/cpp/rubygen/templates/Proxy.rb +++ b/cpp/rubygen/templates/Proxy.rb @@ -26,7 +26,7 @@ virtual ~#{cname}() {} static #{cname}& get(#{@classname}& proxy) { return proxy.get#{cname}(); } EOS - c.amqp_methods_on(@chassis).each { |m| + c.methods_on(@chassis).each { |m| genl "virtual void #{m.cppname}(#{m.signature.join(",\n ")});" genl }} @@ -34,7 +34,7 @@ EOS def inner_class_defn(c) cname=c.cppname - c.amqp_methods_on(@chassis).each { |m| + c.methods_on(@chassis).each { |m| genl "void #{@classname}::#{cname}::#{m.cppname}(#{m.signature.join(", ")})" scope { params=(["channel.getVersion()"]+m.param_names).join(", ") @@ -51,14 +51,14 @@ EOS public genl "#{@classname}(ChannelAdapter& ch);" genl - @amqp.amqp_classes.each { |c| + @amqp.classes.each { |c| inner_class_decl(c) genl genl "#{c.cppname}& get#{c.cppname}() { return #{proxy_member(c)}; }" genl } private - @amqp.amqp_classes.each{ |c| gen c.cppname+" "+proxy_member(c)+";\n" } + @amqp.classes.each{ |c| gen c.cppname+" "+proxy_member(c)+";\n" } }}} # .cpp file @@ -67,14 +67,14 @@ EOS include "#{@classname}.h" include "qpid/framing/ChannelAdapter.h" include "qpid/framing/amqp_types_full.h" - Amqp.amqp_methods_on(@chassis).each { |m| include "qpid/framing/"+m.body_name } + Amqp.methods_on(@chassis).each { |m| include "qpid/framing/"+m.body_name } genl namespace("qpid::framing") { genl "#{@classname}::#{@classname}(ChannelAdapter& ch) :" gen " Proxy(ch)" - @amqp.amqp_classes.each { |c| gen ",\n "+proxy_member(c)+"(channel)" } + @amqp.classes.each { |c| gen ",\n "+proxy_member(c)+"(channel)" } genl "{}\n" - @amqp.amqp_classes.each { |c| inner_class_defn(c) } + @amqp.classes.each { |c| inner_class_defn(c) } }} end end diff --git a/cpp/rubygen/templates/Session.rb b/cpp/rubygen/templates/Session.rb index 0d5808318a..f4af2041dd 100644 --- a/cpp/rubygen/templates/Session.rb +++ b/cpp/rubygen/templates/Session.rb @@ -13,7 +13,7 @@ class SessionGen < CppGen end def declare_method (m) - gen "Response #{m.amqp_parent.name.lcaps}#{m.name.caps}(" + gen "Response #{m.parent.name.lcaps}#{m.name.caps}(" if (m.content()) params=m.signature + ["const MethodContent& content"] else @@ -24,11 +24,11 @@ class SessionGen < CppGen end def declare_class(c) - c.amqp_methods_on(@chassis).each { |m| declare_method(m) } + c.methods_on(@chassis).each { |m| declare_method(m) } end def define_method (m) - gen "Response Session::#{m.amqp_parent.name.lcaps}#{m.name.caps}(" + gen "Response Session::#{m.parent.name.lcaps}#{m.name.caps}(" if (m.content()) params=m.signature + ["const MethodContent& content"] else @@ -55,7 +55,7 @@ class SessionGen < CppGen end def define_class(c) - c.amqp_methods_on(@chassis).each { |m| define_method(m) } + c.methods_on(@chassis).each { |m| define_method(m) } end def generate() @@ -92,7 +92,7 @@ public: void setSynchronous(bool sync) { impl->setSync(sync); } void close(); EOS - indent { @amqp.amqp_classes.each { |c| declare_class(c) if !excludes.include?(c.name) } } + indent { @amqp.classes.each { |c| declare_class(c) if !excludes.include?(c.name) } } gen <<EOS }; /* class #{@classname} */ } @@ -134,7 +134,7 @@ void #{@classname}::close() EOS - @amqp.amqp_classes.each { |c| define_class(c) if !excludes.include?(c.name) } + @amqp.classes.each { |c| define_class(c) if !excludes.include?(c.name) } gen <<EOS }} // namespace qpid::client diff --git a/cpp/rubygen/templates/all_method_bodies.rb b/cpp/rubygen/templates/all_method_bodies.rb index 38fbc31593..d06f459493 100755 --- a/cpp/rubygen/templates/all_method_bodies.rb +++ b/cpp/rubygen/templates/all_method_bodies.rb @@ -12,7 +12,7 @@ class AllMethodBodiesGen < CppGen def generate() h_file(@filename) { - @amqp.amqp_methods.each { |m| include "qpid/framing/"+m.body_name } + @amqp.methods_.each { |m| include "qpid/framing/"+m.body_name } } end end diff --git a/cpp/rubygen/templates/frame_body_lists.rb b/cpp/rubygen/templates/frame_body_lists.rb index 25231e7e1a..634001ab14 100644 --- a/cpp/rubygen/templates/frame_body_lists.rb +++ b/cpp/rubygen/templates/frame_body_lists.rb @@ -15,7 +15,7 @@ class FrameBodyListsGen < CppGen */ EOS gen "#define METHOD_BODIES() " - @amqp.amqp_methods.each { |m| gen "\\\n (#{m.body_name}) " } + @amqp.methods_.each { |m| gen "\\\n (#{m.body_name}) " } gen <<EOS diff --git a/cpp/rubygen/templates/structs.rb b/cpp/rubygen/templates/structs.rb index 571a85b827..47670e9953 100644 --- a/cpp/rubygen/templates/structs.rb +++ b/cpp/rubygen/templates/structs.rb @@ -18,10 +18,10 @@ class StructGen < CppGen "longstr"=>"LongString", "shortstr"=>"ShortString", "timestamp"=>"LongLong", - "uuid"=>"ShortString",#FIXME "table"=>"FieldTable", "content"=>"Content", - "long-struct"=>"LongString" + "long-struct"=>"LongString", + "uuid" => "ShortString" # FIXME aconway 2007-08-27: } SizeMap={ "octet"=>"1", @@ -34,7 +34,7 @@ class StructGen < CppGen ValueTypes=["octet", "short", "long", "longlong", "timestamp"] def printable_form(f) - if (f.cpptype == "u_int8_t") + if (f.cpptype.name == "u_int8_t") return "(int) " + f.cppname else return f.cppname @@ -42,53 +42,39 @@ class StructGen < CppGen end def generate_encode(f, combined) - if (f.field_type == "bit") + if (f.domain.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 - encoded = EncodingMap[f.field_type] - if (encoded) - genl "buffer.put#{encoded}(#{f.cppname});" - else - genl "#{f.cppname}.encode(buffer);" - end + genl f.domain.cpptype.encode(f.cppname,"buffer") end end def generate_decode(f, combined) - if (f.field_type == "bit") + if (f.domain.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 - encoded = EncodingMap[f.field_type] - if (encoded) - if (ValueTypes.include?(f.field_type)) - genl "#{f.cppname} = buffer.get#{encoded}();" - else - genl "buffer.get#{encoded}(#{f.cppname});" - end - else - genl "#{f.cppname}.decode(buffer);" - end + genl f.domain.cpptype.decode(f.cppname,"buffer") end end def generate_size(f, combined) - if (f.field_type == "bit") + if (f.domain.type_ == "bit") names = ([f] + combined).collect {|g| g.cppname} genl "+ 1 //#{names.join(", ")}" else - size = SizeMap[f.field_type] + size = SizeMap[f.domain.type_] if (size) genl "+ #{size} //#{f.cppname}" - elsif (f.cpp_member_type == "SequenceNumberSet") + elsif (f.cpptype.name == "SequenceNumberSet") genl "+ #{f.cppname}.encodedSize()" else - encoded = EncodingMap[f.field_type] + encoded = EncodingMap[f.domain.type_] gen "+ 4 " if encoded == "LongString" gen "+ 1 " if encoded == "ShortString" genl "+ #{f.cppname}.size()" @@ -137,7 +123,7 @@ EOS if (s.kind_of? AmqpMethod) indent {gen "ProtocolVersion, "} end - indent { gen s.fields.collect { |f| "#{f.cpptype} _#{f.cppname}" }.join(",\n") } + indent { gen s.fields.collect { |f| "#{f.cpptype.param} _#{f.cppname}" }.join(",\n") } gen ")" genl ": " if s.fields.size > 0 indent { gen s.fields.collect { |f| " #{f.cppname}(_#{f.cppname})" }.join(",\n") } @@ -149,8 +135,8 @@ EOS end def define_accessors(f) - genl "void set#{f.name.caps}(#{f.cpptype} _#{f.cppname}) { #{f.cppname} = _#{f.cppname}; }" - genl "#{f.cpptype} get#{f.name.caps}() const { return #{f.cppname}; }" + 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}; }" end def define_struct(s) @@ -171,7 +157,7 @@ EOS end #need to include any nested struct definitions - s.fields.select {|f| f.defined_as_struct }.map {|f| include f.name.caps} + s.fields.each { |f| include f.cpptype.name if f.domain.struct } gen <<EOS @@ -183,23 +169,23 @@ namespace framing { class #{classname} #{inheritance} { EOS - indent { s.fields.each { |f| genl "#{f.cpp_member_type} #{f.cppname};" } } + indent { s.fields.each { |f| genl "#{f.cpptype.name} #{f.cppname};" } } genl "public:" if (s.kind_of? AmqpMethod) - indent { genl "static const ClassId CLASS_ID = #{s.amqp_parent.index};" } + indent { genl "static const ClassId CLASS_ID = #{s.parent.index};" } indent { genl "static const MethodId METHOD_ID = #{s.index};" } end if (s.kind_of? AmqpStruct) - if (s.type) + if (s.type_) if (s.result?) #as result structs have types that are only unique to the #class, they have a class dependent qualifier added to them #(this is inline with current python code but a formal #solution is expected from the WG - indent { genl "static const uint16_t TYPE = #{s.type} + #{s.amqp_parent.amqp_parent.index} * 256;" } + indent { genl "static const uint16_t TYPE = #{s.type_} + #{s.parent.parent.parent.index} * 256;" } else - indent { genl "static const uint16_t TYPE = #{s.type};" } + indent { genl "static const uint16_t TYPE = #{s.type_};" } end end end @@ -295,10 +281,10 @@ EOS end def generate() - @amqp.amqp_structs.each { |s| define_struct(s) } - @amqp.amqp_methods.each { |m| define_struct(m) } + @amqp.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 - h_file("qpid/framing/amqp_structs.h") { @amqp.amqp_structs.each { |s| genl "#include \"#{s.cppname}.h\"" } } + h_file("qpid/framing/amqp_structs.h") { @amqp.structs.each { |s| genl "#include \"#{s.cppname}.h\"" } } end end |