diff options
author | Gordon Sim <gsim@apache.org> | 2007-09-27 16:50:25 +0000 |
---|---|---|
committer | Gordon Sim <gsim@apache.org> | 2007-09-27 16:50:25 +0000 |
commit | 2986ee70a6af129a03ffb0a0d629bf4f5054fc36 (patch) | |
tree | b91c64e71313256d11d9f318246f732d73576d20 | |
parent | 7190479334fb9bf3942eae4d2d92685d72e82d55 (diff) | |
download | qpid-python-2986ee70a6af129a03ffb0a0d629bf4f5054fc36.tar.gz |
Some revisions to rubygen for packed structs and execution header (changes not yet enabled)
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@580094 13f79535-47bb-0310-9956-ffa450edef68
-rwxr-xr-x | cpp/rubygen/amqpgen.rb | 6 | ||||
-rwxr-xr-x | cpp/rubygen/cppgen.rb | 5 | ||||
-rw-r--r-- | cpp/rubygen/templates/structs.rb | 162 | ||||
-rw-r--r-- | cpp/src/Makefile.am | 1 | ||||
-rw-r--r-- | cpp/src/qpid/framing/ModelMethod.h | 48 |
5 files changed, 194 insertions, 28 deletions
diff --git a/cpp/rubygen/amqpgen.rb b/cpp/rubygen/amqpgen.rb index f47b8e2f9f..21bc05c651 100755 --- a/cpp/rubygen/amqpgen.rb +++ b/cpp/rubygen/amqpgen.rb @@ -151,7 +151,7 @@ end class AmqpStruct < AmqpElement def initialize(xml, parent) super; end - amqp_attr_reader :size, :type + amqp_attr_reader :size, :type, :pack amqp_child_reader :field def result?() parent.xml.name == "result"; end @@ -181,6 +181,10 @@ class AmqpClass < AmqpElement @methods_on ||= { } @methods_on[chassis] ||= methods_.select { |m| m.on_chassis? chassis } end + + def l4?() + !["connection", "session", "execution"].include?(name) + end end diff --git a/cpp/rubygen/cppgen.rb b/cpp/rubygen/cppgen.rb index 0de448869d..7973bccf5b 100755 --- a/cpp/rubygen/cppgen.rb +++ b/cpp/rubygen/cppgen.rb @@ -135,6 +135,10 @@ class AmqpDomain CppType.new(d.cppname).passcref.retcref or raise "Invalid type #{self}" end + + def AmqpDomain.lookup_type(t) + @@typemap[t] + end end class AmqpResult @@ -144,6 +148,7 @@ class AmqpResult end class AmqpStruct + def cpp_pack_type() AmqpDomain.lookup_type(pack()) or CppType.new("uint16_t"); end def cpptype() parent.cpptype; end def cppname() cpptype.name; end end diff --git a/cpp/rubygen/templates/structs.rb b/cpp/rubygen/templates/structs.rb index 422fd8c207..15962af4df 100644 --- a/cpp/rubygen/templates/structs.rb +++ b/cpp/rubygen/templates/structs.rb @@ -32,6 +32,18 @@ class StructGen < CppGen ValueTypes=["octet", "short", "long", "longlong", "timestamp"] + def is_packed(s) + false and s.kind_of? AmqpStruct and s.pack + end + + def execution_header?(s) + false and s.kind_of? AmqpMethod and s.parent.l4? + end + + def has_bitfields_only(s) + s.fields.select {|f| f.domain.type_ != "bit"}.empty? + end + def default_initialisation(s) params = s.fields.select {|f| ValueTypes.include?(f.domain.type_) || f.domain.type_ == "bit"} strings = params.collect {|f| "#{f.cppname}(0)"} @@ -50,6 +62,57 @@ class StructGen < CppGen end end + def get_flags_impl(s) + genl "#{s.cpp_pack_type.name} flags = 0;" + process_packed_fields(s) { |f, i| set_field_flag(f, i) } + genl "return flags;" + end + + def set_field_flag(f, i) + if (ValueTypes.include?(f.domain.type_) || f.domain.type_ == "bit") + genl "if (#{f.cppname}) flags |= (1 << #{i});" + else + genl "if (#{f.cppname}.size()) flags |= (1 << #{i});" + end + end + + def encode_packed_struct(s) + genl "#{s.cpp_pack_type.name} flags = getFlags();" + genl s.cpp_pack_type.encode('flags', 'buffer') + process_packed_fields(s) { |f, i| encode_packed_field(f, i) unless f.domain.type_ == "bit" } + end + + def decode_packed_struct(s) + genl "#{s.cpp_pack_type.name} #{s.cpp_pack_type.decode('flags', 'buffer')}" + process_packed_fields(s) { |f, i| decode_packed_field(f, i) unless f.domain.type_ == "bit" } + process_packed_fields(s) { |f, i| set_bitfield(f, i) if f.domain.type_ == "bit" } + end + + def size_packed_struct(s) + genl "#{s.cpp_pack_type.name} flags = getFlags();" unless has_bitfields_only(s) + genl "total += #{SizeMap[s.pack]};" + process_packed_fields(s) { |f, i| size_packed_field(f, i) unless f.domain.type_ == "bit" } + end + + def encode_packed_field(f, i) + genl "if (flags & (1 << #{i}))" + indent { genl f.domain.cpptype.encode(f.cppname,"buffer") } + end + + def decode_packed_field(f, i) + genl "if (flags & (1 << #{i}))" + indent { genl f.domain.cpptype.decode(f.cppname,"buffer") } + end + + def size_packed_field(f, i) + genl "if (flags & (1 << #{i}))" + indent { generate_size(f, []) } + end + + def set_bitfield(f, i) + genl "#{f.cppname} = (flags & (1 << #{i}));" + end + def generate_encode(f, combined) if (f.domain.type_ == "bit") genl "uint8_t #{f.cppname}_bits = #{f.cppname};" @@ -75,22 +138,27 @@ class StructGen < CppGen def generate_size(f, combined) if (f.domain.type_ == "bit") names = ([f] + combined).collect {|g| g.cppname} - genl "+ 1 //#{names.join(", ")}" + genl "total += 1;//#{names.join(", ")}" else size = SizeMap[f.domain.type_] if (size) - genl "+ #{size} //#{f.cppname}" + genl "total += #{size};//#{f.cppname}" elsif (f.cpptype.name == "SequenceNumberSet") - genl "+ #{f.cppname}.encodedSize()" + genl "total += #{f.cppname}.encodedSize();" else encoded = EncodingMap[f.domain.type_] - gen "+ 4 " if encoded == "LongString" - gen "+ 1 " if encoded == "ShortString" - genl "+ #{f.cppname}.size()" + gen "total += (" + gen "4 " if encoded == "LongString" + gen "1 " if encoded == "ShortString" + genl "+ #{f.cppname}.size());" end end end + def process_packed_fields(s) + s.fields.each { |f| yield f, s.fields.index(f) } + end + def process_fields(s) last = nil count = 0 @@ -162,7 +230,11 @@ EOS inheritance = "" if (s.kind_of? AmqpMethod) classname = s.body_name - inheritance = ": public AMQMethodBody" + if (execution_header?(s)) + inheritance = ": public ModelMethod" + else + inheritance = ": public AMQMethodBody" + end end h_file("qpid/framing/#{classname}.h") { @@ -173,6 +245,7 @@ EOS #include "qpid/framing/MethodBodyConstVisitor.h" EOS end + include "qpid/framing/ModelMethod.h" if (execution_header?(s)) #need to include any nested struct definitions s.fields.each { |f| include f.cpptype.name if f.domain.struct } @@ -188,6 +261,9 @@ namespace framing { class #{classname} #{inheritance} { EOS indent { s.fields.each { |f| genl "#{f.cpptype.name} #{f.cppname};" } } + if (is_packed(s)) + indent { genl "#{s.cpp_pack_type.name} getFlags() const;"} + end genl "public:" if (s.kind_of? AmqpMethod) indent { genl "static const ClassId CLASS_ID = #{s.parent.index};" } @@ -231,7 +307,7 @@ EOS EOS } cpp_file("qpid/framing/#{classname}.cpp") { - if (s.fields.size > 0) + if (s.fields.size > 0 || execution_header?(s)) buffer = "buffer" else buffer = "/*buffer*/" @@ -241,46 +317,79 @@ EOS using namespace qpid::framing; +EOS + + if (is_packed(s)) + genl "#{s.cpp_pack_type.name} #{classname}::getFlags() const" + genl "{" + indent { get_flags_impl(s) } + genl "}" + end + gen <<EOS void #{classname}::encode(Buffer& #{buffer}) const { EOS - indent { process_fields(s) { |f, combined| generate_encode(f, combined) } } - gen <<EOS + if (execution_header?(s)) + genl "ModelMethod::encode(buffer);" + end + + if (is_packed(s)) + indent {encode_packed_struct(s)} + else + indent { process_fields(s) { |f, combined| generate_encode(f, combined) } } + end + gen <<EOS } void #{classname}::decode(Buffer& #{buffer}, uint32_t /*size*/) { EOS - indent { process_fields(s) { |f, combined| generate_decode(f, combined) } } - gen <<EOS + if (execution_header?(s)) + genl "ModelMethod::decode(buffer);" + end + + if (is_packed(s)) + indent {decode_packed_struct(s)} + else + indent { process_fields(s) { |f, combined| generate_decode(f, combined) } } + end + gen <<EOS } uint32_t #{classname}::size() const { - return 0 + uint32_t total = 0; EOS - indent { process_fields(s) { |f, combined| generate_size(f, combined) } } - gen <<EOS - ; + if (execution_header?(s)) + genl "total += ModelMethod::size();" + end + + if (is_packed(s)) + indent {size_packed_struct(s)} + else + indent { process_fields(s) { |f, combined| generate_size(f, combined) } } + end + gen <<EOS + return total; } void #{classname}::print(std::ostream& out) const { out << "#{classname}: "; EOS - copy = Array.new(s.fields) - f = copy.shift + copy = Array.new(s.fields) + f = copy.shift - indent { - genl "out << \"#{f.name}=\" << #{printable_form(f)};" if f - copy.each { |f| genl "out << \"; #{f.name}=\" << #{printable_form(f)};" } - } - gen <<EOS + indent { + genl "out << \"#{f.name}=\" << #{printable_form(f)};" if f + copy.each { |f| genl "out << \"; #{f.name}=\" << #{printable_form(f)};" } + } + gen <<EOS } EOS - if (s.kind_of? AmqpStruct) - gen <<EOS + if (s.kind_of? AmqpStruct) + gen <<EOS namespace qpid{ namespace framing{ @@ -293,8 +402,7 @@ namespace framing{ } } EOS - end - + end } end diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am index ae3eb4c403..06e857bc4f 100644 --- a/cpp/src/Makefile.am +++ b/cpp/src/Makefile.am @@ -343,6 +343,7 @@ nobase_include_HEADERS = \ qpid/framing/MethodContent.h \ qpid/framing/MethodHolder.h \ qpid/framing/MethodHolderMaxSize.h \ + qpid/framing/ModelMethod.h \ qpid/framing/OutputHandler.h \ qpid/framing/ProtocolInitiation.h \ qpid/framing/ProtocolVersion.h \ diff --git a/cpp/src/qpid/framing/ModelMethod.h b/cpp/src/qpid/framing/ModelMethod.h new file mode 100644 index 0000000000..6861295194 --- /dev/null +++ b/cpp/src/qpid/framing/ModelMethod.h @@ -0,0 +1,48 @@ +#ifndef _ModelMethod_ +#define _ModelMethod_ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "AMQMethodBody.h" +#include "qpid/framing/ExecutionHeader.h" + +namespace qpid { +namespace framing { + + +class ModelMethod : public AMQMethodBody +{ + ExecutionHeader header; +public: + virtual ~ModelMethod() {} + virtual void encode(Buffer& buffer) const { header.encode(buffer); } + virtual void decode(Buffer& buffer, uint32_t size=0) { header.decode(buffer, size); } + virtual uint32_t size() const { return header.size(); } + + ExecutionHeader& getHeader() { return header; } + const ExecutionHeader& getHeader() const { return header; } +}; + + +}} // namespace qpid::framing + + +#endif |