http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/error.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/error.hpp b/proton-c/bindings/cpp/include/proton/error.hpp index 0d3a2f5..dd30867 100644 --- a/proton-c/bindings/cpp/include/proton/error.hpp +++ b/proton-c/bindings/cpp/include/proton/error.hpp @@ -36,19 +36,19 @@ namespace proton { /// subclasses of proton::error. struct PN_CPP_CLASS_EXTERN error : public std::runtime_error { - PN_CPP_EXTERN explicit error(const std::string&); + PN_CPP_EXTERN explicit error(const std::string&); ///< Construct with message }; /// Raised if a timeout expires. struct PN_CPP_CLASS_EXTERN timeout_error : public error { - PN_CPP_EXTERN explicit timeout_error(const std::string&); + PN_CPP_EXTERN explicit timeout_error(const std::string&); ///< Construct with message }; /// Raised if there is an error converting between AMQP and C++ data. struct PN_CPP_CLASS_EXTERN conversion_error : public error { - PN_CPP_EXTERN explicit conversion_error(const std::string&); + PN_CPP_EXTERN explicit conversion_error(const std::string&); ///< Construct with message }; }
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/forward_list.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/forward_list.hpp b/proton-c/bindings/cpp/include/proton/forward_list.hpp index 9358da9..00e3b2c 100644 --- a/proton-c/bindings/cpp/include/proton/forward_list.hpp +++ b/proton-c/bindings/cpp/include/proton/forward_list.hpp @@ -30,7 +30,7 @@ namespace codec { /// std::forward_list<T> for most T is encoded as an AMQP array. template <class T, class A> encoder& operator<<(encoder& e, const std::forward_list<T, A>& x) { - return e << encoder::array(x, type_id_of<T>::value); + return e << encoder::array(x, internal::type_id_of<T>::value); } /// Specialize for std::forward_list<value>, encode as AMQP forward_list (variable type) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/io.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/io.hpp b/proton-c/bindings/cpp/include/proton/io.hpp index 35a7223..9c63edb 100644 --- a/proton-c/bindings/cpp/include/proton/io.hpp +++ b/proton-c/bindings/cpp/include/proton/io.hpp @@ -25,6 +25,7 @@ namespace proton { +///@details /// IO using sockets, file descriptors, or handles, for use with /// proton::connection_engine. /// @@ -32,7 +33,6 @@ namespace proton { /// over your own IO implementation or to integrate an existing IO framework of /// your choice, this implementation is provided as a convenience if sockets is /// sufficient for your needs. - namespace io { /// @name Setup and teardown @@ -67,6 +67,7 @@ struct guard { /// An IO resource. typedef int64_t descriptor; +/// An invalid descriptor. PN_CPP_EXTERN extern const descriptor INVALID_DESCRIPTOR; /// Return a string describing the most recent IO error. http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/link.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/link.hpp b/proton-c/bindings/cpp/include/proton/link.hpp index e626398..8de2e7b 100644 --- a/proton-c/bindings/cpp/include/proton/link.hpp +++ b/proton-c/bindings/cpp/include/proton/link.hpp @@ -124,12 +124,14 @@ PN_CPP_CLASS_EXTERN link : public internal::object<pn_link_t> , public endpoint /// Session that owns this link. PN_CPP_EXTERN class session session() const; + ///@cond INTERNAL /// XXX local versus remote, mutability /// XXX - local_sender_settle_mode and local_receiver_settle_mode PN_CPP_EXTERN link_options::sender_settle_mode sender_settle_mode(); PN_CPP_EXTERN link_options::receiver_settle_mode receiver_settle_mode(); PN_CPP_EXTERN link_options::sender_settle_mode remote_sender_settle_mode(); PN_CPP_EXTERN link_options::receiver_settle_mode remote_receiver_settle_mode(); + ///@endcond private: // Used by link_options @@ -154,8 +156,11 @@ PN_CPP_CLASS_EXTERN link : public internal::object<pn_link_t> , public endpoint /// An iterator for links. class link_iterator : public internal::iter_base<link, link_iterator> { public: + ///@cond INTERNAL explicit link_iterator(link l = 0, pn_session_t* s = 0) : internal::iter_base<link, link_iterator>(l), session_(s) {} + ///@endcond + /// Advance PN_CPP_EXTERN link_iterator operator++(); private: http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/list.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/list.hpp b/proton-c/bindings/cpp/include/proton/list.hpp index 0172b24..1a996a0 100644 --- a/proton-c/bindings/cpp/include/proton/list.hpp +++ b/proton-c/bindings/cpp/include/proton/list.hpp @@ -30,7 +30,7 @@ namespace codec { /// std::list<T> for most T is encoded as an AMQP array. template <class T, class A> encoder& operator<<(encoder& e, const std::list<T, A>& x) { - return e << encoder::array(x, type_id_of<T>::value); + return e << encoder::array(x, internal::type_id_of<T>::value); } /// Specialize for std::list<value>, encode as AMQP list (variable type) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 0fc4cc1..2bba148 100644 --- a/proton-c/bindings/cpp/include/proton/message.hpp +++ b/proton-c/bindings/cpp/include/proton/message.hpp @@ -164,7 +164,7 @@ class message { /// @name Transfer headers /// @{ - + /// Get the durable flag for a message. /// /// The durable flag indicates that any parties taking @@ -206,7 +206,7 @@ class message { /// does not mean the message has not been delivered to, but not /// acquired, by other recipients. PN_CPP_EXTERN bool first_acquirer() const; - + /// Set the first acquirer flag for a message. PN_CPP_EXTERN void first_acquirer(bool); @@ -240,7 +240,7 @@ class message { PN_CPP_EXTERN void group_sequence(int32_t); /// @} - + /// @name Extended attributes /// @{ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 index 0def327..2860a2a 100644 --- a/proton-c/bindings/cpp/include/proton/message_id.hpp +++ b/proton-c/bindings/cpp/include/proton/message_id.hpp @@ -21,7 +21,7 @@ */ #include <proton/binary.hpp> -#include <proton/scalar.hpp> +#include <proton/scalar_base.hpp> #include <proton/uuid.hpp> #include <string> @@ -37,53 +37,49 @@ namespace proton { /// - proton::uuid /// - proton::binary /// -class message_id : public restricted_scalar { +class message_id : public scalar_base { public: /// An empty message_id has a uint64_t == 0 value. - message_id() { scalar_ = uint64_t(0); } - message_id(const message_id& x) { scalar_ = x; } - message_id& operator=(const message_id& x) { scalar_ = x; return *this; } + message_id() { put_(uint64_t(0)); } - message_id(uint64_t x) { scalar_ = x; } - message_id(const uuid& x) { scalar_ = x; } - message_id(const binary& x) { scalar_ = x; } - message_id(const std::string& x) { scalar_ = x; } - - /// Extra conversion - treat char* as amqp::STRING - message_id(const char* x) { scalar_ = x; } + /// Construct from any type that can be assigned + template <class T> message_id(const T& x) { *this = x; } /// @name Assignment operators - /// /// Assign a C++ value, deduce the AMQP type() /// /// @{ - message_id& operator=(uint64_t x) { scalar_ = x; return *this; } - message_id& operator=(const uuid& x) { scalar_ = x; return *this; } - message_id& operator=(const binary& x) { scalar_ = x; return *this; } - message_id& operator=(const std::string& x) { scalar_ = x; return *this; } - /// @} - - /// @name Get methods - /// - /// get(T&) extracts the value if the types match exactly and - /// throws conversion_error otherwise. - /// - /// @{ - void get(uint64_t& x) const { scalar_.get(x); } - void get(uuid& x) const { scalar_.get(x); } - void get(binary& x) const { scalar_.get(x); } - void get(std::string& x) const { scalar_.get(x); } + message_id& operator=(uint64_t x) { put_(x); return *this; } + message_id& operator=(const uuid& x) { put_(x); return *this; } + message_id& operator=(const binary& x) { put_(x); return *this; } + message_id& operator=(const std::string& x) { put_(x); return *this; } + message_id& operator=(const char* x) { put_(x); return *this; } ///< Treated as amqp::STRING /// @} - /// Return the value as type T. - template<class T> T get() const { T x; get(x); return x; } - private: - message_id(const pn_atom_t& a): restricted_scalar(a) {} + message_id(const pn_atom_t& a): scalar_base(a) {} + ///@cond INTERNAL friend class message; friend class codec::decoder; + ///@endcond }; +///@cond internal +template <class T> T get(const message_id& x); +///@endcond + +/// Get the uint64_t value or throw conversion_error. @related message_id +template<> inline uint64_t get<uint64_t>(const message_id& x) { return internal::get<uint64_t>(x); } +/// Get the @ref uuid value or throw conversion_error. @related message_id +template<> inline uuid get<uuid>(const message_id& x) { return internal::get<uuid>(x); } +/// Get the @ref binary value or throw conversion_error. @related message_id +template<> inline binary get<binary>(const message_id& x) { return internal::get<binary>(x); } +/// Get the std::string value or throw conversion_error. @related message_id +template<> inline std::string get<std::string>(const message_id& x) { return internal::get<std::string>(x); } + +/// @copydoc scalar::coerce +/// @related message_id +template<class T> T coerce(const message_id& x) { return internal::coerce<T>(x); } } #endif // MESSAGE_ID_HPP http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/scalar.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/scalar.hpp b/proton-c/bindings/cpp/include/proton/scalar.hpp index dd55e95..af16a89 100644 --- a/proton-c/bindings/cpp/include/proton/scalar.hpp +++ b/proton-c/bindings/cpp/include/proton/scalar.hpp @@ -1,5 +1,5 @@ -#ifndef SCALAR_HPP -#define SCALAR_HPP +#ifndef PROTON_SCALAR_HPP +#define PROTON_SCALAR_HPP /* * Licensed to the Apache Software Foundation (ASF) under one @@ -20,14 +20,7 @@ * under the License. */ -#include <proton/binary.hpp> -#include <proton/export.hpp> -#include <proton/comparable.hpp> -#include <proton/types_fwd.hpp> -#include <proton/type_id.hpp> - -#include <iosfwd> -#include <string> +#include <proton/scalar_base.hpp> namespace proton { @@ -36,190 +29,48 @@ class decoder; class encoder; } -/// A holder for an instance of any scalar AMQP type. -/// The conversions for scalar types are documented in proton::amqp. +/// A holder for an instance of any scalar AMQP type, see \ref types. /// -class scalar : private comparable<scalar> { +class scalar : public scalar_base { public: /// Create an empty scalar. - PN_CPP_EXTERN scalar(); - - /// Copy a scalar. - PN_CPP_EXTERN scalar(const scalar&); - - /// Copy a scalar. - PN_CPP_EXTERN scalar& operator=(const scalar&); - - /// Type for the value in the scalar, NULL_TYPE if empty() - PN_CPP_EXTERN type_id type() const; - - /// True if the scalar is empty. - PN_CPP_EXTERN bool empty() const; - - /// @name Construct from a C++ value. - /// See proton::amqp for the list of type correspondences. - /// - /// @{ - PN_CPP_EXTERN scalar(bool x); - PN_CPP_EXTERN scalar(uint8_t x); - PN_CPP_EXTERN scalar(int8_t x); - PN_CPP_EXTERN scalar(uint16_t x); - PN_CPP_EXTERN scalar(int16_t x); - PN_CPP_EXTERN scalar(uint32_t x); - PN_CPP_EXTERN scalar(int32_t x); - PN_CPP_EXTERN scalar(uint64_t x); - PN_CPP_EXTERN scalar(int64_t x); - PN_CPP_EXTERN scalar(wchar_t x); - PN_CPP_EXTERN scalar(float x); - PN_CPP_EXTERN scalar(double x); - PN_CPP_EXTERN scalar(timestamp x); - PN_CPP_EXTERN scalar(const decimal32& x); - PN_CPP_EXTERN scalar(const decimal64& x); - PN_CPP_EXTERN scalar(const decimal128& x); - PN_CPP_EXTERN scalar(const uuid& x); - PN_CPP_EXTERN scalar(const std::string& x); - PN_CPP_EXTERN scalar(const symbol& x); - PN_CPP_EXTERN scalar(const binary& x); - PN_CPP_EXTERN scalar(const char* s); ///< Treated as an AMQP string - /// @} - - - /// @name Assignment operators - /// - /// Assign a C++ value as the corresponding AMQP type. - /// See proton::amqp for the list of type correspondences. - /// - /// @{ - PN_CPP_EXTERN scalar& operator=(bool); - PN_CPP_EXTERN scalar& operator=(uint8_t); - PN_CPP_EXTERN scalar& operator=(int8_t); - PN_CPP_EXTERN scalar& operator=(uint16_t); - PN_CPP_EXTERN scalar& operator=(int16_t); - PN_CPP_EXTERN scalar& operator=(uint32_t); - PN_CPP_EXTERN scalar& operator=(int32_t); - PN_CPP_EXTERN scalar& operator=(uint64_t); - PN_CPP_EXTERN scalar& operator=(int64_t); - PN_CPP_EXTERN scalar& operator=(wchar_t); - PN_CPP_EXTERN scalar& operator=(float); - PN_CPP_EXTERN scalar& operator=(double); - PN_CPP_EXTERN scalar& operator=(timestamp); - PN_CPP_EXTERN scalar& operator=(const decimal32&); - PN_CPP_EXTERN scalar& operator=(const decimal64&); - PN_CPP_EXTERN scalar& operator=(const decimal128&); - PN_CPP_EXTERN scalar& operator=(const uuid&); - PN_CPP_EXTERN scalar& operator=(const std::string&); - PN_CPP_EXTERN scalar& operator=(const symbol&); - PN_CPP_EXTERN scalar& operator=(const binary&); - PN_CPP_EXTERN scalar& operator=(const char* s); ///< Treated as an AMQP string - /// @} - - - /// @name Get methods - /// - /// get(T&) extracts the value if the types match exactly and - /// throws conversion_error otherwise. - /// - /// @{ - PN_CPP_EXTERN void get(bool&) const; - PN_CPP_EXTERN void get(uint8_t&) const; - PN_CPP_EXTERN void get(int8_t&) const; - PN_CPP_EXTERN void get(uint16_t&) const; - PN_CPP_EXTERN void get(int16_t&) const; - PN_CPP_EXTERN void get(uint32_t&) const; - PN_CPP_EXTERN void get(int32_t&) const; - PN_CPP_EXTERN void get(uint64_t&) const; - PN_CPP_EXTERN void get(int64_t&) const; - PN_CPP_EXTERN void get(wchar_t&) const; - PN_CPP_EXTERN void get(float&) const; - PN_CPP_EXTERN void get(double&) const; - PN_CPP_EXTERN void get(timestamp&) const; - PN_CPP_EXTERN void get(decimal32&) const; - PN_CPP_EXTERN void get(decimal64&) const; - PN_CPP_EXTERN void get(decimal128&) const; - PN_CPP_EXTERN void get(uuid&) const; - PN_CPP_EXTERN void get(symbol&) const; - PN_CPP_EXTERN void get(binary&) const; - PN_CPP_EXTERN void get(std::string&) const; - /// @} - - /// get<T>() is like get(T&) but returns the value. - template<class T> T get() const { T x; get(x); return x; } - - /// @name As methods - /// - /// As methods do "loose" conversion. They will convert the - /// scalar's value to the requested type if possible, else throw - /// conversion_error. - /// - /// @{ - PN_CPP_EXTERN int64_t as_int() const; ///< Allowed if type_id_is_integral(type()) - PN_CPP_EXTERN uint64_t as_uint() const; ///< Allowed if type_id_is_integral(type()) - PN_CPP_EXTERN double as_double() const; ///< Allowed if type_id_is_floating_point(type()) - PN_CPP_EXTERN std::string as_string() const; ///< Allowed if type_id_is_string_like(type()) - /// @} - - /// @cond INTERNAL + PN_CPP_EXTERN scalar() {} - friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const scalar&); + /// Construct from any scalar type, see \ref types. + template <class T> scalar(const T& x) { *this = x; } - /// Scalars with different type() are considered unequal even if the values - /// are equal as numbers or strings. - friend PN_CPP_EXTERN bool operator==(const scalar& x, const scalar& y); + /// Assign from any scalar type, see \ref types. + template <class T> scalar& operator=(const T& x) { put_(x); return *this; } - /// For scalars of different type(), operator< sorts by order of type(). - friend PN_CPP_EXTERN bool operator<(const scalar& x, const scalar& y); + /// No contents, type() == NULL_TYPE + bool empty() const { return type() == NULL_TYPE; } - /// @endcond + /// Clear the scalar, make it empty() + void clear() { *this = null(); } - private: - scalar(const pn_atom_t& a); - void ok(pn_type_t) const; - void set(const binary&, pn_type_t); - void set(const pn_atom_t&); - pn_atom_t atom_; - binary bytes_; // Hold binary data. - - friend class message; - friend class restricted_scalar; - friend class codec::encoder; - friend class codec::decoder; }; -/// @cond INTERNAL -/// Base class for restricted scalar types. -class restricted_scalar : private comparable<restricted_scalar> { - public: - operator const scalar&() const { return scalar_; } - type_id type() const { return scalar_.type(); } - - /// @name As methods - /// - /// As methods do "loose" conversion. They will convert the - /// scalar's value to the requested type if possible, else throw - /// conversion_error. - /// - /// @{ - int64_t as_int() const { return scalar_.as_int(); } - uint64_t as_uint() const { return scalar_.as_uint(); } - double as_double() const { return scalar_.as_double(); } - std::string as_string() const { return scalar_.as_string(); } - /// @} - - protected: - restricted_scalar() {} - restricted_scalar(const pn_atom_t& a) : scalar_(a) {} - restricted_scalar(const restricted_scalar& x) : scalar_(x.scalar_) {} - - scalar scalar_; - - friend class message; +/// Get a contained value of type T. For example: +/// +/// uint64_t i = get<uint64_t>(x) +/// +/// Will succeed if and only if x contains a uint64_t value. +/// +/// @throw conversion_error if contained value is not of type T. +/// @related scalar +template<class T> T get(const scalar& s) { return internal::get<T>(s); } - friend std::ostream& operator<<(std::ostream& o, const restricted_scalar& x) { return o << x.scalar_; } - friend bool operator<(const restricted_scalar& x, const restricted_scalar& y) { return x.scalar_ < y.scalar_; } - friend bool operator==(const restricted_scalar& x, const restricted_scalar& y) { return x.scalar_ == y.scalar_; } -}; -/// @endcond +/// Coerce the contained value to type T. For example: +/// +/// uint64_t i = get<uint64_t>(x) +/// +/// Will succeed if x contains any numeric value, but may lose precision if it +/// contains a float or double value. +/// +/// @throw conversion_error if the value cannot be converted to T according to `std::is_convertible` +/// @related scalar +template<class T> T coerce(const scalar& x) { return internal::coerce<T>(x); } } -#endif // SCALAR_HPP +#endif /*!PROTON_SCALAR_HPP*/ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/scalar_base.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/scalar_base.hpp b/proton-c/bindings/cpp/include/proton/scalar_base.hpp new file mode 100644 index 0000000..43003c8 --- /dev/null +++ b/proton-c/bindings/cpp/include/proton/scalar_base.hpp @@ -0,0 +1,181 @@ +#ifndef PROTON_SCALAR_BASE_HPP +#define PROTON_SCALAR_BASE_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/binary.hpp> +#include <proton/comparable.hpp> +#include <proton/decimal.hpp> +#include <proton/error.hpp> +#include <proton/export.hpp> +#include <proton/symbol.hpp> +#include <proton/timestamp.hpp> +#include <proton/type_id.hpp> +#include <proton/types_fwd.hpp> +#include <proton/type_traits.hpp> +#include <proton/uuid.hpp> + +#include <iosfwd> +#include <string> + +namespace proton { + +namespace codec { +class decoder; +class encoder; +} + + +/// Base class for scalar types. +class scalar_base : private comparable<scalar_base> { + public: + /// AMQP type of data stored in the scalar + PN_CPP_EXTERN type_id type() const; + + /// @cond INTERNAL + /// deprecated + PN_CPP_EXTERN int64_t as_int() const; + PN_CPP_EXTERN uint64_t as_uint() const; + PN_CPP_EXTERN double as_double() const; + PN_CPP_EXTERN std::string as_string() const; + template <class T> void get(T& x) const { get_(x); } + template <class T> T get() const { T x; get_(x); return x; } + /// @endcond + + /// Compare + friend PN_CPP_EXTERN bool operator<(const scalar_base& x, const scalar_base& y); + /// Compare + friend PN_CPP_EXTERN bool operator==(const scalar_base& x, const scalar_base& y); + /// Print contained value + friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream& o, const scalar_base& x); + + protected: + PN_CPP_EXTERN scalar_base(const pn_atom_t& a); + PN_CPP_EXTERN scalar_base(); + PN_CPP_EXTERN scalar_base(const scalar_base&); + PN_CPP_EXTERN scalar_base& operator=(const scalar_base&); + + PN_CPP_EXTERN void put_(bool); + PN_CPP_EXTERN void put_(uint8_t); + PN_CPP_EXTERN void put_(int8_t); + PN_CPP_EXTERN void put_(uint16_t); + PN_CPP_EXTERN void put_(int16_t); + PN_CPP_EXTERN void put_(uint32_t); + PN_CPP_EXTERN void put_(int32_t); + PN_CPP_EXTERN void put_(uint64_t); + PN_CPP_EXTERN void put_(int64_t); + PN_CPP_EXTERN void put_(wchar_t); + PN_CPP_EXTERN void put_(float); + PN_CPP_EXTERN void put_(double); + PN_CPP_EXTERN void put_(timestamp); + PN_CPP_EXTERN void put_(const decimal32&); + PN_CPP_EXTERN void put_(const decimal64&); + PN_CPP_EXTERN void put_(const decimal128&); + PN_CPP_EXTERN void put_(const uuid&); + PN_CPP_EXTERN void put_(const std::string&); + PN_CPP_EXTERN void put_(const symbol&); + PN_CPP_EXTERN void put_(const binary&); + PN_CPP_EXTERN void put_(const char* s); ///< Treated as an AMQP string + PN_CPP_EXTERN void put_(const null&); + + PN_CPP_EXTERN void get_(bool&) const; + PN_CPP_EXTERN void get_(uint8_t&) const; + PN_CPP_EXTERN void get_(int8_t&) const; + PN_CPP_EXTERN void get_(uint16_t&) const; + PN_CPP_EXTERN void get_(int16_t&) const; + PN_CPP_EXTERN void get_(uint32_t&) const; + PN_CPP_EXTERN void get_(int32_t&) const; + PN_CPP_EXTERN void get_(uint64_t&) const; + PN_CPP_EXTERN void get_(int64_t&) const; + PN_CPP_EXTERN void get_(wchar_t&) const; + PN_CPP_EXTERN void get_(float&) const; + PN_CPP_EXTERN void get_(double&) const; + PN_CPP_EXTERN void get_(timestamp&) const; + PN_CPP_EXTERN void get_(decimal32&) const; + PN_CPP_EXTERN void get_(decimal64&) const; + PN_CPP_EXTERN void get_(decimal128&) const; + PN_CPP_EXTERN void get_(uuid&) const; + PN_CPP_EXTERN void get_(std::string&) const; + PN_CPP_EXTERN void get_(symbol&) const; + PN_CPP_EXTERN void get_(binary&) const; + PN_CPP_EXTERN void get_(null&) const; + + private: + void ok(pn_type_t) const; + void set(const pn_atom_t&); + void set(const binary& x, pn_type_t t); + + pn_atom_t atom_; + binary bytes_; // Hold binary data. + + friend class message; + friend class codec::encoder; + friend class codec::decoder; +}; + +namespace internal { + +template<class T> T get(const scalar_base& s) { T x; s.get(x); return x; } + +template <class R, class F> R visit(const scalar_base& s, F f) { + switch(s.type()) { + case BOOLEAN: return f(s.get<bool>()); + case UBYTE: return f(s.get<uint8_t>()); + case BYTE: return f(s.get<int8_t>()); + case USHORT: return f(s.get<uint16_t>()); + case SHORT: return f(s.get<int16_t>()); + case UINT: return f(s.get<uint32_t>()); + case INT: return f(s.get<int32_t>()); + case CHAR: return f(s.get<wchar_t>()); + case ULONG: return f(s.get<uint64_t>()); + case LONG: return f(s.get<int64_t>()); + case TIMESTAMP: return f(s.get<timestamp>()); + case FLOAT: return f(s.get<float>()); + case DOUBLE: return f(s.get<double>()); + case DECIMAL32: return f(s.get<decimal32>()); + case DECIMAL64: return f(s.get<decimal64>()); + case DECIMAL128: return f(s.get<decimal128>()); + case UUID: return f(s.get<uuid>()); + case BINARY: return f(s.get<binary>()); + case STRING: return f(s.get<std::string>()); + case SYMBOL: return f(s.get<symbol>()); + default: throw conversion_error("invalid scalar type "+type_name(s.type())); + } +} + +template<class T> struct coerce_op { + template <class U> + typename enable_if<is_convertible<U, T>::value, T>::type operator()(const U& x) { + return static_cast<T>(x); + } + template <class U> + typename enable_if<!is_convertible<U, T>::value, T>::type operator()(const U&) { + throw conversion_error("cannot coerce from " + type_name(type_id_of<U>::value)); + } +}; + +template <class T> T coerce(const scalar_base& s) { return visit<T>(s, coerce_op<T>()); } + +} // internal + + +} // proton + +#endif /*!PROTON_SCALAR_BASE_HPP*/ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/session.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/session.hpp b/proton-c/bindings/cpp/include/proton/session.hpp index 5b08669..014ab2a 100644 --- a/proton-c/bindings/cpp/include/proton/session.hpp +++ b/proton-c/bindings/cpp/include/proton/session.hpp @@ -105,8 +105,10 @@ PN_CPP_CLASS_EXTERN session : public internal::object<pn_session_t>, public endp /// An iterator for sessions. class session_iterator : public internal::iter_base<session, session_iterator> { public: + ///@cond INTERNAL explicit session_iterator(session s = 0) : internal::iter_base<session, session_iterator>(s) {} - PN_CPP_EXTERN session_iterator operator++(); + ///@endcond + PN_CPP_EXTERN session_iterator operator++(); ///< Advance }; /// A range of sessions. http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/symbol.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/symbol.hpp b/proton-c/bindings/cpp/include/proton/symbol.hpp index 24a5213..7a5764a 100644 --- a/proton-c/bindings/cpp/include/proton/symbol.hpp +++ b/proton-c/bindings/cpp/include/proton/symbol.hpp @@ -26,8 +26,12 @@ namespace proton { /// class symbol : public std::string { public: + /// Construct from a std::string symbol(const std::string& s=std::string()) : std::string(s) {} + /// Construct from a C-string symbol(const char* s) : std::string(s) {} + /// Construct from any sequence of char + template<class Iter> symbol(Iter start, Iter finish) : std::string(start, finish) {} }; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/timestamp.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/timestamp.hpp b/proton-c/bindings/cpp/include/proton/timestamp.hpp index 00282dd..61d8cf3 100644 --- a/proton-c/bindings/cpp/include/proton/timestamp.hpp +++ b/proton-c/bindings/cpp/include/proton/timestamp.hpp @@ -22,28 +22,32 @@ #include "proton/duration.hpp" namespace proton { -/// A timestamp in milliseconds since the epoch 00:00:00 (UTC), 1 January 1970. +/// 64 bit timestamp in milliseconds since the epoch 00:00:00 (UTC), 1 January 1970. class timestamp : private comparable<timestamp> { public: - typedef int64_t numeric_type; - PN_CPP_EXTERN static timestamp now(); + typedef int64_t numeric_type; ///< Numeric type holding milliseconds value + PN_CPP_EXTERN static timestamp now(); ///< Current wall-clock time - explicit timestamp(numeric_type ms = 0) : ms_(ms) {} - timestamp& operator=(numeric_type ms) { ms_ = ms; return *this; } - numeric_type milliseconds() const { return ms_; } - numeric_type ms() const { return ms_; } + explicit timestamp(numeric_type ms = 0) : ms_(ms) {} ///< Construct from milliseconds + timestamp& operator=(numeric_type ms) { ms_ = ms; return *this; } ///< Assign from milliseconds + numeric_type milliseconds() const { return ms_; } ///< Get milliseconds + numeric_type ms() const { return ms_; } ///< Get milliseconds private: numeric_type ms_; }; +///@name Comparison and arithmetic operators +///@{ inline bool operator==(timestamp x, timestamp y) { return x.ms() == y.ms(); } inline bool operator<(timestamp x, timestamp y) { return x.ms() < y.ms(); } inline timestamp operator+(timestamp ts, duration d) { return timestamp(ts.ms() + d.ms()); } inline duration operator-(timestamp t0, timestamp t1) { return duration(t0.ms() - t1.ms()); } inline timestamp operator+(duration d, timestamp ts) { return ts + d; } +///@} +/// Printable format. PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, timestamp); } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/type_id.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/type_id.hpp b/proton-c/bindings/cpp/include/proton/type_id.hpp index 2d399a5..8a6e841 100644 --- a/proton-c/bindings/cpp/include/proton/type_id.hpp +++ b/proton-c/bindings/cpp/include/proton/type_id.hpp @@ -1,5 +1,5 @@ -#ifndef TYPES_H -#define TYPES_H +#ifndef PROTON_TYPE_ID_HPP +#define PROTON_TYPE_ID_HPP /* * Licensed to the Apache Software Foundation (ASF) under one @@ -20,6 +20,10 @@ * under the License. */ +///@file +/// +/// Type-identifiers for AMQP types. + #include <proton/export.hpp> #include <proton/codec.h> #include <string> @@ -64,6 +68,19 @@ PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, type_id); /// Throw a conversion_error if want != got with a message including the names of the types. PN_CPP_EXTERN void assert_type_equal(type_id want, type_id got); +///@name Test propreties of a type_id. +///@{ +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; } +///} + } // proton -#endif // TYPES_H +#endif /*!PROTON_TYPE_ID_HPP*/ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 1000a63..db4d685 100644 --- a/proton-c/bindings/cpp/include/proton/type_traits.hpp +++ b/proton-c/bindings/cpp/include/proton/type_traits.hpp @@ -20,8 +20,6 @@ * under the License. */ -/// @cond INTERNAL - /// @file /// /// Internal: Type traits for mapping between AMQP and C++ types. @@ -33,8 +31,9 @@ #include <proton/types_fwd.hpp> #include <proton/type_id.hpp> +///@cond INTERNAL namespace proton { -namespace codec { +namespace internal { class decoder; class encoder; @@ -83,35 +82,39 @@ template <class T> struct is_same<T,T> { static const bool value=true; }; template< class T > struct remove_const { typedef T type; }; template< class T > struct remove_const<const T> { typedef T type; }; -template <type_id ID> struct type_id_constant { static const type_id value = ID; }; - -// Metafunction returning AMQP type for scalar C++ types. -template <class T, class Enable=void> struct type_id_of; -template<> struct type_id_of<bool> : public type_id_constant<BOOLEAN> {}; -template<> struct type_id_of<uint8_t> : public type_id_constant<UBYTE> {}; -template<> struct type_id_of<int8_t> : public type_id_constant<BYTE> {}; -template<> struct type_id_of<uint16_t> : public type_id_constant<USHORT> {}; -template<> struct type_id_of<int16_t> : public type_id_constant<SHORT> {}; -template<> struct type_id_of<uint32_t> : public type_id_constant<UINT> {}; -template<> struct type_id_of<int32_t> : public type_id_constant<INT> {}; -template<> struct type_id_of<uint64_t> : public type_id_constant<ULONG> {}; -template<> struct type_id_of<int64_t> : public type_id_constant<LONG> {}; -template<> struct type_id_of<wchar_t> : public type_id_constant<CHAR> {}; -template<> struct type_id_of<timestamp> : public type_id_constant<TIMESTAMP> {}; -template<> struct type_id_of<float> : public type_id_constant<FLOAT> {}; -template<> struct type_id_of<double> : public type_id_constant<DOUBLE> {}; -template<> struct type_id_of<decimal32> : public type_id_constant<DECIMAL32> {}; -template<> struct type_id_of<decimal64> : public type_id_constant<DECIMAL64> {}; -template<> struct type_id_of<decimal128> : public type_id_constant<DECIMAL128> {}; -template<> struct type_id_of<uuid> : public type_id_constant<UUID> {}; -template<> struct type_id_of<binary> : public type_id_constant<BINARY> {}; -template<> struct type_id_of<std::string> : public type_id_constant<STRING> {}; -template<> struct type_id_of<symbol> : public type_id_constant<SYMBOL> {}; -template<> struct type_id_of<const char*> : public type_id_constant<STRING> {}; - -// Metafunction to test if a class has a type_id. +template <type_id ID, class T> struct type_id_constant { + typedef T type; + static const type_id value = ID; +}; + +///@name Metafunction returning AMQP type for scalar C++ types. +///@{ +template <class T> struct type_id_of; +template<> struct type_id_of<bool> : public type_id_constant<BOOLEAN, bool> {}; +template<> struct type_id_of<uint8_t> : public type_id_constant<UBYTE, uint8_t> {}; +template<> struct type_id_of<int8_t> : public type_id_constant<BYTE, int8_t> {}; +template<> struct type_id_of<uint16_t> : public type_id_constant<USHORT, uint16_t> {}; +template<> struct type_id_of<int16_t> : public type_id_constant<SHORT, int16_t> {}; +template<> struct type_id_of<uint32_t> : public type_id_constant<UINT, uint32_t> {}; +template<> struct type_id_of<int32_t> : public type_id_constant<INT, int32_t> {}; +template<> struct type_id_of<uint64_t> : public type_id_constant<ULONG, uint64_t> {}; +template<> struct type_id_of<int64_t> : public type_id_constant<LONG, int64_t> {}; +template<> struct type_id_of<wchar_t> : public type_id_constant<CHAR, wchar_t> {}; +template<> struct type_id_of<float> : public type_id_constant<FLOAT, float> {}; +template<> struct type_id_of<double> : public type_id_constant<DOUBLE, double> {}; +template<> struct type_id_of<timestamp> : public type_id_constant<TIMESTAMP, timestamp> {}; +template<> struct type_id_of<decimal32> : public type_id_constant<DECIMAL32, decimal32> {}; +template<> struct type_id_of<decimal64> : public type_id_constant<DECIMAL64, decimal64> {}; +template<> struct type_id_of<decimal128> : public type_id_constant<DECIMAL128, decimal128> {}; +template<> struct type_id_of<uuid> : public type_id_constant<UUID, uuid> {}; +template<> struct type_id_of<std::string> : public type_id_constant<STRING, std::string> {}; +template<> struct type_id_of<symbol> : public type_id_constant<SYMBOL, symbol> {}; +template<> struct type_id_of<binary> : public type_id_constant<BINARY, binary> {}; +///@} + +/// Metafunction to test if a class has a type_id. template <class T, class Enable=void> struct has_type_id : public false_type {}; -template <class T> struct has_type_id<T, typename enable_if<!!type_id_of<T>::value>::type> : public true_type {}; +template <class T> struct has_type_id<T, typename type_id_of<T>::type> : public true_type {}; // Map arbitrary integral types to known AMQP integral types. template<size_t SIZE, bool IS_SIGNED> struct integer_type; @@ -129,41 +132,22 @@ template <class T> struct is_unknown_integer { static const bool value = !has_type_id<T>::value && is_integral<T>::value; }; -namespace is_encodable_impl { // Protected the world from wildcard operator<< - -typedef char yes; -typedef double no; -struct wildcard { wildcard(...); }; - -no operator<<(wildcard, wildcard); // Fallback - -template<typename T> struct is_encodable { - 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); +// Helper base for SFINAE test templates. +struct sfinae { + typedef char yes; + typedef double no; + struct wildcard { wildcard(...); }; }; -// Avoid recursion -template <> struct is_encodable<value> : public true_type {}; - -} // namespace is_encodable_impl - -/// is_encodable<T>::value is true if there is an operator<< for encoder and T. -using is_encodable_impl::is_encodable; -/// An enabler template for C++ values that can be converted to AMQP values. -template<class T, class U=void> struct enable_amqp_type : - public enable_if<is_encodable<T>::value, U> {}; - -/// Enabler for encodable types excluding proton::value. -template<class T, class U=void> struct assignable : enable_amqp_type<T, U> {}; -template<class U> struct assignable<value, U> : public false_type {}; -/// An enabler for integer types that are not directly AMQP types. -template <class T, class U=void> struct enable_unknown_integer : - public enable_if<is_unknown_integer<T>::value, U> {}; +template <class From, class To> struct is_convertible : public sfinae { + static yes test(const To&); + static no test(...); + static const From& from; + static bool const value = sizeof(test(from)) == sizeof(yes); +}; } // internal } // proton +//@endcond #endif // PROTON_TYPE_TRAITS_HPP http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 bb2017b..66f0f93 100644 --- a/proton-c/bindings/cpp/include/proton/types.hpp +++ b/proton-c/bindings/cpp/include/proton/types.hpp @@ -22,8 +22,90 @@ ///@file /// /// Include the definitions of all proton types used to represent AMQP types. -/// Provided for convenience, you can include types individually instead. +/**@page types AMQP and C++ types + +@details + +An AMQP message body can hold binary data using any encoding you like. AMQP also +defines its own encoding and types. The AMQP encoding is often used in message +bodies because it is supported by AMQP libraries on many languages and +platforms. You also need to use the AMQP types to set and examine message +properties. + +## Scalar types + +Each type is identified by a proton::type_id. + +C++ type | AMQP type_id | Description +--------------------|----------------------|----------------------- +bool | proton::BOOLEAN | Boolean true/false +uint8_t | proton::UBYTE | 8 bit unsigned byte +int8_t | proton::BYTE | 8 bit signed byte +uint16_t | proton::USHORT | 16 bit unsigned integer +int16_t | proton::SHORT | 16 bit signed integer +uint32_t | proton::UINT | 32 bit unsigned integer +int32_t | proton::INT | 32 bit signed integer +uint64_t | proton::ULONG | 64 bit unsigned integer +int64_t | proton::LONG | 64 bit signed integer +wchar_t | proton::CHAR | 32 bit unicode code point +float | proton::FLOAT | 32 bit binary floating point +double | proton::DOUBLE | 64 bit binary floating point +proton::timestamp | proton::TIMESTAMP | 64 bit signed milliseconds since 00:00:00 (UTC), 1 January 1970. +proton::decimal32 | proton::DECIMAL32 | 32 bit decimal floating point +proton::decimal64 | proton::DECIMAL64 | 64 bit decimal floating point +proton::decimal128 | proton::DECIMAL128 | 128 bit decimal floating point +proton::uuid | proton::UUID | 128 bit universally-unique identifier +std::string | proton::STRING | UTF-8 encoded unicode string +proton::symbol | proton::SYMBOL | 7-bit ASCII encoded string +proton::binary | proton::BINARY | Variable-length binary data + +proton::scalar is a holder that can hold a scalar value of any type. + +## Compound types + +C++ type | AMQP type_id | Description +--------------------|----------------------|----------------------- +see below | proton::ARRAY | Sequence of values of the same type +see below | proton::LIST | Sequence of values of mixed types +see below | proton::MAP | Map of key/value pairs + +proton::value is a holder that can hold any AMQP value, scalar or compound + +proton::ARRAY converts to/from C++ sequences: std::vector, std::deque, std::list and +std::forward_list. + +proton::LIST converts to/from sequences of proton::value or proton::scalar, +which can hold mixed types of data. + +proton::MAP converts to/from std::map, std::unordered_map and sequences of +std::pair. + +When decoding the encoded map types must be convertible to element type of the +C++ sequence or the key/value types of the C++ map. Use proton::value as the +element or key/value type to decode any ARRAY/LIST/MAP. + +For example you can decode any AMQP MAP into: + + std::map<proton::value, proton::value> + +You can decode any AMQP LIST or ARRAY into + + std::vector<proton::value> + +## Include files + +You can simply include proton/types.hpp to include all the type definitions and +conversions. Alternatively, you can selectively include only what you need: + + - proton/types_fwd.hpp: forward declarations for all types. + - proton/list.hpp, proton/vector.hpp etc.: conversions for std::list, std::vector etc. + - include individual .hpp files as per the table above. +*/ + +// TODO aconway 2016-03-15: described types, described arrays. + +#include <proton/annotation_key.hpp> #include <proton/binary.hpp> #include <proton/config.hpp> #include <proton/decimal.hpp> @@ -31,6 +113,7 @@ #include <proton/duration.hpp> #include <proton/list.hpp> #include <proton/map.hpp> +#include <proton/message_id.hpp> #include <proton/scalar.hpp> #include <proton/symbol.hpp> #include <proton/timestamp.hpp> @@ -39,9 +122,6 @@ #include <proton/value.hpp> #include <proton/vector.hpp> -#include <proton/annotation_key.hpp> -#include <proton/message_id.hpp> - #include <proton/config.hpp> #if PN_CPP_HAS_CPP11 #include <proton/forward_list.hpp> http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/types_fwd.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/types_fwd.hpp b/proton-c/bindings/cpp/include/proton/types_fwd.hpp index 0eca2ed..77e2bf3 100644 --- a/proton-c/bindings/cpp/include/proton/types_fwd.hpp +++ b/proton-c/bindings/cpp/include/proton/types_fwd.hpp @@ -24,9 +24,13 @@ /// /// Forward declarations for all the C++ types used by proton to represent AMQP types. +#include <proton/config.hpp> + #include <proton/type_compat.h> + #include <string> +/// The proton namespace namespace proton { class binary; @@ -40,8 +44,13 @@ class duration; class uuid; class uuid; class value; -struct null {}; +struct null { + null() {} +#if PN_CPP_HAS_CPP11 + null(std::nullptr_t) {} +#endif +}; } #endif // PROTON_TYPES_FWD_HPP http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 c863971..869692c 100644 --- a/proton-c/bindings/cpp/include/proton/url.hpp +++ b/proton-c/bindings/cpp/include/proton/url.hpp @@ -33,7 +33,7 @@ namespace proton { struct PN_CPP_CLASS_EXTERN url_error : public error { /// @cond INTERNAL - PN_CPP_EXTERN explicit url_error(const std::string&); + PN_CPP_EXTERN explicit url_error(const std::string&); ///< Construct with message /// @endcond }; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 e0b7317..fb3c5a3 100644 --- a/proton-c/bindings/cpp/include/proton/value.hpp +++ b/proton-c/bindings/cpp/include/proton/value.hpp @@ -49,38 +49,33 @@ class value_base { friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const value_base&); }; -/// A holder for any single AMQP value, simple or complex (can be list, array, map etc.) -/// -/// @see proton::amqp for conversions rules between C++ and AMQP types. -/// +/// A holder for any AMQP value, simple or complex, see @ref types. class value : public value_base, private comparable<value> { + private: + // Enabler for encodable types excluding proton::value. + template<class T, class U=void> struct assignable : + public internal::enable_if<codec::is_encodable<T>::value, U> {}; + template<class U> struct assignable<value, U> {}; + public: - /// Create a null value. + /// Create a null value PN_CPP_EXTERN value(); - /// Create a null value. - PN_CPP_EXTERN value(const null&); - /// Copy a value. + ///@name Copy a value + ///@{ PN_CPP_EXTERN value(const value&); PN_CPP_EXTERN value& operator=(const value&); #if PN_CPP_HAS_CPP11 PN_CPP_EXTERN value(value&&); PN_CPP_EXTERN value& operator=(value&&); #endif + ///@} - ///@internal - PN_CPP_EXTERN explicit value(const codec::data&); + /// Construct from any allowed type T, see @ref types. + template <class T> value(const T& x, typename assignable<T>::type* = 0) { *this = x; } - /// Construct from any allowed type T. @see proton::amqp for allowed types. - template <class T> value(const T& x, typename codec::assignable<T>::type* = 0) { - codec::encoder e(*this); - e << x; - } - PN_CPP_EXTERN value& operator=(const null&); - - /// Assign from any encodable type T. @see proton::amqp for encodable types. - template <class T> - typename codec::assignable<T, value&>::type operator=(const T& x) { + /// Assign from any allowed type T, see @ref types. + template <class T> typename assignable<T, value&>::type operator=(const T& x) { codec::encoder e(*this); e << x; return *this; @@ -89,40 +84,55 @@ class value : public value_base, private comparable<value> { /// Reset the value to null PN_CPP_EXTERN void clear(); - /// @name Get methods - /// - /// Extract the value to type T. - /// - /// @{ - - /// Get the value. - template<class T> void get(T &t) const { codec::decoder d(*this); d >> t; } - - PN_CPP_EXTERN void get(null&) const; - /// @} - - /// Get the value as C++ type T. - template<class T> T get() const { T t; get(t); return t; } - - /// @name As methods - /// - /// As methods do "loose" conversion, they will convert the scalar - /// value to the requested type if possible, else throw conversion_error. - /// - /// @{ - PN_CPP_EXTERN int64_t as_int() const; ///< Allowed if `type_id_is_integral(type())` - PN_CPP_EXTERN uint64_t as_uint() const; ///< Allowed if `type_id_is_integral(type())` - PN_CPP_EXTERN double as_double() const; ///< Allowed if `type_id_is_floating_point(type())` - PN_CPP_EXTERN std::string as_string() const; ///< Allowed if `type_id_is_string_like(type())` - /// @} + ///@cond INTERNAL (deprecated) + template<class T> void get(T &t) const; + template<class T> T get() const; + PN_CPP_EXTERN int64_t as_int() const; + PN_CPP_EXTERN uint64_t as_uint() const; + PN_CPP_EXTERN double as_double() const; + PN_CPP_EXTERN std::string as_string() const; + ///@endcond + /// swap values friend PN_CPP_EXTERN void swap(value&, value&); + ///@name Comparison operators + ///@{ friend PN_CPP_EXTERN bool operator==(const value& x, const value& y); friend PN_CPP_EXTERN bool operator<(const value& x, const value& y); -}; + ///@} -template<class T> T get(const value_base& v) { return codec::decoder(v).extract<T>(); } + ///@cond INTERNAL + PN_CPP_EXTERN explicit value(const codec::data&); + ///@endcond +}; +///@copydoc scalar::get +///@related proton::value +template<class T> T get(const value& v) { T x; get(v, x); return x; } + +/// Like get(const value&) but assigns the value to a reference instead of returning it. +/// May be more efficient for complex values (arrays, maps etc.) +///@related proton::value +template<class T> void get(const value& v, T& x) { codec::decoder d(v, true); d >> x; } + +///@copydoc scalar::coerce +///@related proton::value +template<class T> T coerce(const value& v) { T x; coerce(v, x); return x; } + +/// Like coerce(const value&) but assigns the value to a reference instead of returning it. +/// May be more efficient for complex values (arrays, maps etc.) +///@related proton::value +template<class T> void coerce(const value& v, T& x) { codec::decoder d(v, false); d >> x; } + +///@cond INTERNAL +template<> inline void get<null>(const value& v, null&) { assert_type_equal(NULL_TYPE, v.type()); } +template<class T> void value::get(T &x) const { x = proton::get<T>(*this); } +template<class T> T value::get() const { return proton::get<T>(*this); } +inline int64_t value::as_int() const { return proton::coerce<int64_t>(*this); } +inline uint64_t value::as_uint() const { return proton::coerce<uint64_t>(*this); } +inline double value::as_double() const { return proton::coerce<double>(*this); } +inline std::string value::as_string() const { return proton::coerce<std::string>(*this); } +///@endcond } // proton http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/vector.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/vector.hpp b/proton-c/bindings/cpp/include/proton/vector.hpp index 350960d..1e04b0d 100644 --- a/proton-c/bindings/cpp/include/proton/vector.hpp +++ b/proton-c/bindings/cpp/include/proton/vector.hpp @@ -30,7 +30,7 @@ namespace codec { /// Encode std::vector<T> as amqp::ARRAY (same type elements) template <class T, class A> encoder& operator<<(encoder& e, const std::vector<T, A>& x) { - return e << encoder::array(x, type_id_of<T>::value); + return e << encoder::array(x, internal::type_id_of<T>::value); } /// Encode std::vector<value> encode as amqp::LIST (mixed type elements) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 890fac5..ba94c00 100644 --- a/proton-c/bindings/cpp/src/decoder.cpp +++ b/proton-c/bindings/cpp/src/decoder.cpp @@ -23,6 +23,7 @@ #include <proton/decimal.hpp> #include <proton/encoder.hpp> #include <proton/message_id.hpp> +#include <proton/scalar.hpp> #include <proton/symbol.hpp> #include <proton/timestamp.hpp> #include <proton/value.hpp> @@ -42,7 +43,7 @@ namespace codec { * to be returned by the decoder. */ -decoder::decoder(const value_base& v) : data(v.data()) { rewind(); } +decoder::decoder(const value_base& v, bool exact) : data(v.data()), exact_(exact) { rewind(); } namespace { template <class T> T check(T result) { @@ -80,8 +81,6 @@ void assign(uuid& x, const pn_uuid_t y) { byte_copy(x, y); } void assign(decimal32& x, const pn_decimal32_t y) { byte_copy(x, y); } void assign(decimal64& x, const pn_decimal64_t y) { byte_copy(x, y); } void assign(decimal128& x, const pn_decimal128_t y) { byte_copy(x, y); } -void -assign(std::string& x, const pn_bytes_t y) { x = str(y); } void assign(symbol& x, const pn_bytes_t y) { x = str(y); } void assign(binary& x, const pn_bytes_t y) { x = bin(y); } @@ -91,7 +90,7 @@ void assign(binary& x, const pn_bytes_t y) { x = bin(y); } // Simple extract with no type conversion. template <class T, class U> decoder& decoder::extract(T& x, U (*get)(pn_data_t*)) { state_guard sg(*this); - assert_type_equal(type_id_of<T>::value, pre_get()); + assert_type_equal(internal::type_id_of<T>::value, pre_get()); assign(x, get(pn_object())); sg.cancel(); // No error, cancel the reset. return *this; @@ -144,35 +143,37 @@ decoder& decoder::operator>>(value_base& x) { throw conversion_error("extract into self"); data d = x.data(); d.clear(); - { - narrow_guard n(*this); + narrow(); + try { check(d.appendn(*this, 1)); + widen(); + } catch(...) { + widen(); + throw; } next(); return *this; } decoder& decoder::operator>>(message_id& x) { - switch (next_type()) { - case ULONG: - case UUID: - case BINARY: - case STRING: - return *this >> x.scalar_; - default: + state_guard sg(*this); + type_id got = pre_get(); + if (got != ULONG && got != UUID && got != BINARY && got != STRING) throw conversion_error( - msg() << "expected one of ulong, uuid, binary or string but found " << next_type()); - }; + msg() << "expected one of ulong, uuid, binary or string but found " << got); + x.set(pn_data_get_atom(pn_object())); + sg.cancel(); + return *this; } decoder& decoder::operator>>(annotation_key& x) { - switch (next_type()) { - case ULONG: - case SYMBOL: - return *this >> x.scalar_; - default: - throw conversion_error("expected one of ulong or symbol but found " + type_name(next_type())); - }; + state_guard sg(*this); + type_id got = pre_get(); + if (got != ULONG && got != SYMBOL) + throw conversion_error(msg() << "expected one of ulong or symbol but found " << got); + x.set(pn_data_get_atom(pn_object())); + sg.cancel(); + return *this; } decoder& decoder::operator>>(scalar& x) { @@ -187,32 +188,18 @@ decoder& decoder::operator>>(scalar& x) { decoder& decoder::operator>>(bool &x) { return extract(x, pn_data_get_bool); } -decoder& decoder::operator>>(uint8_t &x) { - state_guard sg(*this); - switch (pre_get()) { - case UBYTE: x = pn_data_get_ubyte(pn_object()); break; - default: assert_type_equal(UBYTE, type_id(type_id(pn_data_type(pn_object())))); - } - sg.cancel(); - return *this; -} +decoder& decoder::operator>>(uint8_t &x) { return extract(x, pn_data_get_ubyte); } -decoder& decoder::operator>>(int8_t &x) { - state_guard sg(*this); - switch (pre_get()) { - case BYTE: x = pn_data_get_byte(pn_object()); break; - default: assert_type_equal(BYTE, type_id(type_id(pn_data_type(pn_object())))); - } - sg.cancel(); - return *this; -} +decoder& decoder::operator>>(int8_t &x) { return extract(x, pn_data_get_byte); } decoder& decoder::operator>>(uint16_t &x) { state_guard sg(*this); - switch (pre_get()) { + type_id tid = pre_get(); + if (exact_) assert_type_equal(USHORT, tid); + switch (tid) { case UBYTE: x = pn_data_get_ubyte(pn_object()); break; case USHORT: x = pn_data_get_ushort(pn_object()); break; - default: assert_type_equal(USHORT, type_id(type_id(pn_data_type(pn_object())))); + default: assert_type_equal(USHORT, tid); } sg.cancel(); return *this; @@ -220,10 +207,12 @@ decoder& decoder::operator>>(uint16_t &x) { decoder& decoder::operator>>(int16_t &x) { state_guard sg(*this); - switch (pre_get()) { + type_id tid = pre_get(); + if (exact_) assert_type_equal(SHORT, tid); + switch (tid) { case BYTE: x = pn_data_get_byte(pn_object()); break; case SHORT: x = pn_data_get_short(pn_object()); break; - default: assert_type_equal(SHORT, type_id(pn_data_type(pn_object()))); + default: assert_type_equal(SHORT, tid); } sg.cancel(); return *this; @@ -231,11 +220,13 @@ decoder& decoder::operator>>(int16_t &x) { decoder& decoder::operator>>(uint32_t &x) { state_guard sg(*this); - switch (pre_get()) { + type_id tid = pre_get(); + if (exact_) assert_type_equal(UINT, tid); + switch (tid) { case UBYTE: x = pn_data_get_ubyte(pn_object()); break; case USHORT: x = pn_data_get_ushort(pn_object()); break; case UINT: x = pn_data_get_uint(pn_object()); break; - default: assert_type_equal(UINT, type_id(pn_data_type(pn_object()))); + default: assert_type_equal(UINT, tid); } sg.cancel(); return *this; @@ -243,11 +234,13 @@ decoder& decoder::operator>>(uint32_t &x) { decoder& decoder::operator>>(int32_t &x) { state_guard sg(*this); - switch (pre_get()) { + type_id tid = pre_get(); + if (exact_) assert_type_equal(INT, tid); + switch (tid) { case BYTE: x = pn_data_get_byte(pn_object()); break; case SHORT: x = pn_data_get_short(pn_object()); break; case INT: x = pn_data_get_int(pn_object()); break; - default: assert_type_equal(INT, type_id(pn_data_type(pn_object()))); + default: assert_type_equal(INT, tid); } sg.cancel(); return *this; @@ -255,12 +248,14 @@ decoder& decoder::operator>>(int32_t &x) { decoder& decoder::operator>>(uint64_t &x) { state_guard sg(*this); - switch (pre_get()) { + type_id tid = pre_get(); + if (exact_) assert_type_equal(ULONG, tid); + switch (tid) { case UBYTE: x = pn_data_get_ubyte(pn_object()); break; case USHORT: x = pn_data_get_ushort(pn_object()); break; case UINT: x = pn_data_get_uint(pn_object()); break; case ULONG: x = pn_data_get_ulong(pn_object()); break; - default: assert_type_equal(ULONG, type_id(pn_data_type(pn_object()))); + default: assert_type_equal(ULONG, tid); } sg.cancel(); return *this; @@ -268,12 +263,14 @@ decoder& decoder::operator>>(uint64_t &x) { decoder& decoder::operator>>(int64_t &x) { state_guard sg(*this); - switch (pre_get()) { + type_id tid = pre_get(); + if (exact_) assert_type_equal(LONG, tid); + switch (tid) { case BYTE: x = pn_data_get_byte(pn_object()); break; case SHORT: x = pn_data_get_short(pn_object()); break; case INT: x = pn_data_get_int(pn_object()); break; case LONG: x = pn_data_get_long(pn_object()); break; - default: assert_type_equal(LONG, type_id(pn_data_type(pn_object()))); + default: assert_type_equal(LONG, tid); } sg.cancel(); return *this; @@ -285,10 +282,12 @@ decoder& decoder::operator>>(timestamp &x) { return extract(x, pn_data_get_times decoder& decoder::operator>>(float &x) { state_guard sg(*this); - switch (pre_get()) { + type_id tid = pre_get(); + if (exact_) assert_type_equal(FLOAT, tid); + switch (tid) { case FLOAT: x = pn_data_get_float(pn_object()); break; case DOUBLE: x = float(pn_data_get_double(pn_object())); break; - default: assert_type_equal(FLOAT, type_id(pn_data_type(pn_object()))); + default: assert_type_equal(FLOAT, tid); } sg.cancel(); return *this; @@ -296,10 +295,12 @@ decoder& decoder::operator>>(float &x) { decoder& decoder::operator>>(double &x) { state_guard sg(*this); - switch (pre_get()) { + type_id tid = pre_get(); + if (exact_) assert_type_equal(DOUBLE, tid); + switch (tid) { case FLOAT: x = pn_data_get_float(pn_object()); break; case DOUBLE: x = pn_data_get_double(pn_object()); break; - default: assert_type_equal(DOUBLE, type_id(pn_data_type(pn_object()))); + default: assert_type_equal(DOUBLE, tid); } sg.cancel(); return *this; @@ -312,7 +313,19 @@ decoder& decoder::operator>>(decimal128 &x) { return extract(x, pn_data_get_dec decoder& decoder::operator>>(uuid &x) { return extract(x, pn_data_get_uuid); } decoder& decoder::operator>>(binary &x) { return extract(x, pn_data_get_binary); } decoder& decoder::operator>>(symbol &x) { return extract(x, pn_data_get_symbol); } -decoder& decoder::operator>>(std::string &x) { return extract(x, pn_data_get_string); } + +decoder& decoder::operator>>(std::string &x) { + state_guard sg(*this); + type_id tid = pre_get(); + if (exact_) assert_type_equal(STRING, tid); + switch (tid) { + case STRING: x = str(pn_data_get_string(pn_object())); break; + case SYMBOL: x = str(pn_data_get_symbol(pn_object())); break; + default: assert_type_equal(STRING, tid); + } + sg.cancel(); + return *this; +} } // codec } // proton http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 538decc..2952d0e 100644 --- a/proton-c/bindings/cpp/src/encoder.cpp +++ b/proton-c/bindings/cpp/src/encoder.cpp @@ -27,6 +27,7 @@ #include <proton/decimal.hpp> #include <proton/encoder.hpp> #include <proton/message_id.hpp> +#include <proton/scalar_base.hpp> #include <proton/symbol.hpp> #include <proton/timestamp.hpp> #include <proton/value.hpp> @@ -100,11 +101,11 @@ encoder& encoder::operator<<(const finish&) { namespace { -template <class T, class U> T convert(const U &x) { return x; } -template <> pn_uuid_t convert(const uuid& x) { pn_uuid_t y; byte_copy(y, x); return y; } -template <> pn_decimal32_t convert(const decimal32 &x) { pn_decimal32_t y; byte_copy(y, x); return y; } -template <> pn_decimal64_t convert(const decimal64 &x) { pn_decimal64_t y; byte_copy(y, x); return y; } -template <> pn_decimal128_t convert(const decimal128 &x) { pn_decimal128_t y; byte_copy(y, x); return y; } +template <class T, class U> T coerce(const U &x) { return x; } +template <> pn_uuid_t coerce(const uuid& x) { pn_uuid_t y; byte_copy(y, x); return y; } +template <> pn_decimal32_t coerce(const decimal32 &x) { pn_decimal32_t y; byte_copy(y, x); return y; } +template <> pn_decimal64_t coerce(const decimal64 &x) { pn_decimal64_t y; byte_copy(y, x); return y; } +template <> pn_decimal128_t coerce(const decimal128 &x) { pn_decimal128_t y; byte_copy(y, x); return y; } int pn_data_put_amqp_string(pn_data_t *d, const std::string& x) { return pn_data_put_string(d, pn_bytes(x)); } int pn_data_put_amqp_binary(pn_data_t *d, const binary& x) { return pn_data_put_binary(d, pn_bytes(x)); } @@ -114,7 +115,7 @@ int pn_data_put_amqp_symbol(pn_data_t *d, const symbol& x) { return pn_data_put_ template <class T, class U> encoder& encoder::insert(const T& x, int (*put)(pn_data_t*, U)) { state_guard sg(*this); // Save state in case of error. - check(put(pn_object(), convert<U>(x))); + check(put(pn_object(), coerce<U>(x))); sg.cancel(); // Don't restore state, all is good. return *this; } @@ -139,14 +140,16 @@ encoder& encoder::operator<<(const uuid& x) { return insert(x, pn_data_put_uuid) encoder& encoder::operator<<(const std::string& x) { return insert(x, pn_data_put_amqp_string); } encoder& encoder::operator<<(const symbol& x) { return insert(x, pn_data_put_amqp_symbol); } encoder& encoder::operator<<(const binary& x) { return insert(x, pn_data_put_amqp_binary); } +encoder& encoder::operator<<(const null&) { pn_data_put_null(pn_object()); return *this; } -encoder& encoder::operator<<(const scalar& x) { return insert(x.atom_, pn_data_put_atom); } +encoder& encoder::operator<<(const scalar_base& x) { return insert(x.atom_, pn_data_put_atom); } encoder& encoder::operator<<(const value_base& x) { if (*this == x.data_) throw conversion_error("cannot insert into self"); - if (x.empty()) - pn_data_put_null(pn_object()); + if (x.empty()) { + return *this << null(); + } data d = x.data(); d.rewind(); check(append(d)); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 b05c098..abe7cb8 100644 --- a/proton-c/bindings/cpp/src/interop_test.cpp +++ b/proton-c/bindings/cpp/src/interop_test.cpp @@ -42,13 +42,6 @@ string read(string filename) { return string(istreambuf_iterator<char>(ifs), istreambuf_iterator<char>()); } -template <class T> T get(decoder& d) { - assert_type_equal(type_id_of<T>::value, d.next_type()); - T v; - d >> v; - return v; -} - // Test data ostream operator void test_data_ostream() { value dv; @@ -98,19 +91,6 @@ void test_encoder_primitives() { ASSERT_EQUAL(read("primitives"), data); } -// Test type conversions. -void test_value_conversions() { - value v; - ASSERT_EQUAL(true, (v=true).get<bool>()); - ASSERT_EQUAL(2, (v=int8_t(2)).get<int>()); - ASSERT_EQUAL(3, (v=int8_t(3)).get<long>()); - ASSERT_EQUAL(3, (v=int8_t(3)).get<long>()); - ASSERT_EQUAL(1.0, (v=float(1.0)).get<double>()); - ASSERT_EQUAL(1.0, (v=double(1.0)).get<float>()); - try { (void)(v = int8_t(1)).get<bool>(); FAIL("got byte as bool"); } catch (conversion_error) {} - try { (void)(v = true).get<float>(); FAIL("got bool as float"); } catch (conversion_error) {} -} - // TODO aconway 2015-06-11: interop test is not complete. int main(int argc, char** argv) { @@ -124,6 +104,5 @@ int main(int argc, char** argv) { RUN_TEST(failed, test_data_ostream()); RUN_TEST(failed, test_decoder_primitves_exact()); RUN_TEST(failed, test_encoder_primitives()); - RUN_TEST(failed, test_value_conversions()); return failed; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 6d95256..e00218a 100644 --- a/proton-c/bindings/cpp/src/message.cpp +++ b/proton-c/bindings/cpp/src/message.cpp @@ -87,7 +87,7 @@ void check(int err) { } } // namespace -void message::id(const message_id& id) { pn_message_set_id(pn_msg(), id.scalar_.atom_); } +void message::id(const message_id& id) { pn_message_set_id(pn_msg(), id.atom_); } message_id message::id() const { return pn_message_get_id(pn_msg()); @@ -130,7 +130,7 @@ std::string message::reply_to() const { void message::correlation_id(const message_id& id) { codec::encoder e(pn_message_correlation_id(pn_msg())); - e << id.scalar_; + e << id; } message_id message::correlation_id() const { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/src/message_test.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/message_test.cpp b/proton-c/bindings/cpp/src/message_test.cpp index 8c1e585..bfdbb06 100644 --- a/proton-c/bindings/cpp/src/message_test.cpp +++ b/proton-c/bindings/cpp/src/message_test.cpp @@ -40,7 +40,7 @@ using namespace test; void test_message_properties() { message m("hello"); - std::string s = m.body().get<std::string>(); + std::string s = get<std::string>(m.body()); ASSERT_EQUAL("hello", s); CHECK_MESSAGE_ID(id); @@ -59,7 +59,7 @@ void test_message_properties() { ASSERT_EQUAL(m.creation_time().ms(), 4242); message m2(m); - ASSERT_EQUAL("hello", m2.body().get<std::string>()); + ASSERT_EQUAL("hello", get<std::string>(m2.body())); ASSERT_EQUAL(message_id("id"), m2.id()); ASSERT_EQUAL("user_id", m2.user_id()); ASSERT_EQUAL("address", m2.address()); @@ -74,7 +74,7 @@ void test_message_properties() { ASSERT_EQUAL(4242, m.creation_time().ms()); m2 = m; - ASSERT_EQUAL("hello", m2.body().get<std::string>()); + ASSERT_EQUAL("hello", get<std::string>(m2.body())); ASSERT_EQUAL(message_id("id"), m2.id()); ASSERT_EQUAL("user_id", m2.user_id()); ASSERT_EQUAL("address", m2.address()); @@ -92,14 +92,14 @@ void test_message_properties() { void test_message_body() { std::string s("hello"); message m1(s.c_str()); - ASSERT_EQUAL(s, m1.body().get<std::string>()); + ASSERT_EQUAL(s, get<std::string>(m1.body())); message m2(s); - ASSERT_EQUAL(s, m2.body().as_string()); + ASSERT_EQUAL(s, coerce<std::string>(m2.body())); message m3; m3.body(s); - ASSERT_EQUAL(s, m3.body().as_string()); - ASSERT_EQUAL(5, message(5).body().as_int()); - ASSERT_EQUAL(3.1, message(3.1).body().as_double()); + ASSERT_EQUAL(s, coerce<std::string>(m3.body())); + ASSERT_EQUAL(5, coerce<int64_t>(message(5).body())); + ASSERT_EQUAL(3.1, coerce<double>(message(3.1).body())); } void test_message_maps() { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 deleted file mode 100644 index b862af0..0000000 --- a/proton-c/bindings/cpp/src/scalar.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - * 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.hpp" -#include "proton/symbol.hpp" -#include "proton/timestamp.hpp" -#include "proton/type_traits.hpp" -#include "proton/uuid.hpp" - -#include <ostream> - -namespace proton { - -scalar::scalar() { atom_.type = PN_NULL; } -scalar::scalar(const pn_atom_t& a) { set(a); } -scalar::scalar(const scalar& x) { set(x.atom_); } - -scalar& scalar::operator=(const scalar& x) { - if (this != &x) - set(x.atom_); - return *this; -} - -type_id scalar::type() const { return type_id(atom_.type); } - -bool scalar::empty() const { return type() == NULL_TYPE; } - -void scalar::set(const binary& x, pn_type_t t) { - atom_.type = t; - bytes_ = x; - atom_.u.as_bytes = pn_bytes(bytes_); -} - -void scalar::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; -} - -scalar::scalar(bool x) { *this = x; } -scalar::scalar(uint8_t x) { *this = x; } -scalar::scalar(int8_t x) { *this = x; } -scalar::scalar(uint16_t x) { *this = x; } -scalar::scalar(int16_t x) { *this = x; } -scalar::scalar(uint32_t x) { *this = x; } -scalar::scalar(int32_t x) { *this = x; } -scalar::scalar(uint64_t x) { *this = x; } -scalar::scalar(int64_t x) { *this = x; } -scalar::scalar(wchar_t x) { *this = x; } -scalar::scalar(float x) { *this = x; } -scalar::scalar(double x) { *this = x; } -scalar::scalar(timestamp x) { *this = x; } -scalar::scalar(const decimal32& x) { *this = x; } -scalar::scalar(const decimal64& x) { *this = x; } -scalar::scalar(const decimal128& x) { *this = x; } -scalar::scalar(const uuid& x) { *this = x; } -scalar::scalar(const std::string& x) { *this = x; } -scalar::scalar(const symbol& x) { *this = x; } -scalar::scalar(const binary& x) { *this = x; } -scalar::scalar(const char* x) { *this = x; } - -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=(timestamp x) { atom_.u.as_timestamp = x.ms(); atom_.type = PN_TIMESTAMP; return *this; } - -scalar& scalar::operator=(const decimal32& x) { - byte_copy(atom_.u.as_decimal32, x); - atom_.type = PN_DECIMAL32; - return *this; -} - -scalar& scalar::operator=(const decimal64& x) { - byte_copy(atom_.u.as_decimal64, x); - atom_.type = PN_DECIMAL64; - return *this; -} - -scalar& scalar::operator=(const decimal128& x) { - byte_copy(atom_.u.as_decimal128, x); - atom_.type = PN_DECIMAL128; - return *this; -} - -scalar& scalar::operator=(const uuid& x) { - byte_copy(atom_.u.as_uuid, x); - atom_.type = PN_UUID; - return *this; -} - -scalar& scalar::operator=(const std::string& x) { set(binary(x), PN_STRING); return *this; } -scalar& scalar::operator=(const symbol& x) { set(binary(x), PN_SYMBOL); return *this; } -scalar& scalar::operator=(const binary& x) { set(x, PN_BINARY); return *this; } -scalar& scalar::operator=(const char* x) { set(binary(std::string(x)), PN_STRING); return *this; } - -void scalar::ok(pn_type_t t) const { - if (atom_.type != t) throw make_conversion_error(type_id(t), type()); -} - -void scalar::get(bool& x) const { ok(PN_BOOL); x = atom_.u.as_bool; } -void scalar::get(uint8_t& x) const { ok(PN_UBYTE); x = atom_.u.as_ubyte; } -void scalar::get(int8_t& x) const { ok(PN_BYTE); x = atom_.u.as_byte; } -void scalar::get(uint16_t& x) const { ok(PN_USHORT); x = atom_.u.as_ushort; } -void scalar::get(int16_t& x) const { ok(PN_SHORT); x = atom_.u.as_short; } -void scalar::get(uint32_t& x) const { ok(PN_UINT); x = atom_.u.as_uint; } -void scalar::get(int32_t& x) const { ok(PN_INT); x = atom_.u.as_int; } -void scalar::get(wchar_t& x) const { ok(PN_CHAR); x = wchar_t(atom_.u.as_char); } -void scalar::get(uint64_t& x) const { ok(PN_ULONG); x = atom_.u.as_ulong; } -void scalar::get(int64_t& x) const { ok(PN_LONG); x = atom_.u.as_long; } -void scalar::get(timestamp& x) const { ok(PN_TIMESTAMP); x = atom_.u.as_timestamp; } -void scalar::get(float& x) const { ok(PN_FLOAT); x = atom_.u.as_float; } -void scalar::get(double& x) const { ok(PN_DOUBLE); x = atom_.u.as_double; } -void scalar::get(decimal32& x) const { ok(PN_DECIMAL32); byte_copy(x, atom_.u.as_decimal32); } -void scalar::get(decimal64& x) const { ok(PN_DECIMAL64); byte_copy(x, atom_.u.as_decimal64); } -void scalar::get(decimal128& x) const { ok(PN_DECIMAL128); byte_copy(x, atom_.u.as_decimal128); } -void scalar::get(uuid& x) const { ok(PN_UUID); byte_copy(x, atom_.u.as_uuid); } -void scalar::get(std::string& x) const { - ok(PN_STRING); - x = bytes_.str(); -} -void scalar::get(symbol& x) const { ok(PN_SYMBOL); x = symbol(bytes_.str()); } -void scalar::get(binary& x) const { ok(PN_BINARY); x = bytes_; } - -int64_t scalar::as_int() const { - if (type_id_is_floating_point(type())) - return int64_t(as_double()); - switch (atom_.type) { - case PN_BOOL: return atom_.u.as_bool; - case PN_UBYTE: return atom_.u.as_ubyte; - case PN_BYTE: return atom_.u.as_byte; - case PN_USHORT: return atom_.u.as_ushort; - case PN_SHORT: return atom_.u.as_short; - case PN_UINT: return atom_.u.as_uint; - case PN_INT: return atom_.u.as_int; - 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; - case PN_TIMESTAMP: return atom_.u.as_timestamp; - default: throw make_conversion_error(LONG, type()); - } -} - -uint64_t scalar::as_uint() const { - if (!type_id_is_integral(type())) - throw make_conversion_error(ULONG, type()); - return uint64_t(as_int()); -} - -double scalar::as_double() const { - if (type_id_is_integral(type())) { - return type_id_is_signed(type()) ? double(as_int()) : double(as_uint()); - } - switch (atom_.type) { - case PN_DOUBLE: return atom_.u.as_double; - case PN_FLOAT: return atom_.u.as_float; - default: throw make_conversion_error(DOUBLE, type()); - } -} - -std::string scalar::as_string() const { - if (type_id_is_string_like(type())) - return bytes_.str(); - throw make_conversion_error(STRING, type()); -} - -namespace { - -template <class T, class F> T type_switch(const scalar& a, F f) { - switch(a.type()) { - case BOOLEAN: return f(a.get<bool>()); - case UBYTE: return f(a.get<uint8_t>()); - case BYTE: return f(a.get<int8_t>()); - case USHORT: return f(a.get<uint16_t>()); - case SHORT: return f(a.get<int16_t>()); - case UINT: return f(a.get<uint32_t>()); - case INT: return f(a.get<int32_t>()); - case CHAR: return f(a.get<wchar_t>()); - case ULONG: return f(a.get<uint64_t>()); - case LONG: return f(a.get<int64_t>()); - case TIMESTAMP: return f(a.get<timestamp>()); - case FLOAT: return f(a.get<float>()); - case DOUBLE: return f(a.get<double>()); - case DECIMAL32: return f(a.get<decimal32>()); - case DECIMAL64: return f(a.get<decimal64>()); - case DECIMAL128: return f(a.get<decimal128>()); - case UUID: return f(a.get<uuid>()); - case BINARY: return f(a.get<binary>()); - case STRING: return f(a.get<std::string>()); - case SYMBOL: return f(a.get<symbol>()); - default: - throw std::logic_error("bad proton::scalar type"); - } -} - -struct equal_op { - const scalar& a; - equal_op(const scalar& a_) : a(a_) {} - template<class T> bool operator()(T x) { return x == a.get<T>(); } -}; - -struct less_op { - const scalar& a; - less_op(const scalar& a_) : a(a_) {} - template<class T> bool operator()(T x) { return x < a.get<T>(); } -}; - -struct ostream_op { - std::ostream& o; - ostream_op(std::ostream& o_) : o(o_) {} - template<class T> std::ostream& operator()(T x) { return o << x; } -}; - -} // namespace - -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 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 --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
