You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by kp...@apache.org on 2016/03/17 16:34:25 UTC
[2/4] qpid-proton git commit: PROTON-1138: c++: get<>/coerce<> API
and documentation.
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: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org