summaryrefslogtreecommitdiff
path: root/cpp/rubygen
diff options
context:
space:
mode:
authorRafael H. Schloming <rhs@apache.org>2009-12-26 12:42:57 +0000
committerRafael H. Schloming <rhs@apache.org>2009-12-26 12:42:57 +0000
commit248f1fe188fe2307b9dcf2c87a83b653eaa1920c (patch)
treed5d0959a70218946ff72e107a6c106e32479a398 /cpp/rubygen
parent3c83a0e3ec7cf4dc23e83a340b25f5fc1676f937 (diff)
downloadqpid-python-248f1fe188fe2307b9dcf2c87a83b653eaa1920c.tar.gz
synchronized with trunk except for ruby dir
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/qpid.rnr@893970 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/rubygen')
-rwxr-xr-xcpp/rubygen/0-10/allsegmenttypes.rb18
-rwxr-xr-xcpp/rubygen/0-10/exceptions.rb18
-rwxr-xr-xcpp/rubygen/0-10/handlers.rb20
-rwxr-xr-xcpp/rubygen/0-10/specification.rb22
-rwxr-xr-xcpp/rubygen/0-10/typecode.rb18
-rwxr-xr-xcpp/rubygen/MethodBodyDefaultVisitor.rb19
-rwxr-xr-xcpp/rubygen/amqpgen.rb83
-rwxr-xr-xcpp/rubygen/cppgen.rb5
-rwxr-xr-xcpp/rubygen/framing.0-10/MethodBodyConstVisitor.rb18
-rwxr-xr-xcpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb23
-rw-r--r--cpp/rubygen/framing.0-10/MethodBodyFactory.rb58
-rwxr-xr-xcpp/rubygen/framing.0-10/MethodHolder.rb100
-rwxr-xr-xcpp/rubygen/framing.0-10/Operations.rb24
-rwxr-xr-xcpp/rubygen/framing.0-10/OperationsInvoker.rb27
-rwxr-xr-xcpp/rubygen/framing.0-10/Proxy.rb30
-rwxr-xr-x[-rw-r--r--]cpp/rubygen/framing.0-10/Session.rb214
-rwxr-xr-xcpp/rubygen/framing.0-10/all_method_bodies.rb18
-rwxr-xr-xcpp/rubygen/framing.0-10/constants.rb184
-rw-r--r--cpp/rubygen/framing.0-10/frame_body_lists.rb20
-rwxr-xr-x[-rw-r--r--]cpp/rubygen/framing.0-10/structs.rb80
-rwxr-xr-xcpp/rubygen/generate103
21 files changed, 839 insertions, 263 deletions
diff --git a/cpp/rubygen/0-10/allsegmenttypes.rb b/cpp/rubygen/0-10/allsegmenttypes.rb
index c4c4095e02..26363d6a1f 100755
--- a/cpp/rubygen/0-10/allsegmenttypes.rb
+++ b/cpp/rubygen/0-10/allsegmenttypes.rb
@@ -1,4 +1,22 @@
#!/usr/bin/env ruby
+#
+# 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 .. in load path
require 'cppgen'
diff --git a/cpp/rubygen/0-10/exceptions.rb b/cpp/rubygen/0-10/exceptions.rb
index 2f62b2ccdf..02e3a5d547 100755
--- a/cpp/rubygen/0-10/exceptions.rb
+++ b/cpp/rubygen/0-10/exceptions.rb
@@ -1,4 +1,22 @@
#!/usr/bin/env ruby
+#
+# 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 .. in load path
require 'cppgen'
diff --git a/cpp/rubygen/0-10/handlers.rb b/cpp/rubygen/0-10/handlers.rb
index c23eb5faf4..981ea890e6 100755
--- a/cpp/rubygen/0-10/handlers.rb
+++ b/cpp/rubygen/0-10/handlers.rb
@@ -1,4 +1,22 @@
#!/usr/bin/env ruby
+#
+# 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 .. in load path
require 'cppgen'
@@ -17,7 +35,7 @@ class GenHandlers < CppGen
def generate()
h_file("#{@dir}/handlers.h") {
- include "specification"
+ include "#{@dir}/specification"
namespace("#{@ns}") {
action_handler "Command", @amqp.collect_all(AmqpCommand)
action_handler "Control", @amqp.collect_all(AmqpControl)
diff --git a/cpp/rubygen/0-10/specification.rb b/cpp/rubygen/0-10/specification.rb
index a98292ee4e..7366599eba 100755
--- a/cpp/rubygen/0-10/specification.rb
+++ b/cpp/rubygen/0-10/specification.rb
@@ -1,4 +1,22 @@
#!/usr/bin/env ruby
+#
+# 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 .. in load path
require 'cppgen'
@@ -324,8 +342,8 @@ class Specification < CppGen
}
cpp_file("#{@dir}/#{name}") {
- include "#{name}"
- include "exceptions.h"
+ include "#{@dir}/#{name}"
+ include "#{@dir}/exceptions.h"
namespace(@ns) {
genl "using framing::in_place;"
genl
diff --git a/cpp/rubygen/0-10/typecode.rb b/cpp/rubygen/0-10/typecode.rb
index e36b92c07c..0ab9c4be5d 100755
--- a/cpp/rubygen/0-10/typecode.rb
+++ b/cpp/rubygen/0-10/typecode.rb
@@ -1,4 +1,22 @@
#!/usr/bin/env ruby
+#
+# 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 .. in load path
require 'cppgen'
diff --git a/cpp/rubygen/MethodBodyDefaultVisitor.rb b/cpp/rubygen/MethodBodyDefaultVisitor.rb
index 1fff1d51db..4f9b369117 100755
--- a/cpp/rubygen/MethodBodyDefaultVisitor.rb
+++ b/cpp/rubygen/MethodBodyDefaultVisitor.rb
@@ -1,4 +1,23 @@
#!/usr/bin/env ruby
+#
+# 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 .. in load path
require 'cppgen'
diff --git a/cpp/rubygen/amqpgen.rb b/cpp/rubygen/amqpgen.rb
index bfa15bb391..69e65a4056 100755
--- a/cpp/rubygen/amqpgen.rb
+++ b/cpp/rubygen/amqpgen.rb
@@ -1,7 +1,22 @@
+# 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.
#
# Generic AMQP code generation library.
#
-
# TODO aconway 2008-02-21:
#
# The amqp_attr_reader and amqp_child_reader for each Amqp* class
@@ -15,6 +30,7 @@
require 'delegate'
require 'rexml/document'
require 'pathname'
+require 'set'
include REXML
# Handy String functions for converting names.
@@ -150,7 +166,7 @@ class AmqpElement
# The root <amqp> element.
def root() @root ||=parent ? parent.root : self; end
- def to_s() "#<#{self.class}(#{fqname})>"; end
+ def to_s() "#<#{self.class}(#{fqname})>"; end
def inspect() to_s; end
# Text of doc child if there is one.
@@ -166,6 +182,21 @@ class AmqpElement
return self if is_a? AmqpClass
return parent && parent.containing_class
end
+
+ # 0-10 array domains are missing element type information, add it here.
+ ArrayTypes={
+ "str16-array" => "str-16",
+ "amqp-host-array" => "connection.amqp-host-url",
+ "command-fragments" => "session.command-fragment",
+ "in-doubt" => "dtx.xid",
+ "tx-publish" => "str-8",
+ "queues" => "str-8"
+ }
+
+ def array_type(name)
+ return ArrayTypes[name] if ArrayTypes[name]
+ raise "Missing ArrayType entry for " + name
+ end
end
@@ -189,14 +220,6 @@ class AmqpEnum < AmqpElement
amqp_child_reader :choice
end
-# 0-10 array domains are missing element type information, add it here.
-ArrayTypes={
- "str16-array" => "str-16",
- "amqp-host-array" => "connection.amqp-host-url",
- "command-fragments" => "session.command-fragment",
- "in-doubt" => "dtx.xid"
-}
-
class AmqpDomain < AmqpElement
def initialize(xml, parent)
super
@@ -295,7 +318,7 @@ class AmqpFakeMethod < AmqpMethod
def content() return "1" if @action.is_a? AmqpCommand and @action.segments end
def index() @action.code end
def code() @action.code end
- def synchronous() end # FIXME aconway 2008-04-10: ???
+ def synchronous() end
def on_chassis?(chassis)
@action.received_by?(chassis)
end
@@ -318,7 +341,14 @@ class AmqpAction < AmqpElement
def initialize(xml,amqp) super; end
amqp_child_reader :implement, :field, :response
amqp_attr_reader :code
- def implement?(role) xml.elements["./implement[@role='#{role}']"] end
+ def implement?(role)
+ # we can't use xpath for this because it triggers a bug in some
+ # versions of ruby, including version 1.8.6.110
+ xml.elements.each {|el|
+ return true if el.name == "implement" and el.attributes["role"] == role
+ }
+ return false
+ end
def received_by?(client_or_server)
return (implement?(client_or_server) or implement?("sender") or implement?("receiver"))
end
@@ -434,9 +464,12 @@ end
# Collect information about generated files.
class GenFiles
- @@files =[]
- def GenFiles.add(f) @@files << f; end
+ @@files = Set.new
+ @@public_api = []
+ def GenFiles.add(f) @@files.add(f); end
def GenFiles.get() @@files; end
+ def GenFiles.public_api(file) @@public_api << file; end
+ def GenFiles.public_api?(file) @@public_api.find { |f| f == file }; end
end
# Base class for code generators.
@@ -446,27 +479,27 @@ class Generator
# Takes directory for output or "-", meaning print file names that
# would be generated.
def initialize (outdir, amqp)
+ @outdir=outdir[0]
+ @apidir=outdir[1]
@amqp=amqp
- @outdir=outdir
+ raise "outdir is not an array" unless outdir.class == Array
@prefix=[''] # For indentation or comments.
@indentstr=' ' # One indent level.
@outdent=2
- Pathname.new(@outdir).mkpath unless @outdir=="-"
end
+ # Declare next file to be public API
+ def public_api(file) GenFiles.public_api(file); end
+
# Create a new file, set @out.
def file(file, &block)
- GenFiles.add file
- if (@outdir != "-")
- @path=Pathname.new "#{@outdir}/#{file}"
+ GenFiles.add(file)
+ dir = GenFiles.public_api?(file) ? @apidir : @outdir
+ if (dir != "-")
+ @path=Pathname.new "#{dir}/#{file}"
@path.parent.mkpath
@out=String.new # Generate in memory first
- if block then yield; endfile; end
- end
- end
-
- def endfile()
- if @outdir != "-"
+ yield if block
if @path.exist? and @path.read == @out
puts "Skipped #{@path} - unchanged" # Dont generate if unchanged
else
diff --git a/cpp/rubygen/cppgen.rb b/cpp/rubygen/cppgen.rb
index 3a4228567a..7818e1c4b0 100755
--- a/cpp/rubygen/cppgen.rb
+++ b/cpp/rubygen/cppgen.rb
@@ -118,6 +118,7 @@ class AmqpRoot
# preview; map 0-10 types to preview code generator types
@@typemap = {
"bit"=> CppType.new("bool").code("Octet").defval("false"),
+ "boolean"=> CppType.new("bool").code("Octet").defval("false"),
"uint8"=>CppType.new("uint8_t").code("Octet").defval("0"),
"uint16"=>CppType.new("uint16_t").code("Short").defval("0"),
"uint32"=>CppType.new("uint32_t").code("Long").defval("0"),
@@ -146,7 +147,7 @@ end
class AmqpElement
# convert my amqp type_ attribute to a C++ type.
def amqp2cpp()
- return "ArrayDomain<#{ArrayTypes[name].amqp2cpp}> " if type_=="array"
+ return "ArrayDomain<#{array_type(name).amqp2cpp}> " if type_=="array"
return type_.amqp2cpp
end
@@ -189,7 +190,7 @@ class AmqpField
c=containing_class
c.struct(type_)
end
- def cpptype() lookup_cpptype(type_) or raise "no cpptype #{self}" end
+ def cpptype() lookup_cpptype(type_) or raise "no cpptype #{type_} for field #{self}" end
def cppname() name.lcaps.cppsafe; end
def bit?() type_ == "bit"; end
def signature() cpptype.param+" "+cppname; end
diff --git a/cpp/rubygen/framing.0-10/MethodBodyConstVisitor.rb b/cpp/rubygen/framing.0-10/MethodBodyConstVisitor.rb
index f9ef95f5a0..d784e589df 100755
--- a/cpp/rubygen/framing.0-10/MethodBodyConstVisitor.rb
+++ b/cpp/rubygen/framing.0-10/MethodBodyConstVisitor.rb
@@ -1,4 +1,22 @@
#!/usr/bin/env ruby
+#
+# 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 .. in load path
require 'cppgen'
diff --git a/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb b/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb
index a74b0c06d6..00962de4f9 100755
--- a/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb
+++ b/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb
@@ -1,4 +1,22 @@
#!/usr/bin/env ruby
+#
+# 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 .. in load path
require 'cppgen'
@@ -12,18 +30,19 @@ class MethodBodyDefaultVisitorGen < CppGen
def generate()
h_file(@filename) {
include "qpid/framing/MethodBodyConstVisitor"
+ include "qpid/CommonImportExport.h"
namespace(@namespace) {
genl "class AMQMethodBody;"
cpp_class(@classname, "public MethodBodyConstVisitor") {
genl "public:"
genl "virtual void defaultVisit(const AMQMethodBody&) = 0;"
@amqp.methods_.each { |m|
- genl "virtual void visit(const #{m.body_name}&);" }
+ genl "QPID_COMMON_EXTERN virtual void visit(const #{m.body_name}&);" }
}}}
cpp_file(@filename) {
include(@filename)
- include("all_method_bodies.h")
+ include("qpid/framing/all_method_bodies.h")
namespace(@namespace) {
@amqp.methods_.each { |m|
genl "void #{@classname}::visit(const #{m.body_name}& b) { defaultVisit(b); }"
diff --git a/cpp/rubygen/framing.0-10/MethodBodyFactory.rb b/cpp/rubygen/framing.0-10/MethodBodyFactory.rb
new file mode 100644
index 0000000000..95c79fd1a4
--- /dev/null
+++ b/cpp/rubygen/framing.0-10/MethodBodyFactory.rb
@@ -0,0 +1,58 @@
+#!/usr/bin/env ruby
+#
+# 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 .. in load path
+require 'cppgen'
+
+class MethodBodyFactoryGen < CppGen
+
+ def initialize(outdir, amqp)
+ super(outdir, amqp)
+ @namespace="qpid::framing"
+ @classname="MethodBodyFactory"
+ @filename="qpid/framing/MethodBodyFactory"
+ end
+
+ def generate()
+ cpp_file(@filename) {
+ include @filename
+ include "qpid/framing/BodyFactory"
+ @amqp.methods_.each { |m| include "qpid/framing/#{m.body_name}" }
+ include "qpid/Exception.h"
+ genl
+ namespace(@namespace) {
+ scope("boost::intrusive_ptr<AMQMethodBody> #{@classname}::create(ClassId c, MethodId m) {") {
+ scope("switch (c) {") {
+ @amqp.classes.each { |c|
+ scope("case #{c.code}: switch(m) {") {
+ c.methods_.each { |m|
+ genl "case #{m.code}: return BodyFactory::create<#{m.body_name}>();"
+ }
+ genl "default: throw Exception(QPID_MSG(\"Invalid method id \" << int(m) << \" for class #{c.name} \"));"
+ }
+ genl "break;"
+ }
+ genl "default: throw Exception(QPID_MSG(\"Invalid class id \" << int(c)));"
+ }
+ }
+ }}
+ end
+end
+
+MethodBodyFactoryGen.new($outdir, $amqp).generate();
diff --git a/cpp/rubygen/framing.0-10/MethodHolder.rb b/cpp/rubygen/framing.0-10/MethodHolder.rb
index 90a9333916..e69de29bb2 100755
--- a/cpp/rubygen/framing.0-10/MethodHolder.rb
+++ b/cpp/rubygen/framing.0-10/MethodHolder.rb
@@ -1,100 +0,0 @@
-#!/usr/bin/env ruby
-$: << ".." # Include .. in load path
-require 'cppgen'
-
-class MethodHolderGen < CppGen
-
- def initialize(outdir, amqp)
- super(outdir, amqp)
- @namespace="qpid::framing"
- @classname="BodyHolder"
- @filename="qpid/framing/BodyHolder"
- end
-
- def gen_max_size()
- # Generate program to generate MaxSize.h
- cpp_file("generate_MaxMethodBodySize_h") {
- include "qpid/framing/AMQHeaderBody"
- include "qpid/framing/AMQContentBody"
- include "qpid/framing/AMQHeartbeatBody"
- @amqp.methods_.each { |m| include "qpid/framing/#{m.body_name}" }
- genl
- include "<algorithm>"
- include "<fstream>"
- genl
- genl "using namespace std;"
- genl "using namespace qpid::framing;"
- genl
- scope("int main(int, char** argv) {") {
- genl "size_t maxSize=0;"
- genl "maxSize=max(maxSize, sizeof(AMQHeaderBody));"
- genl "maxSize=max(maxSize, sizeof(AMQContentBody));"
- genl "maxSize=max(maxSize, sizeof(AMQHeartbeatBody));"
- @amqp.methods_.each { |m|
- genl "maxSize=max(maxSize, sizeof(#{m.body_name}));" }
- gen <<EOS
-ofstream out("qpid/framing/MaxMethodBodySize.h");
-out << "// GENERATED CODE: generated by " << argv[0] << endl;
-out << "namespace qpid{ namespace framing { " << endl;
-out << "const size_t MAX_METHOD_BODY_SIZE=" << maxSize << ";" << endl;
-out << "}}" << endl;
-EOS
- }
- }
- end
-
- def gen_construct
- cpp_file(@filename+"_gen") {
- include @filename
- include "qpid/framing/AMQHeaderBody"
- include "qpid/framing/AMQContentBody"
- include "qpid/framing/AMQHeartbeatBody"
- @amqp.methods_.each { |m| include "qpid/framing/#{m.body_name}" }
- include "qpid/framing/FrameDefaultVisitor.h"
- include "qpid/Exception.h"
- genl
- namespace(@namespace) {
- scope("void #{@classname}::setMethod(ClassId c, MethodId m) {") {
- scope("switch (c) {") {
- @amqp.classes.each { |c|
- scope("case #{c.code}: switch(m) {") {
- c.methods_.each { |m|
- genl "case #{m.code}: blob = in_place<#{m.body_name}>(); break;"
- }
- genl "default: throw Exception(QPID_MSG(\"Invalid method id \" << int(m) << \" for class #{c.name} \"));"
- }
- genl "break;"
- }
- genl "default: throw Exception(QPID_MSG(\"Invalid class id \" << int(c)));"
- }
- }
-
- struct("CopyVisitor", "public FrameDefaultVisitor") {
- genl "using FrameDefaultVisitor::visit;"
- genl "using FrameDefaultVisitor::defaultVisit;"
- genl "BodyHolder& holder;"
- genl "CopyVisitor(BodyHolder& h) : holder(h) {}"
- ["Header", "Content", "Heartbeat"].each { |type|
- genl "void visit(const AMQ#{type}Body& x) { holder=x; }"
- }
- @amqp.methods_.each { |m|
- genl "void visit(const #{m.body_name}& x) { holder=x; }"
- }
- genl "void defaultVisit(const AMQBody&) { assert(0); }"
- }
- genl
-
- scope("void BodyHolder::setBody(const AMQBody& b) {") {
- genl "CopyVisitor cv(*this); b.accept(cv);"
- }
- }}
- end
-
- def generate
- gen_max_size
- gen_construct
- end
-end
-
-MethodHolderGen.new($outdir, $amqp).generate();
-
diff --git a/cpp/rubygen/framing.0-10/Operations.rb b/cpp/rubygen/framing.0-10/Operations.rb
index 4a67df8b92..cd6a363c56 100755
--- a/cpp/rubygen/framing.0-10/Operations.rb
+++ b/cpp/rubygen/framing.0-10/Operations.rb
@@ -1,4 +1,22 @@
#!/usr/bin/env ruby
+#
+# 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.
+#
# Usage: output_directory xml_spec_file [xml_spec_file...]
#
$: << '..'
@@ -97,7 +115,7 @@ EOS
end
end
-OperationsGen.new("client",ARGV[0], $amqp).generate()
-OperationsGen.new("server",ARGV[0], $amqp).generate()
-OperationsGen.new("all",ARGV[0], $amqp).generate()
+OperationsGen.new("client",$outdir, $amqp).generate()
+OperationsGen.new("server",$outdir, $amqp).generate()
+OperationsGen.new("all",$outdir, $amqp).generate()
diff --git a/cpp/rubygen/framing.0-10/OperationsInvoker.rb b/cpp/rubygen/framing.0-10/OperationsInvoker.rb
index 44006207ca..f9b6cac76b 100755
--- a/cpp/rubygen/framing.0-10/OperationsInvoker.rb
+++ b/cpp/rubygen/framing.0-10/OperationsInvoker.rb
@@ -1,4 +1,22 @@
#!/usr/bin/env ruby
+#
+# 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.
+#
# Usage: output_directory xml_spec_file [xml_spec_file...]
#
$: << '..'
@@ -56,7 +74,7 @@ class OperationsInvokerGen < CppGen
public
genl("Invoker(#{target}& target_) : target(target_) {}")
genl "using MethodBodyDefaultVisitor::visit;"
- methods.each { |m| genl "void visit(const #{m.body_name}& body);" }
+ methods.each { |m| genl "QPID_COMMON_EXTERN void visit(const #{m.body_name}& body);" }
}
end
@@ -64,6 +82,7 @@ class OperationsInvokerGen < CppGen
h_file(@filename) {
include "qpid/framing/#{@ops}"
include "qpid/framing/Invoker.h"
+ include "qpid/CommonImportExport.h"
namespace("qpid::framing") {
# AMQP_*Operations invoker.
methods=@amqp.classes.map { |c| visit_methods(c).to_a }.flatten
@@ -93,6 +112,6 @@ class OperationsInvokerGen < CppGen
end
end
-OperationsInvokerGen.new("client",ARGV[0], $amqp).generate()
-OperationsInvokerGen.new("server",ARGV[0], $amqp).generate()
-OperationsInvokerGen.new("all",ARGV[0], $amqp).generate()
+OperationsInvokerGen.new("client",$outdir, $amqp).generate()
+OperationsInvokerGen.new("server",$outdir, $amqp).generate()
+OperationsInvokerGen.new("all",$outdir, $amqp).generate()
diff --git a/cpp/rubygen/framing.0-10/Proxy.rb b/cpp/rubygen/framing.0-10/Proxy.rb
index 71a6b954c6..6e3cb4fd4d 100755
--- a/cpp/rubygen/framing.0-10/Proxy.rb
+++ b/cpp/rubygen/framing.0-10/Proxy.rb
@@ -1,4 +1,22 @@
#!/usr/bin/env ruby
+#
+# 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 .. in load path
require 'cppgen'
@@ -19,14 +37,14 @@ class ProxyGen < CppGen
def inner_class_decl(c)
cname=c.name.caps
- cpp_class(cname, "Proxy") {
+ cpp_class(cname, "public Proxy") {
gen <<EOS
public:
#{cname}(FrameHandler& f) : Proxy(f) {}
static #{cname}& get(#{@classname}& proxy) { return proxy.get#{cname}(); }
EOS
methods_on(c, @chassis).each { |m|
- genl "virtual void #{m.cppname}(#{m.signature.join(",\n ")});"
+ genl "QPID_COMMON_EXTERN virtual void #{m.cppname}(#{m.signature.join(",\n ")});"
genl
}}
end
@@ -48,10 +66,12 @@ EOS
include "qpid/framing/Array.h"
include "qpid/framing/amqp_types.h"
include "qpid/framing/amqp_structs.h"
+ include "qpid/CommonImportExport.h"
+
namespace("qpid::framing") {
cpp_class(@classname, "public Proxy") {
public
- genl "#{@classname}(FrameHandler& out);"
+ genl "QPID_COMMON_EXTERN #{@classname}(FrameHandler& out);"
genl
@amqp.classes.each { |c|
inner_class_decl(c)
@@ -66,7 +86,7 @@ EOS
# .cpp file
cpp_file(@filename) {
include "<sstream>"
- include "#{@classname}.h"
+ include "qpid/framing/#{@classname}.h"
include "qpid/framing/amqp_types_full.h"
methods_on(@amqp, @chassis).each {
|m| include "qpid/framing/"+m.body_name
@@ -74,7 +94,7 @@ EOS
genl
namespace("qpid::framing") {
genl "#{@classname}::#{@classname}(FrameHandler& f) :"
- gen " Proxy(f)"
+ gen " Proxy(f)"
@amqp.classes.each { |c| gen ",\n "+proxy_member(c)+"(f)" }
genl "{}\n"
@amqp.classes.each { |c| inner_class_defn(c) }
diff --git a/cpp/rubygen/framing.0-10/Session.rb b/cpp/rubygen/framing.0-10/Session.rb
index 9f54ad1675..61f0e03a8b 100644..100755
--- a/cpp/rubygen/framing.0-10/Session.rb
+++ b/cpp/rubygen/framing.0-10/Session.rb
@@ -1,17 +1,38 @@
#!/usr/bin/env ruby
+#
+# 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.
+#
# Usage: output_directory xml_spec_file [xml_spec_file...]
#
$: << '..'
require 'cppgen'
class CppGen
- def session_methods
+ def session_methods(sync_default)
excludes = ["connection", "session", "file", "stream"]
gen_methods=@amqp.methods_on(@chassis).reject { |m|
excludes.include? m.parent.name or m.body_name.include?("010")
}
+ gen_methods.each { |m| m.set_sync_default(sync_default) }
end
+
+ # Generates a doxygen comment for AmqpMethod m.
def doxygen(m)
doxygen_comment {
genl m.doc
@@ -34,9 +55,9 @@ module SyncAsync
def decl_ctor_opeq()
genl
- genl "#{@classname}();"
- genl "#{@classname}(const #{@version_base}& other);"
- genl "#{@classname}& operator=(const #{@version_base}& other);"
+ genl "QPID_CLIENT_EXTERN #{@classname}();"
+ genl "QPID_CLIENT_EXTERN #{@classname}(const #{@version_base}& other);"
+ genl "QPID_CLIENT_EXTERN #{@classname}& operator=(const #{@version_base}& other);"
end
def defn_ctor_opeq(inline="")
@@ -50,23 +71,35 @@ module SyncAsync
genl "return *this;"
}
end
+
+ def sync_default() !@async end
end
class ContentField # For extra content parameters
def cppname() "content" end
- def signature() "const MethodContent& content" end
- def sig_default() signature+"="+"DefaultContent(std::string())" end
- def unpack() "p[arg::content|DefaultContent(std::string())]"; end
+ def signature() "const Message& content" end
+ def sig_default() signature+"="+"Message(std::string())" end
+ def unpack() "p[arg::content|Message(std::string())]"; end
def doc() "Message content"; end
end
+class SyncField # For extra sync parameters
+ def initialize(default_value) @default_value=default_value ? "true" : "false" end
+ def cppname() "sync" end
+ def signature() "bool sync" end
+ def sig_default() signature+"="+@default_value end
+ def unpack() "p[arg::sync|#{@default_value}]"; end
+ def doc() "If true the broker will respond with completion status as soon as possible."; end
+end
+
class AmqpField
def unpack() "p[arg::#{cppname}|#{default_value}]"; end
def sig_default() signature+"="+default_value; end
end
class AmqpMethod
- def fields_c() content ? fields+[ContentField.new] : fields end
+ def set_sync_default(sync_default) @sync_default=sync_default end
+ def fields_c() result = fields + (content ? [ContentField.new] : []) + [SyncField.new(@sync_default)] end
def param_names_c() fields_c.map { |f| f.cppname} end
def signature_c() fields_c.map { |f| f.signature }; end
def sig_c_default() fields_c.map { |f| f.sig_default }; end
@@ -103,8 +136,10 @@ class SessionNoKeywordGen < CppGen
end
def generate()
+ public_api("#{@file}.h")
h_file(@file) {
include "qpid/client/#{@version_base}.h"
+ include "qpid/client/ClientImportExport.h"
namespace(@namespace) {
doxygen_comment {
genl "AMQP #{@amqp.version} #{sync_adjective} session API."
@@ -114,31 +149,36 @@ class SessionNoKeywordGen < CppGen
cpp_class(@classname, "public #{@version_base}") {
public
decl_ctor_opeq()
- session_methods.each { |m|
+ session_methods(sync_default).each { |m|
genl
doxygen(m)
args=m.sig_c_default.join(", ")
- genl "#{m.return_type(@async)} #{m.session_function}(#{args});"
+ genl "QPID_CLIENT_EXTERN #{m.return_type(@async)} #{m.session_function}(#{args});"
}
}
}}
cpp_file(@file) {
- include @classname
+ include "qpid/client/#{@classname}"
include "qpid/framing/all_method_bodies.h"
+ include "qpid/client/SessionImpl.h"
+ include "qpid/client/MessageImpl.h"
+ include "qpid/client/PrivateImplRef.h"
+ include "qpid/client/CompletionImpl.h"
+ include "<boost/intrusive_ptr.hpp>"
namespace(@namespace) {
genl "using namespace framing;"
- session_methods.each { |m|
+ session_methods(sync_default).each { |m|
genl
sig=m.signature_c.join(", ")
func="#{@classname}::#{m.session_function}"
scope("#{m.return_type(@async)} #{func}(#{sig}) {") {
args=(["ProtocolVersion(#{@amqp.major},#{@amqp.minor})"]+m.param_names).join(", ")
genl "#{m.body_name} body(#{args});";
- genl "body.setSync(#{@async ? 'false':'true'});"
+ genl "body.setSync(sync);"
sendargs="body"
- sendargs << ", content" if m.content
- async_retval="#{m.return_type(true)}(impl->send(#{sendargs}), impl)"
+ sendargs << ", *MessageImpl::get(content)" if m.content
+ async_retval="#{m.return_type(true)}(new CompletionImpl(impl->send(#{sendargs}), impl))"
if @async then
genl "return #{async_retval};"
else
@@ -180,9 +220,10 @@ class SessionGen < CppGen
end
def generate()
- keyword_methods=session_methods.reject { |m| m.fields_c.empty? }
+ keyword_methods=session_methods(sync_default).reject { |m| m.fields_c.empty? }
max_arity = keyword_methods.map{ |m| m.fields_c.size }.max
+ public_api("qpid/client/arg.h")
h_file("qpid/client/arg.h") {
# Generate keyword tag declarations.
genl "#define BOOST_PARAMETER_MAX_ARITY #{max_arity}"
@@ -192,10 +233,11 @@ class SessionGen < CppGen
genl "BOOST_PARAMETER_KEYWORD(keyword_tags, #{k})"
}}
}
-
+ public_api("#{@fqclass.file}.h")
h_file(@fqclass.file) {
include @fqbase.file
include "qpid/client/arg"
+ include "qpid/client/ClientImportExport"
namespace("qpid::client") {
# Doxygen comment.
doxygen_comment {
@@ -219,6 +261,136 @@ which provides the same set of functions using normal non-keyword
declarations.
\\ingroup clientapi
+
+
+\\details
+
+<h2>Publishing Messages</h2>
+<ul>
+<li><p>messageTransfer()</p>
+<pre>session.messageTransfer(arg::content=message, arg::destination="amq.topic");</pre></li>
+<li><p>messageTransfer() &mdash; asynchronous</p>
+<pre>#include &lt;qpid/client/AsyncSession.h>
+
+for (int i=0; i&lt;10; i++) {
+ message.setData(message_data.str());
+ async(session).messageTransfer(arg::content=message, arg::destination="amq.direct");
+}
+
+session.sync();
+</pre>
+</li>
+</ul>
+
+<h2>Exchanges</h2>
+<ul>
+<li><p>exchangeBind()</p>
+<pre>session.exchangeBind(arg::exchange="amq.topic", arg::queue=queue, arg::bindingKey=routing_key);</pre>
+</li>
+<li><p>exchangeUnbind()</p>
+<pre>session.exchangeUnBind(arg::exchange="amq.topic", arg::queue=queue, arg::bindingKey=routing_key);</pre></li>
+<li><p>exchangeBound()</p>
+<pre>if (session.exchangeBound(arg::exchange="amq.topic", arg::queue=queue, arg::bindingKey=rk)){...}</pre>
+<pre>if (session.exchangeBound(arg::exchange="amq.topic", arg::queue=queue)){...}</pre>
+</li>
+<li><p>exchangeDeclare()</p>
+<pre>session.exchangeDeclare(arg::exchange="my.topic", arg::type="topic");</pre>
+<pre>session.exchangeDeclare(arg::exchange="xml", arg::type="xml");</pre>
+</li>
+<li><p>exchangeDelete()</p>
+<pre>session.exchangeDeclare(arg::exchange="my.topic");</pre>
+<pre>session.exchangeDeclare(arg::exchange="xml", arg::ifUnused=true);</pre>
+</li>
+<li><p>exchangeQuery()</p>
+<pre>ExchangeQueryResult eqr = session.exchangeQuery(arg::exchange="my.topic");</pre></li>
+</ul>
+
+
+<h2>Configuring exchanges in session.exchangeDeclare</h2>
+
+<pre>arg::durable=true</pre>
+<p>Default: false.</p>
+<p>If durable=true, an exchange remains active even if the server is restarted. If durable=false, an exchange is purged when a server restarts.</p>
+
+<pre>arg::autoDelete=true</pre>
+<p>Default: false.</p>
+<p>If autoDelete=true, deleting the last binding for an exchange also deletes the exchange.</p>
+
+<pre>arg::alternatExchange="my.exchange"</pre>
+<p>Default: none.</p>
+<p>If an alternate exchange is specified, messages that can not be delivered to any queue are sent to the alternate exchange.</p>
+
+<h2>Queues</h2>
+<ul>
+<li><p>queueDeclare()</p>
+<pre>session.queueDeclare(arg::queue="message_queue");</pre>
+</li>
+<li><p>queueDelete()</p>
+<pre>session.queueDelete(arg::queue="message_queue");</pre></li>
+<li><p>queuePurge()</p>
+<pre>session.queuePurge(arg::queue="message_queue");</pre></li>
+<li><p>queueQuery()</p>
+<pre>QueueQueryResult qqr = session.queueQuery(arg::queue="message_queue");</pre></li>
+</ul>
+
+
+<h2>Configuring queues with session.queueDeclare</h2>
+<pre>arg::durable=true</pre>
+<p>Default: false.</p>
+<p>If durable=true, a queue remains active if the server is restarted. If durable=false, a queue and its contents are lost when a server restarts.</p>
+<br/>
+
+<pre>arg::autoDelete=true</pre>
+<p>Default: false.</p>
+<p>If autoDelete=true, the queue is deleted when the last active Subscription to the Queue is canceled.</p>
+<br/>
+
+<pre>arg::exclusive=true</pre>
+<p>Default: false.</p>
+<p>If exclusive=true, only the Session that created a queue can access it.</p>
+<br/>
+
+<pre>arg::alternateExchange="my.exchange"</pre>
+<p>Default: none. </p>
+<p>If an alternate exchange is specified, messages are routed to it if (1) they are rejected by a client, or (2) they remain on the queue when it is deleted.</p>
+<br/>
+
+
+<h2>Accepting, Acquiring, Rejecting, or Releasing Messages</h2>
+<ul>
+<li><p>messageAccept() &mdash; acknowledges messages</p>
+<pre>SequenceSet tobeAccepted;
+toAccepted.add(msg.getId());
+session.messageAccept(toBeAccepted);</pre>
+</li>
+<li><p>messageAcquire()</p>
+<pre>SequenceSet tobeAcquired;
+toBeAcquired.add(msg.getId());
+session.messageAcquire(toBeAcquired);</pre>
+</li>
+<li><p>messageReject()</p>
+<pre>SequenceSet tobeRejected;
+toRejected.add(msg.getId());
+session.messageReject(toBeRejected);</pre>
+</li>
+<li><p>messageRelease()</p>
+<pre>SequenceSet tobeReleased;
+toReleased.add(msg.getId());
+session.messageRelease(toBeReleased);</pre></li>
+</ul>
+
+<h2>Transactions</h2>
+<ul>
+<li><p>txSelect()</p>
+<pre>session.txSelect();</pre>
+</li>
+<li><p>txCommit()</p>
+<pre>session.txSelect();</pre></li>
+<li><p>txRollback()</p>
+<pre>session.txRollback();</pre></li>
+</ul>
+
+
EOS
}
# Session class.
@@ -238,8 +410,8 @@ EOS
end
end
-SessionNoKeywordGen.new(ARGV[0], $amqp, true).generate()
-SessionNoKeywordGen.new(ARGV[0], $amqp, false).generate()
-SessionGen.new(ARGV[0], $amqp, true).generate()
-SessionGen.new(ARGV[0], $amqp, false).generate()
+SessionNoKeywordGen.new($outdir, $amqp, true).generate()
+SessionNoKeywordGen.new($outdir, $amqp, false).generate()
+SessionGen.new($outdir, $amqp, true).generate()
+SessionGen.new($outdir, $amqp, false).generate()
diff --git a/cpp/rubygen/framing.0-10/all_method_bodies.rb b/cpp/rubygen/framing.0-10/all_method_bodies.rb
index 5971d49189..4c7fccfff5 100755
--- a/cpp/rubygen/framing.0-10/all_method_bodies.rb
+++ b/cpp/rubygen/framing.0-10/all_method_bodies.rb
@@ -1,4 +1,22 @@
#!/usr/bin/env ruby
+#
+# 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 .. in load path
require 'cppgen'
diff --git a/cpp/rubygen/framing.0-10/constants.rb b/cpp/rubygen/framing.0-10/constants.rb
index 7f026a3e54..5c1c1047f7 100755
--- a/cpp/rubygen/framing.0-10/constants.rb
+++ b/cpp/rubygen/framing.0-10/constants.rb
@@ -1,4 +1,22 @@
#!/usr/bin/env ruby
+#
+# 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 .. in load path
require 'cppgen'
@@ -11,8 +29,10 @@ class ConstantsGen < CppGen
end
def constants_h()
- h_file("#{@dir}/constants") {
- namespace(@namespace) {
+ public_api("#{@dir}/constants.h")
+ h_file("#{@dir}/constants.h") {
+ namespace(@namespace) {
+ # Constants for class/method names.
scope("enum AmqpConstant {","};") {
l=[]
l.concat @amqp.constants.map { |c| "#{c.name.shout}=#{c.value}" }
@@ -23,53 +43,137 @@ class ConstantsGen < CppGen
}
genl l.join(",\n")
}
- define_constants_for(@amqp.domain("segment-type").enum)
- namespace("execution") {
- define_constants_for(@amqp.class_("execution").domain("error-code").enum)
+ }
+ }
+ end
+
+ def typecode_enum(t) "TYPE_CODE_#{t.name.shout}" end
+
+ def typecode_h_cpp
+ path="#{@dir}/TypeCode"
+ public_api(path+".h")
+ h_file(path) {
+ include("<iosfwd>")
+ include("\"qpid/sys/IntegerTypes.h\"")
+ namespace(@namespace) {
+ scope("enum TypeCode {", "};") {
+ genl @amqp.types.map { |t| "#{typecode_enum t} = #{t.code}" if t.code }.compact.join(",\n")
}
- namespace("connection") {
- define_constants_for(@amqp.class_("connection").domain("close-code").enum)
+ genl <<EOS
+
+/** True if t is a valid TypeCode value */
+bool isTypeCode(uint8_t t);
+
+/** Throw exception if not a valid TypeCode */
+TypeCode typeCode(uint8_t);
+
+/**@return 0 if t is not a valid enum TypeCode value. */
+const char* typeName(TypeCode t);
+
+std::ostream& operator<<(std::ostream&, TypeCode);
+EOS
+ }
+ }
+
+ cpp_file(path) {
+ include(path);
+ include("qpid/Exception.h")
+ include("<ostream>")
+ namespace(@namespace) {
+ scope("const char* typeName(TypeCode t) {") {
+ scope("switch (t) {") {
+ @amqp.types.each { |t| genl "case #{typecode_enum t}: return \"#{t.name}\";" if t.code }
+ genl "default: break;"
+ }
+ genl "return 0;";
}
- namespace("session") {
- define_constants_for(@amqp.class_("session").domain("detach-code").enum)
+ genl <<EOS
+
+bool isTypeCode(uint8_t t) { return typeName(TypeCode(t)); }
+
+TypeCode typeCode(uint8_t t) {
+ if (!isTypeCode(t)) throw Exception(QPID_MSG("Invalid TypeCode " << t));
+ return TypeCode(t);
+}
+
+std::ostream& operator<<(std::ostream& o, TypeCode t) {
+ if (isTypeCode(t)) return o << typeName(t);
+ else return o << "Invalid TypeCode " << t;
+}
+EOS
+ }
+ }
+ end
+
+ def enum_h()
+ public_api("#{@dir}/enum.h")
+ h_file("#{@dir}/enum.h") {
+ # Constants for enum domains.
+ namespace(@namespace) {
+ @amqp.domains.each { |d| declare_enum(d.enum) if d.enum }
+ @amqp.classes.each { |c|
+ enums=c.collect_all(AmqpEnum)
+ if !enums.empty? then
+ namespace(c.nsname) { enums.each { |e| declare_enum(e) } }
+ end
}
- define_constants_for(@amqp.class_("dtx").domain("xa-status").enum)
}
}
end
- def define_constants_for(enum)
- scope("enum #{enum.parent.name.caps} {","};") {
- genl enum.choices.collect { |c| "#{c.name.shout}=#{c.value}" }.join(",\n")
+ def declare_enum(enum)
+ # Generated like this: enum containing_class::Foo { FOO_X, FOO_Y; }
+ name="#{enum.parent.name.caps}"
+ prefix=enum.parent.name.shout+"_"
+ scope("enum #{name} {","};") {
+ genl enum.choices.collect { |c| "#{prefix}#{c.name.shout}=#{c.value}" }.join(",\n")
}
end
- def define_exception(c, base, package)
- name=c.name.caps+"Exception"
- genl
- doxygen_comment { genl c.doc }
- struct(c.name.caps+"Exception", base) {
+ def declare_exception(c, base, package, enum)
+ name=c.name.caps+"Exception"
+ value="#{package}::#{enum.parent.name.shout}_#{c.name.shout}"
+ genl
+ doxygen_comment { genl c.doc }
+ struct(c.name.caps+"Exception", base) {
genl "std::string getPrefix() const { return \"#{c.name}\"; }"
- genl "#{c.name.caps}Exception(const std::string& msg=std::string()) : #{base}(#{c.value}, \"\"+msg) {}"
- }
+ genl "#{c.name.caps}Exception(const std::string& msg=std::string()) : #{base}(#{value}, \"\"+msg) {}"
+ }
end
- def define_exceptions_for(class_name, domain_name, base)
+ def declare_exceptions(class_name, domain_name, base)
enum = @amqp.class_(class_name).domain(domain_name).enum
- enum.choices.each { |c| define_exception(c, base, class_name) unless c.name == "normal" }
+ enum.choices.each { |c| declare_exception(c, base, class_name, enum) unless c.name == "normal" }
+ genl
+ genl "QPID_COMMON_EXTERN sys::ExceptionHolder create#{base}(int code, const std::string& text);"
+ end
+
+ def create_exception(class_name, domain_name, base, invalid)
+ scope("sys::ExceptionHolder create#{base}(int code, const std::string& text) {") {
+ genl "sys::ExceptionHolder holder;"
+ scope("switch (code) {") {
+ enum = @amqp.class_(class_name).domain(domain_name).enum
+ enum.choices.each { |c|
+ assign = "holder = new #{c.name.caps}Exception(text); " unless c.name == "normal"
+ genl "case #{c.value}: #{assign}break;"
+ }
+ genl "default: holder = new #{invalid}(QPID_MSG(\"Bad #{enum.parent.name}: \" << code << \": \" << text));"
+ }
+ genl "return holder;"
+ }
end
def reply_exceptions_h()
- h_file("#{@dir}/reply_exceptions") {
+ public_api("#{@dir}/reply_exceptions.h")
+ h_file("#{@dir}/reply_exceptions.h") {
include "qpid/Exception"
include "qpid/sys/ExceptionHolder"
+ include "qpid/framing/enum"
+ include "qpid/CommonImportExport.h"
namespace(@namespace) {
- define_exceptions_for("execution", "error-code", "SessionException")
- define_exceptions_for("connection", "close-code", "ConnectionException")
- define_exceptions_for("session", "detach-code", "ChannelException")
- genl
- genl "void throwExecutionException(int code, const std::string& text);"
- genl "void setExecutionException(sys::ExceptionHolder& holder, int code, const std::string& text);"
+ declare_exceptions("execution", "error-code", "SessionException")
+ declare_exceptions("connection", "close-code", "ConnectionException")
+ declare_exceptions("session", "detach-code", "ChannelException")
}
}
end
@@ -80,29 +184,21 @@ class ConstantsGen < CppGen
include "<sstream>"
include "<assert.h>"
namespace("qpid::framing") {
- scope("void throwExecutionException(int code, const std::string& text) {"){
- genl "sys::ExceptionHolder h;"
- genl "setExecutionException(h, code, text);"
- genl "h.raise();"
- }
- scope("void setExecutionException(sys::ExceptionHolder& holder, int code, const std::string& text) {"){
- scope("switch (code) {") {
- enum = @amqp.class_("execution").domain("error-code").enum
- enum.choices.each { |c|
- genl "case #{c.value}: holder = new #{c.name.caps}Exception(text); break;"
- }
- genl 'default: assert(0);'
- genl ' holder = new InvalidArgumentException(QPID_MSG("Bad exception code: " << code << ": " << text));'
- }
- }
+ create_exception("execution", "error-code", "SessionException", "InvalidArgumentException")
+ # FIXME aconway 2008-10-07: there are no good exception codes in 0-10 for an invalid code.
+ # The following choices are arbitrary.
+ create_exception("connection", "close-code", "ConnectionException", "FramingErrorException")
+ create_exception("session", "detach-code", "ChannelException", "NotAttachedException")
}
}
end
def generate()
constants_h
+ enum_h
reply_exceptions_h
reply_exceptions_cpp
+ typecode_h_cpp
end
end
diff --git a/cpp/rubygen/framing.0-10/frame_body_lists.rb b/cpp/rubygen/framing.0-10/frame_body_lists.rb
index b20e4550f3..4f1b976032 100644
--- a/cpp/rubygen/framing.0-10/frame_body_lists.rb
+++ b/cpp/rubygen/framing.0-10/frame_body_lists.rb
@@ -1,3 +1,21 @@
+#
+# 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 .. in load path
require 'cppgen'
@@ -26,6 +44,6 @@ EOS
end
end
-FrameBodyListsGen.new(ARGV[0], $amqp).generate;
+FrameBodyListsGen.new($outdir, $amqp).generate;
diff --git a/cpp/rubygen/framing.0-10/structs.rb b/cpp/rubygen/framing.0-10/structs.rb
index e4d57ca75d..c3684aea66 100644..100755
--- a/cpp/rubygen/framing.0-10/structs.rb
+++ b/cpp/rubygen/framing.0-10/structs.rb
@@ -1,4 +1,22 @@
#!/usr/bin/env ruby
+#
+# 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.
+#
# Usage: output_directory xml_spec_file [xml_spec_file...]
#
$: << '..'
@@ -26,6 +44,12 @@ class StructGen < CppGen
"timestamp"=>8
}
+ StringSizeMap={
+ "LongString"=>4,
+ "MediumString"=>2,
+ "ShortString"=>1
+ }
+
SizeType={
1=>"Octet",
2=>"Short",
@@ -153,13 +177,10 @@ class StructGen < CppGen
genl "total += #{size};//#{f.cppname}"
elsif (f.cpptype.name == "SequenceNumberSet")
genl "total += #{f.cppname}.encodedSize();"
- else
- encoded = f.cpptype.encoded
- gen "total += ("
- gen "4 + " if encoded == "LongString"
- gen "2 + " if encoded == "MediumString"
- gen "1 + " if encoded == "ShortString"
- genl "#{f.cppname}.size());"
+ elsif (size = StringSizeMap[f.cpptype.encoded])
+ genl "total += #{size} + #{f.cppname}.size();"
+ else
+ genl "total += #{f.cppname}.encodedSize();"
end
end
end
@@ -212,6 +233,7 @@ class StructGen < CppGen
using AMQMethodBody::accept;
void accept(MethodBodyConstVisitor& v) const { v.visit(*this); }
+ boost::intrusive_ptr<AMQBody> clone() const { return BodyFactory::copy(*this); }
ClassId amqpClassId() const { return CLASS_ID; }
MethodId amqpMethodId() const { return METHOD_ID; }
@@ -329,15 +351,15 @@ EOS
end
def declare_packed_accessors(f)
- genl "void set#{f.name.caps}(#{f.cpptype.param} _#{f.cppname});";
- genl "#{f.cpptype.ret} get#{f.name.caps}() const;"
+ genl "QPID_COMMON_EXTERN void set#{f.name.caps}(#{f.cpptype.param} _#{f.cppname});";
+ genl "QPID_COMMON_EXTERN #{f.cpptype.ret} get#{f.name.caps}() const;"
if (f.cpptype.name == "FieldTable")
- genl "#{f.cpptype.name}& get#{f.name.caps}();"
+ genl "QPID_COMMON_EXTERN #{f.cpptype.name}& get#{f.name.caps}();"
end
if (f.type_ != "bit")
#extra 'accessors' for packed fields:
- genl "bool has#{f.name.caps}() const;"
- genl "void clear#{f.name.caps}Flag();"
+ genl "QPID_COMMON_EXTERN bool has#{f.name.caps}() const;"
+ genl "QPID_COMMON_EXTERN void clear#{f.name.caps}Flag();"
end
end
@@ -359,9 +381,11 @@ EOS
else
inheritance = ": public AMQMethodBody"
end
+ else
+ public_api("qpid/framing/#{classname}.h") # Non-method structs are public
end
- h_file("qpid/framing/#{classname}.h") {
+ h_file("qpid/framing/#{classname}.h") {
if (s.kind_of? AmqpMethod)
gen <<EOS
#include "qpid/framing/AMQMethodBody.h"
@@ -377,6 +401,7 @@ EOS
#include <ostream>
#include "qpid/framing/amqp_types_full.h"
+#include "qpid/CommonImportExport.h"
namespace qpid {
namespace framing {
@@ -416,17 +441,17 @@ EOS
methodbody_extra_defs(s)
end
if (s.kind_of? AmqpStruct)
- indent {genl "friend std::ostream& operator<<(std::ostream&, const #{classname}&);" }
+ indent {genl "QPID_COMMON_EXTERN friend std::ostream& operator<<(std::ostream&, const #{classname}&);" }
end
gen <<EOS
- void encode(Buffer&) const;
- void decode(Buffer&, uint32_t=0);
- void encodeStructBody(Buffer&) const;
- void decodeStructBody(Buffer&, uint32_t=0);
- uint32_t size() const;
- uint32_t bodySize() const;
- void print(std::ostream& out) const;
+ QPID_COMMON_EXTERN void encode(Buffer&) const;
+ QPID_COMMON_EXTERN void decode(Buffer&, uint32_t=0);
+ QPID_COMMON_EXTERN void encodeStructBody(Buffer&) const;
+ QPID_COMMON_EXTERN void decodeStructBody(Buffer&, uint32_t=0);
+ QPID_COMMON_EXTERN uint32_t encodedSize() const;
+ QPID_COMMON_EXTERN uint32_t bodySize() const;
+ QPID_COMMON_EXTERN void print(std::ostream& out) const;
}; /* class #{classname} */
}}
@@ -439,9 +464,8 @@ EOS
buffer = "/*buffer*/"
end
gen <<EOS
-#include "#{classname}.h"
-
-#include "reply_exceptions.h"
+#include "qpid/framing/#{classname}.h"
+#include "qpid/framing/reply_exceptions.h"
using namespace qpid::framing;
@@ -528,8 +552,7 @@ EOS
return total;
}
-uint32_t #{classname}::size() const
-{
+uint32_t #{classname}::encodedSize() const {
uint32_t total = bodySize();
EOS
if (s.kind_of? AmqpStruct)
@@ -583,9 +606,10 @@ EOS
structs.each { |s| define_struct(s) }
@amqp.methods_.each { |m| define_struct(m) }
#generate a single include file containing the list of structs for convenience
- h_file("qpid/framing/amqp_structs.h") { structs.each { |s| genl "#include \"#{s.cppname}.h\"" } }
+ public_api("qpid/framing/amqp_structs.h")
+ h_file("qpid/framing/amqp_structs.h") { structs.each { |s| genl "#include \"qpid/framing/#{s.cppname}.h\"" } }
end
end
-StructGen.new(ARGV[0], $amqp).generate()
+StructGen.new($outdir, $amqp).generate()
diff --git a/cpp/rubygen/generate b/cpp/rubygen/generate
index 9acbd4fe83..89b9b99520 100755
--- a/cpp/rubygen/generate
+++ b/cpp/rubygen/generate
@@ -1,4 +1,22 @@
#!/usr/bin/env ruby
+#
+# 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.
+#
require 'pathname'
require 'amqpgen'
@@ -7,14 +25,14 @@ require 'amqpgen'
#
if ARGV.size < 3
puts <<EOS
-Usage: #{ARGV[0]} OUTDIR SPEC.xml [ ... ] TEMPLATE.rb [ ... ]
-or: #{ARGV[0]} OUTDIR SPEC.xml [ ... ] all [ makefragment.mk ]
+Usage: #{ARGV[0]} SRCDIR APIDIR SPEC.xml [ ... ] TEMPLATE.rb [ ... ]
+or: #{ARGV[0]} SRCDIR APIDIR SPEC.xml [ ... ] all [ makefragment.mk | makefragment.cmake ]
Parse all SPEC.xml files to create an AMQP model, run each TEMPLATE
-putting the resulting files under OUTDIR. Prints a list of files
-generated to standard output.
+putting the resulting files under SRCDIR, public API files in APIdir.
+Prints a list of files generated to standard output.
-If OUTDIR is '-' then just prints file list without generating files.
+If SRCDIR and APIDIR are '-' then just prints file list without generating files.
EOS
exit 1
end
@@ -39,15 +57,16 @@ gendir=File.dirname(__FILE__)
if ARGV.any? { |arg| arg=="all" }
templates=Dir["#{gendir}/*/*.rb"]
else
- templates=ARGV.grep(/\.rb$/)
+templates=ARGV.grep(/\.rb$/)
ARGV.each { |arg|
d=File.join gendir,arg
templates += Dir["#{d}/*.rb"] if File.directory? d
}
end
-$outdir=ARGV[0]
+$outdir=[ ARGV[0], ARGV[1] ]
$models=parse_specs(ARGV.grep(/\.xml$/))
+
templates.each { |t|
ver=Pathname.new(t).dirname.basename.to_s.split('.')[-1]
$amqp=$models[ver]
@@ -58,50 +77,84 @@ templates.each { |t|
end
}
+def cmake_continue(lines) lines.join(" \n "); end
def make_continue(lines) lines.join(" \\\n "); end
# Generate makefile
makefile=ARGV.grep(/.mk$/)[0]
-if makefile
+cmakefile=ARGV.grep(/.cmake$/)[0]
+if cmakefile || makefile
+ srcdir,apidir=$outdir
dir=Dir.getwd
Dir.chdir File.dirname(__FILE__)
generator_files=Dir["**/*.rb"] << File.basename(__FILE__)
Dir.chdir dir
rgen_generator=generator_files.map{ |f| "$(rgen_dir)/#{f}" }
- rgen_srcs=GenFiles.get.map{ |f| "#{$outdir}/#{f}" }
+ cmake_rgen_generator=generator_files.map{ |f| "${rgen_dir}/#{f}" }
+ rgen_srcs=GenFiles.get.map{ |f| "#{GenFiles.public_api?(f) ? apidir : srcdir}/#{f}" }
rgen_subdirs={}
rgen_srcs.each { |src|
- if src.match(%r{#{$outdir}/qpid/([^/]+)/})
- subdir=$1
+ if src.match(%r{(#{srcdir}|#{apidir})/qpid/([^/]+)/})
+ subdir=$2
rgen_subdirs[subdir] ||= []
rgen_subdirs[subdir] << src
end
}
- File.open(makefile, 'w') { |out|
- out << <<EOS
+ if (makefile)
+ File.open(makefile, 'w') { |out|
+ out << <<EOS
# Generated makefile fragment.
# Including makefile defines $(rgen_dir) $(rgen_cmd) and $(specs).
rgen_generator=#{make_continue rgen_generator}
EOS
- rgen_subdirs.each_key { |subdir|
- out << "\nrgen_#{subdir}_srcs = #{make_continue(rgen_subdirs[subdir])}\n"
- }
- out << <<EOS
+ rgen_subdirs.each_key { |subdir|
+ out << "\nrgen_#{subdir}_srcs = #{make_continue(rgen_subdirs[subdir])}\n"
+ }
+ out << <<EOS
rgen_srcs=#{make_continue rgen_srcs}
# Header file install rules.
EOS
- ["amqp_0_10", "framing", "client/no_keyword","client", "broker"].each { |ns|
- dir="qpid/#{ns}"
- dir_ = dir.tr("/", "_")
- regex=%r|#{dir}/[^/]+\.h$|
- out << <<EOS
+ ["amqp_0_10", "framing", "client/no_keyword","client", "broker"].each { |ns|
+ dir="qpid/#{ns}"
+ dir_ = dir.tr("/", "_")
+ regex=%r|#{dir}/[^/]+\.h$|
+ out << <<EOS
#{dir_}dir = $(includedir)/#{dir}
dist_#{dir_}_HEADERS = #{make_continue rgen_srcs.grep(regex)}
EOS
- }
- }
-end
+ } # each
+ } # File makefile
+ end # if (makefile)
+ if (cmakefile)
+ File.open(cmakefile, 'w') { |out|
+ out << <<EOS
+# Generated makefile fragment.
+# Including makefile defines ${rgen_dir} ${rgen_cmd} and ${specs}.
+
+set(rgen_generator #{cmake_continue cmake_rgen_generator})
+EOS
+ rgen_subdirs.each_key { |subdir|
+ out << "\nset(rgen_#{subdir}_srcs #{cmake_continue(rgen_subdirs[subdir])})\n"
+ }
+ out << <<EOS
+set(rgen_srcs #{cmake_continue rgen_srcs})
+
+# Header file install rules.
+EOS
+ ["amqp_0_10", "framing", "client/no_keyword","client", "broker"].each { |ns|
+ dir="qpid/#{ns}"
+ dir_ = dir.tr("/", "_")
+ regex=%r|#{dir}/[^/]+\.h$|
+ out << <<EOS
+set(#{dir_}dir \${includedir}/#{dir})
+set(dist_#{dir_}_HEADERS #{cmake_continue rgen_srcs.grep(regex)})
+
+EOS
+ } # each
+ } # File makefile
+ end # if (makefile)
+end