summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpp/examples/messaging/topic_receiver.cpp2
-rw-r--r--cpp/include/qpid/messaging/Address.h2
-rw-r--r--cpp/src/qpid/messaging/Address.cpp69
-rw-r--r--cpp/src/tests/Address.cpp8
-rw-r--r--cpp/src/tests/MessagingSessionTests.cpp28
5 files changed, 72 insertions, 37 deletions
diff --git a/cpp/examples/messaging/topic_receiver.cpp b/cpp/examples/messaging/topic_receiver.cpp
index 6f6c1a5677..45ab9448db 100644
--- a/cpp/examples/messaging/topic_receiver.cpp
+++ b/cpp/examples/messaging/topic_receiver.cpp
@@ -37,7 +37,7 @@ int main(int argc, char** argv) {
try {
Connection connection = Connection::open(url);
Session session = connection.newSession();
- Receiver receiver = session.createReceiver("news_service {filter:[control, " + pattern + "]}");
+ Receiver receiver = session.createReceiver("news_service; {filter:[control, " + pattern + "]}");
while (true) {
Message message = receiver.fetch();
std::cout << "Message: " << message.getContent() << std::endl;
diff --git a/cpp/include/qpid/messaging/Address.h b/cpp/include/qpid/messaging/Address.h
index f255de14f0..eaf5a02782 100644
--- a/cpp/include/qpid/messaging/Address.h
+++ b/cpp/include/qpid/messaging/Address.h
@@ -51,7 +51,7 @@ class AddressImpl;
* All parts of an address can be specified in a string of the
* following form:
*
- * <address> [ / <subject> ] [ { <key> : <value> , ... } ]
+ * <address> [ / <subject> ] ; [ { <key> : <value> , ... } ]
*
* Here the <address> is a simple name for the addressed entity and
* <subject> is a subject or subject pattern for messages sent to or
diff --git a/cpp/src/qpid/messaging/Address.cpp b/cpp/src/qpid/messaging/Address.cpp
index edb1ddc79d..fff7c453b8 100644
--- a/cpp/src/qpid/messaging/Address.cpp
+++ b/cpp/src/qpid/messaging/Address.cpp
@@ -28,6 +28,7 @@ namespace messaging {
namespace {
const std::string SUBJECT_DIVIDER = "/";
+const std::string OPTIONS_DIVIDER = ";";
const std::string SPACE = " ";
const std::string TYPE = "type";
}
@@ -54,18 +55,22 @@ class AddressParser
static const std::string RESERVED;
bool readChar(char c);
- bool readQuotedString(Variant& value);
- bool readString(Variant& value, char delimiter);
- bool readWord(std::string& word);
+ bool readQuotedString(std::string& s);
+ bool readQuotedValue(Variant& value);
+ bool readString(std::string& value, char delimiter);
+ bool readWord(std::string& word, const std::string& delims = RESERVED);
bool readSimpleValue(Variant& word);
bool readKey(std::string& key);
bool readValue(Variant& value);
bool readKeyValuePair(Variant::Map& map);
bool readMap(Variant& value);
bool readList(Variant& value);
+ bool readName(std::string& name);
+ bool readSubject(std::string& subject);
bool error(const std::string& message);
bool eos();
bool iswhitespace();
+ bool in(const std::string& delims);
bool isreserved();
};
@@ -90,7 +95,7 @@ std::string Address::toStr() const
std::stringstream out;
out << impl->name;
if (!impl->subject.empty()) out << SUBJECT_DIVIDER << impl->subject;
- if (!impl->options.empty()) out << " {" << impl->options << "}";
+ if (!impl->options.empty()) out << OPTIONS_DIVIDER << " {" << impl->options << "}";
return out.str();
}
Address::operator bool() const { return !impl->name.empty(); }
@@ -145,22 +150,26 @@ bool AddressParser::error(const std::string& message)
bool AddressParser::parse(Address& address)
{
std::string name;
- if (readWord(name)) {
+ if (readName(name)) {
if (name.find('#') == 0) name = qpid::framing::Uuid(true).str() + name;
address.setName(name);
if (readChar('/')) {
std::string subject;
- if (readWord(subject)) {
+ if (readSubject(subject)) {
address.setSubject(subject);
} else {
return error("Expected subject after /");
}
}
- Variant options = Variant::Map();
- if (readMap(options)) {
- address.setOptions(options.asMap());
+ if (readChar(';')) {
+ Variant options = Variant::Map();
+ if (readMap(options)) {
+ address.setOptions(options.asMap());
+ }
}
- return true;
+ //skip trailing whitespace
+ while (!eos() && iswhitespace()) ++current;
+ return eos() || error("Unexpected chars in address: " + input.substr(current));
} else {
return input.empty() || error("Expected name");
}
@@ -215,11 +224,11 @@ bool AddressParser::readKey(std::string& key)
bool AddressParser::readValue(Variant& value)
{
- return readSimpleValue(value) || readQuotedString(value) ||
+ return readSimpleValue(value) || readQuotedValue(value) ||
readMap(value) || readList(value) || error("Expected value");
}
-bool AddressParser::readString(Variant& value, char delimiter)
+bool AddressParser::readString(std::string& value, char delimiter)
{
if (readChar(delimiter)) {
std::string::size_type start = current++;
@@ -242,9 +251,30 @@ bool AddressParser::readString(Variant& value, char delimiter)
}
}
-bool AddressParser::readQuotedString(Variant& value)
+bool AddressParser::readName(std::string& name)
+{
+ return readQuotedString(name) || readWord(name, "/;");
+}
+
+bool AddressParser::readSubject(std::string& subject)
+{
+ return readQuotedString(subject) || readWord(subject, ";");
+}
+
+bool AddressParser::readQuotedString(std::string& s)
+{
+ return readString(s, '"') || readString(s, '\'');
+}
+
+bool AddressParser::readQuotedValue(Variant& value)
{
- return readString(value, '"') || readString(value, '\'');
+ std::string s;
+ if (readQuotedString(s)) {
+ value = s;
+ return true;
+ } else {
+ return false;
+ }
}
bool AddressParser::readSimpleValue(Variant& value)
@@ -260,14 +290,14 @@ bool AddressParser::readSimpleValue(Variant& value)
}
}
-bool AddressParser::readWord(std::string& value)
+bool AddressParser::readWord(std::string& value, const std::string& delims)
{
//skip leading whitespace
while (!eos() && iswhitespace()) ++current;
//read any number of non-whitespace, non-reserved chars into value
std::string::size_type start = current;
- while (!eos() && !iswhitespace() && !isreserved()) ++current;
+ while (!eos() && !iswhitespace() && !in(delims)) ++current;
if (current > start) {
value = input.substr(start, current - start);
@@ -299,7 +329,12 @@ bool AddressParser::iswhitespace()
bool AddressParser::isreserved()
{
- return RESERVED.find(input.at(current)) != std::string::npos;
+ return in(RESERVED);
+}
+
+bool AddressParser::in(const std::string& chars)
+{
+ return chars.find(input.at(current)) != std::string::npos;
}
bool AddressParser::eos()
diff --git a/cpp/src/tests/Address.cpp b/cpp/src/tests/Address.cpp
index ab4017a788..319710ec24 100644
--- a/cpp/src/tests/Address.cpp
+++ b/cpp/src/tests/Address.cpp
@@ -46,7 +46,7 @@ QPID_AUTO_TEST_CASE(testParseSubject)
QPID_AUTO_TEST_CASE(testParseOptions)
{
- Address address("my-topic {a:bc, x:101, y:'a string'}");
+ Address address("my-topic; {a:bc, x:101, y:'a string'}");
BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName());
BOOST_CHECK_EQUAL(std::string("bc"), address.getOption("a").asString());
BOOST_CHECK_EQUAL((uint16_t) 101, address.getOption("x").asInt64());
@@ -55,7 +55,7 @@ QPID_AUTO_TEST_CASE(testParseOptions)
QPID_AUTO_TEST_CASE(testParseSubjectAndOptions)
{
- Address address("my-topic/my-subject {a:bc, x:101, y:'a string'}");
+ Address address("my-topic/my-subject; {a:bc, x:101, y:'a string'}");
BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName());
BOOST_CHECK_EQUAL(std::string("my-subject"), address.getSubject());
BOOST_CHECK_EQUAL(std::string("bc"), address.getOption("a").asString());
@@ -65,7 +65,7 @@ QPID_AUTO_TEST_CASE(testParseSubjectAndOptions)
QPID_AUTO_TEST_CASE(testParseNestedOptions)
{
- Address address("my-topic {a:{p:202, q:'another string'}, x:101, y:'a string'}");
+ Address address("my-topic; {a:{p:202, q:'another string'}, x:101, y:'a string'}");
BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName());
BOOST_CHECK_EQUAL((uint16_t) 202, address.getOptions()["a"].asMap()["p"].asInt64());
BOOST_CHECK_EQUAL(std::string("another string"), address.getOptions()["a"].asMap()["q"].asString());
@@ -75,7 +75,7 @@ QPID_AUTO_TEST_CASE(testParseNestedOptions)
QPID_AUTO_TEST_CASE(testParseOptionsWithList)
{
- Address address("my-topic {a:[202, 'another string'], x:101}");
+ Address address("my-topic; {a:[202, 'another string'], x:101}");
BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName());
Variant::List& list = address.getOptions()["a"].asList();
Variant::List::const_iterator i = list.begin();
diff --git a/cpp/src/tests/MessagingSessionTests.cpp b/cpp/src/tests/MessagingSessionTests.cpp
index 00a8481c93..6d7f45bc0a 100644
--- a/cpp/src/tests/MessagingSessionTests.cpp
+++ b/cpp/src/tests/MessagingSessionTests.cpp
@@ -248,7 +248,7 @@ QPID_AUTO_TEST_CASE(testSenderError)
MessagingFixture fix;
ScopedSuppressLogging sl;
BOOST_CHECK_THROW(fix.session.createSender("NonExistentAddress"), qpid::messaging::InvalidAddress);
- BOOST_CHECK_THROW(fix.session.createSender("NonExistentAddress {create:receiver, type:queue}"),
+ BOOST_CHECK_THROW(fix.session.createSender("NonExistentAddress; {create:receiver, type:queue}"),
qpid::messaging::InvalidAddress);
}
@@ -257,7 +257,7 @@ QPID_AUTO_TEST_CASE(testReceiverError)
MessagingFixture fix;
ScopedSuppressLogging sl;
BOOST_CHECK_THROW(fix.session.createReceiver("NonExistentAddress"), qpid::messaging::InvalidAddress);
- BOOST_CHECK_THROW(fix.session.createReceiver("NonExistentAddress {create:sender, type:queue}"),
+ BOOST_CHECK_THROW(fix.session.createReceiver("NonExistentAddress; {create:sender, type:queue}"),
qpid::messaging::InvalidAddress);
}
@@ -466,9 +466,9 @@ QPID_AUTO_TEST_CASE(testBrowse)
QueueFixture fix;
Sender sender = fix.session.createSender(fix.queue);
send(sender, 10);
- Receiver browser1 = fix.session.createReceiver(fix.queue + " {browse:true}");
+ Receiver browser1 = fix.session.createReceiver(fix.queue + "; {browse:true}");
receive(browser1, 10);
- Receiver browser2 = fix.session.createReceiver(fix.queue + " {browse:true}");
+ Receiver browser2 = fix.session.createReceiver(fix.queue + "; {browse:true}");
receive(browser2, 10);
Receiver consumer = fix.session.createReceiver(fix.queue);
receive(consumer, 10);
@@ -495,13 +495,13 @@ struct QueueCreatePolicyFixture : public MessagingFixture
QPID_AUTO_TEST_CASE(testCreatePolicyQueueAlways)
{
- QueueCreatePolicyFixture fix("# {create:always, type:queue}");
+ QueueCreatePolicyFixture fix("#; {create:always, type:queue}");
fix.test();
}
QPID_AUTO_TEST_CASE(testCreatePolicyQueueReceiver)
{
- QueueCreatePolicyFixture fix("# {create:receiver, type:queue}");
+ QueueCreatePolicyFixture fix("#; {create:receiver, type:queue}");
Receiver r = fix.session.createReceiver(fix.address);
fix.test();
r.cancel();
@@ -509,7 +509,7 @@ QPID_AUTO_TEST_CASE(testCreatePolicyQueueReceiver)
QPID_AUTO_TEST_CASE(testCreatePolicyQueueSender)
{
- QueueCreatePolicyFixture fix("# {create:sender, type:queue}");
+ QueueCreatePolicyFixture fix("#; {create:sender, type:queue}");
Sender s = fix.session.createSender(fix.address);
fix.test();
s.cancel();
@@ -539,14 +539,14 @@ struct ExchangeCreatePolicyFixture : public MessagingFixture
QPID_AUTO_TEST_CASE(testCreatePolicyTopic)
{
- ExchangeCreatePolicyFixture fix("# {create:always, type:topic, node-properties:{x-amqp0-10-exchange-type:topic}}",
+ ExchangeCreatePolicyFixture fix("#; {create:always, type:topic, node-properties:{x-amqp0-10-exchange-type:topic}}",
"topic");
fix.test();
}
QPID_AUTO_TEST_CASE(testCreatePolicyTopicReceiverFanout)
{
- ExchangeCreatePolicyFixture fix("#/my-subject {create:receiver, type:topic, node-properties:{x-amqp0-10-exchange-type:fanout}}", "fanout");
+ ExchangeCreatePolicyFixture fix("#/my-subject; {create:receiver, type:topic, node-properties:{x-amqp0-10-exchange-type:fanout}}", "fanout");
Receiver r = fix.session.createReceiver(fix.address);
fix.test();
r.cancel();
@@ -554,7 +554,7 @@ QPID_AUTO_TEST_CASE(testCreatePolicyTopicReceiverFanout)
QPID_AUTO_TEST_CASE(testCreatePolicyTopicSenderDirect)
{
- ExchangeCreatePolicyFixture fix("#/my-subject {create:sender, type:topic, node-properties:{x-amqp0-10-exchange-type:direct}}", "direct");
+ ExchangeCreatePolicyFixture fix("#/my-subject; {create:sender, type:topic, node-properties:{x-amqp0-10-exchange-type:direct}}", "direct");
Sender s = fix.session.createSender(fix.address);
fix.test();
s.cancel();
@@ -594,7 +594,7 @@ struct DeletePolicyFixture : public MessagingFixture
void test(Mode mode)
{
- qpid::messaging::Address address("# " + getPolicy(mode));
+ qpid::messaging::Address address("#; " + getPolicy(mode));
create(address);
Sender s = session.createSender(address);
@@ -681,18 +681,18 @@ QPID_AUTO_TEST_CASE(testDeletePolicyExchange)
QPID_AUTO_TEST_CASE(testAssertPolicyQueue)
{
MessagingFixture fix;
- std::string a1 = "q {create:always, assert:always, type:queue, node-properties:{durable:false, x-amqp0-10-arguments:{qpid.max-count:100}}}";
+ std::string a1 = "q; {create:always, assert:always, type:queue, node-properties:{durable:false, x-amqp0-10-arguments:{qpid.max-count:100}}}";
Sender s1 = fix.session.createSender(a1);
s1.cancel();
Receiver r1 = fix.session.createReceiver(a1);
r1.cancel();
- std::string a2 = "q {assert:receiver, node-properties:{durable:true, x-amqp0-10-arguments:{qpid.max-count:100}}}";
+ std::string a2 = "q; {assert:receiver, node-properties:{durable:true, x-amqp0-10-arguments:{qpid.max-count:100}}}";
Sender s2 = fix.session.createSender(a2);
s2.cancel();
BOOST_CHECK_THROW(fix.session.createReceiver(a2), qpid::messaging::InvalidAddress);
- std::string a3 = "q {assert:sender, node-properties:{x-amqp0-10-arguments:{qpid.max-count:99}}}";
+ std::string a3 = "q; {assert:sender, node-properties:{x-amqp0-10-arguments:{qpid.max-count:99}}}";
BOOST_CHECK_THROW(fix.session.createSender(a3), qpid::messaging::InvalidAddress);
Receiver r3 = fix.session.createReceiver(a3);
r3.cancel();