http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1622d0e6/proton-c/bindings/cpp/src/scalar.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/scalar.cpp b/proton-c/bindings/cpp/src/scalar.cpp index 13daf32..9e8d124 100644 --- a/proton-c/bindings/cpp/src/scalar.cpp +++ b/proton-c/bindings/cpp/src/scalar.cpp @@ -17,6 +17,7 @@ * under the License. */ +#include "msg.hpp" #include "proton/scalar.hpp" #include "proton/type_traits.hpp" @@ -25,37 +26,50 @@ namespace proton { scalar::scalar() { atom_.type = PN_NULL; } +scalar::scalar(const scalar& x) { set(x.atom_); } +scalar& scalar::operator=(const scalar& x) { set(x.atom_); return *this; } type_id scalar::type() const { return type_id(atom_.type); } bool scalar::empty() const { return type() == NULL_TYPE; } -scalar::scalar(bool x) { atom_.u.as_bool = x; atom_.type = PN_BOOL; } -scalar::scalar(uint8_t x) { atom_.u.as_ubyte = x; atom_.type = PN_UBYTE; } -scalar::scalar(int8_t x) { atom_.u.as_byte = x; atom_.type = PN_BYTE; } -scalar::scalar(uint16_t x) { atom_.u.as_ushort = x; atom_.type = PN_USHORT; } -scalar::scalar(int16_t x) { atom_.u.as_short = x; atom_.type = PN_SHORT; } -scalar::scalar(uint32_t x) { atom_.u.as_uint = x; atom_.type = PN_UINT; } -scalar::scalar(int32_t x) { atom_.u.as_int = x; atom_.type = PN_INT; } -scalar::scalar(uint64_t x) { atom_.u.as_ulong = x; atom_.type = PN_ULONG; } -scalar::scalar(int64_t x) { atom_.u.as_long = x; atom_.type = PN_LONG; } -scalar::scalar(wchar_t x) { atom_.u.as_char = pn_char_t(x); atom_.type = PN_CHAR; } -scalar::scalar(float x) { atom_.u.as_float = x; atom_.type = PN_FLOAT; } -scalar::scalar(double x) { atom_.u.as_double = x; atom_.type = PN_DOUBLE; } -scalar::scalar(amqp_timestamp x) { atom_.u.as_timestamp = x; atom_.type = PN_TIMESTAMP; } -scalar::scalar(const amqp_decimal32& x) { atom_.u.as_decimal32 = x; atom_.type = PN_DECIMAL32; } -scalar::scalar(const amqp_decimal64& x) { atom_.u.as_decimal64 = x; atom_.type = PN_DECIMAL64; } -scalar::scalar(const amqp_decimal128& x) { atom_.u.as_decimal128 = x; atom_.type = PN_DECIMAL128; } -scalar::scalar(const amqp_uuid& x) { atom_.u.as_uuid = x; atom_.type = PN_UUID; } - -void scalar::set(const std::string& x) { str_ = x; atom_.u.as_bytes = pn_bytes(str_); } -scalar::scalar(const amqp_string& x) { set(x); atom_.type = PN_STRING; } -scalar::scalar(const amqp_symbol& x) { set(x); atom_.type = PN_SYMBOL; } -scalar::scalar(const amqp_binary& x) { set(x); atom_.type = PN_BINARY; } -scalar::scalar(const std::string& x) { *this = amqp_string(x); } -scalar::scalar(const char* x) { *this = amqp_string(x); } +void scalar::set(const std::string& x, pn_type_t t) { + atom_.type = t; + str_ = x; + atom_.u.as_bytes = pn_bytes(str_); +} + +void scalar::set(const pn_atom_t& atom) { + if (type_id_is_string_like(type_id(atom.type))) + set(str(atom.u.as_bytes), atom.type); + else + atom_ = atom; +} + +scalar& scalar::operator=(bool x) { atom_.u.as_bool = x; atom_.type = PN_BOOL; return *this; } +scalar& scalar::operator=(uint8_t x) { atom_.u.as_ubyte = x; atom_.type = PN_UBYTE; return *this; } +scalar& scalar::operator=(int8_t x) { atom_.u.as_byte = x; atom_.type = PN_BYTE; return *this; } +scalar& scalar::operator=(uint16_t x) { atom_.u.as_ushort = x; atom_.type = PN_USHORT; return *this; } +scalar& scalar::operator=(int16_t x) { atom_.u.as_short = x; atom_.type = PN_SHORT; return *this; } +scalar& scalar::operator=(uint32_t x) { atom_.u.as_uint = x; atom_.type = PN_UINT; return *this; } +scalar& scalar::operator=(int32_t x) { atom_.u.as_int = x; atom_.type = PN_INT; return *this; } +scalar& scalar::operator=(uint64_t x) { atom_.u.as_ulong = x; atom_.type = PN_ULONG; return *this; } +scalar& scalar::operator=(int64_t x) { atom_.u.as_long = x; atom_.type = PN_LONG; return *this; } +scalar& scalar::operator=(wchar_t x) { atom_.u.as_char = x; atom_.type = PN_CHAR; return *this; } +scalar& scalar::operator=(float x) { atom_.u.as_float = x; atom_.type = PN_FLOAT; return *this; } +scalar& scalar::operator=(double x) { atom_.u.as_double = x; atom_.type = PN_DOUBLE; return *this; } +scalar& scalar::operator=(amqp_timestamp x) { atom_.u.as_timestamp = x; atom_.type = PN_TIMESTAMP; return *this; } +scalar& scalar::operator=(const amqp_decimal32& x) { atom_.u.as_decimal32 = x; atom_.type = PN_DECIMAL32; return *this; } +scalar& scalar::operator=(const amqp_decimal64& x) { atom_.u.as_decimal64 = x; atom_.type = PN_DECIMAL64; return *this; } +scalar& scalar::operator=(const amqp_decimal128& x) { atom_.u.as_decimal128 = x; atom_.type = PN_DECIMAL128; return *this; } +scalar& scalar::operator=(const amqp_uuid& x) { atom_.u.as_uuid = x; atom_.type = PN_UUID; return *this; } +scalar& scalar::operator=(const amqp_string& x) { set(x, PN_STRING); return *this; } +scalar& scalar::operator=(const amqp_symbol& x) { set(x, PN_SYMBOL); return *this; } +scalar& scalar::operator=(const amqp_binary& x) { set(x, PN_BINARY); return *this; } +scalar& scalar::operator=(const std::string& x) { set(x, PN_STRING); return *this; } +scalar& scalar::operator=(const char* x) { set(x, PN_STRING); return *this; } void scalar::ok(pn_type_t t) const { - if (atom_.type != t) throw type_mismatch(type_id(t), type()); + if (atom_.type != t) throw type_error(type_id(t), type()); } void scalar::get(bool& x) const { ok(PN_BOOL); x = atom_.u.as_bool; } @@ -75,9 +89,9 @@ void scalar::get(amqp_decimal32& x) const { ok(PN_DECIMAL32); x = atom_.u.as_dec void scalar::get(amqp_decimal64& x) const { ok(PN_DECIMAL64); x = atom_.u.as_decimal64; } void scalar::get(amqp_decimal128& x) const { ok(PN_DECIMAL128); x = atom_.u.as_decimal128; } void scalar::get(amqp_uuid& x) const { ok(PN_UUID); x = atom_.u.as_uuid; } -void scalar::get(amqp_string& x) const { ok(PN_STRING); x = str_; } -void scalar::get(amqp_symbol& x) const { ok(PN_SYMBOL); x = str_; } -void scalar::get(amqp_binary& x) const { ok(PN_BINARY); x = str_; } +void scalar::get(amqp_string& x) const { ok(PN_STRING); x = amqp_string(str_); } +void scalar::get(amqp_symbol& x) const { ok(PN_SYMBOL); x = amqp_symbol(str_); } +void scalar::get(amqp_binary& x) const { ok(PN_BINARY); x = amqp_binary(str_); } void scalar::get(std::string& x) const { x = get<amqp_string>(); } int64_t scalar::as_int() const { @@ -94,13 +108,14 @@ int64_t scalar::as_int() const { case PN_CHAR: return atom_.u.as_char; case PN_ULONG: return int64_t(atom_.u.as_ulong); case PN_LONG: return atom_.u.as_long; - default: throw type_mismatch(LONG, type(), "cannot convert"); + case PN_TIMESTAMP: return atom_.u.as_timestamp; + default: throw type_error(LONG, type(), "cannot convert"); } } uint64_t scalar::as_uint() const { if (!type_id_is_integral(type())) - throw type_mismatch(ULONG, type(), "cannot convert"); + throw type_error(ULONG, type(), "cannot convert"); return uint64_t(as_int()); } @@ -111,18 +126,19 @@ double scalar::as_double() const { switch (atom_.type) { case PN_DOUBLE: return atom_.u.as_double; case PN_FLOAT: return atom_.u.as_float; - default: throw type_mismatch(DOUBLE, type(), "cannot convert"); + default: throw type_error(DOUBLE, type(), "cannot convert"); } } std::string scalar::as_string() const { if (type_id_is_string_like(type())) return str_; - throw type_mismatch(DOUBLE, type(), "cannot convert"); + throw type_error(STRING, type(), "cannot convert"); } - namespace { +template<class T> int opaque_cmp(const T& x, const T& y) { return memcmp(&x, &y, sizeof(T)); } + template <class T, class F> T type_switch(const scalar& a, F f) { switch(a.type()) { case BOOLEAN: return f(a.get<bool>()); @@ -170,16 +186,21 @@ struct ostream_op { } // namespace -bool scalar::operator==(const scalar& x) const { - return type_switch<bool>(*this, equal_op(x)); +bool operator==(const scalar& x, const scalar& y) { + if (x.type() != y.type()) return false; + if (x.empty()) return true; + return type_switch<bool>(x, equal_op(y)); } -bool scalar::operator<(const scalar& x) const { - return type_switch<bool>(*this, less_op(x)); +bool operator<(const scalar& x, const scalar& y) { + if (x.type() != y.type()) return x.type() < y.type(); + if (x.empty()) return false; + return type_switch<bool>(x, less_op(y)); } std::ostream& operator<<(std::ostream& o, const scalar& a) { + if (a.empty()) return o << "<null>"; return type_switch<std::ostream&>(a, ostream_op(o)); } -} +} // namespace proton
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1622d0e6/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 c7de785..cb66e41 100644 --- a/proton-c/bindings/cpp/src/scalar_test.cpp +++ b/proton-c/bindings/cpp/src/scalar_test.cpp @@ -21,51 +21,62 @@ #include "proton/type_traits.hpp" #include <proton/scalar.hpp> +#include <proton/value.hpp> +#include <proton/message_id.hpp> +#include <proton/annotation_key.hpp> + +#include <sstream> using namespace std; using namespace proton; // Inserting and extracting simple C++ values. template <class T> void type_test(T x, type_id tid, T y) { - scalar v(x); - ASSERT_EQUAL(tid, v.type()); - ASSERT(!v.empty()); - ASSERT_EQUAL(x, v.get<T>()); + scalar s(x); + ASSERT_EQUAL(tid, s.type()); + ASSERT(!s.empty()); + ASSERT_EQUAL(x, s.get<T>()); scalar v2; ASSERT(v2.type() == NULL_TYPE); v2 = x; ASSERT_EQUAL(tid, v2.type()); ASSERT_EQUAL(x, v2.get<T>()); - ASSERT_EQUAL(v, v2); - ASSERT_EQUAL(str(x), str(v)); + ASSERT_EQUAL(s, v2); + ASSERT_EQUAL(str(x), str(s)); v2 = y; - ASSERT(v != v2); - ASSERT(v < v2); - ASSERT(v2 > v); + ASSERT(s != v2); + ASSERT(s < v2); + ASSERT(v2 > s); } -#define ASSERT_MISMATCH(EXPR) \ - try { (void)(EXPR); FAIL("expected type_mismatch: " #EXPR); } catch (type_mismatch) {} +#define ASSERT_MISMATCH(EXPR, WANT, GOT) \ + try { \ + (void)(EXPR); \ + FAIL("expected type_error: " #EXPR); \ + } catch (const type_error& e) { \ + ASSERT_EQUAL(WANT, e.want); \ + ASSERT_EQUAL(GOT, e.got); \ + } void convert_test() { scalar a; ASSERT_EQUAL(NULL_TYPE, a.type()); ASSERT(a.empty()); - ASSERT_MISMATCH(a.get<float>()); + ASSERT_MISMATCH(a.get<float>(), FLOAT, NULL_TYPE); a = amqp_binary("foo"); - ASSERT_MISMATCH(a.get<int16_t>()); - ASSERT_MISMATCH(a.as_int()); - ASSERT_MISMATCH(a.as_double()); - ASSERT_MISMATCH(a.get<amqp_string>()); // No strict conversion + ASSERT_MISMATCH(a.get<int16_t>(), SHORT, BINARY); + ASSERT_MISMATCH(a.as_int(), LONG, BINARY); + ASSERT_MISMATCH(a.as_double(), DOUBLE, BINARY); + ASSERT_MISMATCH(a.get<amqp_string>(), STRING, BINARY); // No strict conversion ASSERT_EQUAL(a.as_string(), std::string("foo")); // OK string-like conversion a = int16_t(42); - ASSERT_MISMATCH(a.get<std::string>()); - ASSERT_MISMATCH(a.get<amqp_timestamp>()); - ASSERT_MISMATCH(a.as_string()); + ASSERT_MISMATCH(a.get<std::string>(), STRING, SHORT); + ASSERT_MISMATCH(a.get<amqp_timestamp>(), TIMESTAMP, SHORT); + ASSERT_MISMATCH(a.as_string(), STRING, SHORT); ASSERT_EQUAL(a.as_int(), 42); ASSERT_EQUAL(a.as_uint(), 42); ASSERT_EQUAL(a.as_double(), 42); @@ -76,6 +87,33 @@ void convert_test() { ASSERT_EQUAL(a.as_double(), -42); } +void encode_decode_test() { + value v; + 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"), a2.get<std::string>()); +} + +void message_id_test() { + ASSERT_EQUAL(23, message_id(23).as_int()); + ASSERT_EQUAL(23, message_id(23).get<uint64_t>()); + ASSERT(message_id("foo") != message_id(amqp_binary("foo"))); + ASSERT_EQUAL(scalar("foo"), message_id("foo")); + ASSERT_EQUAL("foo", message_id("foo").as_string()); + ASSERT(message_id("a") < message_id("z")); + ASSERT_EQUAL(amqp_uuid(), message_id(amqp_uuid()).get<amqp_uuid>()); +} + +void annotation_key_test() { + ASSERT_EQUAL(23, annotation_key(23).as_int()); + ASSERT_EQUAL(23, annotation_key(23).get<uint64_t>()); + ASSERT_EQUAL("foo", annotation_key("foo").as_string()); + ASSERT_EQUAL(scalar(amqp_symbol("foo")), annotation_key("foo")); +} + int main(int, char**) { int failed = 0; RUN_TEST(failed, type_test(false, BOOLEAN, true)); @@ -101,5 +139,9 @@ int main(int, char**) { RUN_TEST(failed, type_test(amqp_symbol("aaa"), SYMBOL, amqp_symbol("aaaa"))); RUN_TEST(failed, type_test(amqp_binary("aaa"), BINARY, amqp_binary("aaaa"))); RUN_TEST(failed, type_test(std::string("xxx"), STRING, std::string("yyy"))); + RUN_TEST(failed, encode_decode_test()); + RUN_TEST(failed, message_id_test()); + RUN_TEST(failed, annotation_key_test()); + RUN_TEST(failed, convert_test()); return failed; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1622d0e6/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 fa7b0bd..7a38f12 100644 --- a/proton-c/bindings/cpp/src/types.cpp +++ b/proton-c/bindings/cpp/src/types.cpp @@ -33,20 +33,18 @@ inline std::ostream& print_segment(std::ostream& o, const amqp_uuid& u, size_t b return o << sep; } -std::string mismatch_message(type_id want, type_id got, const std::string& msg=std::string()) -{ +std::string mismatch_message(type_id want, type_id got, const std::string& msg=std::string()) { std::ostringstream s; - s << "type mismatch: want " << type_name(want) << " got " << type_name(got); + s << "want " << want << " got " << got; if (!msg.empty()) s << ": " << msg; return s.str(); } -} +} // namespace -type_mismatch::type_mismatch(type_id want_, type_id got_, const std::string &msg) - : error(mismatch_message(want_, got_, msg)), want(want_), got(got_) +type_error::type_error(type_id want_, type_id got_, const std::string &msg) + : decode_error(mismatch_message(want_, got_, msg)), want(want_), got(got_) {} - std::ostream& operator<<(std::ostream& o, const amqp_decimal32&) { return o << "<decimal32>"; } std::ostream& operator<<(std::ostream& o, const amqp_decimal64&) { return o << "<decimal64>"; } std::ostream& operator<<(std::ostream& o, const amqp_decimal128&) { return o << "<decimal128>"; } @@ -95,9 +93,9 @@ std::string type_name(type_id t) { return "unknown"; } -static bool type_id_is_signed_int(type_id t) { return t == BYTE || t == SHORT || t == INT || t == LONG; } -static bool type_id_is_unsigned_int(type_id t) { return t == UBYTE || t == USHORT || t == UINT || t == ULONG; } -bool type_id_is_integral(type_id t) { return t == BOOLEAN || t == CHAR || type_id_is_unsigned_int(t) || type_id_is_signed_int(t); } +bool type_id_is_signed_int(type_id t) { return t == BYTE || t == SHORT || t == INT || t == LONG; } +bool type_id_is_unsigned_int(type_id t) { return t == UBYTE || t == USHORT || t == UINT || t == ULONG; } +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); } bool type_id_is_floating_point(type_id t) { return t == FLOAT || t == DOUBLE; } bool type_id_is_decimal(type_id t) { return t == DECIMAL32 || t == DECIMAL64 || t == DECIMAL128; } 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); } @@ -106,7 +104,7 @@ bool type_id_is_container(type_id t) { return t == LIST || t == MAP || t == ARRA 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; } -std::ostream& operator<<(std::ostream& o,type_id t) { return o << type_name(t); } +std::ostream& operator<<(std::ostream& o, type_id t) { return o << type_name(t); } pn_bytes_t pn_bytes(const std::string& s) { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1622d0e6/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 b603bf9..bf652c5 100644 --- a/proton-c/bindings/cpp/src/value.cpp +++ b/proton-c/bindings/cpp/src/value.cpp @@ -30,8 +30,20 @@ value::value() : data_(data::create()) {} value::value(const value& x) : data_(data::create()) { data_.copy(x.data_); } +#if PN_HAS_CPP11 +value::value(value&& x) : data_(0) { swap(x); } +#endif + +// Referencing an external value +value::value(data d) : data_(d) {} + +// Referencing an external value +value& value::ref(data d) { data_ = d; return *this; } + value& value::operator=(const value& x) { data_.copy(x.data_); return *this; } +void value::swap(value& x) { std::swap(data_, x.data_); } + void value::clear() { data_.clear(); } bool value::empty() const { return data_.empty(); } @@ -48,6 +60,8 @@ bool value::operator<(const value& x) const { return data_.less(x.data_); } std::ostream& operator<<(std::ostream& o, const value& v) { // pn_inspect prints strings with quotes which is not normal in C++. + if (v.empty()) + return o << "<empty>"; switch (v.type()) { case STRING: case SYMBOL: --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
