Repository: qpid-proton Updated Branches: refs/heads/master 9528a77bb -> f62369d92 (forced update)
PROTON-1263: c++ add proton::to_string for value and scalar types Provides ostream<< representation as a string, with std::boolalpha so boolean prints as true/false. 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/f62369d9 Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/f62369d9 Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/f62369d9 Branch: refs/heads/master Commit: f62369d9219b45ecf12d2cf8a2a2424ce54cb75e 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:28:43 2016 -0400 ---------------------------------------------------------------------- proton-c/bindings/cpp/CMakeLists.txt | 1 + .../cpp/include/proton/codec/encoder.hpp | 6 +- .../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 +++++++++++++------- 12 files changed, 134 insertions(+), 54 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f62369d9/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/f62369d9/proton-c/bindings/cpp/include/proton/codec/encoder.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/codec/encoder.hpp b/proton-c/bindings/cpp/include/proton/codec/encoder.hpp index ac611a4..847e0a9 100644 --- a/proton-c/bindings/cpp/include/proton/codec/encoder.hpp +++ b/proton-c/bindings/cpp/include/proton/codec/encoder.hpp @@ -180,9 +180,9 @@ sfinae::no operator<<(sfinae::wildcard, sfinae::wildcard); // Fallback template<typename T> struct is_encodable : public sfinae { static yes test(encoder); static no test(...); // Failed test, no match. - static encoder &e; - static const T& t; - static bool const value = sizeof(test(e << t)) == sizeof(yes); + static encoder* e; + static const T* t; + static bool const value = sizeof(test(*e << *t)) == sizeof(yes); }; // Avoid recursion http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f62369d9/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..2e491d1 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. +PN_CPP_EXTERN 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/f62369d9/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/f62369d9/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..aa943ed 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. +PN_CPP_EXTERN 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/f62369d9/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/f62369d9/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/f62369d9/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/f62369d9/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/f62369d9/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/f62369d9/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/f62369d9/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]
