diff options
Diffstat (limited to 'cpp')
-rwxr-xr-x | cpp/rubygen/amqpgen.rb | 37 | ||||
-rwxr-xr-x | cpp/rubygen/cppgen.rb | 25 | ||||
-rwxr-xr-x | cpp/rubygen/generate | 2 | ||||
-rwxr-xr-x | cpp/rubygen/templates/amqp_0_10.rb | 64 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/helpers.h | 70 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/visitors.h | 15 | ||||
-rw-r--r-- | cpp/src/qpid/client/Session.h | 2 |
7 files changed, 198 insertions, 17 deletions
diff --git a/cpp/rubygen/amqpgen.rb b/cpp/rubygen/amqpgen.rb index f998909ec8..da6ed689a3 100755 --- a/cpp/rubygen/amqpgen.rb +++ b/cpp/rubygen/amqpgen.rb @@ -127,6 +127,9 @@ class AmqpElement @cache_child[[elname,name]] ||= children(elname).find { |c| c.name==name } end + # Fully qualified amqp dotted name of this element + def dotted_name() (parent ? parent.dotted_name+"." : "") + name; end + # The root <amqp> element. def root() @root ||=parent ? parent.root : self; end @@ -142,7 +145,9 @@ class AmqpElement end -AmqpResponse = AmqpElement +class AmqpResponse < AmqpElement + def initialize(xml, parent) super; end +end class AmqpDoc < AmqpElement def initialize(xml,parent) super; end @@ -183,7 +188,6 @@ class AmqpField < AmqpElement def initialize(xml, amqp) super; end; def domain() root.domain(xml.attributes["domain"]); end amqp_single_child_reader :struct # preview - # FIXME aconway 2008-02-21: exceptions in fields - need to update c++ mapping. amqp_child_reader :exception amqp_attr_reader :type, :default, :code, :required end @@ -198,11 +202,6 @@ class AmqpConstant < AmqpElement amqp_attr_reader :value, :class end -# FIXME aconway 2008-02-21: -# class AmqpResponse < AmqpElement -# def initialize(xml, parent) super; end -# end - class AmqpResult < AmqpElement def initialize(xml, parent) super; end amqp_single_child_reader :struct # preview @@ -236,8 +235,8 @@ class AmqpStruct < AmqpElement amqp_attr_reader :size, :code, :pack amqp_child_reader :field - alias :raw_pack :pack # preview - preview code needs default "short" for pack. + alias :raw_pack :pack def pack() raw_pack or (not parent.final? and "short"); end def result?() parent.xml.name == "result"; end def domain?() parent.xml.name == "domain"; end @@ -299,9 +298,14 @@ class AmqpClass < AmqpElement end class AmqpType < AmqpElement + def initialize(xml,amqp) super; end amqp_attr_reader :code, :fixed_width, :variable_width end +class AmqpXref < AmqpElement + def initialize(xml,amqp) super; end +end + # AMQP root element. class AmqpRoot < AmqpElement amqp_attr_reader :major, :minor, :port, :comment @@ -319,9 +323,9 @@ class AmqpRoot < AmqpElement def version() major + "-" + minor; end - # Find a child node from a dotted amqp name, e.g. message.transfer - def lookup(dotted_name) elements[dotted_name.gsub(/\./,"/")]; end - + # Find the element corresponding to an amqp dotted name. + def lookup(dotted_name) xml.elements[dotted_name.gsub(/\./,"/")]; end + # preview - only struct child reader remains for new mapping def domain_structs() domains.map{ |d| d.struct }.compact; end def result_structs() @@ -353,7 +357,7 @@ end # Collect information about generated files. class GenFiles @@files =[] - def GenFiles.add(f) @@files << f; puts f; end + def GenFiles.add(f) @@files << f; end def GenFiles.get() @@files; end end @@ -378,7 +382,14 @@ class Generator if (@outdir != "-") path=Pathname.new "#{@outdir}/#{file}" path.parent.mkpath - path.open('w') { |@out| yield } + @out=String.new # Generate in memory first + yield # Generate to @out + if path.exist? and path.read == @out + puts "Skipped #{path} - unchanged" # Dont generate if unchanged + else + path.open('w') { |f| f << @out } + puts "Generated #{path}" + end end end diff --git a/cpp/rubygen/cppgen.rb b/cpp/rubygen/cppgen.rb index 60a653e18d..d3cdcca603 100755 --- a/cpp/rubygen/cppgen.rb +++ b/cpp/rubygen/cppgen.rb @@ -54,12 +54,23 @@ CppKeywords = Set.new(["and", "and_eq", "asm", "auto", "bitand", CppMangle = CppKeywords+Set.new(["string"]) class String - def cppsafe() - CppMangle.include?(self) ? self+"_" : self + def cppsafe() CppMangle.include?(self) ? self+"_" : self; end + def amqp2cpp() + path=split(".") + name=path.pop + path.map! { |n| n.bars } + (path << name.caps).join("::") end end # Hold information about a C++ type. +# +# preview - new mapping does not use CppType, +# Each amqp type corresponds exactly by dotted name +# to a type, domain or struct, which in turns +# corresponds by name to a C++ type or typedef. +# (see String.amqp2cpp) +# class CppType def initialize(name) @name=@param=@ret=name; end attr_reader :name, :param, :ret, :code @@ -93,6 +104,16 @@ class CppType def to_s() name; end; end +class AmqpElement + def cppfqname() + names=parent.dotted_name.split(".") + # Field children are moved up to method in C++b + prefix.pop if parent.is_a? AmqpField + prefix.push cppname + prefix.join("::") + end +end + class AmqpField def cppname() name.lcaps.cppsafe; end def cpptype() domain.cpptype; end diff --git a/cpp/rubygen/generate b/cpp/rubygen/generate index 94b194aaa4..f7bf334569 100755 --- a/cpp/rubygen/generate +++ b/cpp/rubygen/generate @@ -69,7 +69,7 @@ EOS } out << <<EOS if GENERATE -$(rgen_srcs) $(srcdir)/#{File.basename makefile}: $(rgen_generator) $(specs) +$(srcdir)/#{File.basename makefile}: $(rgen_generator) $(specs) $(rgen_cmd) # Empty rule in case a generator file is renamed/removed. diff --git a/cpp/rubygen/templates/amqp_0_10.rb b/cpp/rubygen/templates/amqp_0_10.rb new file mode 100755 index 0000000000..ef779c9015 --- /dev/null +++ b/cpp/rubygen/templates/amqp_0_10.rb @@ -0,0 +1,64 @@ +#!/usr/bin/env ruby +$: << ".." # Include .. in load path +require 'cppgen' + +class Amqp_0_10 < CppGen + + def initialize(outdir, amqp) + super(outdir, amqp) + @namespace="qpid::amqp_0_10" + @filename="qpid/amqp_0_10" + end + + def action_h(a, base) + struct(a.cppname, "public #{base}") { + genl "static const uint8_t CODE=#{a.code};" + a.fields.each { |f| + genl "#{(f.type_.amqp2cpp)} #{f.cppname};" + } + } + end + + def action_cpp(a, base) + + end + + def gen_amqp_0_10_h + h_file("#{@filename}.h") { + namespace(@namespace) { + @amqp.classes.each { |cl| + namespace(cl.cppname) { + struct("ClassInfo") { + genl "static const uint8_t CODE=#{cl.code};" + genl "static const char* NAME;" + } + cl.commands.each { |c| action_h c, "Command"} + cl.controls.each { |c| action_h c, "Control"} + } + } + } + } + end + + def gen_amqp_0_10_cpp + cpp_file("#{@filename}.cpp") { + include @filename + + namespace(@namespace) { + @amqp.classes.each { |cl| + namespace(cl.cppname) { + genl "static const char* ClassInfo::NAME=\"#{cl.name};" + } + } + } + } + end + + def generate + gen_amqp_0_10_h + gen_amqp_0_10_cpp + end +end + +Amqp_0_10.new(Outdir, Amqp).generate(); + diff --git a/cpp/src/qpid/amqp_0_10/helpers.h b/cpp/src/qpid/amqp_0_10/helpers.h new file mode 100644 index 0000000000..1d93d1d51c --- /dev/null +++ b/cpp/src/qpid/amqp_0_10/helpers.h @@ -0,0 +1,70 @@ +#ifndef QPID_AMQP_0_10_HELPERS_H +#define QPID_AMQP_0_10_HELPERS_H + +/* + * + * 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 <string> + +namespace qpid { + +namespace amqp_0_10 { + +struct ClassAttributes { uint8_t code; const char* name }; + +struct MemberAttributes { + ClassAttributes class_; + const char* name + uint8_t code; + + std::string fullName() const { + return std::string(class_.name)+"."+name; + } +}; + +struct StructAttributes : public MemberAttributes { uint8_t size, pack; }; + +static const ClassAttributes getClass(uint8_t code); +static const MemberAttributes getCommand(uint8_t classCode, uint8_t code); +static const MemberAttributes getControl(uint8_t classCode, uint8_t code); + +struct Command : public Member { + class Visitor; + virtual const MemberAttributes& attributes() const = 0; + virtual void accept(Visitor&) const = 0; +}; + +struct Control : public Member { + class Visitor; + struct Attributes { uint8_t classCode, code }; + + virtual const MemberAttributes& attributes() const = 0; + virtual void accept(Visitor&) const = 0; +}; + + +struct Struct : public Member { + virtual const StructAttributes& attributes() const = 0; +}; + + +}} // namespace qpid::amqp_0_10 + +#endif /*!QPID_AMQP_0_10_HELPERS_H*/ diff --git a/cpp/src/qpid/amqp_0_10/visitors.h b/cpp/src/qpid/amqp_0_10/visitors.h new file mode 100644 index 0000000000..3835f37f3e --- /dev/null +++ b/cpp/src/qpid/amqp_0_10/visitors.h @@ -0,0 +1,15 @@ +// Visitors +template <class Base> struct Visitor; +template <class Base, class F, class R> FunctorVisitor; + +/** Template base implementation for visitables. */ +template <class Base, class Derived> +struct VisitableBase : public Base { + virtual void accept(Visitor<Derived>& v) { + v.visit(static_cast<Derived>&(*this)); + } + virtual void accept(Visitor<Derived>& v) const { + v.visit(static_cast<const Derived>&(*this)); + } +}; + diff --git a/cpp/src/qpid/client/Session.h b/cpp/src/qpid/client/Session.h index 3293af60fe..5d91f289e2 100644 --- a/cpp/src/qpid/client/Session.h +++ b/cpp/src/qpid/client/Session.h @@ -27,7 +27,7 @@ namespace qpid { namespace client { /** - * Session is currently just an alias for Session_0_10 + * Session is currently just an alias for Session_99_0 * * \ingroup clientapi */ |