You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2016/03/08 16:58:34 UTC
qpid-proton git commit: PROTON-1138: c++: Enable implicit value
conversion
Repository: qpid-proton
Updated Branches:
refs/heads/master 1f4337c4a -> bdaf901a1
PROTON-1138: c++: Enable implicit value conversion
Enable implicit template conversion constructor for proton::value, with
a compile-time enable_amqp_type template test to ensure it only matches
C++ types that can be encoded as AMQP values. Messge constructor and
body setter also use this test.
Type traits is_encodable and is_decodable are true if the << or >>
operators exist on the proton::encoder and proton::decoder. This means
user-defined operators for custom type encodings are respected by value
and message.
Other notes:
- encoder operator<< for value is a template to ensure exact
match and avoid recursion via implicit conversion in is_encodable
- Moved encoder, decoder, data into proton::internal namespace.
- Cleaned up some friendships (more work to do) Make encoder/decoder operators
members operators for built-in types (friend of class not free operator function.)
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/bdaf901a
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/bdaf901a
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/bdaf901a
Branch: refs/heads/master
Commit: bdaf901a13b4d710b9db845b7c102e10c7d88778
Parents: 1f4337c
Author: Alan Conway <ac...@redhat.com>
Authored: Mon Mar 7 15:03:31 2016 -0500
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Mar 8 10:43:43 2016 -0500
----------------------------------------------------------------------
cpp.cmake | 34 ++++
examples/cpp/encode_decode.cpp | 40 ++---
proton-c/bindings/cpp/CMakeLists.txt | 5 +-
.../cpp/include/proton/annotation_key.hpp | 32 +---
.../cpp/include/proton/connection_engine.hpp | 1 -
proton-c/bindings/cpp/include/proton/data.hpp | 13 +-
.../bindings/cpp/include/proton/decoder.hpp | 136 +++++----------
.../bindings/cpp/include/proton/encoder.hpp | 100 +++++------
.../bindings/cpp/include/proton/message.hpp | 9 +-
.../bindings/cpp/include/proton/message_id.hpp | 9 +-
proton-c/bindings/cpp/include/proton/scalar.hpp | 12 +-
.../bindings/cpp/include/proton/type_traits.hpp | 143 +++++++++++----
proton-c/bindings/cpp/include/proton/types.hpp | 31 ----
proton-c/bindings/cpp/include/proton/value.hpp | 56 +++---
proton-c/bindings/cpp/src/codec_test.cpp | 123 +++++++++++++
proton-c/bindings/cpp/src/data.cpp | 7 +-
proton-c/bindings/cpp/src/decoder.cpp | 174 ++++++++++---------
proton-c/bindings/cpp/src/encoder.cpp | 93 +++++-----
proton-c/bindings/cpp/src/interop_test.cpp | 3 +-
proton-c/bindings/cpp/src/link_options.cpp | 14 +-
proton-c/bindings/cpp/src/message.cpp | 10 +-
proton-c/bindings/cpp/src/types.cpp | 7 +-
proton-c/bindings/cpp/src/types_internal.hpp | 2 +-
proton-c/bindings/cpp/src/value.cpp | 12 +-
24 files changed, 603 insertions(+), 463 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/cpp.cmake
----------------------------------------------------------------------
diff --git a/cpp.cmake b/cpp.cmake
new file mode 100644
index 0000000..0998546
--- /dev/null
+++ b/cpp.cmake
@@ -0,0 +1,34 @@
+#
+# 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.
+#
+
+# Check C++ capabilities.
+
+include(CheckCXXSourceCompiles)
+
+if (CMAKE_CXX_COMPILER)
+ set(CMAKE_REQUIRED_FLAGS "${CXX_WARNING_FLAGS}")
+ check_cxx_source_compiles("long long ll; int main(int, char**) { return 0; }" HAS_LONG_LONG)
+ if (HAS_LONG_LONG)
+ add_definitions(-DPN_HAS_LONG_LONG=1)
+ endif()
+ check_cxx_source_compiles("#include <memory>\nstd::shared_ptr<int> i; std::unique_ptr<int> u; int main(int, char**) { return 0; }" HAS_STD_PTR)
+ if (HAS_STD_PTR)
+ add_definitions(-DPN_HAS_STD_PTR=1)
+ endif()
+endif()
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/examples/cpp/encode_decode.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/encode_decode.cpp b/examples/cpp/encode_decode.cpp
index b2a07ae..8944f6d 100644
--- a/examples/cpp/encode_decode.cpp
+++ b/examples/cpp/encode_decode.cpp
@@ -77,7 +77,7 @@ void uniform_containers() {
std::cout << a1 << std::endl;
// You can specify that a container should be encoded as an AMQP list instead.
- v = proton::as<proton::LIST>(a1);
+ v = proton::internal::as<proton::LIST>(a1);
print(v);
std::cout << v.get<std::vector<int> >() << std::endl;
@@ -94,11 +94,11 @@ void uniform_containers() {
std::vector<std::pair<std::string, int> > pairs;
pairs.push_back(std::make_pair("z", 3));
pairs.push_back(std::make_pair("a", 4));
- v = proton::as<proton::MAP>(pairs);
+ v = proton::internal::as<proton::MAP>(pairs);
print(v);
// You can also decode an AMQP map as a sequence of pairs using decoder() and proton::to_pairs
std::vector<std::pair<std::string, int> > pairs2;
- v.decode() >> proton::to_pairs(pairs2);
+ v.decode() >> proton::internal::to_pairs(pairs2);
std::cout << pairs2 << std::endl;
}
@@ -132,22 +132,22 @@ void insert_stream_operators() {
proton::value v;
// Create an array of INT with values [1, 2, 3]
- v.encode() << proton::start::array(proton::INT)
- << int32_t(1) << int32_t(2) << int32_t(3)
- << proton::finish();
+ v.encode() << proton::internal::start::array(proton::INT)
+ << int32_t(1) << int32_t(2) << int32_t(3)
+ << proton::internal::finish();
print(v);
// Create a mixed-type list of the values [42, false, "x"].
- v.encode() << proton::start::list()
- << int32_t(42) << false << proton::symbol("x")
- << proton::finish();
+ v.encode() << proton::internal::start::list()
+ << int32_t(42) << false << proton::symbol("x")
+ << proton::internal::finish();
print(v);
// Create a map { "k1":42, "k2": false }
- v.encode() << proton::start::map()
- << "k1" << int32_t(42)
- << proton::symbol("k2") << false
- << proton::finish();
+ v.encode() << proton::internal::start::map()
+ << "k1" << int32_t(42)
+ << proton::symbol("k2") << false
+ << proton::internal::finish();
print(v);
}
@@ -168,9 +168,9 @@ int main(int, char**) {
// NOTE this is for example puroses only: There is a built in ostream operator<< for values.
//
//
-void print_next(proton::decoder& d) {
+void print_next(proton::internal::decoder& d) {
proton::type_id type = d.type();
- proton::start s;
+ proton::internal::start s;
switch (type) {
case proton::ARRAY: {
d >> s;
@@ -185,7 +185,7 @@ void print_next(proton::decoder& d) {
print_next(d);
}
std::cout << "]";
- d >> proton::finish();
+ d >> proton::internal::finish();
break;
}
case proton::LIST: {
@@ -196,7 +196,7 @@ void print_next(proton::decoder& d) {
print_next(d);
}
std::cout << "]";
- d >> proton::finish();
+ d >> proton::internal::finish();
break;
}
case proton::MAP: {
@@ -209,7 +209,7 @@ void print_next(proton::decoder& d) {
print_next(d);
}
std::cout << "}";
- d >> proton::finish();
+ d >> proton::internal::finish();
break;
}
case proton::DESCRIBED: {
@@ -217,7 +217,7 @@ void print_next(proton::decoder& d) {
std::cout << "described(";
print_next(d); // Descriptor
print_next(d); // value
- d >> proton::finish();
+ d >> proton::internal::finish();
break;
}
default:
@@ -231,7 +231,7 @@ void print_next(proton::decoder& d) {
// Print a value, for example purposes. Normal code can use operator<<
void print(proton::value& v) {
- proton::decoder d = v.decode();
+ proton::internal::decoder d = v.decode();
d.rewind();
while (d.more()) {
print_next(d);
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/proton-c/bindings/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt
index c435e20..74a2356 100644
--- a/proton-c/bindings/cpp/CMakeLists.txt
+++ b/proton-c/bindings/cpp/CMakeLists.txt
@@ -168,8 +168,9 @@ macro(add_cpp_test test)
endif ()
endmacro(add_cpp_test)
+add_cpp_test(codec_test)
+add_cpp_test(engine_test)
add_cpp_test(interop_test ${CMAKE_SOURCE_DIR}/tests)
add_cpp_test(message_test)
-add_cpp_test(value_test)
add_cpp_test(scalar_test)
-add_cpp_test(engine_test)
+add_cpp_test(value_test)
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/proton-c/bindings/cpp/include/proton/annotation_key.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/annotation_key.hpp b/proton-c/bindings/cpp/include/proton/annotation_key.hpp
index 30953cd..cfb883d 100644
--- a/proton-c/bindings/cpp/include/proton/annotation_key.hpp
+++ b/proton-c/bindings/cpp/include/proton/annotation_key.hpp
@@ -20,37 +20,26 @@
* under the License.
*/
-#include "proton/types.hpp"
-#include "proton/scalar.hpp"
-#include "proton/symbol.hpp"
+#include <proton/scalar.hpp>
+#include <proton/symbol.hpp>
+#include <proton/types.hpp>
namespace proton {
-class encoder;
-class decoder;
-
/// A key for use with AMQP annotation maps.
///
/// An annotation_key can contain either a uint64_t or a proton::symbol.
class annotation_key : public restricted_scalar {
public:
- /// Create an empty key.
- annotation_key() { scalar_ = uint64_t(0); }
+ annotation_key(uint64_t x = 0) { *this = x; }
+ annotation_key(const symbol& x) { *this = x; }
+ /// `char*` is encoded as proton::amqp::symbol.
+ annotation_key(const char *x) { *this = x; }
- /// @name Assignment operators
- ///
- /// Assign a C++ value, deducing the AMQP type().
- ///
- /// @{
annotation_key& operator=(uint64_t x) { scalar_ = x; return *this; }
annotation_key& operator=(const symbol& x) { scalar_ = x; return *this; }
/// `char*` is encoded as proton::amqp::symbol.
annotation_key& operator=(const char *x) { scalar_ = symbol(x); return *this; }
- /// @}
-
- /// A constructor that converts from any type that we can assign
- /// from.
- template <class T> annotation_key(T x) { *this = x; }
/// @name Get methods
///
@@ -62,11 +51,8 @@ class annotation_key : public restricted_scalar {
/// Return the value as type T.
template<class T> T get() const { T x; get(x); return x; }
- /// @cond INTERNAL
- PN_CPP_EXTERN friend encoder operator<<(encoder, const annotation_key&);
- PN_CPP_EXTERN friend decoder operator>>(decoder, annotation_key&);
- friend class message;
- /// @endcond
+ friend class message;
+ friend class internal::decoder;
};
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/proton-c/bindings/cpp/include/proton/connection_engine.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/connection_engine.hpp b/proton-c/bindings/cpp/include/proton/connection_engine.hpp
index be6f19c..e6946c7 100644
--- a/proton-c/bindings/cpp/include/proton/connection_engine.hpp
+++ b/proton-c/bindings/cpp/include/proton/connection_engine.hpp
@@ -64,7 +64,6 @@ class connection;
class
PN_CPP_CLASS_EXTERN connection_engine {
public:
- // FIXME aconway 2016-01-23: DOC
class container {
public:
/// Create a container with id. Default to random UUID if id
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/proton-c/bindings/cpp/include/proton/data.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/data.hpp b/proton-c/bindings/cpp/include/proton/data.hpp
index 151b9d9..31baf0f 100644
--- a/proton-c/bindings/cpp/include/proton/data.hpp
+++ b/proton-c/bindings/cpp/include/proton/data.hpp
@@ -33,22 +33,25 @@
struct pn_data_t;
namespace proton {
+namespace internal {
class data;
/// Holds a sequence of AMQP values, allows inserting and extracting
/// via encoder() and decoder(). Cannot be directly instantiated, use
/// `value`.
-class data : public internal::object<pn_data_t> {
+class data : public object<pn_data_t> {
public:
- data(pn_data_t* d=0) : internal::object<pn_data_t>(d) {}
+ data(pn_data_t* d=0) : object<pn_data_t>(d) {}
PN_CPP_EXTERN static data create();
// Copy the contents of another data object t this one.
PN_CPP_EXTERN data& copy(const data&);
- template<class T> data& copy(T &t) { clear(); encoder() << t; return *this; }
+ template<class T> typename enable_amqp_type<T, data>::type& copy(T &t) {
+ clear(); encoder() << t; return *this;
+ }
/** Clear the data. */
PN_CPP_EXTERN void clear();
@@ -93,12 +96,12 @@ class data : public internal::object<pn_data_t> {
friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const data&);
friend class value;
private:
- data(internal::pn_ptr<pn_data_t> d) : internal::object<pn_data_t>(d) {}
+ data(pn_ptr<pn_data_t> d) : object<pn_data_t>(d) {}
class decoder decoder() const { return const_cast<data*>(this)->decoder(); }
};
}
-
+}
/// @endcond
#endif // DATA_H
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/proton-c/bindings/cpp/include/proton/decoder.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/decoder.hpp b/proton-c/bindings/cpp/include/proton/decoder.hpp
index ce84824..e08ac65 100644
--- a/proton-c/bindings/cpp/include/proton/decoder.hpp
+++ b/proton-c/bindings/cpp/include/proton/decoder.hpp
@@ -46,11 +46,13 @@ struct pn_data_t;
namespace proton {
class scalar;
-class data;
class message_id;
class annotation_key;
class value;
+namespace internal {
+class data;
+
/** Skips a value with `dec >> skip()`. */
struct skip{};
@@ -69,9 +71,9 @@ struct rewind{};
///
/// Internal use only, see proton::value, proton::scalar and proton::amqp
/// for the recommended ways to manage AMQP data.
-class decoder : public internal::object<pn_data_t> {
+class decoder : public object<pn_data_t> {
public:
- decoder(pn_data_t* d) : internal::object<pn_data_t>(d) {}
+ decoder(pn_data_t* d) : object<pn_data_t>(d) {}
/** Copy AMQP data from a byte buffer into the decoder. */
PN_CPP_EXTERN decoder(const char* buffer, size_t size);
@@ -102,79 +104,49 @@ class decoder : public internal::object<pn_data_t> {
/** Back up by one value */
PN_CPP_EXTERN void backup();
- PN_CPP_EXTERN class data data();
-
/** @name Extract simple types
* Overloads to extract simple types.
* @throw error if the decoder is empty or the current value has an incompatible type.
* @{
*/
- friend PN_CPP_EXTERN decoder operator>>(decoder, bool&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, uint8_t&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, int8_t&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, uint16_t&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, int16_t&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, uint32_t&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, int32_t&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, wchar_t&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, uint64_t&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, int64_t&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, timestamp&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, float&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, double&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, decimal32&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, decimal64&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, decimal128&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, uuid&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, std::string&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, message_id&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, annotation_key&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, value&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, scalar&);
+ PN_CPP_EXTERN decoder operator>>(bool&);
+ PN_CPP_EXTERN decoder operator>>(uint8_t&);
+ PN_CPP_EXTERN decoder operator>>(int8_t&);
+ PN_CPP_EXTERN decoder operator>>(uint16_t&);
+ PN_CPP_EXTERN decoder operator>>(int16_t&);
+ PN_CPP_EXTERN decoder operator>>(uint32_t&);
+ PN_CPP_EXTERN decoder operator>>(int32_t&);
+ PN_CPP_EXTERN decoder operator>>(wchar_t&);
+ PN_CPP_EXTERN decoder operator>>(uint64_t&);
+ PN_CPP_EXTERN decoder operator>>(int64_t&);
+ PN_CPP_EXTERN decoder operator>>(timestamp&);
+ PN_CPP_EXTERN decoder operator>>(float&);
+ PN_CPP_EXTERN decoder operator>>(double&);
+ PN_CPP_EXTERN decoder operator>>(decimal32&);
+ PN_CPP_EXTERN decoder operator>>(decimal64&);
+ PN_CPP_EXTERN decoder operator>>(decimal128&);
+ PN_CPP_EXTERN decoder operator>>(uuid&);
+ PN_CPP_EXTERN decoder operator>>(std::string&);
+ PN_CPP_EXTERN decoder operator>>(message_id&);
+ PN_CPP_EXTERN decoder operator>>(annotation_key&);
+ PN_CPP_EXTERN decoder operator>>(scalar&);
+ PN_CPP_EXTERN decoder operator>>(value&);
///@}
- /** Extract and return a value of type T. */
- template <class T> T extract() { T value; *this >> value; return value; }
-
- /** start extracting a container value, one of array, list, map, described.
- * The basic pattern is:
- *
- * start s;
- * dec >> s;
- * // check s.type() to see if this is an ARRAY, LIST, MAP or DESCRIBED type.
- * if (s.described) extract the descriptor...
- * for (size_t i = 0; i < s.size(); ++i) Extract each element...
- * dec >> finish();
- *
- * The first value of an ARRAY is a descriptor if start::descriptor is true,
- * followed by start.size elements of type start::element.
- *
- * A LIST has start.size elements which may be of mixed type.
- *
- * A MAP has start.size elements which alternate key, value, key, value...
- * and may be of mixed type.
- *
- * A DESCRIBED contains a descriptor and a single element, so it always has
- * start.described=true and start.size=1.
- *
- * You must always end a complex type by extracting to an instance of `finish`,
- * the decoder::scope automates this.
- *
- *@throw decoder::error if the current value is not a container type.
- */
- PN_CPP_EXTERN friend decoder operator>>(decoder, start&);
+ // start extracting complex type.
+ PN_CPP_EXTERN decoder operator>>(start&);
- /** Finish extracting a container value. */
- PN_CPP_EXTERN friend decoder operator>>(decoder, finish);
+ /// Finish extracting a container value. */
+ PN_CPP_EXTERN decoder operator>>(finish);
/** Skip a value */
- PN_CPP_EXTERN friend decoder operator>>(decoder, struct skip);
+ PN_CPP_EXTERN decoder operator>>(struct skip);
/** Throw an exception if decoder.type() != assert_type.type */
- PN_CPP_EXTERN friend decoder operator>>(decoder, assert_type);
+ PN_CPP_EXTERN decoder operator>>(assert_type);
/** Rewind to the beginning */
- PN_CPP_EXTERN friend decoder operator>>(decoder, struct rewind);
+ PN_CPP_EXTERN decoder operator>>(struct rewind);
private:
PN_CPP_EXTERN void check_type(type_id);
@@ -190,12 +162,11 @@ struct scope : public start {
};
// operator >> for integer types that are not covered by the standard overrides.
-template <class T>
-typename enable_if<is_unknown_integer<T>::value, decoder>::type
+template <class T> typename enable_integer<T, decoder>::type
operator>>(decoder d, T& i) {
typename integer_type<sizeof(T), is_signed<T>::value>::type v;
d >> v; // Extract as a known integer type
- i = v;
+ i = v; // C++ conversion to the target type.
return d;
}
@@ -207,43 +178,13 @@ template <class T> struct ref {
template <class T> struct sequence_ref : public ref<T> { sequence_ref(T& v) : ref<T>(v) {} };
template <class T> struct map_ref : public ref<T> { map_ref(T& v) : ref<T>(v) {} };
template <class T> struct pairs_ref : public ref<T> { pairs_ref(T& v) : ref<T>(v) {} };
-///@endcond
-/**
- * Return a wrapper for a C++ container to be decoded as a sequence. The AMQP
- * ARRAY, LIST, and MAP types can all be decoded as a sequence, a map will be
- * decoded as alternating key and value (provided they can both be converted to
- * the container's value_type)
- *
- * The following expressions must be valid for T t;
- * T::iterator
- * t.clear()
- * t.resize()
- * t.begin()
- * t.end()
- */
+// FIXME aconway 2016-03-03: rename
+
template <class T> sequence_ref<T> to_sequence(T& v) { return sequence_ref<T>(v); }
-/** Return a wrapper for a C++ map container to be decoded from an AMQP MAP.
- * The following expressions must be valid for T t;
- * T::key_type
- * T::mapped_type
- * t.clear()
- * T::key_type k; T::mapped_type v; t[k] = v;
- */
template <class T> map_ref<T> to_map(T& v) { return map_ref<T>(v); }
-/** Return a wrapper for a C++ container of std::pair that can be decoded from AMQP maps,
- * preserving the encoded map order.
- *
- * The following expressions must be valid for T t;
- * T::iterator
- * t.clear()
- * t.resize()
- * t.begin()
- * t.end()
- * T::iterator i; i->first; i->second
- */
template <class T> pairs_ref<T> to_pairs(T& v) { return pairs_ref<T>(v); }
/** Extract any AMQP sequence (ARRAY, LIST or MAP) to a C++ container of T if
@@ -310,6 +251,7 @@ template <class K, class T, class C, class A> decoder operator>>(decoder d, std:
#endif // PN_CPP_HAS_CPP11
}
+}
/// @endcond
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/proton-c/bindings/cpp/include/proton/encoder.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/encoder.hpp b/proton-c/bindings/cpp/include/proton/encoder.hpp
index 5e08095..79c4ec4 100644
--- a/proton-c/bindings/cpp/include/proton/encoder.hpp
+++ b/proton-c/bindings/cpp/include/proton/encoder.hpp
@@ -48,11 +48,12 @@ struct pn_data_t;
namespace proton {
class scalar;
-class data;
-class message_id;
-class annotation_key;
class value;
+namespace internal {
+
+class data;
+
template<class T, type_id A> struct cref {
typedef T cpp_type;
static const type_id type;
@@ -72,12 +73,13 @@ template <type_id A, class T> cref<T, A> as(const T& value) { return cref<T, A>(
///
/// Internal use only, see proton::value, proton::scalar and proton::amqp
/// for the recommended ways to manage AMQP data.
-class encoder : public internal::object<pn_data_t> {
+class encoder : public object<pn_data_t> {
public:
- encoder(pn_data_t* e) : internal::object<pn_data_t>(e) {}
+ encoder(pn_data_t* e) : object<pn_data_t>(e) {}
/**
- * Encode the current values into buffer and update size to reflect the number of bytes encoded.
+ * Encode the current values into buffer and update size to reflect the
+ * number of bytes encoded.
*
* Clears the encoder.
*
@@ -95,45 +97,39 @@ class encoder : public internal::object<pn_data_t> {
/** Encode the current values into a std::string. Clears the encoder. */
PN_CPP_EXTERN std::string encode();
- PN_CPP_EXTERN class data data();
-
- /** @name Insert simple types.
- *@{
- */
- friend PN_CPP_EXTERN encoder operator<<(encoder, bool);
- friend PN_CPP_EXTERN encoder operator<<(encoder, uint8_t);
- friend PN_CPP_EXTERN encoder operator<<(encoder, int8_t);
- friend PN_CPP_EXTERN encoder operator<<(encoder, uint16_t);
- friend PN_CPP_EXTERN encoder operator<<(encoder, int16_t);
- friend PN_CPP_EXTERN encoder operator<<(encoder, uint32_t);
- friend PN_CPP_EXTERN encoder operator<<(encoder, int32_t);
- friend PN_CPP_EXTERN encoder operator<<(encoder, wchar_t);
- friend PN_CPP_EXTERN encoder operator<<(encoder, uint64_t);
- friend PN_CPP_EXTERN encoder operator<<(encoder, int64_t);
- friend PN_CPP_EXTERN encoder operator<<(encoder, timestamp);
- friend PN_CPP_EXTERN encoder operator<<(encoder, float);
- friend PN_CPP_EXTERN encoder operator<<(encoder, double);
- friend PN_CPP_EXTERN encoder operator<<(encoder, decimal32);
- friend PN_CPP_EXTERN encoder operator<<(encoder, decimal64);
- friend PN_CPP_EXTERN encoder operator<<(encoder, decimal128);
- friend PN_CPP_EXTERN encoder operator<<(encoder, uuid);
- friend PN_CPP_EXTERN encoder operator<<(encoder, std::string);
- friend PN_CPP_EXTERN encoder operator<<(encoder, symbol);
- friend PN_CPP_EXTERN encoder operator<<(encoder, binary);
- friend PN_CPP_EXTERN encoder operator<<(encoder, const message_id&);
- friend PN_CPP_EXTERN encoder operator<<(encoder, const annotation_key&);
- friend PN_CPP_EXTERN encoder operator<<(encoder, const value&);
- friend PN_CPP_EXTERN encoder operator<<(encoder, const scalar&);
- ///@}
-
- /**
- * Start a container type.
- */
- friend PN_CPP_EXTERN encoder operator<<(encoder, const start&);
-
- /** Finish a container type. See operator<<(encoder&, const start&) */
- friend PN_CPP_EXTERN encoder operator<<(encoder e, finish);
-
+ PN_CPP_EXTERN encoder operator<<(bool);
+ PN_CPP_EXTERN encoder operator<<(uint8_t);
+ PN_CPP_EXTERN encoder operator<<(int8_t);
+ PN_CPP_EXTERN encoder operator<<(uint16_t);
+ PN_CPP_EXTERN encoder operator<<(int16_t);
+ PN_CPP_EXTERN encoder operator<<(uint32_t);
+ PN_CPP_EXTERN encoder operator<<(int32_t);
+ PN_CPP_EXTERN encoder operator<<(wchar_t);
+ PN_CPP_EXTERN encoder operator<<(uint64_t);
+ PN_CPP_EXTERN encoder operator<<(int64_t);
+ PN_CPP_EXTERN encoder operator<<(timestamp);
+ PN_CPP_EXTERN encoder operator<<(float);
+ PN_CPP_EXTERN encoder operator<<(double);
+ PN_CPP_EXTERN encoder operator<<(decimal32);
+ PN_CPP_EXTERN encoder operator<<(decimal64);
+ PN_CPP_EXTERN encoder operator<<(decimal128);
+ PN_CPP_EXTERN encoder operator<<(const uuid&);
+ PN_CPP_EXTERN encoder operator<<(const std::string&);
+ PN_CPP_EXTERN encoder operator<<(const symbol&);
+ PN_CPP_EXTERN encoder operator<<(const binary&);
+ PN_CPP_EXTERN encoder operator<<(const scalar&);
+
+ /// Start encoding a complex type.
+ PN_CPP_EXTERN encoder operator<<(const start&);
+ /// Finish a complex type
+ PN_CPP_EXTERN encoder operator<<(const finish&);
+
+ // FIXME aconway 2016-03-03: hide
+ PN_CPP_EXTERN void insert(const value& v);
+
+ private:
+
+ friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const encoder&);
/**@name Insert values returned by the as<type_id> helper.
*@{
@@ -150,11 +146,16 @@ class encoder : public internal::object<pn_data_t> {
inline encoder operator<<(encoder e, char* s) { return e << std::string(s); }
inline encoder operator<<(encoder e, const char* s) { return e << std::string(s); }
+
+// FIXME aconway 2016-03-08: explain
+template <class T> typename enable_if<is_same<T, value>::value, encoder>::type
+operator<<(encoder e, const T& x) { e.insert(x); return e; }
+ ///@}
+
// operator << for integer types that are not covered by the standard overrides.
-template <class T>
-typename enable_if<is_unknown_integer<T>::value, encoder>::type operator<<(encoder e, T i) {
- typename integer_type<sizeof(T), is_signed<T>::value>::type v = i;
- return e << v; // Insert as a known integer type
+template <class T> typename enable_integer<T, encoder>::type
+operator<<(encoder e, T i) {
+ return e << static_cast<typename integer_type<sizeof(T), is_signed<T>::value>::type>(i);
}
// TODO aconway 2015-06-16: described array insertion.
@@ -213,6 +214,7 @@ template <class K, class T, class C, class A> encoder operator<<(encoder e, cons
#endif // PN_CPP_HAS_CPP11
}
+}
/// @endcond
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/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 1e310a2..88bac15 100644
--- a/proton-c/bindings/cpp/include/proton/message.hpp
+++ b/proton-c/bindings/cpp/include/proton/message.hpp
@@ -67,8 +67,9 @@ class message {
#endif
/// Create a message with its body set from any value that can be
- /// assigned to a proton::value.
- template <class T> message(const T& x) : pn_msg_(0) { body() = x; }
+ /// assigned to a proton::value. proton::amqp for encoding
+ template <class T> message(const T& x, typename enable_amqp_type<T>::type * = 0) :
+ pn_msg_(0) { body() = x; }
PN_CPP_EXTERN ~message();
@@ -109,7 +110,7 @@ class message {
PN_CPP_EXTERN void address(const std::string &addr);
PN_CPP_EXTERN std::string address() const;
-
+
PN_CPP_EXTERN void reply_to(const std::string &addr);
PN_CPP_EXTERN std::string reply_to() const;
@@ -122,7 +123,7 @@ class message {
/// @{
/// Set the body, equivalent to body() = v
- template<class T> void body(const T& v) { body() = v; }
+ template<class T> typename enable_amqp_type<T>::type body(const T& v) { body() = v; }
/// Get the body.
PN_CPP_EXTERN const value& body() const;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/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 8d74c51..dbc62c3 100644
--- a/proton-c/bindings/cpp/include/proton/message_id.hpp
+++ b/proton-c/bindings/cpp/include/proton/message_id.hpp
@@ -25,9 +25,6 @@
namespace proton {
-class encoder;
-class decoder;
-
/// An AMQP message ID.
///
/// It can contain one of the following types:
@@ -73,15 +70,11 @@ class message_id : public restricted_scalar {
/// Return the value as type T.
template<class T> T get() const { T x; get(x); return x; }
- friend PN_CPP_EXTERN encoder operator<<(encoder, const message_id&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, message_id&);
-
- /// @cond INTERNAL
private:
message_id(const pn_atom_t& a): restricted_scalar(a) {}
friend class message;
- /// @endcond
+ friend class internal::decoder;
};
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/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 56c7177..234d547 100644
--- a/proton-c/bindings/cpp/include/proton/scalar.hpp
+++ b/proton-c/bindings/cpp/include/proton/scalar.hpp
@@ -32,12 +32,15 @@ class binary;
class decimal128;
class decimal32;
class decimal64;
-class decoder;
-class encoder;
class symbol;
class timestamp;
class uuid;
+namespace internal {
+class decoder;
+class encoder;
+}
+
/// A holder for an instance of any scalar AMQP type.
/// The conversions for scalar types are documented in proton::amqp.
///
@@ -137,8 +140,6 @@ class scalar : private comparable<scalar> {
/// @cond INTERNAL
friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const scalar&);
- friend PN_CPP_EXTERN encoder operator<<(encoder, const scalar&);
- friend PN_CPP_EXTERN decoder operator>>(decoder, scalar&);
/// Scalars with different type() are considered unequal even if the values
/// are equal as numbers or strings.
@@ -159,6 +160,9 @@ class scalar : private comparable<scalar> {
friend class message;
friend class restricted_scalar;
+ friend class internal::encoder;
+ friend class internal::decoder;
+
};
/// @cond INTERNAL
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/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 af62a1d..7c1f6b0 100644
--- a/proton-c/bindings/cpp/include/proton/type_traits.hpp
+++ b/proton-c/bindings/cpp/include/proton/type_traits.hpp
@@ -38,11 +38,17 @@ class binary;
class decimal128;
class decimal32;
class decimal64;
+class scalar;
class symbol;
class timestamp;
class uuid;
class value;
+namespace internal {
+
+class decoder;
+class encoder;
+
template <bool, class T=void> struct enable_if {};
template <class T> struct enable_if<true, T> { typedef T type; };
@@ -50,6 +56,10 @@ struct true_type { static const bool value = true; };
struct false_type { static const bool value = false; };
template <class T> struct is_integral : public false_type {};
+template <class T> struct is_signed : public false_type {};
+
+template <> struct is_integral<char> : public true_type {};
+template <> struct is_signed<char> : public false_type {};
template <> struct is_integral<unsigned char> : public true_type {};
template <> struct is_integral<unsigned short> : public true_type {};
@@ -61,9 +71,6 @@ template <> struct is_integral<signed short> : public true_type {};
template <> struct is_integral<signed int> : public true_type {};
template <> struct is_integral<signed long> : public true_type {};
-template <class T> struct is_signed : public false_type {};
-
-template <> struct is_signed<unsigned char> : public false_type {};
template <> struct is_signed<unsigned short> : public false_type {};
template <> struct is_signed<unsigned int> : public false_type {};
template <> struct is_signed<unsigned long> : public false_type {};
@@ -83,37 +90,38 @@ template <> struct is_signed<signed long long> : public true_type {};
template <class T, class U> struct is_same { static const bool value=false; };
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; };
-// Metafunction returning AMQP type for scalar C++ types
-template <class T, class Enable=void> struct type_id_of;
-template<> struct type_id_of<bool> { static const type_id value=BOOLEAN; };
-template<> struct type_id_of<uint8_t> { static const type_id value=UBYTE; };
-template<> struct type_id_of<int8_t> { static const type_id value=BYTE; };
-template<> struct type_id_of<uint16_t> { static const type_id value=USHORT; };
-template<> struct type_id_of<int16_t> { static const type_id value=SHORT; };
-template<> struct type_id_of<uint32_t> { static const type_id value=UINT; };
-template<> struct type_id_of<int32_t> { static const type_id value=INT; };
-template<> struct type_id_of<wchar_t> { static const type_id value=CHAR; };
-template<> struct type_id_of<uint64_t> { static const type_id value=ULONG; };
-template<> struct type_id_of<int64_t> { static const type_id value=LONG; };
-template<> struct type_id_of<timestamp> { static const type_id value=TIMESTAMP; };
-template<> struct type_id_of<float> { static const type_id value=FLOAT; };
-template<> struct type_id_of<double> { static const type_id value=DOUBLE; };
-template<> struct type_id_of<decimal32> { static const type_id value=DECIMAL32; };
-template<> struct type_id_of<decimal64> { static const type_id value=DECIMAL64; };
-template<> struct type_id_of<decimal128> { static const type_id value=DECIMAL128; };
-template<> struct type_id_of<uuid> { static const type_id value=UUID; };
-template<> struct type_id_of<binary> { static const type_id value=BINARY; };
-template<> struct type_id_of<std::string> { static const type_id value=STRING; };
-template<> struct type_id_of<symbol> { static const type_id value=SYMBOL; };
+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 <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> {
- static const bool value = true;
-};
+template <class T> struct has_type_id<T, typename enable_if<!!type_id_of<T>::value>::type> : public true_type {};
// Map arbitrary integral types to known AMQP integral types.
template<size_t SIZE, bool IS_SIGNED> struct integer_type;
@@ -126,12 +134,85 @@ template<> struct integer_type<2, false> { typedef uint16_t type; };
template<> struct integer_type<4, false> { typedef uint32_t type; };
template<> struct integer_type<8, false> { typedef uint64_t type; };
-// True if T is an integer type that does not have a type_id mapping.
+// True if T is an integer type that does not have an explicit type_id.
template <class T> struct is_unknown_integer {
static const bool value = !has_type_id<T>::value && is_integral<T>::value;
};
-}
+// Types for SFINAE tests.
+typedef char yes;
+typedef double no;
+struct wildcard { wildcard(...); };
+
+namespace is_decodable_impl { // Protected the world from wildcard operator<<
+
+no operator>>(wildcard, wildcard); // Fallback
+
+template<typename T> struct is_decodable {
+ static char test(decoder);
+ static double test(...); // Failed test, no match.
+ static decoder& d;
+ static T &t;
+ static bool const value = (sizeof(test(d >> t)) == sizeof(yes));
+};
+} // namespace is_decodable_impl
+
+
+namespace is_encodable_impl { // Protected the world from wildcard operator<<
+
+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);
+};
+
+} // 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;
+
+/// Metafunction: is_decodable<T>::value is true if `T t; decoder >> t` is valid.
+using is_decodable_impl::is_decodable;
+
+
+// Start encoding a complex type.
+struct start {
+ PN_CPP_EXTERN start(type_id type=NULL_TYPE, type_id element=NULL_TYPE, bool described=false, size_t size=0);
+ type_id type; ///< The container type: ARRAY, LIST, MAP or DESCRIBED.
+ type_id element; ///< the element type for array only.
+ bool is_described; ///< true if first value is a descriptor.
+ size_t size; ///< the element count excluding the descriptor (if any)
+
+ /// Return a start for an array.
+ PN_CPP_EXTERN static start array(type_id element, bool described=false);
+
+ /// Return a start for a list.
+ PN_CPP_EXTERN static start list();
+
+ /// Return a start for a map.
+ PN_CPP_EXTERN static start map();
+
+ /// Return a start for a described type.
+ PN_CPP_EXTERN static start described();
+};
+
+/// Finish inserting or extracting a container value.
+struct finish {};
+
+} // namespace internal
+
+/// An enabler template for C++ values that can be converted to AMQP.
+template<class T, class U=void> struct enable_amqp_type :
+ public internal::enable_if<internal::is_encodable<T>::value, U> {};
+
+/// An enabler for integer types.
+template <class T, class U=void> struct enable_integer :
+ public internal::enable_if<internal::is_unknown_integer<T>::value, U> {};
+} // namespace proton
/// @endcond
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/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 54b8391..f0667fc 100644
--- a/proton-c/bindings/cpp/include/proton/types.hpp
+++ b/proton-c/bindings/cpp/include/proton/types.hpp
@@ -125,37 +125,6 @@ PN_CPP_EXTERN bool type_id_is_container(type_id);
/// Print the name of a type.
PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, type_id);
-
-/// @cond INTERNAL
-/// XXX change namespace
-
-/// Information needed to start extracting or inserting a container type.
-///
-/// See encoder::operator<<(encoder&, const start&) and
-/// decoder::operator>>(decoder&, start&) for examples of use.
-struct start {
- PN_CPP_EXTERN start(type_id type=NULL_TYPE, type_id element=NULL_TYPE, bool described=false, size_t size=0);
- type_id type; ///< The container type: ARRAY, LIST, MAP or DESCRIBED.
- type_id element; ///< the element type for array only.
- bool is_described; ///< true if first value is a descriptor.
- size_t size; ///< the element count excluding the descriptor (if any)
-
- /// Return a start for an array.
- PN_CPP_EXTERN static start array(type_id element, bool described=false);
-
- /// Return a start for a list.
- PN_CPP_EXTERN static start list();
-
- /// Return a start for a map.
- PN_CPP_EXTERN static start map();
-
- /// Return a start for a described type.
- PN_CPP_EXTERN static start described();
-};
-
-/// Finish inserting or extracting a container value.
-struct finish {};
-
/// @endcond
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/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 7b7ff26..cf04c43 100644
--- a/proton-c/bindings/cpp/include/proton/value.hpp
+++ b/proton-c/bindings/cpp/include/proton/value.hpp
@@ -47,17 +47,11 @@ class value : private comparable<value> {
PN_CPP_EXTERN value(value&&);
#endif
- /// Copy a value.
- PN_CPP_EXTERN value& operator=(const value&);
-
- /// Explicit conversion from from C++ type T.
- template <class T> explicit value(const T& x) : data_(proton::data::create()) { encode() << x; }
-
- /// Allow implicit conversion from a proton::scalar.
- value(const scalar& x) { encode() << x; }
+ /// Construct from any allowed type T. @see proton::amqp for allowed types.
+ /// Ignore the default parameter, it restricts the template to match only allowed types.
+ template <class T> value(const T& x, typename enable_amqp_type<T>::type* = 0) { encode() << x; }
- /// Create a value from C++ type T.
- template <class T> value& operator=(const T& x) { encode() << x; return *this; }
+ PN_CPP_EXTERN value& operator=(const value&);
/// Remove any contained data.
PN_CPP_EXTERN void clear();
@@ -65,7 +59,7 @@ class value : private comparable<value> {
/// True if the value contains no data.
PN_CPP_EXTERN bool empty() const;
- /// Get the type of the current value.
+ /// Get the type ID for the current value.
PN_CPP_EXTERN type_id type() const;
/// @name Get methods
@@ -78,13 +72,13 @@ class value : private comparable<value> {
template<class T> void get(T &t) const { decode() >> t; }
/// Get an AMQP map as any type T that satisfies the map concept.
- template<class T> void get_map(T& t) const { decode() >> to_map(t); }
+ template<class T> void get_map(T& t) const { decode() >> internal::to_map(t); }
/// Get a map as a as any type T that is a sequence pair-like types with first and second.
- template<class T> void get_pairs(T& t) const { decode() >> to_pairs(t); }
+ template<class T> void get_pairs(T& t) const { decode() >> internal::to_pairs(t); }
/// Get an AMQP array or list as type T that satisfies the sequence concept. */
- template<class T> void get_sequence(T& t) const { decode() >> to_sequence(t); }
+ template<class T> void get_sequence(T& t) const { decode() >> internal::to_sequence(t); }
/// @}
@@ -103,25 +97,25 @@ class value : private comparable<value> {
PN_CPP_EXTERN std::string as_string() const; ///< Allowed if `type_id_is_string_like(type())`
/// @}
- /// @cond INTERNAL
- /// XXX undiscussed
- PN_CPP_EXTERN encoder encode(); ///< Clear and return an encoder for this value.
- PN_CPP_EXTERN decoder decode() const; ///< Rewind and return an encoder for this value.
- PN_CPP_EXTERN class data& data() const; ///< Return a data reference, no clear or rewind.
- /// @endcond
+ friend PN_CPP_EXTERN void swap(value&, value&);
+ friend PN_CPP_EXTERN bool operator==(const value& x, const value& y);
+ friend PN_CPP_EXTERN bool operator<(const value& x, const value& y);
+ friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream& o, const value& dv);
+
+ ///@cond INTERNAL
+ PN_CPP_EXTERN internal::encoder encode();
+ PN_CPP_EXTERN internal::decoder decode() const;
+ PN_CPP_EXTERN explicit value(pn_data_t*); ///< Copies the data
+ ///@endcond
private:
- mutable class data data_;
-
- /// @cond INTERNAL
- friend PN_CPP_EXTERN void swap(value&, value&);
- friend PN_CPP_EXTERN bool operator==(const value& x, const value& y);
- friend PN_CPP_EXTERN bool operator<(const value& x, const value& y);
- friend PN_CPP_EXTERN class encoder operator<<(class encoder e, const value& dv);
- friend PN_CPP_EXTERN class decoder operator>>(class decoder d, value& dv);
- friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream& o, const value& dv);
- friend class message;
- /// @endcond
+
+ mutable class internal::data data_;
+ internal::data& data() const; // On-demand access.
+
+ friend class message;
+ friend class internal::encoder;
+ friend class internal::decoder;
};
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/proton-c/bindings/cpp/src/codec_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/codec_test.cpp b/proton-c/bindings/cpp/src/codec_test.cpp
new file mode 100644
index 0000000..e3b45d7
--- /dev/null
+++ b/proton-c/bindings/cpp/src/codec_test.cpp
@@ -0,0 +1,123 @@
+#ifndef CODEC_TEST_HPP
+#define CODEC_TEST_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
+nn * "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 "test_bits.hpp"
+
+#include <proton/types.hpp>
+#include <proton/binary.hpp>
+#include <proton/decimal.hpp>
+#include <proton/decoder.hpp>
+#include <proton/encoder.hpp>
+#include <proton/symbol.hpp>
+#include <proton/value.hpp>
+#include <proton/scalar.hpp>
+#include <proton/annotation_key.hpp>
+#include <proton/message_id.hpp>
+
+using namespace test;
+using namespace proton;
+
+template <class T> void simple_type_test(const T& x) {
+ ASSERT(internal::is_encodable<T>::value);
+ ASSERT(internal::is_decodable<T>::value);
+ value v;
+ v.encode() << x;
+ T y;
+ v.decode() >> y;
+ ASSERT_EQUAL(x, y);
+}
+
+template <class T> T make_fill(const char c) {
+ T x; std::fill(x.begin(), x.end(), c);
+ return x;
+}
+
+template <class T> void uncodable_type_test() {
+ ASSERT(!internal::is_encodable<T>::value);
+ ASSERT(!internal::is_decodable<T>::value);
+}
+
+int main(int, char**) {
+ int failed = 0;
+
+ // Basic AMQP types
+ RUN_TEST(failed, simple_type_test(false));
+ RUN_TEST(failed, simple_type_test(uint8_t(42)));
+ RUN_TEST(failed, simple_type_test(int8_t(-42)));
+ RUN_TEST(failed, simple_type_test(uint16_t(4242)));
+ RUN_TEST(failed, simple_type_test(int16_t(-4242)));
+ RUN_TEST(failed, simple_type_test(uint32_t(4242)));
+ RUN_TEST(failed, simple_type_test(int32_t(-4242)));
+ RUN_TEST(failed, simple_type_test(uint64_t(4242)));
+ RUN_TEST(failed, simple_type_test(int64_t(-4242)));
+ RUN_TEST(failed, simple_type_test(wchar_t('X')));
+ RUN_TEST(failed, simple_type_test(float(1.234)));
+ RUN_TEST(failed, simple_type_test(double(11.2233)));
+ RUN_TEST(failed, simple_type_test(timestamp(1234)));
+ RUN_TEST(failed, simple_type_test(make_fill<decimal32>(0)));
+ RUN_TEST(failed, simple_type_test(make_fill<decimal64>(0)));
+ RUN_TEST(failed, simple_type_test(make_fill<decimal128>(0)));
+ // FIXME aconway 2016-03-07:
+ // RUN_TEST(failed, simple_type_test(uuid::copy("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff")));
+ RUN_TEST(failed, simple_type_test(std::string("xxx")));
+ RUN_TEST(failed, simple_type_test(symbol("aaa")));
+ RUN_TEST(failed, simple_type_test(binary("aaa")));
+
+ // Native int type that may map differently per platform to uint types.
+ RUN_TEST(failed, simple_type_test(char(42)));
+ RUN_TEST(failed, simple_type_test(short(42)));
+ RUN_TEST(failed, simple_type_test(int(42)));
+ RUN_TEST(failed, simple_type_test(long(42)));
+
+ RUN_TEST(failed, simple_type_test(static_cast<signed char>(42)));
+ RUN_TEST(failed, simple_type_test(static_cast<signed short>(42)));
+ RUN_TEST(failed, simple_type_test(static_cast<signed int>(42)));
+ RUN_TEST(failed, simple_type_test(static_cast<signed long>(42)));
+
+ RUN_TEST(failed, simple_type_test(static_cast<unsigned char>(42)));
+ RUN_TEST(failed, simple_type_test(static_cast<unsigned short>(42)));
+ RUN_TEST(failed, simple_type_test(static_cast<unsigned int>(42)));
+ RUN_TEST(failed, simple_type_test(static_cast<unsigned long>(42)));
+
+#if PN_HAS_LONG_LONG
+ RUN_TEST(failed, simple_type_test(static_cast<long>(42)));
+ RUN_TEST(failed, simple_type_test(static_cast<signed long>(42)));
+ RUN_TEST(failed, simple_type_test(static_cast<unsigned long>(42)));
+#endif
+
+ // value and scalar types, more tests in value_test and scalar_test.
+ RUN_TEST(failed, simple_type_test(value("foo")));
+ value v(23); // Make sure we can take a non-const ref also
+ RUN_TEST(failed, simple_type_test(v));
+ RUN_TEST(failed, simple_type_test(scalar(23)));
+ RUN_TEST(failed, simple_type_test(static_cast<annotation_key>(42)));
+ RUN_TEST(failed, simple_type_test(static_cast<message_id>(42)));
+
+ // Make sure we reject uncodable types
+ RUN_TEST(failed, (uncodable_type_test<std::pair<int, float> >()));
+ RUN_TEST(failed, (uncodable_type_test<std::pair<scalar, value> >()));
+ RUN_TEST(failed, (uncodable_type_test<std::basic_string<wchar_t> >()));
+
+ return failed;
+}
+
+
+#endif // CODEC_TEST_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/proton-c/bindings/cpp/src/data.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/data.cpp b/proton-c/bindings/cpp/src/data.cpp
index 3cd2bc8..a714cf6 100644
--- a/proton-c/bindings/cpp/src/data.cpp
+++ b/proton-c/bindings/cpp/src/data.cpp
@@ -30,6 +30,7 @@
#include <ostream>
namespace proton {
+namespace internal {
data& data::copy(const data& x) { ::pn_data_copy(pn_object(), x.pn_object()); return *this; }
@@ -69,8 +70,8 @@ std::ostream& operator<<(std::ostream& o, const data& d) {
data data::create() { return internal::take_ownership(pn_data(0)); }
-encoder data::encoder() { return proton::encoder(pn_object()); }
-decoder data::decoder() { return proton::decoder(pn_object()); }
+class encoder data::encoder() { return internal::encoder(pn_object()); }
+class decoder data::decoder() { return internal:: decoder(pn_object()); }
type_id data::type() const { return decoder().type(); }
@@ -167,5 +168,5 @@ bool data::equal(const data& x) const {
bool data::less(const data& x) const {
return compare(const_cast<data&>(*this), const_cast<data&>(x)) < 0;
}
-
+}
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/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 17f85da..ceaca77 100644
--- a/proton-c/bindings/cpp/src/decoder.cpp
+++ b/proton-c/bindings/cpp/src/decoder.cpp
@@ -32,6 +32,7 @@
#include <proton/codec.h>
namespace proton {
+namespace internal {
/**@file
*
@@ -85,8 +86,6 @@ void decoder::backup() { ::pn_data_prev(pn_object()); }
void decoder::skip() { ::pn_data_next(pn_object()); }
-data decoder::data() { return proton::data(pn_object()); }
-
namespace {
void bad_type(type_id want, type_id got) {
@@ -126,8 +125,8 @@ type_id decoder::type() const {
return pre_get(pn_object());
}
-decoder operator>>(decoder d0, start& s) {
- pn_data_t* d = d0.pn_object();
+decoder decoder::operator>>(start& s) {
+ pn_data_t* d = pn_object();
save_state ss(d);
s.type = pre_get(d);
switch (s.type) {
@@ -150,91 +149,93 @@ decoder operator>>(decoder d0, start& s) {
}
pn_data_enter(d);
ss.cancel();
- return d0;
+ return *this;
}
-decoder operator>>(decoder d, finish) { pn_data_exit(d.pn_object()); return d; }
+// FIXME aconway 2016-03-08: remove
+decoder decoder::operator>>(struct finish) { pn_data_exit(pn_object()); return *this; }
-decoder operator>>(decoder d, skip) { pn_data_next(d.pn_object()); return d; }
+decoder decoder::operator>>(struct skip) { pn_data_next(pn_object()); return *this; }
-decoder operator>>(decoder d, assert_type a) { bad_type(a.type, d.type()); return d; }
+decoder decoder::operator>>(struct assert_type a) { bad_type(a.type, type()); return *this; }
-decoder operator>>(decoder d, rewind) { d.rewind(); return d; }
+decoder decoder::operator>>(struct rewind) { rewind(); return *this; }
-decoder operator>>(decoder d, value& v) {
- data ddata = d.data();
- data vdata = v.encode().data();
- if (d.data() == v.data_) throw conversion_error("extract into self");
+decoder decoder::operator>>(value& v) {
+ data mine(pn_object());
+ if (mine == v.data_)
+ throw conversion_error("extract into self");
+ v.clear();
{
- narrow n(ddata);
- check(vdata.appendn(ddata, 1));
+ narrow n(pn_object());
+ check(v.data().appendn(mine, 1));
}
- if (!ddata.next()) throw conversion_error("no more data");
- return d;
+ if (!mine.next()) throw conversion_error("no more data");
+ return *this;
}
-decoder operator>>(decoder d, message_id& x) {
- switch (d.type()) {
+decoder decoder::operator>>(message_id& x) {
+ switch (type()) {
case ULONG:
case UUID:
case BINARY:
case STRING:
- return d >> x.scalar_;
+ return *this >> x.scalar_;
default:
- throw conversion_error("expected one of ulong, uuid, binary or string but found " +
- type_name(d.type()));
+ throw conversion_error(
+ msg() << "expected one of ulong, uuid, binary or string but found " << type());
};
}
-decoder operator>>(decoder d, annotation_key& x) {
- switch (d.type()) {
+decoder decoder::operator>>(annotation_key& x) {
+ switch (type()) {
case ULONG:
case SYMBOL:
- return d >> x.scalar_;
+ return *this >> x.scalar_;
default:
- throw conversion_error("expected one of ulong or symbol but found " + type_name(d.type()));
+ throw conversion_error("expected one of ulong or symbol but found " + type_name(type()));
};
}
-decoder operator>>(decoder d, scalar& x) {
- save_state ss(d.pn_object());
- type_id got = pre_get(d.pn_object());
+decoder decoder::operator>>(scalar& x) {
+ save_state ss(pn_object());
+ type_id got = pre_get(pn_object());
if (!type_id_is_scalar(got))
throw conversion_error("expected scalar, found "+type_name(got));
- x.set(pn_data_get_atom(d.pn_object()));
+ x.set(pn_data_get_atom(pn_object()));
ss.cancel(); // No error, no rewind
- return d;
+ return *this;
}
-decoder operator>>(decoder d, amqp::boolean_type &x) {
- extract(d.pn_object(), x, pn_data_get_bool);
- return d;
+decoder decoder::operator>>(amqp::boolean_type &x) {
+ extract(pn_object(), x, pn_data_get_bool);
+ return *this;
}
-decoder operator>>(decoder d0, amqp::ubyte_type &x) {
- pn_data_t* d = d0.pn_object();
+decoder decoder::operator>>(amqp::ubyte_type &x) {
+ pn_data_t* d = pn_object();
save_state ss(d);
switch (pre_get(d)) {
case UBYTE: x = pn_data_get_ubyte(d); break;
default: bad_type(UBYTE, type_id(type_id(pn_data_type(d))));
}
ss.cancel();
- return d0;
+ return *this;
}
-decoder operator>>(decoder d0, amqp::byte_type &x) {
- pn_data_t* d = d0.pn_object();
+decoder decoder::operator>>(amqp::byte_type &x) {
+ pn_data_t* d = pn_object();
save_state ss(d);
switch (pre_get(d)) {
case BYTE: x = pn_data_get_byte(d); break;
default: bad_type(BYTE, type_id(type_id(pn_data_type(d))));
}
ss.cancel();
- return d0;
+ return *this;
}
-decoder operator>>(decoder d0, amqp::ushort_type &x) {
- pn_data_t* d = d0.pn_object();
+decoder decoder::operator>>(amqp::ushort_type &x) {
+ pn_data_t* d = pn_object();
save_state ss(d);
switch (pre_get(d)) {
case UBYTE: x = pn_data_get_ubyte(d); break;
@@ -242,11 +243,11 @@ decoder operator>>(decoder d0, amqp::ushort_type &x) {
default: bad_type(USHORT, type_id(type_id(pn_data_type(d))));
}
ss.cancel();
- return d0;
+ return *this;
}
-decoder operator>>(decoder d0, amqp::short_type &x) {
- pn_data_t* d = d0.pn_object();
+decoder decoder::operator>>(amqp::short_type &x) {
+ pn_data_t* d = pn_object();
save_state ss(d);
switch (pre_get(d)) {
case BYTE: x = pn_data_get_byte(d); break;
@@ -254,11 +255,11 @@ decoder operator>>(decoder d0, amqp::short_type &x) {
default: bad_type(SHORT, type_id(pn_data_type(d)));
}
ss.cancel();
- return d0;
+ return *this;
}
-decoder operator>>(decoder d0, amqp::uint_type &x) {
- pn_data_t* d = d0.pn_object();
+decoder decoder::operator>>(amqp::uint_type &x) {
+ pn_data_t* d = pn_object();
save_state ss(d);
switch (pre_get(d)) {
case UBYTE: x = pn_data_get_ubyte(d); break;
@@ -267,11 +268,11 @@ decoder operator>>(decoder d0, amqp::uint_type &x) {
default: bad_type(UINT, type_id(pn_data_type(d)));
}
ss.cancel();
- return d0;
+ return *this;
}
-decoder operator>>(decoder d0, amqp::int_type &x) {
- pn_data_t* d = d0.pn_object();
+decoder decoder::operator>>(amqp::int_type &x) {
+ pn_data_t* d = pn_object();
save_state ss(d);
switch (pre_get(d)) {
case BYTE: x = pn_data_get_byte(d); break;
@@ -280,11 +281,11 @@ decoder operator>>(decoder d0, amqp::int_type &x) {
default: bad_type(INT, type_id(pn_data_type(d)));
}
ss.cancel();
- return d0;
+ return *this;
}
-decoder operator>>(decoder d0, amqp::ulong_type &x) {
- pn_data_t* d = d0.pn_object();
+decoder decoder::operator>>(amqp::ulong_type &x) {
+ pn_data_t* d = pn_object();
save_state ss(d);
switch (pre_get(d)) {
case UBYTE: x = pn_data_get_ubyte(d); break;
@@ -294,11 +295,11 @@ decoder operator>>(decoder d0, amqp::ulong_type &x) {
default: bad_type(ULONG, type_id(pn_data_type(d)));
}
ss.cancel();
- return d0;
+ return *this;
}
-decoder operator>>(decoder d0, amqp::long_type &x) {
- pn_data_t* d = d0.pn_object();
+decoder decoder::operator>>(amqp::long_type &x) {
+ pn_data_t* d = pn_object();
save_state ss(d);
switch (pre_get(d)) {
case BYTE: x = pn_data_get_byte(d); break;
@@ -308,21 +309,21 @@ decoder operator>>(decoder d0, amqp::long_type &x) {
default: bad_type(LONG, type_id(pn_data_type(d)));
}
ss.cancel();
- return d0;
+ return *this;
}
-decoder operator>>(decoder d, amqp::char_type &x) {
- extract(d.pn_object(), x, pn_data_get_char);
- return d;
+decoder decoder::operator>>(amqp::char_type &x) {
+ extract(pn_object(), x, pn_data_get_char);
+ return *this;
}
-decoder operator>>(decoder d, timestamp &x) {
- extract(d.pn_object(), x, pn_data_get_timestamp);
- return d;
+decoder decoder::operator>>(timestamp &x) {
+ extract(pn_object(), x, pn_data_get_timestamp);
+ return *this;
}
-decoder operator>>(decoder d0, amqp::float_type &x) {
- pn_data_t* d = d0.pn_object();
+decoder decoder::operator>>(amqp::float_type &x) {
+ pn_data_t* d = pn_object();
save_state ss(d);
switch (pre_get(d)) {
case FLOAT: x = pn_data_get_float(d); break;
@@ -330,11 +331,11 @@ decoder operator>>(decoder d0, amqp::float_type &x) {
default: bad_type(FLOAT, type_id(pn_data_type(d)));
}
ss.cancel();
- return d0;
+ return *this;
}
-decoder operator>>(decoder d0, amqp::double_type &x) {
- pn_data_t* d = d0.pn_object();
+decoder decoder::operator>>(amqp::double_type &x) {
+ pn_data_t* d = pn_object();
save_state ss(d);
switch (pre_get(d)) {
case FLOAT: x = pn_data_get_float(d); break;
@@ -342,31 +343,31 @@ decoder operator>>(decoder d0, amqp::double_type &x) {
default: bad_type(DOUBLE, type_id(pn_data_type(d)));
}
ss.cancel();
- return d0;
+ return *this;
}
-decoder operator>>(decoder d, decimal32 &x) {
- extract(d.pn_object(), x, pn_data_get_decimal32);
- return d;
+decoder decoder::operator>>(decimal32 &x) {
+ extract(pn_object(), x, pn_data_get_decimal32);
+ return *this;
}
-decoder operator>>(decoder d, decimal64 &x) {
- extract(d.pn_object(), x, pn_data_get_decimal64);
- return d;
+decoder decoder::operator>>(decimal64 &x) {
+ extract(pn_object(), x, pn_data_get_decimal64);
+ return *this;
}
-decoder operator>>(decoder d, decimal128 &x) {
- extract(d.pn_object(), x, pn_data_get_decimal128);
- return d;
+decoder decoder::operator>>(decimal128 &x) {
+ extract(pn_object(), x, pn_data_get_decimal128);
+ return *this;
}
-decoder operator>>(decoder d, uuid &x) {
- extract(d.pn_object(), x, pn_data_get_uuid);
- return d;
+decoder decoder::operator>>(uuid &x) {
+ extract(pn_object(), x, pn_data_get_uuid);
+ return *this;
}
-decoder operator>>(decoder d0, std::string &x) {
- pn_data_t* d = d0.pn_object();
+decoder decoder::operator>>(std::string &x) {
+ pn_data_t* d = pn_object();
save_state ss(d);
switch (pre_get(d)) {
case STRING: x = str(pn_data_get_string(d)); break;
@@ -375,7 +376,7 @@ decoder operator>>(decoder d0, std::string &x) {
default: bad_type(STRING, type_id(pn_data_type(d)));
}
ss.cancel();
- return d0;
+ return *this;
}
void assert_map_scope(const scope& s) {
@@ -386,4 +387,5 @@ void assert_map_scope(const scope& s) {
}
-}
+} // internal
+} // proton
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/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 a7f1498..0da0994 100644
--- a/proton-c/bindings/cpp/src/encoder.cpp
+++ b/proton-c/bindings/cpp/src/encoder.cpp
@@ -36,6 +36,7 @@
#include <algorithm>
namespace proton {
+namespace internal {
namespace {
struct save_state {
@@ -84,24 +85,22 @@ std::string encoder::encode() {
return s;
}
-data encoder::data() { return proton::data(pn_object()); }
-
-encoder operator<<(encoder e, const start& s) {
+encoder encoder::operator<<(const start& s) {
switch (s.type) {
- case ARRAY: pn_data_put_array(e.pn_object(), s.is_described, pn_type_t(s.element)); break;
- case MAP: pn_data_put_map(e.pn_object()); break;
- case LIST: pn_data_put_list(e.pn_object()); break;
- case DESCRIBED: pn_data_put_described(e.pn_object()); break;
+ case ARRAY: pn_data_put_array(pn_object(), s.is_described, pn_type_t(s.element)); break;
+ case MAP: pn_data_put_map(pn_object()); break;
+ case LIST: pn_data_put_list(pn_object()); break;
+ case DESCRIBED: pn_data_put_described(pn_object()); break;
default:
throw conversion_error(MSG("" << s.type << " is not a container type"));
}
- pn_data_enter(e.pn_object());
- return e;
+ pn_data_enter(pn_object());
+ return *this;
}
-encoder operator<<(encoder e, finish) {
- pn_data_exit(e.pn_object());
- return e;
+encoder encoder::operator<<(const finish&) {
+ pn_data_exit(pn_object());
+ return *this;
}
namespace {
@@ -113,7 +112,7 @@ template <> pn_decimal64_t convert(const decimal64 &x) { pn_decimal64_t y; byte_
template <> pn_decimal128_t convert(const decimal128 &x) { pn_decimal128_t y; byte_copy(y, x); return y; }
template <class T, class U>
-encoder insert(encoder e, pn_data_t* data, const T& x, int (*put)(pn_data_t*, U)) {
+encoder do_put(encoder e, pn_data_t* data, const T& x, int (*put)(pn_data_t*, U)) {
save_state ss(data); // Save state in case of error.
check(put(data, convert<U>(x)), data);
ss.cancel(); // Don't restore state, all is good.
@@ -125,41 +124,41 @@ int pn_data_put_amqp_binary(pn_data_t *d, const amqp::binary_type& x) { return p
int pn_data_put_amqp_symbol(pn_data_t *d, const amqp::symbol_type& x) { return pn_data_put_symbol(d, pn_bytes(x)); }
}
-encoder operator<<(encoder e, amqp::boolean_type x) { return insert(e, e.pn_object(), x, pn_data_put_bool); }
-encoder operator<<(encoder e, amqp::ubyte_type x) { return insert(e, e.pn_object(), x, pn_data_put_ubyte); }
-encoder operator<<(encoder e, amqp::byte_type x) { return insert(e, e.pn_object(), x, pn_data_put_byte); }
-encoder operator<<(encoder e, amqp::ushort_type x) { return insert(e, e.pn_object(), x, pn_data_put_ushort); }
-encoder operator<<(encoder e, amqp::short_type x) { return insert(e, e.pn_object(), x, pn_data_put_short); }
-encoder operator<<(encoder e, amqp::uint_type x) { return insert(e, e.pn_object(), x, pn_data_put_uint); }
-encoder operator<<(encoder e, amqp::int_type x) { return insert(e, e.pn_object(), x, pn_data_put_int); }
-encoder operator<<(encoder e, amqp::char_type x) { return insert(e, e.pn_object(), x, pn_data_put_char); }
-encoder operator<<(encoder e, amqp::ulong_type x) { return insert(e, e.pn_object(), x, pn_data_put_ulong); }
-encoder operator<<(encoder e, amqp::long_type x) { return insert(e, e.pn_object(), x, pn_data_put_long); }
-encoder operator<<(encoder e, timestamp x) { return insert(e, e.pn_object(), x.ms(), pn_data_put_timestamp); }
-encoder operator<<(encoder e, amqp::float_type x) { return insert(e, e.pn_object(), x, pn_data_put_float); }
-encoder operator<<(encoder e, amqp::double_type x) { return insert(e, e.pn_object(), x, pn_data_put_double); }
-
-encoder operator<<(encoder e, decimal32 x) { return insert(e, e.pn_object(), x, pn_data_put_decimal32); }
-encoder operator<<(encoder e, decimal64 x) { return insert(e, e.pn_object(), x, pn_data_put_decimal64); }
-encoder operator<<(encoder e, decimal128 x) { return insert(e, e.pn_object(), x, pn_data_put_decimal128); }
-encoder operator<<(encoder e, uuid x) { return insert(e, e.pn_object(), x, pn_data_put_uuid); }
-encoder operator<<(encoder e, amqp::string_type x) { return insert(e, e.pn_object(), x, pn_data_put_amqp_string); }
-encoder operator<<(encoder e, amqp::symbol_type x) { return insert(e, e.pn_object(), x, pn_data_put_amqp_symbol); }
-encoder operator<<(encoder e, amqp::binary_type x) { return insert(e, e.pn_object(), x, pn_data_put_amqp_binary); }
-
-encoder operator<<(encoder e, const value& v) {
- data edata = e.data();
- if (edata == v.data_) throw conversion_error("cannot insert into self");
- data vdata = v.decode().data();
- check(edata.append(vdata), e.pn_object());
- return e;
+encoder encoder::operator<<(bool x) { return do_put(*this, pn_object(), x, pn_data_put_bool); }
+encoder encoder::operator<<(uint8_t x) { return do_put(*this, pn_object(), x, pn_data_put_ubyte); }
+encoder encoder::operator<<(int8_t x) { return do_put(*this, pn_object(), x, pn_data_put_byte); }
+encoder encoder::operator<<(uint16_t x) { return do_put(*this, pn_object(), x, pn_data_put_ushort); }
+encoder encoder::operator<<(int16_t x) { return do_put(*this, pn_object(), x, pn_data_put_short); }
+encoder encoder::operator<<(uint32_t x) { return do_put(*this, pn_object(), x, pn_data_put_uint); }
+encoder encoder::operator<<(int32_t x) { return do_put(*this, pn_object(), x, pn_data_put_int); }
+encoder encoder::operator<<(wchar_t x) { return do_put(*this, pn_object(), x, pn_data_put_char); }
+encoder encoder::operator<<(uint64_t x) { return do_put(*this, pn_object(), x, pn_data_put_ulong); }
+encoder encoder::operator<<(int64_t x) { return do_put(*this, pn_object(), x, pn_data_put_long); }
+encoder encoder::operator<<(timestamp x) { return do_put(*this, pn_object(), x.ms(), pn_data_put_timestamp); }
+encoder encoder::operator<<(float x) { return do_put(*this, pn_object(), x, pn_data_put_float); }
+encoder encoder::operator<<(double x) { return do_put(*this, pn_object(), x, pn_data_put_double); }
+encoder encoder::operator<<(decimal32 x) { return do_put(*this, pn_object(), x, pn_data_put_decimal32); }
+encoder encoder::operator<<(decimal64 x) { return do_put(*this, pn_object(), x, pn_data_put_decimal64); }
+encoder encoder::operator<<(decimal128 x) { return do_put(*this, pn_object(), x, pn_data_put_decimal128); }
+encoder encoder::operator<<(const uuid& x) { return do_put(*this, pn_object(), x, pn_data_put_uuid); }
+encoder encoder::operator<<(const std::string& x) { return do_put(*this, pn_object(), x, pn_data_put_amqp_string); }
+encoder encoder::operator<<(const symbol& x) { return do_put(*this, pn_object(), x, pn_data_put_amqp_symbol); }
+encoder encoder::operator<<(const binary& x) { return do_put(*this, pn_object(), x, pn_data_put_amqp_binary); }
+
+encoder encoder::operator<<(const scalar& x) { return do_put(*this, pn_object(), x.atom_, pn_data_put_atom); }
+
+void encoder::insert(const value& v) {
+ data mine(pn_object());
+ if (mine == v.data_)
+ throw conversion_error("cannot insert into self");
+ if (v.empty())
+ throw conversion_error("cannot insert empty value");
+ v.decode(); // Rewind
+ check(mine.append(v.data()), pn_object());
}
-encoder operator<<(encoder e, const scalar& x) {
- return insert(e, e.pn_object(), x.atom_, pn_data_put_atom);
+std::ostream& operator<<(std::ostream& o, const encoder& e) {
+ return o << data(e.pn_object());
+}
}
-
-encoder operator<<(encoder e, const message_id& x) { return e << x.scalar_; }
-encoder operator<<(encoder e, const annotation_key& x) { return e << x.scalar_; }
-
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/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 c25dedc..083e0bc 100644
--- a/proton-c/bindings/cpp/src/interop_test.cpp
+++ b/proton-c/bindings/cpp/src/interop_test.cpp
@@ -30,6 +30,7 @@
using namespace std;
using namespace proton;
+using namespace proton::internal;
using namespace test;
std::string tests_dir;
@@ -90,7 +91,7 @@ void test_encoder_primitives() {
e << ::uint32_t(12345) << ::int32_t(-12345);
e << ::uint64_t(12345) << ::int64_t(-12345);
e << float(0.125) << double(0.125);
- ASSERT_EQUAL("true, false, 42, 42, -42, 12345, -12345, 12345, -12345, 0.125, 0.125", str(e.data()));
+ ASSERT_EQUAL("true, false, 42, 42, -42, 12345, -12345, 12345, -12345, 0.125, 0.125", str(str(e)));
std::string data = e.encode();
ASSERT_EQUAL(read("primitives"), data);
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/proton-c/bindings/cpp/src/link_options.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/link_options.cpp b/proton-c/bindings/cpp/src/link_options.cpp
index 6dd32d7..dd0febb 100644
--- a/proton-c/bindings/cpp/src/link_options.cpp
+++ b/proton-c/bindings/cpp/src/link_options.cpp
@@ -108,13 +108,13 @@ class link_options::impl {
if (lifetime_policy.set) lp = lifetime_policy_symbol(lifetime_policy.value);
if (!sender && distribution_mode.set) dm = distribution_mode_symbol(distribution_mode.value);
if (lp.size() || dm.size()) {
- encoder enc = t.node_properties().encode();
- enc << start::map();
+ internal::encoder enc = t.node_properties().encode();
+ enc << internal::start::map();
if (dm.size())
enc << symbol("supported-dist-modes") << std::string(dm);
if (lp.size())
- enc << symbol("lifetime-policy") << start::described()
- << symbol(lp) << start::list() << finish();
+ enc << symbol("lifetime-policy") << internal::start::described()
+ << symbol(lp) << internal::start::list() << internal::finish();
}
}
}
@@ -126,9 +126,9 @@ class link_options::impl {
l.local_source().expiry_policy(terminus::EXPIRE_NEVER);
}
if (selector.set && selector.value.size()) {
- encoder enc = l.local_source().filter().encode();
- enc << start::map() << symbol("selector") << start::described()
- << symbol("apache.org:selector-filter:string") << binary(selector.value) << finish();
+ internal::encoder enc = l.local_source().filter().encode();
+ enc << internal::start::map() << symbol("selector") << internal::start::described()
+ << symbol("apache.org:selector-filter:string") << binary(selector.value) << internal::finish();
}
}
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/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 fcce408..2b793f8 100644
--- a/proton-c/bindings/cpp/src/message.cpp
+++ b/proton-c/bindings/cpp/src/message.cpp
@@ -47,7 +47,7 @@ message::message(message &&m) : pn_msg_(0) { swap(*this, m); }
#endif
message::~message() {
- body_.data_ = data(0); // Must release body before pn_message_free
+ body_.data_ = internal::data(0); // Must release body before pn_message_free
pn_message_free(pn_msg_);
}
@@ -126,7 +126,7 @@ std::string message::reply_to() const {
}
void message::correlation_id(const message_id& id) {
- data(pn_message_correlation_id(pn_msg())).copy(id.scalar_);
+ internal::data(pn_message_correlation_id(pn_msg())).copy(id.scalar_);
}
message_id message::correlation_id() const {
@@ -197,9 +197,9 @@ value& message::body() { pn_msg(); return body_; }
// Decode a map on demand
template<class M> M& get_map(pn_message_t* msg, pn_data_t* (*get)(pn_message_t*), M& map) {
- data d(get(msg));
+ internal::data d(get(msg));
if (map.empty() && !d.empty()) {
- d.decoder() >> rewind() >> map;
+ d.decoder() >> internal::rewind() >> map;
d.clear(); // The map member is now the authority.
}
return map;
@@ -207,7 +207,7 @@ template<class M> M& get_map(pn_message_t* msg, pn_data_t* (*get)(pn_message_t*)
// Encode a map if necessary.
template<class M> M& put_map(pn_message_t* msg, pn_data_t* (*get)(pn_message_t*), M& map) {
- data d(get(msg));
+ internal::data d(get(msg));
if (d.empty() && !map.empty()) {
d.encoder() << map;
map.clear(); // The encoded pn_data_t is now the authority.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/proton-c/bindings/cpp/src/types.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/types.cpp b/proton-c/bindings/cpp/src/types.cpp
index 4f12696..f64d0b6 100644
--- a/proton-c/bindings/cpp/src/types.cpp
+++ b/proton-c/bindings/cpp/src/types.cpp
@@ -17,7 +17,8 @@
* under the License.
*/
-#include "proton/types.hpp"
+#include <proton/types.hpp>
+#include <proton/type_traits.hpp>
#include <proton/codec.h>
#include <ostream>
#include <iomanip>
@@ -70,11 +71,11 @@ bool type_id_is_scalar(type_id t) { return type_id_is_integral(t) || type_id_is_
std::ostream& operator<<(std::ostream& o, type_id t) { return o << type_name(t); }
-
+namespace internal {
start::start(type_id t, type_id e, bool d, size_t s) : type(t), element(e), is_described(d), size(s) {}
start start::array(type_id element, bool described) { return start(ARRAY, element, described); }
start start::list() { return start(LIST); }
start start::map() { return start(MAP); }
start start::described() { return start(DESCRIBED, NULL_TYPE, true); }
-
+}
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/proton-c/bindings/cpp/src/types_internal.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/types_internal.hpp b/proton-c/bindings/cpp/src/types_internal.hpp
index f17f68c..1c0de8a 100644
--- a/proton-c/bindings/cpp/src/types_internal.hpp
+++ b/proton-c/bindings/cpp/src/types_internal.hpp
@@ -30,7 +30,7 @@ namespace proton {
/// Byte copy between two objects, only enabled if their sizes are equal.
template <class T, class U>
-typename enable_if<sizeof(T) == sizeof(U)>::type byte_copy(T &to, const U &from) {
+typename internal::enable_if<sizeof(T) == sizeof(U)>::type byte_copy(T &to, const U &from) {
const char *p = reinterpret_cast<const char*>(&from);
std::copy(p, p + sizeof(T), reinterpret_cast<char*>(&to));
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bdaf901a/proton-c/bindings/cpp/src/value.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/value.cpp b/proton-c/bindings/cpp/src/value.cpp
index 32cfa9b..1de0516 100644
--- a/proton-c/bindings/cpp/src/value.cpp
+++ b/proton-c/bindings/cpp/src/value.cpp
@@ -28,6 +28,8 @@ namespace proton {
value::value() {}
value::value(const value& x) { *this = x; }
+value::value(pn_data_t* p) { if (p) data().copy(internal::data(p)); }
+
#if PN_CPP_HAS_CPP11
value::value(value&& x) { swap(*this, x); }
#endif
@@ -37,7 +39,7 @@ value& value::operator=(const value& x) {
if (x.empty())
clear();
else
- encode() << x;
+ data().copy(x.data());
}
return *this;
}
@@ -49,11 +51,13 @@ void value::clear() { if (!!data_) data_.clear(); }
bool value::empty() const { return !data_ || data_.empty(); }
// On demand
-inline data& value::data() const { if (!data_) data_ = proton::data::create(); return data_; }
+internal::data& value::data() const {
+ if (!data_) data_ = internal::data::create(); return data_;
+}
-class encoder value::encode() { clear(); return data().encoder(); }
+internal::encoder value::encode() { clear(); return data().encoder(); }
-class decoder value::decode() const { return data().decoder() >> rewind(); }
+internal::decoder value::decode() const { return data().decoder() >> internal::rewind(); }
type_id value::type() const { return decode().type(); }
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org