summaryrefslogtreecommitdiff
path: root/cpp/rubygen/cppgen.rb
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/rubygen/cppgen.rb
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/rubygen/cppgen.rb')
-rwxr-xr-xcpp/rubygen/cppgen.rb166
1 files changed, 88 insertions, 78 deletions
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