You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2015/11/23 18:57:32 UTC

[04/50] [abbrv] qpid-proton git commit: NO-JIRA: c++: added message_id type, minor API cleanup.

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/go1
Commit: 1c19ba9e27f6d0f859f18e6c50088ab44e9ef831
Parents: badf8ef
Author: Alan Conway <ac...@redhat.com>
Authored: Thu Oct 29 14:01:53 2015 -0400
Committer: Alan Conway <ac...@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-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org