summaryrefslogtreecommitdiff
path: root/cpp/rubygen
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/rubygen')
-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
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