Repository: qpid-proton
Updated Branches:
  refs/heads/master d8412be36 -> 9528a77bb


PROTON-1263: c++ add proton::to_string for value and scalar types

Also added for proton::url, since conversion to/from string is common.
Cleaned up value op<< to use the scalar op<< for scalar values.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/9528a77b
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/9528a77b
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/9528a77b

Branch: refs/heads/master
Commit: 9528a77bbb08249d6f6edd0cae5c1745a9a200eb
Parents: d8412be
Author: Alan Conway <[email protected]>
Authored: Wed Jul 20 11:09:22 2016 -0400
Committer: Alan Conway <[email protected]>
Committed: Wed Jul 20 13:04:54 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/cpp/CMakeLists.txt            |  1 +
 .../cpp/include/proton/internal/scalar_base.hpp |  4 ++
 proton-c/bindings/cpp/include/proton/url.hpp    |  5 +-
 proton-c/bindings/cpp/include/proton/value.hpp  | 11 +++-
 proton-c/bindings/cpp/src/interop_test.cpp      |  2 +-
 proton-c/bindings/cpp/src/scalar_base.cpp       | 13 +++-
 proton-c/bindings/cpp/src/scalar_test.hpp       |  2 +-
 proton-c/bindings/cpp/src/url.cpp               |  8 ++-
 proton-c/bindings/cpp/src/url_test.cpp          | 36 +++++++++++
 proton-c/bindings/cpp/src/value.cpp             | 36 +++++------
 proton-c/bindings/cpp/src/value_test.cpp        | 64 +++++++++++++-------
 11 files changed, 131 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9528a77b/proton-c/bindings/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/CMakeLists.txt 
b/proton-c/bindings/cpp/CMakeLists.txt
index 52e7656..1561134 100644
--- a/proton-c/bindings/cpp/CMakeLists.txt
+++ b/proton-c/bindings/cpp/CMakeLists.txt
@@ -181,3 +181,4 @@ add_cpp_test(message_test)
 add_cpp_test(scalar_test)
 add_cpp_test(value_test)
 add_cpp_test(container_test)
+add_cpp_test(url_test)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9528a77b/proton-c/bindings/cpp/include/proton/internal/scalar_base.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/internal/scalar_base.hpp 
b/proton-c/bindings/cpp/include/proton/internal/scalar_base.hpp
index bcd0410..5ba866f 100644
--- a/proton-c/bindings/cpp/include/proton/internal/scalar_base.hpp
+++ b/proton-c/bindings/cpp/include/proton/internal/scalar_base.hpp
@@ -197,6 +197,10 @@ template<class T> struct coerce_op {
 template <class T> T coerce(const scalar_base& s) { return visit<T>(s, 
coerce_op<T>()); }
 
 } // internal
+
+/// Return a readable string representation of x for display purposes.
+std::string to_string(const internal::scalar_base& x);
+
 } // proton
 
 #endif // PROTON_INTERNAL_SCALAR_BASE_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9528a77b/proton-c/bindings/cpp/include/proton/url.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/url.hpp 
b/proton-c/bindings/cpp/include/proton/url.hpp
index 0fabe1e..1ff0bba 100644
--- a/proton-c/bindings/cpp/include/proton/url.hpp
+++ b/proton-c/bindings/cpp/include/proton/url.hpp
@@ -59,7 +59,7 @@ class url {
 
     // XXX No constructor for an empty URL?
     // XXX What is the default 'defaults' behavior?
-    
+
     /// Parse `url_str` as an AMQP URL.
     ///
     /// @note Converts automatically from string.
@@ -119,6 +119,9 @@ class url {
 
     /// @}
 
+    /// Return URL as a string.
+    friend PN_CPP_EXTERN std::string to_string(const url&);
+
   private:
     pn_url_t* url_;
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9528a77b/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 6b4caca..81887ae 100644
--- a/proton-c/bindings/cpp/include/proton/value.hpp
+++ b/proton-c/bindings/cpp/include/proton/value.hpp
@@ -50,7 +50,6 @@ class value_base {
   friend class value_ref;
   friend class codec::encoder;
   friend class codec::decoder;
-  friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const 
value_base&);
 };
 
 } // internal
@@ -108,6 +107,9 @@ class value : public internal::value_base, private 
internal::comparable<value> {
     /// @{
   friend PN_CPP_EXTERN bool operator==(const value& x, const value& y);
   friend PN_CPP_EXTERN bool operator<(const value& x, const value& y);
+    ///@}
+
+  friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const value&);
 };
 
 namespace internal {
@@ -175,7 +177,12 @@ template<class T> void coerce(const value& v, T& x) {
 }
 
 /// Special case for get<null>(), just checks that value contains NULL.
-template<> inline void get<null>(const value& v, null&) { 
assert_type_equal(NULL_TYPE, v.type()); }
+template<> inline void get<null>(const value& v, null&) {
+    assert_type_equal(NULL_TYPE, v.type());
+}
+
+/// Return a readable string representation of x for display purposes.
+std::string to_string(const value& x);
 
 /// @cond INTERNAL
 template<class T> void value::get(T &x) const { x = proton::get<T>(*this); }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9528a77b/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 8a9db5d..de6ae63 100644
--- a/proton-c/bindings/cpp/src/interop_test.cpp
+++ b/proton-c/bindings/cpp/src/interop_test.cpp
@@ -93,7 +93,7 @@ void test_encoder_primitives() {
     e << ::uint32_t(12345) << ::int32_t(-12345);
     e << ::uint64_t(12345) << ::int64_t(-12345);
     e << float(0.125) << double(0.125);
-    ASSERT_EQUAL("true, false, 42, 42, -42, 12345, -12345, 12345, -12345, 
0.125, 0.125", str(str(e)));
+    ASSERT_EQUAL("true, false, 42, 42, -42, 12345, -12345, 12345, -12345, 
0.125, 0.125", str(e));
     std::string data = e.encode();
     ASSERT_EQUAL(read("primitives"), data);
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9528a77b/proton-c/bindings/cpp/src/scalar_base.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/scalar_base.cpp 
b/proton-c/bindings/cpp/src/scalar_base.cpp
index a460e95..c005122 100644
--- a/proton-c/bindings/cpp/src/scalar_base.cpp
+++ b/proton-c/bindings/cpp/src/scalar_base.cpp
@@ -29,6 +29,7 @@
 #include "proton/uuid.hpp"
 
 #include <ostream>
+#include <sstream>
 
 namespace proton {
 namespace internal {
@@ -145,7 +146,7 @@ bool operator<(const scalar_base& x, const scalar_base& y) {
 
 std::ostream& operator<<(std::ostream& o, const scalar_base& s) {
     switch (s.type()) {
-      case NULL_TYPE: return o << "<null>";
+      case NULL_TYPE: return o; // NULL is empty, doesn't print (like empty 
string)
         // Print byte types as integer, not char.
       case BYTE: return o << static_cast<int>(get<int8_t>(s));
       case UBYTE: return o << static_cast<unsigned int>(get<uint8_t>(s));
@@ -158,4 +159,12 @@ conversion_error make_coercion_error(const char* cpp, 
type_id amqp) {
     return conversion_error(std::string("invalid proton::coerce<") + cpp + 
">(" + type_name(amqp) + ")");
 }
 
-}} // namespaces
+} // internal
+
+std::string to_string(const internal::scalar_base& x) {
+    std::ostringstream os;
+    os << std::boolalpha << x;
+    return os.str();
+}
+
+} // proton

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9528a77b/proton-c/bindings/cpp/src/scalar_test.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/scalar_test.hpp 
b/proton-c/bindings/cpp/src/scalar_test.hpp
index 79f66e4..b075c98 100644
--- a/proton-c/bindings/cpp/src/scalar_test.hpp
+++ b/proton-c/bindings/cpp/src/scalar_test.hpp
@@ -70,7 +70,7 @@ template <class V, class T> void simple_type_test(T x, 
type_id tid, const std::s
     ASSERT_EQUAL(x, get<T>(v4));
     ASSERT_EQUAL(x, coerce<T>(v4));
 
-    ASSERT_EQUAL(s, str(vx));   // Stringify
+    ASSERT_EQUAL(s, to_string(vx));   // Stringify
     V vy(y);
     ASSERT(vx != vy);           // Compare
     ASSERT(vx < vy);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9528a77b/proton-c/bindings/cpp/src/url.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/url.cpp 
b/proton-c/bindings/cpp/src/url.cpp
index 34616bd..923aaf0 100644
--- a/proton-c/bindings/cpp/src/url.cpp
+++ b/proton-c/bindings/cpp/src/url.cpp
@@ -100,7 +100,13 @@ uint16_t url::port_int() const {
     return result;
 }
 
-std::ostream& operator<<(std::ostream& o, const url& u) { return o << 
pn_url_str(u.url_); }
+std::ostream& operator<<(std::ostream& o, const url& u) {
+    return o << pn_url_str(u.url_);
+}
+
+std::string to_string(const url& u) {
+    return std::string(pn_url_str(u.url_));
+}
 
 std::istream& operator>>(std::istream& i, url& u) {
     std::string s;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9528a77b/proton-c/bindings/cpp/src/url_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/url_test.cpp 
b/proton-c/bindings/cpp/src/url_test.cpp
new file mode 100644
index 0000000..ad9eca4
--- /dev/null
+++ b/proton-c/bindings/cpp/src/url_test.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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/url.hpp>
+
+namespace {
+
+void parse_to_string_test() {
+    std::string s("amqp://foo:xyz/path");
+    proton::url u(s);
+    ASSERT_EQUAL(to_string(u), s);
+}
+}
+
+int main(int, char**) {
+    int failed = 0;
+    RUN_TEST(failed, parse_to_string_test());
+    return failed;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9528a77b/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
index 7ae59ff..7e7afc5 100644
--- a/proton-c/bindings/cpp/src/value.cpp
+++ b/proton-c/bindings/cpp/src/value.cpp
@@ -25,6 +25,7 @@
 #include "proton/error.hpp"
 
 #include <ostream>
+#include <sstream>
 
 namespace proton {
 
@@ -172,28 +173,15 @@ bool operator<(const value& x, const value& y) {
     return compare(x, y) < 0;
 }
 
-namespace internal {
-std::ostream& operator<<(std::ostream& o, const internal::value_base& x) {
-    if (x.empty())
-        return o << "<null>";
+std::ostream& operator<<(std::ostream& o, const value& x) {
+    if (type_id_is_scalar(x.type()) || x.empty())
+        return o << proton::get<scalar>(x); // Print as a scalar
+    // Use pn_inspect for complex types.
     proton::decoder d(x);
-    // Print the following types with operator<<() consistent with C++.
-    switch (d.next_type()) {
-      case BOOLEAN: return o << get<bool>(d); // Respect std::boolalpha 
settings.
-      case STRING: return o << get<std::string>(d);
-      case SYMBOL: return o << get<symbol>(d);
-      case DECIMAL32: return o << get<decimal32>(d);
-      case DECIMAL64: return o << get<decimal64>(d);
-      case DECIMAL128: return o << get<decimal128>(d);
-      case UUID: return o << get<uuid>(d);
-      case TIMESTAMP: return o << get<timestamp>(d);
-      case CHAR: return o << get<wchar_t>(d);
-      default:
-        // Use pn_inspect for other types.
-        return o << d;
-    }
+    return o << d;
 }
 
+namespace internal {
 value_ref::value_ref(pn_data_t* p) { refer(p); }
 value_ref::value_ref(const internal::data& d) { refer(d); }
 value_ref::value_ref(const value_base& v) { refer(v); }
@@ -203,4 +191,12 @@ void value_ref::refer(const internal::data& d) { data_ = 
d; }
 void value_ref::refer(const value_base& v) { data_ = v.data_; }
 
 void value_ref::reset() { refer(0); }
-}}
+} // namespace internal
+
+std::string to_string(const value& x) {
+    std::ostringstream os;
+    os << std::boolalpha << x;
+    return os.str();
+}
+
+} // namespace proton

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9528a77b/proton-c/bindings/cpp/src/value_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/value_test.cpp 
b/proton-c/bindings/cpp/src/value_test.cpp
index 917753c..596cc6b 100644
--- a/proton-c/bindings/cpp/src/value_test.cpp
+++ b/proton-c/bindings/cpp/src/value_test.cpp
@@ -28,7 +28,9 @@ using test::many;
 using test::scalar_test_group;
 
 // Inserting and extracting arrays from a container T of type U
-template <class T> void sequence_test(type_id tid, const many<typename 
T::value_type>& values) {
+template <class T> void sequence_test(
+    type_id tid, const many<typename T::value_type>& values, const string& s)
+{
     T x(values.begin(), values.end());
 
     value vx(x);                // construct
@@ -58,15 +60,19 @@ template <class T> void sequence_test(type_id tid, const 
many<typename T::value_
     ASSERT(vx != vy);
     ASSERT(vx < vy);
     ASSERT(vy > vx);
+
+    ASSERT_EQUAL(s, to_string(vx));
 }
 
-template <class T, class U> void map_test(const U& values) {
+template <class T, class U> void map_test(const U& values, const string& s) {
     T m(values.begin(), values.end());
     value v(m);
     ASSERT_EQUAL(MAP, v.type());
     T m2(get<T>(v));
     ASSERT_EQUAL(m.size(), m2.size());
     ASSERT_EQUAL(m, m2);
+    if (!s.empty())
+        ASSERT_EQUAL(s, to_string(v));
 }
 
 }
@@ -76,35 +82,47 @@ int main(int, char**) {
     scalar_test_group<value>(failed);
 
     // Sequence tests
-    RUN_TEST(failed, sequence_test<std::list<bool> >(ARRAY, many<bool>() + 
false + true));
-    RUN_TEST(failed, sequence_test<std::vector<int> >(ARRAY, many<int>() + -1 
+ 2));
-    RUN_TEST(failed, sequence_test<std::deque<std::string> >(ARRAY, 
many<std::string>() + "a" + "b"));
-    RUN_TEST(failed, sequence_test<std::deque<symbol> >(ARRAY, many<symbol>() 
+ "a" + "b"));
-    RUN_TEST(failed, sequence_test<std::vector<value> >(LIST, many<value>() + 
value(0) + value("a")));
-    RUN_TEST(failed, sequence_test<std::vector<scalar> >(LIST, many<scalar>() 
+ scalar(0) + scalar("a")));
+    RUN_TEST(failed, sequence_test<list<bool> >(
+                 ARRAY, many<bool>() + false + true, "@PN_BOOL[false, true]"));
+    RUN_TEST(failed, sequence_test<vector<int> >(
+                 ARRAY, many<int>() + -1 + 2, "@PN_INT[-1, 2]"));
+    RUN_TEST(failed, sequence_test<deque<string> >(
+                 ARRAY, many<string>() + "a" + "b", "@PN_STRING[\"a\", 
\"b\"]"));
+    RUN_TEST(failed, sequence_test<deque<symbol> >(
+                 ARRAY, many<symbol>() + "a" + "b", "@PN_SYMBOL[:a, :b]"));
+    RUN_TEST(failed, sequence_test<vector<value> >(
+                 LIST, many<value>() + value(0) + value("a"), "[0, \"a\"]"));
+    RUN_TEST(failed, sequence_test<vector<scalar> >(
+                 LIST, many<scalar>() + scalar(0) + scalar("a"), "[0, 
\"a\"]"));
 
     // // Map tests
-    typedef std::pair<std::string, uint64_t> pair;
-    many<pair> pairs;
-    pairs << pair("a", 0) << pair("b", 1) << pair("c", 2);
+    typedef pair<string, uint64_t> si_pair;
+    many<si_pair> si_pairs;
+    si_pairs << si_pair("a", 0) << si_pair("b", 1) << si_pair("c", 2);
 
-    RUN_TEST(failed, (map_test<std::map<std::string, uint64_t> >(pairs)));
-    RUN_TEST(failed, (map_test<std::vector<pair> >(pairs)));
+    RUN_TEST(failed, (map_test<map<string, uint64_t> >(
+                          si_pairs, "{\"a\"=0, \"b\"=1, \"c\"=2}")));
+    RUN_TEST(failed, (map_test<vector<si_pair> >(
+                          si_pairs, "{\"a\"=0, \"b\"=1, \"c\"=2}")));
 
-    many<std::pair<value,value> > value_pairs(pairs);
-    RUN_TEST(failed, (map_test<std::map<value, value> >(value_pairs)));
+    many<std::pair<value,value> > value_pairs(si_pairs);
+    RUN_TEST(failed, (map_test<map<value, value> >(
+                          value_pairs, "{\"a\"=0, \"b\"=1, \"c\"=2}")));
 
-    many<std::pair<scalar,scalar> > scalar_pairs(pairs);
-    RUN_TEST(failed, (map_test<std::map<scalar, scalar> >(scalar_pairs)));
+    many<pair<scalar,scalar> > scalar_pairs(si_pairs);
+    RUN_TEST(failed, (map_test<map<scalar, scalar> >(
+                          scalar_pairs, "{\"a\"=0, \"b\"=1, \"c\"=2}")));
 
-    annotation_key ak(pairs[0].first);
-    std::pair<annotation_key, message_id> p(pairs[0]);
-    many<std::pair<annotation_key, message_id> > restricted_pairs(pairs);
-    RUN_TEST(failed, (map_test<std::map<annotation_key, message_id> 
>(restricted_pairs)));
+    annotation_key ak(si_pairs[0].first);
+    pair<annotation_key, message_id> p(si_pairs[0]);
+    many<pair<annotation_key, message_id> > restricted_pairs(si_pairs);
+    RUN_TEST(failed, (map_test<map<annotation_key, message_id> >(
+                          restricted_pairs, "{:a=0, :b=1, :c=2}")));
 
 #if PN_CPP_HAS_CPP11
-    RUN_TEST(failed, sequence_test<std::forward_list<binary> >(ARRAY, 
many<binary>() + binary("xx") + binary("yy")));
-    RUN_TEST(failed, (map_test<std::unordered_map<std::string, uint64_t> 
>(pairs)));
+    RUN_TEST(failed, sequence_test<forward_list<binary> >(
+                 ARRAY, many<binary>() + binary("xx") + binary("yy"), 
"@PN_BINARY[b\"xx\", b\"yy\"]"));
+    RUN_TEST(failed, (map_test<unordered_map<string, uint64_t> >(si_pairs, 
"")));
 #endif
     return failed;
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to