Repository: qpid-proton Updated Branches: refs/heads/kvdr-PROTON-1159 a8b63a1c2 -> e15bcdd09
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 new file mode 100644 index 0000000..1220a54 --- /dev/null +++ b/proton-c/bindings/cpp/src/scalar_base.cpp @@ -0,0 +1,158 @@ +/* + * 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 "msg.hpp" +#include "types_internal.hpp" + +#include "proton/binary.hpp" +#include "proton/decimal.hpp" +#include "proton/scalar_base.hpp" +#include "proton/symbol.hpp" +#include "proton/timestamp.hpp" +#include "proton/type_traits.hpp" +#include "proton/uuid.hpp" + +#include <ostream> + +namespace proton { + +scalar_base::scalar_base() { atom_.type = PN_NULL; } +scalar_base::scalar_base(const pn_atom_t& a) { set(a); } +scalar_base::scalar_base(const scalar_base& x) { set(x.atom_); } + +scalar_base& scalar_base::operator=(const scalar_base& x) { + if (this != &x) + set(x.atom_); + return *this; +} + +type_id scalar_base::type() const { return type_id(atom_.type); } + +void scalar_base::set(const binary& x, pn_type_t t) { + atom_.type = t; + bytes_ = x; + atom_.u.as_bytes = pn_bytes(bytes_); +} + +void scalar_base::set(const pn_atom_t& atom) { + if (type_id_is_string_like(type_id(atom.type))) { + set(bin(atom.u.as_bytes), atom.type); + } else { + atom_ = atom; + bytes_.clear(); + } +} + +void scalar_base::put_(bool x) { atom_.u.as_bool = x; atom_.type = PN_BOOL; } +void scalar_base::put_(uint8_t x) { atom_.u.as_ubyte = x; atom_.type = PN_UBYTE; } +void scalar_base::put_(int8_t x) { atom_.u.as_byte = x; atom_.type = PN_BYTE; } +void scalar_base::put_(uint16_t x) { atom_.u.as_ushort = x; atom_.type = PN_USHORT; } +void scalar_base::put_(int16_t x) { atom_.u.as_short = x; atom_.type = PN_SHORT; } +void scalar_base::put_(uint32_t x) { atom_.u.as_uint = x; atom_.type = PN_UINT; } +void scalar_base::put_(int32_t x) { atom_.u.as_int = x; atom_.type = PN_INT; } +void scalar_base::put_(uint64_t x) { atom_.u.as_ulong = x; atom_.type = PN_ULONG; } +void scalar_base::put_(int64_t x) { atom_.u.as_long = x; atom_.type = PN_LONG; } +void scalar_base::put_(wchar_t x) { atom_.u.as_char = x; atom_.type = PN_CHAR; } +void scalar_base::put_(float x) { atom_.u.as_float = x; atom_.type = PN_FLOAT; } +void scalar_base::put_(double x) { atom_.u.as_double = x; atom_.type = PN_DOUBLE; } +void scalar_base::put_(timestamp x) { atom_.u.as_timestamp = x.ms(); atom_.type = PN_TIMESTAMP; } +void scalar_base::put_(const decimal32& x) { byte_copy(atom_.u.as_decimal32, x); atom_.type = PN_DECIMAL32;; } +void scalar_base::put_(const decimal64& x) { byte_copy(atom_.u.as_decimal64, x); atom_.type = PN_DECIMAL64; } +void scalar_base::put_(const decimal128& x) { byte_copy(atom_.u.as_decimal128, x); atom_.type = PN_DECIMAL128; } +void scalar_base::put_(const uuid& x) { byte_copy(atom_.u.as_uuid, x); atom_.type = PN_UUID; } +void scalar_base::put_(const std::string& x) { set(binary(x), PN_STRING); } +void scalar_base::put_(const symbol& x) { set(binary(x), PN_SYMBOL); } +void scalar_base::put_(const binary& x) { set(x, PN_BINARY); } +void scalar_base::put_(const char* x) { set(binary(std::string(x)), PN_STRING); } +void scalar_base::put_(const null&) { atom_.type = PN_NULL; } + +void scalar_base::ok(pn_type_t t) const { + if (atom_.type != t) throw make_conversion_error(type_id(t), type()); +} + +void scalar_base::get_(bool& x) const { ok(PN_BOOL); x = atom_.u.as_bool; } +void scalar_base::get_(uint8_t& x) const { ok(PN_UBYTE); x = atom_.u.as_ubyte; } +void scalar_base::get_(int8_t& x) const { ok(PN_BYTE); x = atom_.u.as_byte; } +void scalar_base::get_(uint16_t& x) const { ok(PN_USHORT); x = atom_.u.as_ushort; } +void scalar_base::get_(int16_t& x) const { ok(PN_SHORT); x = atom_.u.as_short; } +void scalar_base::get_(uint32_t& x) const { ok(PN_UINT); x = atom_.u.as_uint; } +void scalar_base::get_(int32_t& x) const { ok(PN_INT); x = atom_.u.as_int; } +void scalar_base::get_(wchar_t& x) const { ok(PN_CHAR); x = wchar_t(atom_.u.as_char); } +void scalar_base::get_(uint64_t& x) const { ok(PN_ULONG); x = atom_.u.as_ulong; } +void scalar_base::get_(int64_t& x) const { ok(PN_LONG); x = atom_.u.as_long; } +void scalar_base::get_(timestamp& x) const { ok(PN_TIMESTAMP); x = atom_.u.as_timestamp; } +void scalar_base::get_(float& x) const { ok(PN_FLOAT); x = atom_.u.as_float; } +void scalar_base::get_(double& x) const { ok(PN_DOUBLE); x = atom_.u.as_double; } +void scalar_base::get_(decimal32& x) const { ok(PN_DECIMAL32); byte_copy(x, atom_.u.as_decimal32); } +void scalar_base::get_(decimal64& x) const { ok(PN_DECIMAL64); byte_copy(x, atom_.u.as_decimal64); } +void scalar_base::get_(decimal128& x) const { ok(PN_DECIMAL128); byte_copy(x, atom_.u.as_decimal128); } +void scalar_base::get_(uuid& x) const { ok(PN_UUID); byte_copy(x, atom_.u.as_uuid); } +void scalar_base::get_(std::string& x) const { ok(PN_STRING); x = std::string(bytes_.begin(), bytes_.end()); } +void scalar_base::get_(symbol& x) const { ok(PN_SYMBOL); x = symbol(bytes_.begin(), bytes_.end()); } +void scalar_base::get_(binary& x) const { ok(PN_BINARY); x = bytes_; } +void scalar_base::get_(null&) const { ok(PN_NULL); } + +int64_t scalar_base::as_int() const { return internal::coerce<int64_t>(*this); } + +uint64_t scalar_base::as_uint() const { return internal::coerce<uint64_t>(*this); } + +double scalar_base::as_double() const { return internal::coerce<double>(*this); } + +std::string scalar_base::as_string() const { return internal::coerce<std::string>(*this); } + +namespace { + +struct equal_op { + const scalar_base& x; + equal_op(const scalar_base& s) : x(s) {} + template<class T> bool operator()(const T& y) { return (x.get<T>() == y); } +}; + +struct less_op { + const scalar_base& x; + less_op(const scalar_base& s) : x(s) {} + template<class T> bool operator()(const T& y) { return (y < x.get<T>()); } +}; + +struct ostream_op { + std::ostream& o; + ostream_op(std::ostream& o_) : o(o_) {} + template<class T> std::ostream& operator()(const T& x) { return o << x; } +}; + +} // namespace + +bool operator==(const scalar_base& x, const scalar_base& y) { + if (x.type() != y.type()) return false; + if (x.type() == NULL_TYPE) return true; + return internal::visit<bool>(x, equal_op(y)); +} + +bool operator<(const scalar_base& x, const scalar_base& y) { + if (x.type() != y.type()) return x.type() < y.type(); + if (x.type() == NULL_TYPE) return false; + return internal::visit<bool>(x, less_op(y)); +} + +std::ostream& operator<<(std::ostream& o, const scalar_base& s) { + if (s.type() == NULL_TYPE) return o << "<null>"; + return internal::visit<std::ostream&>(s, ostream_op(o)); +} + +} // namespace proton http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/src/scalar_test.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/scalar_test.cpp b/proton-c/bindings/cpp/src/scalar_test.cpp index 9b2df1f..b5955d5 100644 --- a/proton-c/bindings/cpp/src/scalar_test.cpp +++ b/proton-c/bindings/cpp/src/scalar_test.cpp @@ -60,13 +60,10 @@ template <class T> void type_test(T x, type_id tid, T y) { try { \ (void)(EXPR); \ FAIL("expected conversion_error: " #EXPR); \ - } catch (const conversion_error& e) { \ - std::ostringstream want; \ - want << "unexpected type, want: " << (WANT) << " got: " << (GOT); \ - ASSERT_EQUAL(want.str(), std::string(e.what())); \ - } + } catch (const conversion_error& e) {} -void convert_test() { +// FIXME aconway 2016-03-15: new coerce stuff. +void coerce_test() { scalar a; ASSERT_EQUAL(NULL_TYPE, a.type()); ASSERT(a.empty()); @@ -98,8 +95,8 @@ void encode_decode_test() { scalar a("foo"); v = a; // Assignment to value does encode, get<> does decode. ASSERT_EQUAL(v, a); - ASSERT_EQUAL(std::string("foo"), v.get<std::string>()); - scalar a2 = v.get<scalar>(); + ASSERT_EQUAL(std::string("foo"), get<std::string>(v)); + scalar a2 = get<scalar>(v); ASSERT_EQUAL(std::string("foo"), a2.get<std::string>()); } @@ -149,6 +146,6 @@ int main(int, char**) { RUN_TEST(failed, encode_decode_test()); RUN_TEST(failed, message_id_test()); RUN_TEST(failed, annotation_key_test()); - RUN_TEST(failed, convert_test()); + RUN_TEST(failed, coerce_test()); return failed; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/src/ssl.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/ssl.cpp b/proton-c/bindings/cpp/src/ssl.cpp index 384c331..62a234f 100644 --- a/proton-c/bindings/cpp/src/ssl.cpp +++ b/proton-c/bindings/cpp/src/ssl.cpp @@ -59,7 +59,7 @@ std::string ssl::peer_hostname() const { if (pn_ssl_get_peer_hostname(object_, NULL, &len) || len == 0) return hostname; hostname.reserve(len); - if (!pn_ssl_get_peer_hostname(object_, const_cast<char *>(hostname.data()), &len)) + if (!pn_ssl_get_peer_hostname(object_, const_cast<char*>(hostname.c_str()), &len)) hostname.resize(len - 1); else hostname.resize(0); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 d45739c..38cd7a8 100644 --- a/proton-c/bindings/cpp/src/test_bits.hpp +++ b/proton-c/bindings/cpp/src/test_bits.hpp @@ -26,15 +26,22 @@ #include <iostream> #include <iterator> #include <sstream> +#include <math.h> namespace test { struct fail : public std::logic_error { fail(const std::string& what) : logic_error(what) {} }; +bool close(double want, double got, double delta) { + return fabs(want-got) <= delta; +} + #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))) \ FAIL(#WANT << " != " << #GOT << ": " << (WANT) << " != " << (GOT)) +#define ASSERT_CLOSE(WANT, GOT, DELTA) if (!close((WANT), (GOT), (DELTA))) \ + FAIL(#WANT << " != " << #GOT << ": " << (WANT) << " != " << (GOT)) #define RUN_TEST(BAD_COUNT, TEST) \ do { \ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/src/types_internal.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/types_internal.hpp b/proton-c/bindings/cpp/src/types_internal.hpp index c3ad1d4..74427a1 100644 --- a/proton-c/bindings/cpp/src/types_internal.hpp +++ b/proton-c/bindings/cpp/src/types_internal.hpp @@ -31,7 +31,7 @@ namespace proton { /// Byte copy between two objects, only enabled if their sizes are equal. template <class T, class U> -typename codec::enable_if<sizeof(T) == sizeof(U)>::type byte_copy(T &to, const U &from) { +typename internal::enable_if<sizeof(T) == sizeof(U)>::type byte_copy(T &to, const U &from) { const char *p = reinterpret_cast<const char*>(&from); std::copy(p, p + sizeof(T), reinterpret_cast<char*>(&to)); } @@ -51,23 +51,13 @@ inline pn_bytes_t pn_bytes(const std::string& s) { } inline pn_bytes_t pn_bytes(const binary& s) { - pn_bytes_t b = { s.size(), const_cast<char*>(&s[0]) }; + pn_bytes_t b = { s.size(), reinterpret_cast<const char*>(&s[0]) }; return b; } inline std::string str(const pn_bytes_t& b) { return std::string(b.start, b.size); } inline binary bin(const pn_bytes_t& b) { return binary(b.start, b.start+b.size); } -inline bool type_id_is_signed_int(type_id t) { return t == BYTE || t == SHORT || t == INT || t == LONG; } -inline bool type_id_is_unsigned_int(type_id t) { return t == UBYTE || t == USHORT || t == UINT || t == ULONG; } -inline bool type_id_is_integral(type_id t) { return t == BOOLEAN || t == CHAR || t == TIMESTAMP || type_id_is_unsigned_int(t) || type_id_is_signed_int(t); } -inline bool type_id_is_floating_point(type_id t) { return t == FLOAT || t == DOUBLE; } -inline bool type_id_is_decimal(type_id t) { return t == DECIMAL32 || t == DECIMAL64 || t == DECIMAL128; } -inline bool type_id_is_signed(type_id t) { return type_id_is_signed_int(t) || type_id_is_floating_point(t) || type_id_is_decimal(t); } -inline bool type_id_is_string_like(type_id t) { return t == BINARY || t == STRING || t == SYMBOL; } -inline bool type_id_is_container(type_id t) { return t == LIST || t == MAP || t == ARRAY || t == DESCRIBED; } -inline bool type_id_is_scalar(type_id t) { return type_id_is_integral(t) || type_id_is_floating_point(t) || type_id_is_decimal(t) || type_id_is_string_like(t) || t == TIMESTAMP || t == UUID; } - } #endif // CODEC_HPP http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 bece42c..ba2f540 100644 --- a/proton-c/bindings/cpp/src/value.cpp +++ b/proton-c/bindings/cpp/src/value.cpp @@ -31,7 +31,6 @@ namespace proton { using namespace codec; value::value() {} -value::value(const null&) {} value::value(const value& x) { *this = x; } value::value(const codec::data& x) { if (!x.empty()) data().copy(x); } #if PN_CPP_HAS_CPP11 @@ -39,8 +38,6 @@ value::value(value&& x) { swap(*this, x); } value& value::operator=(value&& x) { swap(*this, x); return *this; } #endif -value& value::operator=(const null&) { clear(); return *this; } - value& value::operator=(const value& x) { if (this != &x) { if (x.empty()) @@ -176,27 +173,17 @@ std::ostream& operator<<(std::ostream& o, const value_base& x) { decoder d(x); // Print std::string and proton::foo types using their own operator << consistent with C++. switch (d.next_type()) { - case STRING: return o << d.extract<std::string>(); - case SYMBOL: return o << d.extract<symbol>(); - case DECIMAL32: return o << d.extract<decimal32>(); - case DECIMAL64: return o << d.extract<decimal64>(); - case DECIMAL128: return o << d.extract<decimal128>(); - case UUID: return o << d.extract<uuid>(); - case TIMESTAMP: return o << d.extract<timestamp>(); + 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); default: // Use pn_inspect for other types. return o << d; } } -void value::get(null&) const { - if (type() != NULL_TYPE) - throw conversion_error("value is not null"); -} - -int64_t value::as_int() const { return get<scalar>().as_int(); } -uint64_t value::as_uint() const { return get<scalar>().as_uint(); } -double value::as_double() const { return get<scalar>().as_double(); } -std::string value::as_string() const { return get<scalar>().as_string(); } - } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 be24da4..fe7c089 100644 --- a/proton-c/bindings/cpp/src/value_test.cpp +++ b/proton-c/bindings/cpp/src/value_test.cpp @@ -60,8 +60,8 @@ template <class T> void simple_type_test(T x, type_id tid, const std::string& s, } template <class T> void simple_integral_test() { - typedef typename codec::integer_type<sizeof(T), codec::is_signed<T>::value>::type int_type; - simple_type_test(T(3), codec::type_id_of<int_type>::value, "3", T(4)); + typedef typename internal::integer_type<sizeof(T), internal::is_signed<T>::value>::type int_type; + simple_type_test(T(3), internal::type_id_of<int_type>::value, "3", T(4)); } // Inserting and extracting arrays from a container T of type U @@ -90,7 +90,7 @@ template <class T, class U> void map_test(const U& values) { T m(values.begin(), values.end()); value v(m); ASSERT_EQUAL(MAP, v.type()); - T m2(v.get<T>()); + T m2(get<T>(v)); ASSERT_EQUAL(m.size(), m2.size()); ASSERT_EQUAL(m, m2); } @@ -103,18 +103,50 @@ void null_test() { value v; ASSERT(v.empty()); ASSERT_EQUAL(NULL_TYPE, v.type()); + get<null>(v); null n; - v.get(n); + get(v, n); value v2(n); ASSERT(v.empty()); ASSERT_EQUAL(NULL_TYPE, v.type()); v = "foo"; ASSERT_EQUAL(STRING, v.type()); - try { v.get<null>(); FAIL("Expected conversion_error"); } catch (conversion_error) {} + try { get<null>(v); FAIL("Expected conversion_error"); } catch (conversion_error) {} v = null(); - v.get<null>(); + get<null>(v); } +void get_coerce_test() { + // Valid conversions + ASSERT_EQUAL(true, coerce<bool>(value(true))); + + ASSERT_EQUAL(1, coerce<uint8_t>(value(uint8_t(1)))); + ASSERT_EQUAL(-1, coerce<int8_t>(value(int8_t(-1)))); + + ASSERT_EQUAL(2, coerce<uint16_t>(value(uint8_t(2)))); + ASSERT_EQUAL(-2, coerce<int16_t>(value(int8_t(-2)))); + + ASSERT_EQUAL(3, coerce<uint32_t>(value(uint16_t(3)))); + ASSERT_EQUAL(-3, coerce<int32_t>(value(int16_t(-3)))); + + ASSERT_EQUAL(4, coerce<uint64_t>(value(uint32_t(4)))); + ASSERT_EQUAL(-4, coerce<int64_t>(value(int32_t(-4)))); + + ASSERT_CLOSE(1.2, coerce<float>(value(double(1.2))), 0.001); + ASSERT_CLOSE(3.4, coerce<double>(value(float(3.4))), 0.001); + + ASSERT_EQUAL(std::string("foo"), coerce<std::string>(value(symbol("foo")))); + + // Bad conversions + try { get<bool>(value(int8_t(1))); FAIL("byte as bool"); } catch (conversion_error) {} + try { get<uint8_t>(value(true)); FAIL("bool as uint8_t"); } catch (conversion_error) {} + try { get<uint8_t>(value(int8_t(1))); FAIL("int8 as uint8"); } catch (conversion_error) {} + try { get<int16_t>(value(uint16_t(1))); FAIL("uint16 as int16"); } catch (conversion_error) {} + try { get<int16_t>(value(int32_t(1))); FAIL("int32 as int16"); } catch (conversion_error) {} + try { get<symbol>(value(std::string())); FAIL("string as symbol"); } catch (conversion_error) {} +} + + int main(int, char**) { int failed = 0; RUN_TEST(failed, simple_type_test(false, BOOLEAN, "false", true)); @@ -188,6 +220,6 @@ int main(int, char**) { RUN_TEST(failed, (map_test<std::unordered_map<std::string, uint64_t> >(pairs))); #endif - value vv((pn_data_t*)(0)); + RUN_TEST(failed, get_coerce_test()); return failed; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 3ba26e8..224ac71 100644 --- a/tests/tools/apps/cpp/reactor_send.cpp +++ b/tests/tools/apps/cpp/reactor_send.cpp @@ -91,7 +91,7 @@ class reactor_send : public proton::handler { void on_message(proton::event &e) { proton::message &msg = e.message(); - received_content_ = msg.body().get<proton::binary>(); + received_content_ = proton::get<proton::binary>(msg.body()); received_bytes_ += received_content_.size(); if (received_ < total_) { received_++; --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
