Repository: qpid-proton Updated Branches: refs/heads/master badf8ef40 -> 1c19ba9e2
NO-JIRA: c++: added message_id type, minor API cleanup. - renamed amqp_bool to amqp_boolean - added message_id type for message ids, like value but constrained to ulong, string, binary or uuid. - fixed some type safety and ambiguous conversion issues. Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/1c19ba9e Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/1c19ba9e Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/1c19ba9e Branch: refs/heads/master Commit: 1c19ba9e27f6d0f859f18e6c50088ab44e9ef831 Parents: badf8ef Author: Alan Conway <acon...@redhat.com> Authored: Thu Oct 29 14:01:53 2015 -0400 Committer: Alan Conway <acon...@redhat.com> Committed: Thu Oct 29 15:37:11 2015 -0400 ---------------------------------------------------------------------- examples/cpp/direct_recv.cpp | 11 +- examples/cpp/direct_send.cpp | 2 +- examples/cpp/encode_decode.cpp | 152 ++++++------------- examples/cpp/example_test.py | 21 +-- examples/cpp/server.cpp | 2 +- examples/cpp/simple_recv.cpp | 12 +- examples/cpp/simple_send.cpp | 2 +- proton-c/bindings/cpp/CMakeLists.txt | 6 +- proton-c/bindings/cpp/include/proton/data.hpp | 11 +- .../bindings/cpp/include/proton/decoder.hpp | 4 +- .../bindings/cpp/include/proton/encoder.hpp | 4 +- .../bindings/cpp/include/proton/message.hpp | 20 +-- .../bindings/cpp/include/proton/message_id.hpp | 80 ++++++++++ .../bindings/cpp/include/proton/type_traits.hpp | 2 +- proton-c/bindings/cpp/include/proton/types.hpp | 4 +- proton-c/bindings/cpp/include/proton/value.hpp | 75 ++++----- proton-c/bindings/cpp/src/data.cpp | 23 ++- proton-c/bindings/cpp/src/decoder.cpp | 18 ++- .../bindings/cpp/src/encode_decode_test.cpp | 74 +++++++++ proton-c/bindings/cpp/src/encoder.cpp | 10 +- proton-c/bindings/cpp/src/interop_test.cpp | 16 +- proton-c/bindings/cpp/src/message.cpp | 19 +-- proton-c/bindings/cpp/src/request_response.cpp | 4 +- proton-c/bindings/cpp/src/test_bits.hpp | 2 +- proton-c/bindings/cpp/src/types.cpp | 2 +- proton-c/bindings/cpp/src/value.cpp | 74 +++++++++ tests/tools/apps/cpp/reactor_send.cpp | 2 +- 27 files changed, 426 insertions(+), 226 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/examples/cpp/direct_recv.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/direct_recv.cpp b/examples/cpp/direct_recv.cpp index e4d6b4e..50ada7c 100644 --- a/examples/cpp/direct_recv.cpp +++ b/examples/cpp/direct_recv.cpp @@ -34,8 +34,8 @@ class direct_recv : public proton::messaging_handler { private: proton::url url; - int expected; - int received; + uint64_t expected; + uint64_t received; proton::counted_ptr<proton::acceptor> acceptor; public: @@ -48,11 +48,8 @@ class direct_recv : public proton::messaging_handler { void on_message(proton::event &e) { proton::message& msg = e.message(); - proton::value id = msg.id(); - if (id.type() == proton::ULONG) { - if (id.get<int>() < received) - return; // ignore duplicate - } + if (msg.id().get<uint64_t>() < received) + return; // ignore duplicate if (expected == 0 || received < expected) { std::cout << msg.body() << std::endl; received++; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/examples/cpp/direct_send.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/direct_send.cpp b/examples/cpp/direct_send.cpp index 4c5f4c5..62e6ab9 100644 --- a/examples/cpp/direct_send.cpp +++ b/examples/cpp/direct_send.cpp @@ -50,7 +50,7 @@ class simple_send : public proton::messaging_handler { proton::sender& sender = e.sender(); while (sender.credit() && sent < total) { proton::message msg; - msg.id(proton::value(sent + 1)); + msg.id(sent + 1); std::map<std::string, int> m; m["sequence"] = sent+1; msg.body(proton::as<proton::MAP>(m)); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/examples/cpp/encode_decode.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/encode_decode.cpp b/examples/cpp/encode_decode.cpp index b6669a0..4f88c93 100644 --- a/examples/cpp/encode_decode.cpp +++ b/examples/cpp/encode_decode.cpp @@ -31,58 +31,8 @@ using namespace std; // // Print is defined at the end as an example of how to query and extract complex -// values in terms of their simple components. -void print(proton::data&); - -// Inserting and extracting simple C++ values. -void simple_insert_extract() { - cout << endl << "== Simple values: int, string, bool" << endl; - proton::value dv; - dv.encoder() << 42 << "foo" << true; - print(dv); - int i; - string s; - bool b; - dv.decoder().rewind(); - dv.decoder() >> i >> s >> b; - cout << "Extracted: " << i << ", " << s << ", " << b << endl; - // Encode and decode as AMQP - string amqp_data = dv.encoder().encode(); - cout << "Encoded as AMQP in " << amqp_data.size() << " bytes" << endl; - proton::value dt2; - dt2.decoder().decode(amqp_data); - dt2.decoder() >> i >> s >> b; - cout << "Decoded: " << i << ", " << s << ", " << b << endl; -} - -// Inserting values as a specific AMQP type -void simple_insert_extract_exact_type() { - proton::value dv; - cout << endl << "== Specific AMQP types: byte, long, symbol" << endl; - dv.encoder() << proton::amqp_byte('x') << proton::amqp_long(123456789123456789) << proton::amqp_symbol("bar"); - print(dv); - dv.decoder().rewind(); - // Check that we encoded the correct types, but note that decoding will - // still convert to standard C++ types, in particular any AMQP integer type - // can be converted to a long-enough C++ integer type.. - int64_t i1, i2; - string s; - dv.decoder() >> i1 >> i2 >> s; - cout << "Extracted (with conversion) " << i1 << ", " << i2 << ", " << s << endl; - - // Now use the as() function to fail unless we extract the exact AMQP type expected. - dv.decoder().rewind(); // amqp_byte(1) << amqp_long(2) << amqp_symbol("bar"); - proton::amqp_long l; - // Fails, extracting amqp_byte as amqp_long - try { dv.decoder() >> proton::as<proton::LONG>(l); throw logic_error("expected error"); } catch (proton::decode_error) {} - proton::amqp_byte b; - dv.decoder() >> proton::as<proton::BYTE>(b) >> proton::as<proton::LONG>(l); // OK, extract amqp_byte as amqp_byte, amqp_long as amqp_long. - string str; - // Fails, extracting amqp_symbol as amqp_string. - try { dv.decoder() >> proton::as<proton::STRING>(str); throw logic_error("expected error"); } catch (proton::decode_error) {} - dv.decoder() >> proton::as<proton::SYMBOL>(str); // OK, extract amqp_symbol as amqp_symbol - cout << "Extracted (exact) " << b << ", " << l << ", " << str << endl; -} +// values from a decoder in terms of their simple components. +void print(proton::value&); // Some helper templates to print map and vector results. namespace std { @@ -118,14 +68,14 @@ void insert_extract_containers() { m["one"] = 1; m["two"] = 2; - proton::value dv; - dv.encoder() << proton::as<proton::ARRAY>(a) << proton::as<proton::LIST>(l) << proton::as<proton::MAP>(m); - print(dv); + proton::value v; + v.encoder() << proton::as<proton::ARRAY>(a) << proton::as<proton::LIST>(l) << proton::as<proton::MAP>(m); + print(v); vector<int> a1, l1; map<string, int> m1; - dv.decoder().rewind(); - dv.decoder() >> proton::as<proton::ARRAY>(a1) >> proton::as<proton::LIST>(l1) >> proton::as<proton::MAP>(m1); + v.decoder().rewind(); + v.decoder() >> proton::as<proton::ARRAY>(a1) >> proton::as<proton::LIST>(l1) >> proton::as<proton::MAP>(m1); cout << "Extracted: " << a1 << ", " << l1 << ", " << m1 << endl; } @@ -138,40 +88,38 @@ void mixed_containers() { map<proton::value, proton::value> m; m[proton::value("five")] = proton::value(5); m[proton::value(4)] = proton::value("four"); - proton::value dv; - dv.encoder() << proton::as<proton::LIST>(l) << proton::as<proton::MAP>(m); - print(dv); + proton::value v; + v.encoder() << proton::as<proton::LIST>(l) << proton::as<proton::MAP>(m); + print(v); vector<proton::value> l1; map<proton::value, proton::value> m1; - dv.decoder().rewind(); - dv.decoder() >> proton::as<proton::LIST>(l1) >> proton::as<proton::MAP>(m1); + v.decoder().rewind(); + v.decoder() >> proton::as<proton::LIST>(l1) >> proton::as<proton::MAP>(m1); cout << "Extracted: " << l1 << ", " << m1 << endl; } // Insert using stream operators (see print_next for example of extracting with stream ops.) void insert_extract_stream_operators() { cout << endl << "== Insert with stream operators." << endl; - proton::value dv; + proton::value v; // Note: array elements must be encoded with the exact type, they are not // automaticlly converted. Mismatched types for array elements will not - // be detected until dv.encode() is called. - dv.encoder() << proton::start::array(proton::INT) << proton::amqp_int(1) << proton::amqp_int(2) << proton::amqp_int(3) << proton::finish(); - print(dv); + // be detected until v.encode() is called. + v.encoder() << proton::start::array(proton::INT) << proton::amqp_int(1) << proton::amqp_int(2) << proton::amqp_int(3) << proton::finish(); + print(v); - dv.clear(); - dv.encoder() << proton::start::list() << proton::amqp_int(42) << false << proton::amqp_symbol("x") << proton::finish(); - print(dv); + v.clear(); + v.encoder() << proton::start::list() << proton::amqp_int(42) << false << proton::amqp_symbol("x") << proton::finish(); + print(v); - dv.clear(); - dv.encoder() << proton::start::map() << "k1" << proton::amqp_int(42) << proton::amqp_symbol("k2") << false << proton::finish(); - print(dv); + v.clear(); + v.encoder() << proton::start::map() << "k1" << proton::amqp_int(42) << proton::amqp_symbol("k2") << false << proton::finish(); + print(v); } int main(int, char**) { try { - simple_insert_extract(); - simple_insert_extract_exact_type(); insert_extract_containers(); mixed_containers(); insert_extract_stream_operators(); @@ -187,75 +135,75 @@ int main(int, char**) { // NOTE this is for example puroses only: There is a built in ostream operator<< for values. // // -void print_next(proton::data& dv) { - proton::type_id type = dv.type(); +void print_next(proton::decoder& d) { + proton::type_id type = d.type(); proton::start s; switch (type) { case proton::ARRAY: { - dv.decoder() >> s; + d >> s; cout << "array<" << s.element; if (s.is_described) { cout << ", descriptor="; - print_next(dv); + print_next(d); } cout << ">["; for (size_t i = 0; i < s.size; ++i) { if (i) cout << ", "; - print_next(dv); + print_next(d); } cout << "]"; - dv.decoder() >> proton::finish(); + d >> proton::finish(); break; } case proton::LIST: { - dv.decoder() >> s; + d >> s; cout << "list["; for (size_t i = 0; i < s.size; ++i) { if (i) cout << ", "; - print_next(dv); + print_next(d); } cout << "]"; - dv.decoder() >> proton::finish(); + d >> proton::finish(); break; } case proton::MAP: { - dv.decoder() >> s; + d >> s; cout << "map{"; for (size_t i = 0; i < s.size/2; ++i) { if (i) cout << ", "; - print_next(dv); + print_next(d); cout << ":"; // key:value - print_next(dv); + print_next(d); } cout << "}"; - dv.decoder() >> proton::finish(); + d >> proton::finish(); break; } case proton::DESCRIBED: { - dv.decoder() >> s; + d >> s; cout << "described("; - print_next(dv); // Descriptor - print_next(dv); // value - dv.decoder() >> proton::finish(); + print_next(d); // Descriptor + print_next(d); // value + d >> proton::finish(); break; } default: // A simple type. We could continue the switch for all AMQP types but - // instead we us the `value` type which can hold and print any AMQP - // value. - proton::value v; - dv.decoder() >> v; - cout << type << "(" << v << ")"; + // we will take a short cut and extract to another value and print that. + proton::value v2; + d >> v2; + cout << type << "(" << v2 << ")"; } } -// Print all the values with print_next -void print(proton::data& dv) { - dv.decoder().rewind(); +// Print a value, for example purposes. Normal code can use operator<< +void print(proton::value& v) { + proton::decoder& d = v.decoder(); + d.rewind(); cout << "Values: "; - while (dv.decoder().more()) { - print_next(dv); - if (dv.decoder().more()) cout << ", "; + while (d.more()) { + print_next(d); + if (d.more()) cout << ", "; } cout << endl; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/examples/cpp/example_test.py ---------------------------------------------------------------------- diff --git a/examples/cpp/example_test.py b/examples/cpp/example_test.py index bb40265..d2b3169 100644 --- a/examples/cpp/example_test.py +++ b/examples/cpp/example_test.py @@ -197,29 +197,18 @@ class ExampleTest(unittest.TestCase): def test_encode_decode(self): expect=""" -== Simple values: int, string, bool -Values: int(42), string("foo"), bool(true) -Extracted: 42, foo, 1 -Encoded as AMQP in 8 bytes -Decoded: 42, foo, 1 - -== Specific AMQP types: byte, long, symbol -Values: byte(120), long(123456789123456789), symbol(:bar) -Extracted (with conversion) 120, 123456789123456789, bar -Extracted (exact) x, 123456789123456789, bar - == Array, list and map. -Values: array<int>[int(1), int(2), int(3)], list[int(4), int(5)], map{string("one"):int(1), string("two"):int(2)} +Values: array<int>[int(1), int(2), int(3)], list[int(4), int(5)], map{string(one):int(1), string(two):int(2)} Extracted: [ 1 2 3 ], [ 4 5 ], { one:1 two:2 } == List and map of mixed type values. -Values: list[int(42), string("foo")], map{int(4):string("four"), string("five"):int(5)} -Extracted: [ 42 "foo" ], { 4:"four" "five":5 } +Values: list[int(42), string(foo)], map{int(4):string(four), string(five):int(5)} +Extracted: [ 42 foo ], { 4:four five:5 } == Insert with stream operators. Values: array<int>[int(1), int(2), int(3)] -Values: list[int(42), bool(false), symbol(:x)] -Values: map{string("k1"):int(42), symbol(:"k2"):bool(false)} +Values: list[int(42), boolean(false), symbol(x)] +Values: map{string(k1):int(42), symbol(k2):boolean(false)} """ self.maxDiff = None self.assertEqual(expect, execute("encode_decode")) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/examples/cpp/server.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/server.cpp b/examples/cpp/server.cpp index e1de85e..fd00eb1 100644 --- a/examples/cpp/server.cpp +++ b/examples/cpp/server.cpp @@ -69,7 +69,7 @@ class server : public proton::messaging_handler { int main(int argc, char **argv) { // Command line options - std::string address("amqp://127.0.0.1:5672/examples"); + std::string address("amqp://0.0.0.0:5672/examples"); options opts(argc, argv); opts.add_value(address, 'a', "address", "listen on URL", "URL"); try { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/examples/cpp/simple_recv.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/simple_recv.cpp b/examples/cpp/simple_recv.cpp index dfd8b5f..bcb28e3 100644 --- a/examples/cpp/simple_recv.cpp +++ b/examples/cpp/simple_recv.cpp @@ -25,6 +25,7 @@ #include "proton/messaging_handler.hpp" #include "proton/link.hpp" #include "proton/value.hpp" +#include "proton/message_id.hpp" #include <iostream> #include <map> @@ -35,8 +36,8 @@ class simple_recv : public proton::messaging_handler { private: proton::url url; proton::counted_ptr<proton::receiver> receiver; - int expected; - int received; + uint64_t expected; + uint64_t received; public: simple_recv(const std::string &s, int c) : url(s), expected(c), received(0) {} @@ -48,11 +49,8 @@ class simple_recv : public proton::messaging_handler { void on_message(proton::event &e) { proton::message& msg = e.message(); - proton::value id = msg.id(); - if (id.type() == proton::ULONG) { - if (id.get<int>() < received) - return; // ignore duplicate - } + if (msg.id().get<uint64_t>() < received) + return; // ignore duplicate if (expected == 0 || received < expected) { std::cout << msg.body() << std::endl; received++; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/examples/cpp/simple_send.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/simple_send.cpp b/examples/cpp/simple_send.cpp index 23ab76e..cb33207 100644 --- a/examples/cpp/simple_send.cpp +++ b/examples/cpp/simple_send.cpp @@ -48,7 +48,7 @@ class simple_send : public proton::messaging_handler { proton::sender& sender = e.sender(); while (sender.credit() && sent < total) { proton::message msg; - msg.id(proton::value(sent + 1)); + msg.id(sent + 1); std::map<std::string, int> m; m["sequence"] = sent+1; msg.body(proton::as<proton::MAP>(m)); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt index 9f423fb..0c44fb9 100644 --- a/proton-c/bindings/cpp/CMakeLists.txt +++ b/proton-c/bindings/cpp/CMakeLists.txt @@ -57,15 +57,16 @@ set(qpid-proton-cpp-source src/proton_handler.cpp src/reactor.cpp src/receiver.cpp + src/request_response.cpp src/sender.cpp src/session.cpp - src/request_response.cpp src/task.cpp src/terminus.cpp src/transport.cpp src/types.cpp src/url.cpp src/uuid.cpp + src/value.cpp ) @@ -160,4 +161,5 @@ macro(add_cpp_test test) endmacro(add_cpp_test) add_cpp_test(interop_test ${CMAKE_SOURCE_DIR}/tests) -add_cpp_test(conversion_test ${CMAKE_SOURCE_DIR}/tests) +add_cpp_test(conversion_test) +add_cpp_test(encode_decode_test) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/include/proton/data.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/data.hpp b/proton-c/bindings/cpp/include/proton/data.hpp index bbc49c2..21504a5 100644 --- a/proton-c/bindings/cpp/include/proton/data.hpp +++ b/proton-c/bindings/cpp/include/proton/data.hpp @@ -61,11 +61,11 @@ class data : public facade<pn_data_t, data, comparable<data> > { /** Type of the current value*/ PN_CPP_EXTERN type_id type() const; - /** Get the current value, don't move the decoder pointer. */ - template<class T> void get(T &t) { decoder() >> t; decoder().backup(); } + /** Get the first value, don't move the decoder pointer. */ + template<class T> void get(T &t) const { decoder() >> t; decoder().backup(); } - /** Get the current value */ - template<class T> T get() { T t; get(t); return t; } + /** Get the first value, don't move the decoder pointer. */ + template<class T> T get() const { T t; get(t); return t; } PN_CPP_EXTERN bool operator==(const data& x) const; PN_CPP_EXTERN bool operator<(const data& x) const; @@ -74,6 +74,9 @@ class data : public facade<pn_data_t, data, comparable<data> > { /** Human readable representation of data. */ friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const data&); + + private: + class decoder& decoder() const { return const_cast<data*>(this)->decoder(); } }; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/include/proton/decoder.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/decoder.hpp b/proton-c/bindings/cpp/include/proton/decoder.hpp index 0766aba..33ddb4f 100644 --- a/proton-c/bindings/cpp/include/proton/decoder.hpp +++ b/proton-c/bindings/cpp/include/proton/decoder.hpp @@ -30,6 +30,7 @@ struct pn_data_t; namespace proton { class data; +class message_id; /** Raised by decoder operations on error.*/ struct decode_error : public error { PN_CPP_EXTERN explicit decode_error(const std::string&) throw(); }; @@ -104,7 +105,7 @@ class decoder : public facade<pn_data_t, decoder> { * @{ */ PN_CPP_EXTERN friend decoder& operator>>(decoder&, amqp_null); - PN_CPP_EXTERN friend decoder& operator>>(decoder&, amqp_bool&); + PN_CPP_EXTERN friend decoder& operator>>(decoder&, amqp_boolean&); PN_CPP_EXTERN friend decoder& operator>>(decoder&, amqp_ubyte&); PN_CPP_EXTERN friend decoder& operator>>(decoder&, amqp_byte&); PN_CPP_EXTERN friend decoder& operator>>(decoder&, amqp_ushort&); @@ -122,6 +123,7 @@ class decoder : public facade<pn_data_t, decoder> { PN_CPP_EXTERN friend decoder& operator>>(decoder&, amqp_decimal128&); PN_CPP_EXTERN friend decoder& operator>>(decoder&, amqp_uuid&); PN_CPP_EXTERN friend decoder& operator>>(decoder&, std::string&); + PN_CPP_EXTERN friend decoder& operator>>(decoder&, message_id&); PN_CPP_EXTERN friend decoder& operator>>(decoder&, class data&); ///@} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/include/proton/encoder.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/encoder.hpp b/proton-c/bindings/cpp/include/proton/encoder.hpp index 7039061..24684c1 100644 --- a/proton-c/bindings/cpp/include/proton/encoder.hpp +++ b/proton-c/bindings/cpp/include/proton/encoder.hpp @@ -30,6 +30,7 @@ struct pn_data_t; namespace proton { class data; +class message_id; /** Raised by encoder operations on error */ struct encode_error : public error { PN_CPP_EXTERN explicit encode_error(const std::string&) throw(); }; @@ -85,7 +86,7 @@ class encoder : public facade<pn_data_t, encoder> { *@{ */ friend PN_CPP_EXTERN encoder& operator<<(encoder&, amqp_null); - friend PN_CPP_EXTERN encoder& operator<<(encoder&, amqp_bool); + friend PN_CPP_EXTERN encoder& operator<<(encoder&, amqp_boolean); friend PN_CPP_EXTERN encoder& operator<<(encoder&, amqp_ubyte); friend PN_CPP_EXTERN encoder& operator<<(encoder&, amqp_byte); friend PN_CPP_EXTERN encoder& operator<<(encoder&, amqp_ushort); @@ -105,6 +106,7 @@ class encoder : public facade<pn_data_t, encoder> { friend PN_CPP_EXTERN encoder& operator<<(encoder&, amqp_string); friend PN_CPP_EXTERN encoder& operator<<(encoder&, amqp_symbol); friend PN_CPP_EXTERN encoder& operator<<(encoder&, amqp_binary); + friend PN_CPP_EXTERN encoder& operator<<(encoder&, const message_id&); friend PN_CPP_EXTERN encoder& operator<<(encoder&, const class data&); ///@} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/include/proton/message.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/message.hpp b/proton-c/bindings/cpp/include/proton/message.hpp index 61bc04a..e9862c6 100644 --- a/proton-c/bindings/cpp/include/proton/message.hpp +++ b/proton-c/bindings/cpp/include/proton/message.hpp @@ -21,9 +21,10 @@ * under the License. * */ -#include "proton/data.hpp" #include "proton/export.hpp" #include "proton/facade.hpp" +#include "proton/message_id.hpp" +#include "proton/data.hpp" #include "proton/pn_unique_ptr.hpp" #include <string> @@ -35,6 +36,7 @@ namespace proton { class link; class delivery; +class message_id; /** An AMQP message. Value semantics, can be copied or assigned to make a new message. */ class message @@ -56,12 +58,8 @@ class message ///@name Message properties ///@{ - ///@ Set message identifier, can be a string, unsigned long, uuid or binary. - PN_CPP_EXTERN void id(const data& id); - ///@ Get message identifier - PN_CPP_EXTERN data& id(); - ///@ Get message identifier reference, allows modification in-place. - PN_CPP_EXTERN const data& id() const; + PN_CPP_EXTERN void id(const message_id& id); + PN_CPP_EXTERN message_id id() const; PN_CPP_EXTERN void user_id(const std::string &user); PN_CPP_EXTERN std::string user_id() const; @@ -75,12 +73,8 @@ class message PN_CPP_EXTERN void reply_to(const std::string &s); PN_CPP_EXTERN std::string reply_to() const; - /// Get correlation identifier, can be a string, unsigned long, uuid or binary. - PN_CPP_EXTERN void correlation_id(const data&); - /// Get correlation identifier. - PN_CPP_EXTERN const data& correlation_id() const; - /// Get correlation identifier reference, allows modification in-place. - PN_CPP_EXTERN data& correlation_id(); + PN_CPP_EXTERN void correlation_id(const message_id&); + PN_CPP_EXTERN message_id correlation_id() const; PN_CPP_EXTERN void content_type(const std::string &s); PN_CPP_EXTERN std::string content_type() const; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/include/proton/message_id.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/message_id.hpp b/proton-c/bindings/cpp/include/proton/message_id.hpp new file mode 100644 index 0000000..212df34 --- /dev/null +++ b/proton-c/bindings/cpp/include/proton/message_id.hpp @@ -0,0 +1,80 @@ +#ifndef MESSAGE_ID_HPP +#define MESSAGE_ID_HPP +/* + * 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 "proton/types.hpp" +#include "proton/value.hpp" + +namespace proton { +/** A message_id can contain one of the following types: + * uint64_t (aka amqp_ulong), amqp_uuid, amqp_binary or amqp_string. + */ +class message_id : public comparable<message_id> { + public: + message_id() {} + message_id(const uint64_t& x) : value_(x) {} + message_id(const amqp_uuid& x) : value_(x) {} + message_id(const amqp_binary& x) : value_(x) {} + message_id(const amqp_string& x) : value_(x) {} + /// string is encoded as amqp_string + message_id(const std::string& x) : value_(x) {} + + message_id& operator=(const message_id& x) { value_ = x.value_; return *this; } + message_id& operator=(const uint64_t& x) { value_ = x; return *this; } + message_id& operator=(const amqp_uuid& x) { value_ = x; return *this; } + message_id& operator=(const amqp_binary& x) { value_ = x; return *this; } + message_id& operator=(const amqp_string& x) { value_ = x; return *this; } + /// string is encoded as amqp_string + message_id& operator=(const std::string& x) { value_ = x; return *this; } + + void clear() { value_.clear(); } + bool empty() const { return value_.empty(); } + type_id type() { return value_.type(); } + + void get(uint64_t& x) const { value_.get(x); } + void get(amqp_uuid& x) const { value_.get(x); } + void get(amqp_binary& x) const { value_.get(x); } + void get(amqp_string& x) const { value_.get(x); } + /// Both amqp_binary and amqp_string can be converted to std::string + void get(std::string& x) const { value_.get(x); } + + template<class T> T get() const { T x; get(x); return x; } + template<class T> operator T() const { return get<T>(); } + + // String representation: decimal representation of uint64_t, standard text + // representation of UUID, amqp_string or amqp_binary are returned without + // modification. + std::string& str() const; + + bool operator==(const message_id& x) const { return value_ == x.value_; } + bool operator<(const message_id& x) const { return value_ < x.value_; } + + friend std::ostream& operator<<(std::ostream&, const message_id&); + friend encoder& operator<<(encoder&, const message_id&); + friend decoder& operator>>(decoder&, message_id&); + + private: + message_id(const value& v) : value_(v) {} + value value_; + friend class message; +}; + +} +#endif // MESSAGE_ID_HPP http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/include/proton/type_traits.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/type_traits.hpp b/proton-c/bindings/cpp/include/proton/type_traits.hpp index fb43cb9..e9a2a48 100644 --- a/proton-c/bindings/cpp/include/proton/type_traits.hpp +++ b/proton-c/bindings/cpp/include/proton/type_traits.hpp @@ -70,7 +70,7 @@ template <> struct is_signed<signed long long> : public true_type {}; // Metafunction returning exact AMQP type associated with a C++ type template <class T> struct type_id_of; template<> struct type_id_of<amqp_null> { static const type_id value=NULL_; }; -template<> struct type_id_of<amqp_bool> { static const type_id value=BOOL; }; +template<> struct type_id_of<amqp_boolean> { static const type_id value=BOOLEAN; }; template<> struct type_id_of<amqp_ubyte> { static const type_id value=UBYTE; }; template<> struct type_id_of<amqp_byte> { static const type_id value=BYTE; }; template<> struct type_id_of<amqp_ushort> { static const type_id value=USHORT; }; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/include/proton/types.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/types.hpp b/proton-c/bindings/cpp/include/proton/types.hpp index d3944b4..b1e7085 100644 --- a/proton-c/bindings/cpp/include/proton/types.hpp +++ b/proton-c/bindings/cpp/include/proton/types.hpp @@ -40,7 +40,7 @@ namespace proton { /** type_id identifies an AMQP type. */ enum type_id { NULL_=PN_NULL, ///< The null type, contains no data. - BOOL=PN_BOOL, ///< Boolean true or false. + BOOLEAN=PN_BOOL, ///< Boolean true or false. UBYTE=PN_UBYTE, ///< Unsigned 8 bit integer. BYTE=PN_BYTE, ///< Signed 8 bit integer. USHORT=PN_USHORT, ///< Unsigned 16 bit integer. @@ -73,7 +73,7 @@ PN_CPP_EXTERN std::string str(const pn_bytes_t& b); /// AMQP NULL type. struct amqp_null {}; /// AMQP boolean type. -typedef bool amqp_bool; +typedef bool amqp_boolean; /// AMQP unsigned 8-bit type. typedef ::uint8_t amqp_ubyte; /// AMQP signed 8-bit integer type. http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/include/proton/value.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/value.hpp b/proton-c/bindings/cpp/include/proton/value.hpp index c23b0a6..8816064 100644 --- a/proton-c/bindings/cpp/include/proton/value.hpp +++ b/proton-c/bindings/cpp/include/proton/value.hpp @@ -20,57 +20,60 @@ */ #include "proton/data.hpp" +#include "proton/decoder.hpp" +#include "proton/pn_unique_ptr.hpp" +#include "proton/types.hpp" namespace proton { +class data; +class encoder; +class decoder; + /** AMQP data with normal value semantics: copy, assign etc. */ -class value { +class value : public comparable<value> { public: - value() : data_(data::create()) {} - value(const value& x) : data_(data::create()) { *data_ = *x.data_; } - value(const data& x) : data_(data::create()) { *data_ = x; } + PN_CPP_EXTERN value(); + PN_CPP_EXTERN value(const value& x); template <class T> value(const T& x) : data_(data::create()) { *data_ = x; } - operator data&() { return *data_; } - operator const data&() const { return *data_; } - - value& operator=(const value& x) { *data_ = *x.data_; return *this; } - value& operator=(const data& x) { *data_ = x; return *this; } + PN_CPP_EXTERN value& operator=(const value& x); + PN_CPP_EXTERN value& operator=(const data& x); template <class T> value& operator=(const T& x) { *data_ = x; return *this; } - void clear() { data_->clear(); } - bool empty() const { return data_->empty(); } + PN_CPP_EXTERN void clear(); + PN_CPP_EXTERN bool empty() const; - /** Encoder to encode into this value */ - class encoder& encoder() { return data_->encoder(); } + /** Encoder to encode complex data into this value. + * Note if you enocde more than one value, all but the first will be ignored. + */ + PN_CPP_EXTERN class encoder& encoder(); - /** Decoder to decode from this value */ - class decoder& decoder() { return data_->decoder(); } + /** Decoder to decode complex data from this value */ + PN_CPP_EXTERN class decoder& decoder(); /** Type of the current value*/ - type_id type() { return decoder().type(); } - - /** Get the current value, don't move the decoder pointer. */ - template<class T> void get(T &t) { decoder() >> t; decoder().backup(); } - - /** Get the current value */ - template<class T> T get() { T t; get(t); return t; } - template<class T> operator T() { return get<T>(); } - - bool operator==(const value& x) const { return *data_ == *x.data_; } - bool operator<(const value& x) const { return *data_ < *x.data_; } - - friend inline class encoder& operator<<(class encoder& e, const value& dv) { - return e << *dv.data_; - } - friend inline class decoder& operator>>(class decoder& d, value& dv) { - return d >> *dv.data_; - } - friend inline std::ostream& operator<<(std::ostream& o, const value& dv) { - return o << *dv.data_; - } + PN_CPP_EXTERN type_id type() const; + + /** Get the value. */ + template<class T> void get(T &t) const { rewind() >> t; } + + /** Get the value. */ + template<class T> T get() const { T t; get(t); return t; } + + PN_CPP_EXTERN bool operator==(const value& x) const; + PN_CPP_EXTERN bool operator<(const value& x) const; + + friend PN_CPP_EXTERN class encoder& operator<<(class encoder& e, const value& dv); + friend PN_CPP_EXTERN class decoder& operator>>(class decoder& d, value& dv); + friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream& o, const value& dv); + private: + value(const data&); + class decoder& rewind() const { data_->decoder().rewind(); return data_->decoder(); } + pn_unique_ptr<data> data_; + friend class message; }; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/src/data.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/data.cpp b/proton-c/bindings/cpp/src/data.cpp index 53b8c37..0c47019 100644 --- a/proton-c/bindings/cpp/src/data.cpp +++ b/proton-c/bindings/cpp/src/data.cpp @@ -18,10 +18,12 @@ */ #include "proton_bits.hpp" -#include "proton/value.hpp" +#include "proton/data.hpp" #include <proton/codec.h> +#include <ostream> + namespace proton { void data::operator delete(void *p) { ::pn_data_free(reinterpret_cast<pn_data_t*>(p)); } @@ -32,7 +34,20 @@ void data::clear() { ::pn_data_clear(pn_cast(this)); } bool data::empty() const { return ::pn_data_size(pn_cast(this)) == 0; } -std::ostream& operator<<(std::ostream& o, const data& d) { return o << inspectable(pn_cast(&d)); } +namespace { +struct save_state { + pn_data_t* data; + pn_handle_t handle; + save_state(pn_data_t* d) : data(d), handle(pn_data_point(d)) {} + ~save_state() { if (data) pn_data_restore(data, handle); } +}; +} + +std::ostream& operator<<(std::ostream& o, const data& d) { + save_state(pn_cast(&d)); + d.decoder().rewind(); + return o << inspectable(pn_cast(&d)); +} pn_unique_ptr<data> data::create() { return pn_unique_ptr<data>(cast(::pn_data(0))); } @@ -88,7 +103,7 @@ int compare_next(data& a, data& b) { case MAP: case DESCRIBED: return compare_container(a, b); - case BOOL: return compare_simple<amqp_bool>(a, b); + case BOOLEAN: return compare_simple<amqp_boolean>(a, b); case UBYTE: return compare_simple<amqp_ubyte>(a, b); case BYTE: return compare_simple<amqp_byte>(a, b); case USHORT: return compare_simple<amqp_ushort>(a, b); @@ -114,6 +129,8 @@ int compare_next(data& a, data& b) { } int compare(data& a, data& b) { + save_state(pn_cast(&a)); + save_state(pn_cast(&b)); a.decoder().rewind(); b.decoder().rewind(); while (a.decoder().more() && b.decoder().more()) { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/src/decoder.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/decoder.cpp b/proton-c/bindings/cpp/src/decoder.cpp index 78e92c8..1f11b4a 100644 --- a/proton-c/bindings/cpp/src/decoder.cpp +++ b/proton-c/bindings/cpp/src/decoder.cpp @@ -17,12 +17,15 @@ * under the License. */ +#include "proton/data.hpp" #include "proton/decoder.hpp" #include "proton/value.hpp" -#include <proton/codec.h> +#include "proton/message_id.hpp" #include "proton_bits.hpp" #include "msg.hpp" +#include <proton/codec.h> + namespace proton { /**@file @@ -157,6 +160,17 @@ decoder& operator>>(decoder& d, data& v) { return d; } +decoder& operator>>(decoder& d, message_id& id) { + switch (d.type()) { + case ULONG: + case UUID: + case BINARY: + case STRING: + return d >> id.value_; + default: + throw decode_error("expected one of ulong, uuid, binary or string but found "+d.type()); + }; +} decoder& operator>>(decoder& d, amqp_null) { save_state ss(pn_cast(&d)); @@ -164,7 +178,7 @@ decoder& operator>>(decoder& d, amqp_null) { return d; } -decoder& operator>>(decoder& d, amqp_bool& value) { +decoder& operator>>(decoder& d, amqp_boolean& value) { extract(pn_cast(&d), value, pn_data_get_bool); return d; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/src/encode_decode_test.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/encode_decode_test.cpp b/proton-c/bindings/cpp/src/encode_decode_test.cpp new file mode 100644 index 0000000..89f2c36 --- /dev/null +++ b/proton-c/bindings/cpp/src/encode_decode_test.cpp @@ -0,0 +1,74 @@ +/* + * 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 "test_bits.hpp" + +#include <proton/value.hpp> +#include <algorithm> +#include <iostream> +#include <iterator> +#include <map> +#include <sstream> +#include <vector> + +using namespace std; +using namespace proton; + +// Inserting and extracting simple C++ values. +template <class T> void value_test(T x, type_id tid, const std::string& s, T y) { + value v(x); + ASSERT_EQUAL(tid, v.type()); + ASSERT_EQUAL(x, v.get<T>()); + + value v2; + v2 = x; + ASSERT_EQUAL(tid, v2.type()); + ASSERT_EQUAL(x, v2.get<T>()); + + ASSERT_EQUAL(v, v2); + std::ostringstream os; + os << v; + ASSERT_EQUAL(s, os.str()); + ASSERT(x != y); + ASSERT(x < y); + ASSERT(y > x); +} + +void value_tests() { + value_test(false, BOOLEAN, "0", true); + value_test(amqp_ubyte(42), UBYTE, "42", amqp_ubyte(50)); + value_test(amqp_byte(-42), BYTE, "42", amqp_byte(-40)); + value_test(amqp_ushort(-4242), USHORT, "4242", amqp_ushort(5252)); + value_test(amqp_short(4242), SHORT, "-4242", amqp_short(3)); + value_test(amqp_uint(-4242), UINT, "4242", amqp_uint(5252)); + value_test(amqp_int(4242), INT, "-4242", amqp_int(3)); + value_test(amqp_ulong(-4242), ULONG, "4242", amqp_ulong(5252)); + value_test(amqp_long(4242), LONG, "-4242", amqp_long(3)); + value_test(amqp_float(1.234), FLOAT, "4242", amqp_float(2.345)); + value_test(amqp_double(11.2233), DOUBLE, "-4242", amqp_double(12)); + value_test(amqp_string("aaa"), STRING, "aaa", amqp_string("aaaa")); + value_test(std::string("xxx"), STRING, "xxx", std::string("yyy")); + value_test(amqp_symbol("aaa"), SYMBOL, "aaa", amqp_symbol("aaaa")); + value_test(amqp_binary("aaa"), BINARY, "aaa", amqp_binary("aaaa")); +} + +int main(int, char**) { + int failed = 0; + return failed; +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/src/encoder.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/encoder.cpp b/proton-c/bindings/cpp/src/encoder.cpp index ee52f8d..0230e88 100644 --- a/proton-c/bindings/cpp/src/encoder.cpp +++ b/proton-c/bindings/cpp/src/encoder.cpp @@ -17,12 +17,16 @@ * under the License. */ +#include "proton/data.hpp" #include "proton/encoder.hpp" +#include "proton/message_id.hpp" #include "proton/value.hpp" -#include <proton/codec.h> + #include "proton_bits.hpp" #include "msg.hpp" +#include <proton/codec.h> + namespace proton { static const std::string prefix("encode: "); @@ -105,7 +109,7 @@ encoder& insert(encoder& e, pn_data_t* data, T& value, int (*put)(pn_data_t*, U) } encoder& operator<<(encoder& e, amqp_null) { pn_data_put_null(pn_cast(&e)); return e; } -encoder& operator<<(encoder& e, amqp_bool value) { return insert(e, pn_cast(&e), value, pn_data_put_bool); } +encoder& operator<<(encoder& e, amqp_boolean value) { return insert(e, pn_cast(&e), value, pn_data_put_bool); } encoder& operator<<(encoder& e, amqp_ubyte value) { return insert(e, pn_cast(&e), value, pn_data_put_ubyte); } encoder& operator<<(encoder& e, amqp_byte value) { return insert(e, pn_cast(&e), value, pn_data_put_byte); } encoder& operator<<(encoder& e, amqp_ushort value) { return insert(e, pn_cast(&e), value, pn_data_put_ushort); } @@ -132,4 +136,6 @@ encoder& operator<<(encoder& e, const data& v) { return e; } +encoder& operator<<(encoder& e, const message_id& v) { return e << v.value_; } + } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/src/interop_test.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/interop_test.cpp b/proton-c/bindings/cpp/src/interop_test.cpp index da80814..ac2701f 100644 --- a/proton-c/bindings/cpp/src/interop_test.cpp +++ b/proton-c/bindings/cpp/src/interop_test.cpp @@ -98,14 +98,14 @@ void test_encoder_primitives() { // Test type conversions. void test_value_conversions() { value v; - ASSERT_EQUAL(true, bool(v = true)); - ASSERT_EQUAL(2, int(v=amqp_byte(2))); - ASSERT_EQUAL(3, long(v=amqp_byte(3))); - ASSERT_EQUAL(3, long(v=amqp_byte(3))); - ASSERT_EQUAL(1.0, double(v=amqp_float(1.0))); - ASSERT_EQUAL(1.0, float(v=amqp_double(1.0))); - try { (void)bool(v = amqp_byte(1)); FAIL("got byte as bool"); } catch (decode_error) {} - try { (void)float(v = true); FAIL("got bool as float"); } catch (decode_error) {} + ASSERT_EQUAL(true, (v=true).get<bool>()); + ASSERT_EQUAL(2, (v=amqp_byte(2)).get<int>()); + ASSERT_EQUAL(3, (v=amqp_byte(3)).get<long>()); + ASSERT_EQUAL(3, (v=amqp_byte(3)).get<long>()); + ASSERT_EQUAL(1.0, (v=amqp_float(1.0)).get<double>()); + ASSERT_EQUAL(1.0, (v=amqp_double(1.0)).get<float>()); + try { (void)(v = amqp_byte(1)).get<bool>(); FAIL("got byte as bool"); } catch (decode_error) {} + try { (void)(v = true).get<float>(); FAIL("got bool as float"); } catch (decode_error) {} } // TODO aconway 2015-06-11: interop test is not complete. http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/src/message.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/message.cpp b/proton-c/bindings/cpp/src/message.cpp index 49f5c79..63f6520 100644 --- a/proton-c/bindings/cpp/src/message.cpp +++ b/proton-c/bindings/cpp/src/message.cpp @@ -26,6 +26,7 @@ #include "proton/message.h" #include "proton/sender.hpp" #include "proton/receiver.hpp" +#include "proton/message_id.hpp" #include "proton/delivery.h" #include "msg.hpp" #include "proton_bits.hpp" @@ -63,9 +64,9 @@ void check(int err) { } } // namespace -void message::id(const data& id) { *data::cast(pn_message_id(message_)) = id; } -const data& message::id() const { return *data::cast(pn_message_id(message_)); } -data& message::id() { return *data::cast(pn_message_id(message_)); } +void message::id(const message_id& id) { *data::cast(pn_message_id(message_)) = id.value_; } + +message_id message::id() const { return message_id(*data::cast(pn_message_id(message_))); } void message::user_id(const std::string &id) { check(pn_message_set_user_id(message_, pn_bytes(id))); @@ -102,16 +103,12 @@ std::string message::reply_to() const { return s ? std::string(s) : std::string(); } -void message::correlation_id(const data& id) { - *data::cast(pn_message_correlation_id(message_)) = id; -} - -const data& message::correlation_id() const { - return *data::cast(pn_message_correlation_id(message_)); +void message::correlation_id(const message_id& id) { + *data::cast(pn_message_correlation_id(message_)) = id.value_; } -data& message::correlation_id() { - return *data::cast(pn_message_correlation_id(message_)); +message_id message::correlation_id() const { + return message_id(*data::cast(pn_message_correlation_id(message_))); } void message::content_type(const std::string &s) { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/src/request_response.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/request_response.cpp b/proton-c/bindings/cpp/src/request_response.cpp index 38a701c..694d727 100644 --- a/proton-c/bindings/cpp/src/request_response.cpp +++ b/proton-c/bindings/cpp/src/request_response.cpp @@ -22,7 +22,7 @@ #include "proton/request_response.hpp" #include "proton/event.hpp" #include "proton/error.hpp" -#include "proton/value.hpp" +#include "proton/message_id.hpp" #include "blocking_connection_impl.hpp" #include "msg.hpp" @@ -39,7 +39,7 @@ message request_response::call(message &request) { if (address_.empty() && request.address().empty()) throw error(MSG("Request message has no address")); // TODO: atomic increment. - value cid(++correlation_id_); + message_id cid(++correlation_id_); request.correlation_id(cid); request.reply_to(this->reply_to()); sender_->send(request); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/src/test_bits.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/test_bits.hpp b/proton-c/bindings/cpp/src/test_bits.hpp index bd94b8e..2c245cd 100644 --- a/proton-c/bindings/cpp/src/test_bits.hpp +++ b/proton-c/bindings/cpp/src/test_bits.hpp @@ -28,7 +28,7 @@ namespace { struct fail : public std::logic_error { fail(const std::string& what) : logic_error(what) {} }; #define FAIL(WHAT) throw fail(MSG(__FILE__ << ":" << __LINE__ << ": " << WHAT)) #define ASSERT(TEST) do { if (!(TEST)) FAIL("assert failed: " << #TEST); } while(false) -#define ASSERT_EQUAL(WANT, GOT) if ((WANT) != (GOT)) \ +#define ASSERT_EQUAL(WANT, GOT) if (!((WANT) == (GOT))) \ FAIL(#WANT << " != " << #GOT << ": " << WANT << " != " << GOT) int run_test(void (*testfn)(), const char* name) { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/src/types.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/types.cpp b/proton-c/bindings/cpp/src/types.cpp index 916e2fb..0964699 100644 --- a/proton-c/bindings/cpp/src/types.cpp +++ b/proton-c/bindings/cpp/src/types.cpp @@ -46,7 +46,7 @@ std::ostream& operator<<(std::ostream& o, const amqp_uuid& u) { std::string type_name(type_id t) { switch (t) { case NULL_: return "null"; - case BOOL: return "bool"; + case BOOLEAN: return "boolean"; case UBYTE: return "ubyte"; case BYTE: return "byte"; case USHORT: return "ushort"; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/proton-c/bindings/cpp/src/value.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/value.cpp b/proton-c/bindings/cpp/src/value.cpp new file mode 100644 index 0000000..6b4c402 --- /dev/null +++ b/proton-c/bindings/cpp/src/value.cpp @@ -0,0 +1,74 @@ +/* + * 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 "proton_bits.hpp" + +#include "proton/data.hpp" +#include "proton/value.hpp" + +#include <ostream> + +namespace proton { + +value::value() : data_(data::create()) {} + +value::value(const value& x) : data_(data::create()) { *data_ = *x.data_; } + +value::value(const data& x) : data_(data::create()) { *data_ = x; } + +value& value::operator=(const value& x) { *data_ = *x.data_; return *this; } + +value& value::operator=(const data& x) { *data_ = x; return *this; } + +void value::clear() { data_->clear(); } + +bool value::empty() const { return data_->empty(); } + +class encoder& value::encoder() { return data_->encoder(); } + +class decoder& value::decoder() { return data_->decoder(); } + +type_id value::type() const { return rewind().type(); } + +bool value::operator==(const value& x) const { return *data_ == *x.data_; } + +bool value::operator<(const value& x) const { return *data_ < *x.data_; } + + + +std::ostream& operator<<(std::ostream& o, const value& v) { + // pn_inspect prints strings with quotes which is not normal in C++. + switch (v.type()) { + case STRING: + case SYMBOL: + return o << v.get<std::string>(); + default: + return o << *v.data_; + } +} + +class encoder& operator<<(class encoder& e, const value& v) { + return e << *v.data_; +} + +class decoder& operator>>(class decoder& d, value& v) { + return d >> *v.data_; +} + +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1c19ba9e/tests/tools/apps/cpp/reactor_send.cpp ---------------------------------------------------------------------- diff --git a/tests/tools/apps/cpp/reactor_send.cpp b/tests/tools/apps/cpp/reactor_send.cpp index 7064876..6bdab23 100644 --- a/tests/tools/apps/cpp/reactor_send.cpp +++ b/tests/tools/apps/cpp/reactor_send.cpp @@ -48,7 +48,7 @@ class reactor_send : public proton::messaging_handler { size_t received_bytes_; proton::amqp_binary received_content_; bool replying_; - proton::value id_value_; + proton::message_id id_value_; pn_reactor_t *reactor_; public: --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org