| #ifndef PROTON_VALUE_HPP |
| #define PROTON_VALUE_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 "./codec/encoder.hpp" |
| #include "./codec/decoder.hpp" |
| #include "./internal/type_traits.hpp" |
| #include "./scalar.hpp" |
| #include "./types_fwd.hpp" |
| |
| #include <proton/type_compat.h> |
| |
| #include <iosfwd> |
| |
| namespace proton { |
| |
| namespace internal { |
| |
| // Separate value data from implicit conversion constructors to avoid template recursion. |
| class value_base { |
| protected: |
| internal::data& data(); |
| internal::data data_; |
| |
| friend class value_ref; |
| friend class codec::encoder; |
| friend class codec::decoder; |
| }; |
| |
| } // internal |
| |
| /// A holder for any AMQP value, simple or complex. |
| /// |
| /// @see @ref types_page |
| class value : public internal::value_base, private internal::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 |
| PN_CPP_EXTERN value(); |
| |
| /// @name Copy a value |
| /// @{ |
| PN_CPP_EXTERN value(const value&); |
| PN_CPP_EXTERN value& operator=(const value&); |
| #if PN_CPP_HAS_RVALUE_REFERENCES |
| PN_CPP_EXTERN value(value&&); |
| PN_CPP_EXTERN value& operator=(value&&); |
| #endif |
| /// @} |
| |
| /// Construct from any allowed type T. |
| template <class T> value(const T& x, typename assignable<T>::type* = 0) { *this = x; } |
| |
| /// Assign from any allowed type T. |
| template <class T> typename assignable<T, value&>::type operator=(const T& x) { |
| codec::encoder e(*this); |
| e << x; |
| return *this; |
| } |
| |
| /// Get the type ID for the current value. |
| PN_CPP_EXTERN type_id type() const; |
| |
| /// True if the value is null |
| PN_CPP_EXTERN bool empty() const; |
| |
| |
| /// Reset the value to null/empty |
| PN_CPP_EXTERN void clear(); |
| |
| /// @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); |
| ///@} |
| |
| /// If contained value is a scalar type T, print using operator<<(T) |
| /// |
| /// Complex types are printed in a non-standard human-readable format but |
| /// that may change in future so should not be parsed. |
| friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const value&); |
| }; |
| |
| namespace internal { |
| |
| // value_ref is a `pn_data_t* p` that can be returned as a value& and used to modify |
| // the underlying value in-place. |
| // |
| // Classes with a value_ref member can return it as a value& in accessor functions. |
| // It can also be used to copy a pn_data_t* p to a proton::value via: value(value_ref(p)); |
| // None of the constructors make copies, they just refer to the same value. |
| // |
| class value_ref : public value { |
| public: |
| value_ref(pn_data_t* = 0); |
| value_ref(const internal::data&); |
| value_ref(const value_base&); |
| |
| // Use refer() not operator= to avoid confusion with value op= |
| void refer(pn_data_t*); |
| void refer(const internal::data&); |
| void refer(const value_base&); |
| |
| // Reset to refer to nothing, release existing references. Equivalent to refer(0). |
| void reset(); |
| |
| // Assignments to value_ref means assigning to the value. |
| template <class T> value_ref& operator=(const T& x) { |
| static_cast<value&>(*this) = x; |
| return *this; |
| } |
| }; |
| |
| } |
| |
| |
| /// @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; } |
| |
| /// @related proton::value |
| template<class T, class U> inline void get(const U& u, T& x) { const value v(u); get(v, 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); |
| if (type_id_is_scalar(v.type())) { |
| scalar s; |
| d >> s; |
| x = internal::coerce<T>(s); |
| } else { |
| d >> x; |
| } |
| } |
| |
| /// Special case for get<null>(), just checks that value contains NULL. |
| template<> inline void get<null>(const value& v, null&) { |
| assert_type_equal(NULL_TYPE, v.type()); |
| } |
| |
| /// Return a readable string representation of x for display purposes. |
| PN_CPP_EXTERN std::string to_string(const value& x); |
| |
| /// @cond INTERNAL |
| template<class T> void value::get(T &x) const { x = proton::get<T>(*this); } |
| 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 |
| |
| #endif // PROTON_VALUE_HPP |