#!/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", "table"=>"FieldTable", "content"=>"Content", "long-struct"=>"LongString", "uuid" => "ShortString" # FIXME aconway 2007-08-27: Remove. } SizeMap={ "octet"=>"1", "short"=>"2", "long"=>"4", "longlong"=>"8", "timestamp"=>"8" } ValueTypes=["octet", "short", "long", "longlong", "timestamp"] def printable_form(f) if (f.cpptype.name == "u_int8_t") return "(int) " + f.cppname else return f.cppname end end def generate_encode(f, combined) 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 genl f.domain.cpptype.encode(f.cppname,"buffer") end end def generate_decode(f, combined) 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 genl f.domain.cpptype.decode(f.cppname,"buffer") end end def generate_size(f, combined) if (f.domain.type_ == "bit") names = ([f] + combined).collect {|g| g.cppname} genl "+ 1 //#{names.join(", ")}" else size = SizeMap[f.domain.type_] if (size) genl "+ #{size} //#{f.cppname}" elsif (f.cpptype.name == "SequenceNumberSet") genl "+ #{f.cppname}.encodedSize()" else encoded = EncodingMap[f.domain.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 < 0) genl "#{name}(" if (s.kind_of? AmqpMethod) indent {gen "ProtocolVersion, "} end 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") } 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.param} _#{f.cppname}) { #{f.cppname} = _#{f.cppname}; }" genl "#{f.cpptype.ret} 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.cpptype.name} #{f.cppname};" } } genl "public:" if (s.kind_of? AmqpMethod) 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.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.parent.parent.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 <