From bb2883b9f5cfad0e028a9849ed91e36418a2d0ff Mon Sep 17 00:00:00 2001 From: Gordon Sim Date: Tue, 21 Aug 2007 15:51:41 +0000 Subject: Refresh of transitional xml to more closely reflect latest specification Initial execution-result support (not yet handled on c++ client) Generation is now all done through the ruby code (it is a little slower at present I'm afraid, will try to speed it up over the next weeks) git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@568174 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/rubygen/templates/structs.rb | 345 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 cpp/rubygen/templates/structs.rb (limited to 'cpp/rubygen/templates/structs.rb') diff --git a/cpp/rubygen/templates/structs.rb b/cpp/rubygen/templates/structs.rb new file mode 100644 index 0000000000..972a0386b9 --- /dev/null +++ b/cpp/rubygen/templates/structs.rb @@ -0,0 +1,345 @@ +#!/usr/bin/env ruby +# Usage: output_directory xml_spec_file [xml_spec_file...] +# +$: << '..' +require 'cppgen' + +class StructGen < CppGen + + def initialize(outdir, amqp) + super(outdir, amqp) + end + + EncodingMap={ + "octet"=>"Octet", + "short"=>"Short", + "long"=>"Long", + "longlong"=>"LongLong", + "longstr"=>"LongString", + "shortstr"=>"ShortString", + "timestamp"=>"LongLong", + "uuid"=>"ShortString",#FIXME + "table"=>"FieldTable", + "content"=>"Content", + "long-struct"=>"LongString" + } + SizeMap={ + "octet"=>"1", + "short"=>"2", + "long"=>"4", + "longlong"=>"8", + "timestamp"=>"8" + } + + ValueTypes=["octet", "short", "long", "longlong", "timestamp"] + + def printable_form(f) + if (f.cpptype == "u_int8_t") + return "(int) " + f.cppname + else + return f.cppname + end + end + + def generate_encode(f, combined) + if (f.field_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 + end + end + + def generate_decode(f, combined) + if (f.field_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 + end + end + + def generate_size(f, combined) + if (f.field_type == "bit") + names = ([f] + combined).collect {|g| g.cppname} + genl "+ 1 //#{names.join(", ")}" + else + size = SizeMap[f.field_type] + if (size) + genl "+ #{size} //#{f.cppname}" + elsif (f.cpp_member_type == "SequenceNumberSet") + genl "+ #{f.cppname}.encodedSize()" + else + encoded = EncodingMap[f.field_type] + gen "+ 4 " if encoded == "LongString" + gen "+ 1 " if encoded == "ShortString" + genl "+ #{f.cppname}.size()" + end + end + end + + def process_fields(s) + last = nil + count = 0 + bits = [] + s.fields.each { + |f| if (last and last.bit? and f.bit? and count < 7) + count += 1 + bits << f + else + if (last and last.bit?) + yield last, bits + count = 0 + bits = [] + end + if (not f.bit?) + yield f + end + last = f + end + } + if (last and last.bit?) + yield last, bits + end + end + + def methodbody_extra_defs(s) + gen <#{s.cppname} + ( +EOS + if (s.amqp_parent.name == "message" && (s.name == "transfer" || s.name == "append")) + indent(4) { genl "*this" } + else + indent(4) { genl s.param_names.join(",\n") } + end + + genl <(target); + if (ptr) { + ptr->#{s.cppname}( +EOS + if (s.amqp_parent.name == "message" && (s.name == "transfer" || s.name == "append")) + indent(5) { genl "*this" } + else + indent(5) { genl s.param_names.join(",\n") } + end + + gen < 0) + genl "#{name}(" + if (s.kind_of? AmqpMethod) + indent {gen "ProtocolVersion, "} + end + indent { gen s.fields.collect { |f| "#{f.cpptype} _#{f.cppname}" }.join(",\n") } + gen ")" + genl ": " if s.fields.size > 0 + indent { gen s.fields.collect { |f| " #{f.cppname}(_#{f.cppname})" }.join(",\n") } + genl " {}" + end + if (s.kind_of? AmqpMethod) + genl "#{name}(ProtocolVersion=ProtocolVersion()) {}" + end + 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}; }" + end + + def define_struct(s) + classname = s.cppname + inheritance = "" + if (s.kind_of? AmqpMethod) + classname = s.body_name + inheritance = ": public AMQMethodBody" + end + + h_file("qpid/framing/#{classname}.h") { + if (s.kind_of? AmqpMethod) + gen < +#include "qpid/framing/amqp_types_full.h" + +namespace qpid { +namespace framing { + +class #{classname} #{inheritance} { +EOS + indent { s.fields.each { |f| genl "#{f.cpp_member_type} #{f.cppname};" } } + genl "public:" + if (s.kind_of? AmqpMethod) + indent { genl "static const ClassId CLASS_ID = #{s.amqp_parent.index};" } + indent { genl "static const MethodId METHOD_ID = #{s.index};" } + end + + if (s.kind_of? AmqpStruct) + 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;" } + else + indent { genl "static const uint16_t TYPE = #{s.type};" } + end + end + end + + indent { + define_constructor(classname, s) + genl "" + s.fields.each { |f| define_accessors(f) } + } + if (s.kind_of? AmqpMethod) + methodbody_extra_defs(s) + end + if (s.kind_of? AmqpStruct) + indent {genl "friend std::ostream& operator<<(std::ostream&, const #{classname}&);" } + end + + gen < 0) + buffer = "buffer" + else + buffer = "/*buffer*/" + end + gen <