summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2007-08-27 12:56:29 +0000
committerAlan Conway <aconway@apache.org>2007-08-27 12:56:29 +0000
commit54b9b8aeb902851cd52825764938e1b012e06a43 (patch)
treeb48f08f56570a857091dcf6b3276372bb0c0e5a4 /cpp
parent91b71b5e76868d482a0889758acf0675c871d871 (diff)
downloadqpid-python-54b9b8aeb902851cd52825764938e1b012e06a43.tar.gz
* rubygen/amqpgen.rb: Performance and API improvements.
Added nodes for all amqp.xml elements except doc, assert and rule. (They can easily be added.) In particular AmqpDomain is a proper node, providing a place to do type mapping. Every node has reader methods for AMQP attributes/elements: - attr() for each AMQP attribute "attr" returns the string value. - foos() returns AmqpElements for all the "foo" children. - foo(name) returns AmqpElements for the named "foo" child domain() returns an AmqpDomain rather than the string name. Method names that would clash with Object methods get a trailing "_" So: class_/classes, method_/methods_, type_/types Notes: - no amqp_ prefixes. - AmqpElement does not inherit REXML::Element, AmqpElement#xml() to get the REXML element. Performance: all templates run in 2.8 seconds on my laptop, compared to almost two minutes previously. Main change was to replace xpath searches with simple descent of the Amqp model and cache values selectively based on profiling. * rubygen/cppgen.rb: - Updated for amqpgen changes. - Introduced CppType to manage C++ type information - Moved all type mapping to CppType/AmqpDomain Some templates still do their own type calculations, these should be centralized in CppType so they can be re-used. * rubygen/templates/*: Updated for new API * src/qpid/framing/amqp_types_full.h: Added Uuid.h * xml/cluster.xml: change "type" attribute to "domain" git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@570096 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp')
-rwxr-xr-xcpp/rubygen/amqpgen.rb296
-rwxr-xr-xcpp/rubygen/cppgen.rb166
-rwxr-xr-xcpp/rubygen/generate4
-rw-r--r--cpp/rubygen/templates/InvocationVisitor.rb18
-rwxr-xr-xcpp/rubygen/templates/MethodBodyConstVisitor.rb4
-rwxr-xr-xcpp/rubygen/templates/MethodHolder.rb12
-rwxr-xr-xcpp/rubygen/templates/Operations.rb23
-rwxr-xr-xcpp/rubygen/templates/Proxy.rb14
-rw-r--r--cpp/rubygen/templates/Session.rb12
-rwxr-xr-xcpp/rubygen/templates/all_method_bodies.rb2
-rw-r--r--cpp/rubygen/templates/frame_body_lists.rb2
-rw-r--r--cpp/rubygen/templates/structs.rb60
-rw-r--r--cpp/src/qpid/framing/amqp_types_full.h1
-rw-r--r--cpp/xml/cluster.xml2
14 files changed, 303 insertions, 313 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
diff --git a/cpp/src/qpid/framing/amqp_types_full.h b/cpp/src/qpid/framing/amqp_types_full.h
index 027b563caf..bf89d59980 100644
--- a/cpp/src/qpid/framing/amqp_types_full.h
+++ b/cpp/src/qpid/framing/amqp_types_full.h
@@ -33,5 +33,6 @@
#include "FramingContent.h"
#include "FieldTable.h"
#include "SequenceNumberSet.h"
+#include "Uuid.h"
#endif /*!_framing_amqp_types_decl_h*/
diff --git a/cpp/xml/cluster.xml b/cpp/xml/cluster.xml
index fffd3aafc4..80cf80fc6b 100644
--- a/cpp/xml/cluster.xml
+++ b/cpp/xml/cluster.xml
@@ -29,7 +29,7 @@
<method name = "notify" index="10">
<doc>Notify the cluster of a members URL</doc>
<!-- No chassis element, this is handled by separte cluster code for now.-->
- <field name = "url" type = "longstr" />
+ <field name="url" domain="longstr" />
</method>
</class>