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:24 UTC
[1/4] qpid-proton git commit: PROTON-1138: c++: get<>/coerce<> API
and documentation.
Repository: qpid-proton
Updated Branches:
refs/heads/kvdr-PROTON-1159 a8b63a1c2 -> e15bcdd09
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/src/scalar_base.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/scalar_base.cpp b/proton-c/bindings/cpp/src/scalar_base.cpp
new file mode 100644
index 0000000..1220a54
--- /dev/null
+++ b/proton-c/bindings/cpp/src/scalar_base.cpp
@@ -0,0 +1,158 @@
+/*
+ * 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_base.hpp"
+#include "proton/symbol.hpp"
+#include "proton/timestamp.hpp"
+#include "proton/type_traits.hpp"
+#include "proton/uuid.hpp"
+
+#include <ostream>
+
+namespace proton {
+
+scalar_base::scalar_base() { atom_.type = PN_NULL; }
+scalar_base::scalar_base(const pn_atom_t& a) { set(a); }
+scalar_base::scalar_base(const scalar_base& x) { set(x.atom_); }
+
+scalar_base& scalar_base::operator=(const scalar_base& x) {
+ if (this != &x)
+ set(x.atom_);
+ return *this;
+}
+
+type_id scalar_base::type() const { return type_id(atom_.type); }
+
+void scalar_base::set(const binary& x, pn_type_t t) {
+ atom_.type = t;
+ bytes_ = x;
+ atom_.u.as_bytes = pn_bytes(bytes_);
+}
+
+void scalar_base::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;
+ bytes_.clear();
+ }
+}
+
+void scalar_base::put_(bool x) { atom_.u.as_bool = x; atom_.type = PN_BOOL; }
+void scalar_base::put_(uint8_t x) { atom_.u.as_ubyte = x; atom_.type = PN_UBYTE; }
+void scalar_base::put_(int8_t x) { atom_.u.as_byte = x; atom_.type = PN_BYTE; }
+void scalar_base::put_(uint16_t x) { atom_.u.as_ushort = x; atom_.type = PN_USHORT; }
+void scalar_base::put_(int16_t x) { atom_.u.as_short = x; atom_.type = PN_SHORT; }
+void scalar_base::put_(uint32_t x) { atom_.u.as_uint = x; atom_.type = PN_UINT; }
+void scalar_base::put_(int32_t x) { atom_.u.as_int = x; atom_.type = PN_INT; }
+void scalar_base::put_(uint64_t x) { atom_.u.as_ulong = x; atom_.type = PN_ULONG; }
+void scalar_base::put_(int64_t x) { atom_.u.as_long = x; atom_.type = PN_LONG; }
+void scalar_base::put_(wchar_t x) { atom_.u.as_char = x; atom_.type = PN_CHAR; }
+void scalar_base::put_(float x) { atom_.u.as_float = x; atom_.type = PN_FLOAT; }
+void scalar_base::put_(double x) { atom_.u.as_double = x; atom_.type = PN_DOUBLE; }
+void scalar_base::put_(timestamp x) { atom_.u.as_timestamp = x.ms(); atom_.type = PN_TIMESTAMP; }
+void scalar_base::put_(const decimal32& x) { byte_copy(atom_.u.as_decimal32, x); atom_.type = PN_DECIMAL32;; }
+void scalar_base::put_(const decimal64& x) { byte_copy(atom_.u.as_decimal64, x); atom_.type = PN_DECIMAL64; }
+void scalar_base::put_(const decimal128& x) { byte_copy(atom_.u.as_decimal128, x); atom_.type = PN_DECIMAL128; }
+void scalar_base::put_(const uuid& x) { byte_copy(atom_.u.as_uuid, x); atom_.type = PN_UUID; }
+void scalar_base::put_(const std::string& x) { set(binary(x), PN_STRING); }
+void scalar_base::put_(const symbol& x) { set(binary(x), PN_SYMBOL); }
+void scalar_base::put_(const binary& x) { set(x, PN_BINARY); }
+void scalar_base::put_(const char* x) { set(binary(std::string(x)), PN_STRING); }
+void scalar_base::put_(const null&) { atom_.type = PN_NULL; }
+
+void scalar_base::ok(pn_type_t t) const {
+ if (atom_.type != t) throw make_conversion_error(type_id(t), type());
+}
+
+void scalar_base::get_(bool& x) const { ok(PN_BOOL); x = atom_.u.as_bool; }
+void scalar_base::get_(uint8_t& x) const { ok(PN_UBYTE); x = atom_.u.as_ubyte; }
+void scalar_base::get_(int8_t& x) const { ok(PN_BYTE); x = atom_.u.as_byte; }
+void scalar_base::get_(uint16_t& x) const { ok(PN_USHORT); x = atom_.u.as_ushort; }
+void scalar_base::get_(int16_t& x) const { ok(PN_SHORT); x = atom_.u.as_short; }
+void scalar_base::get_(uint32_t& x) const { ok(PN_UINT); x = atom_.u.as_uint; }
+void scalar_base::get_(int32_t& x) const { ok(PN_INT); x = atom_.u.as_int; }
+void scalar_base::get_(wchar_t& x) const { ok(PN_CHAR); x = wchar_t(atom_.u.as_char); }
+void scalar_base::get_(uint64_t& x) const { ok(PN_ULONG); x = atom_.u.as_ulong; }
+void scalar_base::get_(int64_t& x) const { ok(PN_LONG); x = atom_.u.as_long; }
+void scalar_base::get_(timestamp& x) const { ok(PN_TIMESTAMP); x = atom_.u.as_timestamp; }
+void scalar_base::get_(float& x) const { ok(PN_FLOAT); x = atom_.u.as_float; }
+void scalar_base::get_(double& x) const { ok(PN_DOUBLE); x = atom_.u.as_double; }
+void scalar_base::get_(decimal32& x) const { ok(PN_DECIMAL32); byte_copy(x, atom_.u.as_decimal32); }
+void scalar_base::get_(decimal64& x) const { ok(PN_DECIMAL64); byte_copy(x, atom_.u.as_decimal64); }
+void scalar_base::get_(decimal128& x) const { ok(PN_DECIMAL128); byte_copy(x, atom_.u.as_decimal128); }
+void scalar_base::get_(uuid& x) const { ok(PN_UUID); byte_copy(x, atom_.u.as_uuid); }
+void scalar_base::get_(std::string& x) const { ok(PN_STRING); x = std::string(bytes_.begin(), bytes_.end()); }
+void scalar_base::get_(symbol& x) const { ok(PN_SYMBOL); x = symbol(bytes_.begin(), bytes_.end()); }
+void scalar_base::get_(binary& x) const { ok(PN_BINARY); x = bytes_; }
+void scalar_base::get_(null&) const { ok(PN_NULL); }
+
+int64_t scalar_base::as_int() const { return internal::coerce<int64_t>(*this); }
+
+uint64_t scalar_base::as_uint() const { return internal::coerce<uint64_t>(*this); }
+
+double scalar_base::as_double() const { return internal::coerce<double>(*this); }
+
+std::string scalar_base::as_string() const { return internal::coerce<std::string>(*this); }
+
+namespace {
+
+struct equal_op {
+ const scalar_base& x;
+ equal_op(const scalar_base& s) : x(s) {}
+ template<class T> bool operator()(const T& y) { return (x.get<T>() == y); }
+};
+
+struct less_op {
+ const scalar_base& x;
+ less_op(const scalar_base& s) : x(s) {}
+ template<class T> bool operator()(const T& y) { return (y < x.get<T>()); }
+};
+
+struct ostream_op {
+ std::ostream& o;
+ ostream_op(std::ostream& o_) : o(o_) {}
+ template<class T> std::ostream& operator()(const T& x) { return o << x; }
+};
+
+} // namespace
+
+bool operator==(const scalar_base& x, const scalar_base& y) {
+ if (x.type() != y.type()) return false;
+ if (x.type() == NULL_TYPE) return true;
+ return internal::visit<bool>(x, equal_op(y));
+}
+
+bool operator<(const scalar_base& x, const scalar_base& y) {
+ if (x.type() != y.type()) return x.type() < y.type();
+ if (x.type() == NULL_TYPE) return false;
+ return internal::visit<bool>(x, less_op(y));
+}
+
+std::ostream& operator<<(std::ostream& o, const scalar_base& s) {
+ if (s.type() == NULL_TYPE) return o << "<null>";
+ return internal::visit<std::ostream&>(s, ostream_op(o));
+}
+
+} // namespace proton
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/src/scalar_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/scalar_test.cpp b/proton-c/bindings/cpp/src/scalar_test.cpp
index 9b2df1f..b5955d5 100644
--- a/proton-c/bindings/cpp/src/scalar_test.cpp
+++ b/proton-c/bindings/cpp/src/scalar_test.cpp
@@ -60,13 +60,10 @@ template <class T> void type_test(T x, type_id tid, T y) {
try { \
(void)(EXPR); \
FAIL("expected conversion_error: " #EXPR); \
- } catch (const conversion_error& e) { \
- std::ostringstream want; \
- want << "unexpected type, want: " << (WANT) << " got: " << (GOT); \
- ASSERT_EQUAL(want.str(), std::string(e.what())); \
- }
+ } catch (const conversion_error& e) {}
-void convert_test() {
+// FIXME aconway 2016-03-15: new coerce stuff.
+void coerce_test() {
scalar a;
ASSERT_EQUAL(NULL_TYPE, a.type());
ASSERT(a.empty());
@@ -98,8 +95,8 @@ void encode_decode_test() {
scalar a("foo");
v = a; // Assignment to value does encode, get<> does decode.
ASSERT_EQUAL(v, a);
- ASSERT_EQUAL(std::string("foo"), v.get<std::string>());
- scalar a2 = v.get<scalar>();
+ ASSERT_EQUAL(std::string("foo"), get<std::string>(v));
+ scalar a2 = get<scalar>(v);
ASSERT_EQUAL(std::string("foo"), a2.get<std::string>());
}
@@ -149,6 +146,6 @@ int main(int, char**) {
RUN_TEST(failed, encode_decode_test());
RUN_TEST(failed, message_id_test());
RUN_TEST(failed, annotation_key_test());
- RUN_TEST(failed, convert_test());
+ RUN_TEST(failed, coerce_test());
return failed;
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/src/ssl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/ssl.cpp b/proton-c/bindings/cpp/src/ssl.cpp
index 384c331..62a234f 100644
--- a/proton-c/bindings/cpp/src/ssl.cpp
+++ b/proton-c/bindings/cpp/src/ssl.cpp
@@ -59,7 +59,7 @@ std::string ssl::peer_hostname() const {
if (pn_ssl_get_peer_hostname(object_, NULL, &len) || len == 0)
return hostname;
hostname.reserve(len);
- if (!pn_ssl_get_peer_hostname(object_, const_cast<char *>(hostname.data()), &len))
+ if (!pn_ssl_get_peer_hostname(object_, const_cast<char*>(hostname.c_str()), &len))
hostname.resize(len - 1);
else
hostname.resize(0);
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/src/test_bits.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/test_bits.hpp b/proton-c/bindings/cpp/src/test_bits.hpp
index d45739c..38cd7a8 100644
--- a/proton-c/bindings/cpp/src/test_bits.hpp
+++ b/proton-c/bindings/cpp/src/test_bits.hpp
@@ -26,15 +26,22 @@
#include <iostream>
#include <iterator>
#include <sstream>
+#include <math.h>
namespace test {
struct fail : public std::logic_error { fail(const std::string& what) : logic_error(what) {} };
+bool close(double want, double got, double delta) {
+ return fabs(want-got) <= delta;
+}
+
#define FAIL(WHAT) throw fail(MSG(__FILE__ << ":" << __LINE__ << ": " << WHAT))
#define ASSERT(TEST) do { if (!(TEST)) FAIL("assert failed: " << #TEST); } while(false)
#define ASSERT_EQUAL(WANT, GOT) if (!((WANT) == (GOT))) \
FAIL(#WANT << " != " << #GOT << ": " << (WANT) << " != " << (GOT))
+#define ASSERT_CLOSE(WANT, GOT, DELTA) if (!close((WANT), (GOT), (DELTA))) \
+ FAIL(#WANT << " != " << #GOT << ": " << (WANT) << " != " << (GOT))
#define RUN_TEST(BAD_COUNT, TEST) \
do { \
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 c3ad1d4..74427a1 100644
--- a/proton-c/bindings/cpp/src/types_internal.hpp
+++ b/proton-c/bindings/cpp/src/types_internal.hpp
@@ -31,7 +31,7 @@ namespace proton {
/// Byte copy between two objects, only enabled if their sizes are equal.
template <class T, class U>
-typename codec::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));
}
@@ -51,23 +51,13 @@ inline pn_bytes_t pn_bytes(const std::string& s) {
}
inline pn_bytes_t pn_bytes(const binary& s) {
- pn_bytes_t b = { s.size(), const_cast<char*>(&s[0]) };
+ pn_bytes_t b = { s.size(), reinterpret_cast<const char*>(&s[0]) };
return b;
}
inline std::string str(const pn_bytes_t& b) { return std::string(b.start, b.size); }
inline binary bin(const pn_bytes_t& b) { return binary(b.start, b.start+b.size); }
-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; }
-
}
#endif // CODEC_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 bece42c..ba2f540 100644
--- a/proton-c/bindings/cpp/src/value.cpp
+++ b/proton-c/bindings/cpp/src/value.cpp
@@ -31,7 +31,6 @@ namespace proton {
using namespace codec;
value::value() {}
-value::value(const null&) {}
value::value(const value& x) { *this = x; }
value::value(const codec::data& x) { if (!x.empty()) data().copy(x); }
#if PN_CPP_HAS_CPP11
@@ -39,8 +38,6 @@ value::value(value&& x) { swap(*this, x); }
value& value::operator=(value&& x) { swap(*this, x); return *this; }
#endif
-value& value::operator=(const null&) { clear(); return *this; }
-
value& value::operator=(const value& x) {
if (this != &x) {
if (x.empty())
@@ -176,27 +173,17 @@ std::ostream& operator<<(std::ostream& o, const value_base& x) {
decoder d(x);
// Print std::string and proton::foo types using their own operator << consistent with C++.
switch (d.next_type()) {
- case STRING: return o << d.extract<std::string>();
- case SYMBOL: return o << d.extract<symbol>();
- case DECIMAL32: return o << d.extract<decimal32>();
- case DECIMAL64: return o << d.extract<decimal64>();
- case DECIMAL128: return o << d.extract<decimal128>();
- case UUID: return o << d.extract<uuid>();
- case TIMESTAMP: return o << d.extract<timestamp>();
+ case STRING: return o << get<std::string>(d);
+ case SYMBOL: return o << get<symbol>(d);
+ case DECIMAL32: return o << get<decimal32>(d);
+ case DECIMAL64: return o << get<decimal64>(d);
+ case DECIMAL128: return o << get<decimal128>(d);
+ case UUID: return o << get<uuid>(d);
+ case TIMESTAMP: return o << get<timestamp>(d);
default:
// Use pn_inspect for other types.
return o << d;
}
}
-void value::get(null&) const {
- if (type() != NULL_TYPE)
- throw conversion_error("value is not null");
-}
-
-int64_t value::as_int() const { return get<scalar>().as_int(); }
-uint64_t value::as_uint() const { return get<scalar>().as_uint(); }
-double value::as_double() const { return get<scalar>().as_double(); }
-std::string value::as_string() const { return get<scalar>().as_string(); }
-
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/src/value_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/value_test.cpp b/proton-c/bindings/cpp/src/value_test.cpp
index be24da4..fe7c089 100644
--- a/proton-c/bindings/cpp/src/value_test.cpp
+++ b/proton-c/bindings/cpp/src/value_test.cpp
@@ -60,8 +60,8 @@ template <class T> void simple_type_test(T x, type_id tid, const std::string& s,
}
template <class T> void simple_integral_test() {
- typedef typename codec::integer_type<sizeof(T), codec::is_signed<T>::value>::type int_type;
- simple_type_test(T(3), codec::type_id_of<int_type>::value, "3", T(4));
+ typedef typename internal::integer_type<sizeof(T), internal::is_signed<T>::value>::type int_type;
+ simple_type_test(T(3), internal::type_id_of<int_type>::value, "3", T(4));
}
// Inserting and extracting arrays from a container T of type U
@@ -90,7 +90,7 @@ template <class T, class U> void map_test(const U& values) {
T m(values.begin(), values.end());
value v(m);
ASSERT_EQUAL(MAP, v.type());
- T m2(v.get<T>());
+ T m2(get<T>(v));
ASSERT_EQUAL(m.size(), m2.size());
ASSERT_EQUAL(m, m2);
}
@@ -103,18 +103,50 @@ void null_test() {
value v;
ASSERT(v.empty());
ASSERT_EQUAL(NULL_TYPE, v.type());
+ get<null>(v);
null n;
- v.get(n);
+ get(v, n);
value v2(n);
ASSERT(v.empty());
ASSERT_EQUAL(NULL_TYPE, v.type());
v = "foo";
ASSERT_EQUAL(STRING, v.type());
- try { v.get<null>(); FAIL("Expected conversion_error"); } catch (conversion_error) {}
+ try { get<null>(v); FAIL("Expected conversion_error"); } catch (conversion_error) {}
v = null();
- v.get<null>();
+ get<null>(v);
}
+void get_coerce_test() {
+ // Valid conversions
+ ASSERT_EQUAL(true, coerce<bool>(value(true)));
+
+ ASSERT_EQUAL(1, coerce<uint8_t>(value(uint8_t(1))));
+ ASSERT_EQUAL(-1, coerce<int8_t>(value(int8_t(-1))));
+
+ ASSERT_EQUAL(2, coerce<uint16_t>(value(uint8_t(2))));
+ ASSERT_EQUAL(-2, coerce<int16_t>(value(int8_t(-2))));
+
+ ASSERT_EQUAL(3, coerce<uint32_t>(value(uint16_t(3))));
+ ASSERT_EQUAL(-3, coerce<int32_t>(value(int16_t(-3))));
+
+ ASSERT_EQUAL(4, coerce<uint64_t>(value(uint32_t(4))));
+ ASSERT_EQUAL(-4, coerce<int64_t>(value(int32_t(-4))));
+
+ ASSERT_CLOSE(1.2, coerce<float>(value(double(1.2))), 0.001);
+ ASSERT_CLOSE(3.4, coerce<double>(value(float(3.4))), 0.001);
+
+ ASSERT_EQUAL(std::string("foo"), coerce<std::string>(value(symbol("foo"))));
+
+ // Bad conversions
+ try { get<bool>(value(int8_t(1))); FAIL("byte as bool"); } catch (conversion_error) {}
+ try { get<uint8_t>(value(true)); FAIL("bool as uint8_t"); } catch (conversion_error) {}
+ try { get<uint8_t>(value(int8_t(1))); FAIL("int8 as uint8"); } catch (conversion_error) {}
+ try { get<int16_t>(value(uint16_t(1))); FAIL("uint16 as int16"); } catch (conversion_error) {}
+ try { get<int16_t>(value(int32_t(1))); FAIL("int32 as int16"); } catch (conversion_error) {}
+ try { get<symbol>(value(std::string())); FAIL("string as symbol"); } catch (conversion_error) {}
+}
+
+
int main(int, char**) {
int failed = 0;
RUN_TEST(failed, simple_type_test(false, BOOLEAN, "false", true));
@@ -188,6 +220,6 @@ int main(int, char**) {
RUN_TEST(failed, (map_test<std::unordered_map<std::string, uint64_t> >(pairs)));
#endif
- value vv((pn_data_t*)(0));
+ RUN_TEST(failed, get_coerce_test());
return failed;
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/tests/tools/apps/cpp/reactor_send.cpp
----------------------------------------------------------------------
diff --git a/tests/tools/apps/cpp/reactor_send.cpp b/tests/tools/apps/cpp/reactor_send.cpp
index 3ba26e8..224ac71 100644
--- a/tests/tools/apps/cpp/reactor_send.cpp
+++ b/tests/tools/apps/cpp/reactor_send.cpp
@@ -91,7 +91,7 @@ class reactor_send : public proton::handler {
void on_message(proton::event &e) {
proton::message &msg = e.message();
- received_content_ = msg.body().get<proton::binary>();
+ received_content_ = proton::get<proton::binary>(msg.body());
received_bytes_ += received_content_.size();
if (received_ < total_) {
received_++;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[3/4] qpid-proton git commit: PROTON-1138: c++: get<>/coerce<> API
and documentation.
Posted by kp...@apache.org.
PROTON-1138: c++: get<>/coerce<> API and documentation.
Consistent get/coerce templates for proton::value, scalar, message_id and annotation_key.
get<T> - get the value, throw conversion_error if type is not exactly T.
coerce<T> - coerce the value to T if it is std::is_convertible, else throw conversion_error
- documentation page on C++/AMQP type conversion
- API doc for all types involved.
- cleanup/hide some internals.
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/d70dab5d
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/d70dab5d
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/d70dab5d
Branch: refs/heads/kvdr-PROTON-1159
Commit: d70dab5df243f3a595be21a436f1ef46fa8d8c6d
Parents: f5f68d8
Author: Alan Conway <ac...@redhat.com>
Authored: Mon Mar 14 15:55:46 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Wed Mar 16 16:53:27 2016 -0400
----------------------------------------------------------------------
examples/cpp/README.dox | 198 +++++++++
examples/cpp/README.hpp | 198 ---------
examples/cpp/direct_recv.cpp | 8 +-
examples/cpp/encode_decode.cpp | 13 +-
examples/cpp/engine/server.cpp | 2 +-
examples/cpp/server.cpp | 2 +-
examples/cpp/server_direct.cpp | 12 +-
proton-c/bindings/cpp/CMakeLists.txt | 2 +-
proton-c/bindings/cpp/docs/CMakeLists.txt | 1 +
proton-c/bindings/cpp/docs/tutorial.dox | 428 +++++++++++++++++++
proton-c/bindings/cpp/docs/tutorial.hpp | 428 -------------------
proton-c/bindings/cpp/docs/user.doxygen.in | 10 +-
proton-c/bindings/cpp/include/proton/amqp.hpp | 40 +-
.../cpp/include/proton/annotation_key.hpp | 51 ++-
proton-c/bindings/cpp/include/proton/binary.hpp | 26 +-
.../bindings/cpp/include/proton/byte_array.hpp | 52 ++-
.../bindings/cpp/include/proton/comparable.hpp | 2 +
.../cpp/include/proton/connection_engine.hpp | 2 +-
proton-c/bindings/cpp/include/proton/data.hpp | 51 +--
.../bindings/cpp/include/proton/decimal.hpp | 5 +-
.../bindings/cpp/include/proton/decoder.hpp | 49 ++-
proton-c/bindings/cpp/include/proton/deque.hpp | 2 +-
.../bindings/cpp/include/proton/duration.hpp | 17 +-
.../bindings/cpp/include/proton/encoder.hpp | 65 ++-
.../bindings/cpp/include/proton/endpoint.hpp | 5 +-
proton-c/bindings/cpp/include/proton/error.hpp | 6 +-
.../cpp/include/proton/forward_list.hpp | 2 +-
proton-c/bindings/cpp/include/proton/io.hpp | 3 +-
proton-c/bindings/cpp/include/proton/link.hpp | 5 +
proton-c/bindings/cpp/include/proton/list.hpp | 2 +-
.../bindings/cpp/include/proton/message.hpp | 6 +-
.../bindings/cpp/include/proton/message_id.hpp | 62 ++-
proton-c/bindings/cpp/include/proton/scalar.hpp | 217 ++--------
.../bindings/cpp/include/proton/scalar_base.hpp | 181 ++++++++
.../bindings/cpp/include/proton/session.hpp | 4 +-
proton-c/bindings/cpp/include/proton/symbol.hpp | 4 +
.../bindings/cpp/include/proton/timestamp.hpp | 18 +-
.../bindings/cpp/include/proton/type_id.hpp | 23 +-
.../bindings/cpp/include/proton/type_traits.hpp | 108 ++---
proton-c/bindings/cpp/include/proton/types.hpp | 88 +++-
.../bindings/cpp/include/proton/types_fwd.hpp | 11 +-
proton-c/bindings/cpp/include/proton/url.hpp | 2 +-
proton-c/bindings/cpp/include/proton/value.hpp | 106 ++---
proton-c/bindings/cpp/include/proton/vector.hpp | 2 +-
proton-c/bindings/cpp/src/decoder.cpp | 127 +++---
proton-c/bindings/cpp/src/encoder.cpp | 21 +-
proton-c/bindings/cpp/src/interop_test.cpp | 21 -
proton-c/bindings/cpp/src/message.cpp | 4 +-
proton-c/bindings/cpp/src/message_test.cpp | 16 +-
proton-c/bindings/cpp/src/scalar.cpp | 263 ------------
proton-c/bindings/cpp/src/scalar_base.cpp | 158 +++++++
proton-c/bindings/cpp/src/scalar_test.cpp | 15 +-
proton-c/bindings/cpp/src/ssl.cpp | 2 +-
proton-c/bindings/cpp/src/test_bits.hpp | 7 +
proton-c/bindings/cpp/src/types_internal.hpp | 14 +-
proton-c/bindings/cpp/src/value.cpp | 27 +-
proton-c/bindings/cpp/src/value_test.cpp | 46 +-
tests/tools/apps/cpp/reactor_send.cpp | 2 +-
58 files changed, 1688 insertions(+), 1554 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/examples/cpp/README.dox
----------------------------------------------------------------------
diff --git a/examples/cpp/README.dox b/examples/cpp/README.dox
new file mode 100644
index 0000000..1e78774
--- /dev/null
+++ b/examples/cpp/README.dox
@@ -0,0 +1,198 @@
+// Examples overview.
+//
+// For a better overview, see the tutorial in the generated documentation.
+//
+// In your build directory do:
+//
+// make docs-cpp
+//
+// then open proton-c/bindings/cpp/docs/html/tutorial.html in your browser.
+
+// DEVELOPER NOTE: if you are adding or modifying examples you should keep this
+// file and ../proton-c/bindings/cpp/docs/tutorial.hpp up to date.
+
+/** @example helloworld.cpp
+
+Connects to a broker on 127.0.0.1:5672, establishes a subscription
+from the 'examples' node, and creates a sending link to the same
+node. Sends one message and receives it back.
+
+*/
+
+/** @example helloworld_direct.cpp
+
+Variation of helloworld that does not use a broker, but listens for
+incoming connections itself. It establishes a connection to itself
+with a link over which a single message is sent. This demonstrates the
+ease with which a simple daemon an be built using the API.
+
+*/
+
+/** @example simple_send.cpp
+
+An example of sending a fixed number of messages and tracking their
+(asynchronous) acknowledgement. Messages are sent through the 'examples' node on
+an intermediary accessible on 127.0.0.1:5672.
+
+*/
+
+/** @example simple_recv.cpp
+
+Subscribes to the 'examples' node on an intermediary accessible
+on 127.0.0.1:5672. Simply prints out the body of received messages.
+
+*/
+
+/** @example direct_send.cpp
+
+Accepts an incoming connection and then sends like `simple_send`. You can
+connect directly to `direct_send` *without* a broker using \ref simple_recv.cpp.
+Make sure to stop the broker first or use a different port for `direct_send`.
+
+*/
+
+/** @example direct_recv.cpp
+
+Accepts an incoming connection and then receives like `simple_recv`. You can
+connect directly to `direct_recv` *without* a broker using \ref simple_send.cpp.
+Make sure to stop the broker first or use a different port for `direct_recv`.
+
+*/
+
+/// @cond INTERNAL
+/** @example encode_decode.cpp
+
+Shows how C++ data types can be converted to and from AMQP types.
+
+*/
+/// @endcond
+
+/** @example client.cpp
+
+The client part of a request-response example. Sends requests and
+prints out responses. Requires an intermediary that supports the AMQP
+1.0 dynamic nodes on which the responses are received. The requests
+are sent through the 'examples' node.
+
+*/
+
+/** @example server.cpp
+
+The server part of a request-response example, that receives requests
+via the examples node, converts the body to uppercase and sends the
+result back to the indicated reply address.
+
+*/
+
+/** @example server_direct.cpp
+
+A variant of the server part of a request-response example that
+accepts incoming connections and does not need an intermediary. Much
+like the original server, it receives incoming requests, converts the
+body to uppercase and sends the result back to the indicated reply
+address. Can be used in conjunction with any of the client
+alternatives.
+
+*/
+
+/** @example recurring_timer.cpp
+
+Shows how to implement recurring time-based events using the scheduler.
+
+*/
+
+/** @example broker.hpp
+
+Common logic for a simple "mini broker" that creates creates queues
+automatically when a client tries to send or subscribe. This file contains
+the `queue` class that queues messages and the `broker_handler` class
+that manages queues and links and transfers messages to/from clients.
+
+Examples \ref broker.cpp and \ref engine/broker.cpp use this same
+broker logic but show different ways to run it in a server application.
+
+*/
+
+/** @example broker.cpp
+
+A simple, single-threaded broker using the `proton::container`. You can use this
+to run other examples that reqiure an intermediary, or you can use any AMQP 1.0
+broker. This broker creates queues automatically when a client tries to send or
+subscribe.
+
+Uses the broker logic from \ref broker.hpp, the same logic as the
+`proton::connection_engine` broker example \ref engine/broker.cpp.
+
+*/
+
+//////////////// connection_engine examples.
+
+/** \example engine/helloworld.cpp
+
+`proton::connection_engine` example to send a "Hello World" message to
+itself. Compare with the corresponding `proton::container` example \ref
+helloworld.cpp.
+
+*/
+
+/** \example engine/simple_send.cpp
+
+`proton::connection_engine` example of sending a fixed number of messages and
+tracking their (asynchronous) acknowledgement. Messages are sent through the
+'examples' node on an intermediary accessible on 127.0.0.1:5672.
+
+*/
+
+/** \example engine/simple_recv.cpp
+
+`proton::connection_engine` example that subscribes to the 'examples' node and prints
+ the body of received messages.
+
+*/
+
+/** \example engine/direct_send.cpp
+
+`proton::connection_engine` example accepts an incoming connection and then
+sends like `simple_send`. You can connect directly to `direct_send` *without* a
+broker using \ref simple_recv.cpp. Make sure to stop the broker first or use a
+different port for `direct_send`.
+
+*/
+
+/** \example engine/direct_recv.cpp
+
+`proton::connection_engine` example accepts an incoming connection and then
+receives like `simple_recv`. You can connect directly to `direct_recv`
+*without* a broker using \ref simple_send.cpp. Make sure to stop the broker
+first or use a different port for `direct_recv`.
+
+*/
+
+/** \example engine/client.cpp
+
+`proton::connection_engine` client for request-response example. Sends requests and
+prints out responses. Requires an intermediary that supports the AMQP 1.0
+dynamic nodes on which the responses are received. The requests are sent through
+the 'examples' node.
+
+*/
+
+/** \example engine/server.cpp
+
+`proton::connection_engine` server for request-response example, that receives
+requests via the examples node, converts the body to uppercase and sends the
+result back to the indicated reply address.
+
+*/
+
+/** \example engine/broker.cpp
+
+A simple, single-threaded broker using the `proton::container`. You can use this
+to run other examples that reqiure an intermediary, or you can use any AMQP 1.0
+broker. This broker creates queues automatically when a client tries to send or
+subscribe.
+
+Uses the broker logic from \ref broker.hpp, the same logic as the
+proton::container` broker example \ref broker.cpp.
+
+*/
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/examples/cpp/README.hpp
----------------------------------------------------------------------
diff --git a/examples/cpp/README.hpp b/examples/cpp/README.hpp
deleted file mode 100644
index 1e78774..0000000
--- a/examples/cpp/README.hpp
+++ /dev/null
@@ -1,198 +0,0 @@
-// Examples overview.
-//
-// For a better overview, see the tutorial in the generated documentation.
-//
-// In your build directory do:
-//
-// make docs-cpp
-//
-// then open proton-c/bindings/cpp/docs/html/tutorial.html in your browser.
-
-// DEVELOPER NOTE: if you are adding or modifying examples you should keep this
-// file and ../proton-c/bindings/cpp/docs/tutorial.hpp up to date.
-
-/** @example helloworld.cpp
-
-Connects to a broker on 127.0.0.1:5672, establishes a subscription
-from the 'examples' node, and creates a sending link to the same
-node. Sends one message and receives it back.
-
-*/
-
-/** @example helloworld_direct.cpp
-
-Variation of helloworld that does not use a broker, but listens for
-incoming connections itself. It establishes a connection to itself
-with a link over which a single message is sent. This demonstrates the
-ease with which a simple daemon an be built using the API.
-
-*/
-
-/** @example simple_send.cpp
-
-An example of sending a fixed number of messages and tracking their
-(asynchronous) acknowledgement. Messages are sent through the 'examples' node on
-an intermediary accessible on 127.0.0.1:5672.
-
-*/
-
-/** @example simple_recv.cpp
-
-Subscribes to the 'examples' node on an intermediary accessible
-on 127.0.0.1:5672. Simply prints out the body of received messages.
-
-*/
-
-/** @example direct_send.cpp
-
-Accepts an incoming connection and then sends like `simple_send`. You can
-connect directly to `direct_send` *without* a broker using \ref simple_recv.cpp.
-Make sure to stop the broker first or use a different port for `direct_send`.
-
-*/
-
-/** @example direct_recv.cpp
-
-Accepts an incoming connection and then receives like `simple_recv`. You can
-connect directly to `direct_recv` *without* a broker using \ref simple_send.cpp.
-Make sure to stop the broker first or use a different port for `direct_recv`.
-
-*/
-
-/// @cond INTERNAL
-/** @example encode_decode.cpp
-
-Shows how C++ data types can be converted to and from AMQP types.
-
-*/
-/// @endcond
-
-/** @example client.cpp
-
-The client part of a request-response example. Sends requests and
-prints out responses. Requires an intermediary that supports the AMQP
-1.0 dynamic nodes on which the responses are received. The requests
-are sent through the 'examples' node.
-
-*/
-
-/** @example server.cpp
-
-The server part of a request-response example, that receives requests
-via the examples node, converts the body to uppercase and sends the
-result back to the indicated reply address.
-
-*/
-
-/** @example server_direct.cpp
-
-A variant of the server part of a request-response example that
-accepts incoming connections and does not need an intermediary. Much
-like the original server, it receives incoming requests, converts the
-body to uppercase and sends the result back to the indicated reply
-address. Can be used in conjunction with any of the client
-alternatives.
-
-*/
-
-/** @example recurring_timer.cpp
-
-Shows how to implement recurring time-based events using the scheduler.
-
-*/
-
-/** @example broker.hpp
-
-Common logic for a simple "mini broker" that creates creates queues
-automatically when a client tries to send or subscribe. This file contains
-the `queue` class that queues messages and the `broker_handler` class
-that manages queues and links and transfers messages to/from clients.
-
-Examples \ref broker.cpp and \ref engine/broker.cpp use this same
-broker logic but show different ways to run it in a server application.
-
-*/
-
-/** @example broker.cpp
-
-A simple, single-threaded broker using the `proton::container`. You can use this
-to run other examples that reqiure an intermediary, or you can use any AMQP 1.0
-broker. This broker creates queues automatically when a client tries to send or
-subscribe.
-
-Uses the broker logic from \ref broker.hpp, the same logic as the
-`proton::connection_engine` broker example \ref engine/broker.cpp.
-
-*/
-
-//////////////// connection_engine examples.
-
-/** \example engine/helloworld.cpp
-
-`proton::connection_engine` example to send a "Hello World" message to
-itself. Compare with the corresponding `proton::container` example \ref
-helloworld.cpp.
-
-*/
-
-/** \example engine/simple_send.cpp
-
-`proton::connection_engine` example of sending a fixed number of messages and
-tracking their (asynchronous) acknowledgement. Messages are sent through the
-'examples' node on an intermediary accessible on 127.0.0.1:5672.
-
-*/
-
-/** \example engine/simple_recv.cpp
-
-`proton::connection_engine` example that subscribes to the 'examples' node and prints
- the body of received messages.
-
-*/
-
-/** \example engine/direct_send.cpp
-
-`proton::connection_engine` example accepts an incoming connection and then
-sends like `simple_send`. You can connect directly to `direct_send` *without* a
-broker using \ref simple_recv.cpp. Make sure to stop the broker first or use a
-different port for `direct_send`.
-
-*/
-
-/** \example engine/direct_recv.cpp
-
-`proton::connection_engine` example accepts an incoming connection and then
-receives like `simple_recv`. You can connect directly to `direct_recv`
-*without* a broker using \ref simple_send.cpp. Make sure to stop the broker
-first or use a different port for `direct_recv`.
-
-*/
-
-/** \example engine/client.cpp
-
-`proton::connection_engine` client for request-response example. Sends requests and
-prints out responses. Requires an intermediary that supports the AMQP 1.0
-dynamic nodes on which the responses are received. The requests are sent through
-the 'examples' node.
-
-*/
-
-/** \example engine/server.cpp
-
-`proton::connection_engine` server for request-response example, that receives
-requests via the examples node, converts the body to uppercase and sends the
-result back to the indicated reply address.
-
-*/
-
-/** \example engine/broker.cpp
-
-A simple, single-threaded broker using the `proton::container`. You can use this
-to run other examples that reqiure an intermediary, or you can use any AMQP 1.0
-broker. This broker creates queues automatically when a client tries to send or
-subscribe.
-
-Uses the broker logic from \ref broker.hpp, the same logic as the
-proton::container` broker example \ref broker.cpp.
-
-*/
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/examples/cpp/direct_recv.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/direct_recv.cpp b/examples/cpp/direct_recv.cpp
index ffb2f03..89bb966 100644
--- a/examples/cpp/direct_recv.cpp
+++ b/examples/cpp/direct_recv.cpp
@@ -49,16 +49,16 @@ class direct_recv : public proton::handler {
void on_message(proton::event &e) {
proton::message& msg = e.message();
-
- if (msg.id().get<uint64_t>() < received) {
+
+ if (proton::coerce<uint64_t>(msg.id()) < received) {
return; // Ignore duplicate
}
-
+
if (expected == 0 || received < expected) {
std::cout << msg.body() << std::endl;
received++;
}
-
+
if (received == expected) {
e.receiver().close();
e.connection().close();
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/examples/cpp/encode_decode.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/encode_decode.cpp b/examples/cpp/encode_decode.cpp
index 12fc1ed..b1c39b8 100644
--- a/examples/cpp/encode_decode.cpp
+++ b/examples/cpp/encode_decode.cpp
@@ -71,13 +71,13 @@ void uniform_containers() {
v = a;
print(v);
std::list<int> a1;
- v.get(a1); // Decode as a C++ std::list instead
+ proton::get(v, a1);
std::cout << a1 << std::endl;
// You can specify that a container should be encoded as an AMQP list instead.
v = proton::codec::encoder::list(a1);
print(v);
- std::cout << v.get<std::vector<int> >() << std::endl;
+ std::cout << proton::get<std::vector<int> >(v) << std::endl;
// C++ map types (types with key_type, mapped_type) convert to an AMQP map by default.
std::map<std::string, int> m;
@@ -85,7 +85,7 @@ void uniform_containers() {
m["two"] = 2;
v = m;
print(v);
- std::cout << v.get<std::map<std::string, int> >() << std::endl;
+ std::cout << proton::get<std::map<std::string, int> >(v) << std::endl;
// A sequence of pairs encodes as an AMQP MAP, which lets you control the encoded order.
std::vector<std::pair<std::string, int> > pairs;
@@ -121,16 +121,15 @@ void mixed_containers() {
// By default, a sequence of proton::value is treated as an AMQP list.
v = l;
print(v);
- std::vector<proton::value> l2;
- v.get(l2);
+ std::vector<proton::value> l2 = proton::get<std::vector<proton::value> >(v);
std::cout << l2 << std::endl;
std::map<proton::value, proton::value> m;
m[proton::value("five")] = proton::value(5);
m[proton::value(4)] = proton::value("four"); v = m;
print(v);
- std::map<proton::value, proton::value> m2;
- v.get(m2);
+ typedef std::map<proton::value, proton::value> value_map;
+ value_map m2(proton::get<value_map>(v));
std::cout << m2 << std::endl;
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/examples/cpp/engine/server.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/engine/server.cpp b/examples/cpp/engine/server.cpp
index 4641c4c..92ee044 100644
--- a/examples/cpp/engine/server.cpp
+++ b/examples/cpp/engine/server.cpp
@@ -61,7 +61,7 @@ class server : public proton::handler {
std::string reply_to = e.message().reply_to();
proton::message reply;
reply.address(reply_to);
- reply.body(to_upper(e.message().body().get<std::string>()));
+ reply.body(to_upper(proton::get<std::string>(e.message().body())));
reply.correlation_id(e.message().correlation_id());
if (!senders[reply_to])
senders[reply_to] = e.connection().open_sender(reply_to);
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/examples/cpp/server.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/server.cpp b/examples/cpp/server.cpp
index 8ac34cc..58fe52d 100644
--- a/examples/cpp/server.cpp
+++ b/examples/cpp/server.cpp
@@ -65,7 +65,7 @@ class server : public proton::handler {
proton::message reply;
reply.address(reply_to);
- reply.body(to_upper(e.message().body().get<std::string>()));
+ reply.body(to_upper(proton::get<std::string>(e.message().body())));
reply.correlation_id(e.message().correlation_id());
if (!senders[reply_to]) {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/examples/cpp/server_direct.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/server_direct.cpp b/examples/cpp/server_direct.cpp
index 9d3b79c..c166917 100644
--- a/examples/cpp/server_direct.cpp
+++ b/examples/cpp/server_direct.cpp
@@ -66,7 +66,7 @@ class server : public proton::handler {
void on_link_open(proton::event& e) {
proton::link link = e.link();
-
+
if (!!link.sender() && link.remote_source().dynamic()) {
link.local_source().address(generate_address());
senders[link.local_source().address()] = link.sender();
@@ -75,18 +75,18 @@ class server : public proton::handler {
void on_message(proton::event &e) {
std::cout << "Received " << e.message().body() << std::endl;
-
+
std::string reply_to = e.message().reply_to();
sender_map::iterator it = senders.find(reply_to);
-
+
if (it == senders.end()) {
std::cout << "No link for reply_to: " << reply_to << std::endl;
} else {
proton::sender sender = it->second;
proton::message reply;
-
+
reply.address(reply_to);
- reply.body(to_upper(e.message().body().get<std::string>()));
+ reply.body(to_upper(proton::get<std::string>(e.message().body())));
reply.correlation_id(e.message().correlation_id());
sender.send(reply);
@@ -102,7 +102,7 @@ int main(int argc, char **argv) {
try {
opts.parse();
-
+
server srv(address);
proton::container(srv).run();
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt
index 11b299d..ebd38c1 100644
--- a/proton-c/bindings/cpp/CMakeLists.txt
+++ b/proton-c/bindings/cpp/CMakeLists.txt
@@ -27,7 +27,7 @@ include_directories(
set(qpid-proton-cpp-source
src/acceptor.cpp
src/binary.cpp
- src/scalar.cpp
+ src/scalar_base.cpp
src/condition.cpp
src/connection.cpp
src/connection_options.cpp
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/docs/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/docs/CMakeLists.txt b/proton-c/bindings/cpp/docs/CMakeLists.txt
index cf7876e..c5ae4e5 100644
--- a/proton-c/bindings/cpp/docs/CMakeLists.txt
+++ b/proton-c/bindings/cpp/docs/CMakeLists.txt
@@ -18,6 +18,7 @@
#
find_package(Doxygen)
+
if (DOXYGEN_FOUND)
configure_file (
${CMAKE_CURRENT_SOURCE_DIR}/user.doxygen.in
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/docs/tutorial.dox
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/docs/tutorial.dox b/proton-c/bindings/cpp/docs/tutorial.dox
new file mode 100644
index 0000000..dcfbe05
--- /dev/null
+++ b/proton-c/bindings/cpp/docs/tutorial.dox
@@ -0,0 +1,428 @@
+// -*-markdown-*-
+// NOTE: doxygen can include markdown pages directly but there seems to be a bug
+// that shows messed-up line numbers in \skip \until code extracts so this file
+// is markdown wrapped in a C++ comment - which works.
+
+/**\page tutorial Tutorial
+
+This is a brief tutorial that will walk you through the fundamentals of building
+messaging applications in incremental steps. There are further examples, in
+addition the ones mentioned in the tutorial.
+
+Some of the examples require an AMQP *broker* that can receive, store and send
+messages. \ref broker.hpp and \ref broker.cpp define a simple example
+broker. Run without arguments it listens on `0.0.0.0:5672`, the standard AMQP
+port on all network interfaces. To use a different port or network interface:
+
+ broker -a <host>:<port>
+
+Instead of the example broker, you can use any AMQP 1.0 compliant broker. You
+must configure your broker to have a queue (or topic) named "examples".
+
+The `helloworld` examples take an optional URL argument. The other examples take
+an option `-a URL`. A URL looks like:
+
+ HOST:PORT/ADDRESS
+
+It usually defaults to `127.0.0.1:5672/examples`, but you can change this if
+your broker is on a different host or port, or you want to use a different queue
+or topic name (the ADDRESS part of the URL). URL details are at `proton::url`
+
+The first part of the tutorial uses the `proton::container`, later we will
+show some of the same examples implemented using the `proton::connection_engine`.
+Most of the code is the same for either approach.
+
+Hello World!
+------------
+
+\dontinclude helloworld.cpp
+
+Tradition dictates that we start with hello world! This example sends a message
+to a broker and the receives the same message back to demonstrate sending and
+receiving. In a realistic system the sender and receiver would normally be in
+different processes. The complete example is \ref helloworld.cpp
+
+We will include the following classes: `proton::container` runs an event loop
+which dispatches events to a `proton::handler`. This allows a *reactive*
+style of programming which is well suited to messaging applications. `proton::url` is a simple parser for the URL format mentioned above.
+
+\skip proton/container
+\until proton/url
+
+We will define a class `hello_world` which is a subclass of
+`proton::handler` and over-rides functions to handle the events
+of interest in sending and receiving a message.
+
+\skip class hello_world
+\until {}
+
+`on_start()` is called when the event loop first starts. We handle that by
+establishing a connection and creating a sender and a receiver.
+
+\skip on_start
+\until }
+
+`on_sendable()` is called when message can be transferred over the associated
+sender link to the remote peer. We create a `proton::message`, set the message
+body to `"Hello World!"` and send the message. Then we close the sender as we only
+want to send one message. Closing the sender will prevent further calls to
+`on_sendable()`.
+
+\skip on_sendable
+\until }
+
+`on_message()` is called when a message is received. We just print the body of
+the message and close the connection, as we only want one message
+
+\skip on_message
+\until }
+
+The message body is a `proton::value`, see the documentation for more on how to
+extract the message body as type-safe C++ values.
+
+Our `main` function creates an instance of the `hello_world` handler and a
+proton::container using that handler. Calling `proton::container::run` sets
+things in motion and returns when we close the connection as there is nothing
+further to do. It may throw an exception, which will be a subclass of
+`proton::error`. That in turn is a subclass of `std::exception`.
+
+\skip main
+\until }
+\until }
+\until }
+
+Hello World, Direct!
+--------------------
+
+\dontinclude helloworld_direct.cpp
+
+Though often used in conjunction with a broker, AMQP does not *require* this. It
+also allows senders and receivers to communicate directly if desired.
+
+We will modify our example to send a message directly to itself. This is a bit
+contrived but illustrates both sides of the direct send/receive scenario. Full
+code at \ref helloworld_direct.cpp
+
+The first difference, is that rather than creating a receiver on the same
+connection as our sender, we listen for incoming connections by invoking the
+`proton::container::listen()` method on the container.
+
+\skip on_start
+\until }
+
+As we only need then to initiate one link, the sender, we can do that by
+passing in a url rather than an existing connection, and the connection
+will also be automatically established for us.
+
+We send the message in response to the `on_sendable()` callback and
+print the message out in response to the `on_message()` callback exactly
+as before.
+
+\skip on_sendable
+\until }
+\until }
+
+However we also handle two new events. We now close the connection from
+the senders side once the message has been accepted.
+The acceptance of the message is an indication of successful transfer to the
+peer. We are notified of that event through the `on_delivery_accept()`
+callback.
+
+\skip on_delivery_accept
+\until }
+
+Then, once the connection has been closed, of which we are
+notified through the `on_connection_close()` callback, we stop accepting incoming
+connections at which point there is no work to be done and the
+event loop exits, and the run() method will return.
+
+\skip on_connection_close
+\until }
+
+So now we have our example working without a broker involved!
+
+Note that for this example we pick an "unusual" port 8888 since we are talking
+to ourselves rather than a broker.
+
+\skipline url =
+
+Asynchronous Send and Receive
+-----------------------------
+
+Of course, these `HelloWorld!` examples are very artificial, communicating as
+they do over a network connection but with the same process. A more realistic
+example involves communication between separate processes (which could indeed be
+running on completely separate machines).
+
+Let's separate the sender from the receiver, and transfer more than a single
+message between them.
+
+We'll start with a simple sender \ref simple_send.cpp.
+
+\dontinclude simple_send.cpp
+
+As with the previous example, we define the application logic in a class that
+handles events. Because we are transferring more than one message, we need to
+keep track of how many we have sent. We'll use a `sent` member variable for
+that. The `total` member variable will hold the number of messages we want to
+send.
+
+\skip class simple_send
+\until total
+
+As before, we use the `on_start()` event to establish our sender link over which
+we will transfer messages.
+
+\skip on_start
+\until }
+
+AMQP defines a credit-based flow control mechanism. Flow control allows
+the receiver to control how many messages it is prepared to receive at a
+given time and thus prevents any component being overwhelmed by the
+number of messages it is sent.
+
+In the `on_sendable()` callback, we check that our sender has credit
+before sending messages. We also check that we haven't already sent the
+required number of messages.
+
+\skip on_sendable
+\until }
+\until }
+
+The `proton::sender::send()` call above is asynchronous. When it returns the
+message has not yet actually been transferred across the network to the
+receiver. By handling the `on_accepted()` event, we can get notified when the
+receiver has received and accepted the message. In our example we use this event
+to track the confirmation of the messages we have sent. We only close the
+connection and exit when the receiver has received all the messages we wanted to
+send.
+
+\skip on_delivery_accept
+\until }
+\until }
+
+If we are disconnected after a message is sent and before it has been
+confirmed by the receiver, it is said to be `in doubt`. We don't know
+whether or not it was received. In this example, we will handle that by
+resending any in-doubt messages. This is known as an 'at-least-once'
+guarantee, since each message should eventually be received at least
+once, though a given message may be received more than once (i.e.
+duplicates are possible). In the `on_disconnected()` callback, we reset
+the sent count to reflect only those that have been confirmed. The
+library will automatically try to reconnect for us, and when our sender
+is sendable again, we can restart from the point we know the receiver
+got to.
+
+\skip on_disconnect
+\until }
+
+\dontinclude simple_recv.cpp
+
+Now let's look at the corresponding receiver \ref simple_recv.cpp
+
+This time we'll use an `expected` member variable for for the number of messages we expect and
+a `received` variable to count how many we have received so far.
+
+\skip class simple_recv
+\until received
+
+We handle `on_start()` by creating our receiver, much like we
+did for the sender.
+
+\skip on_start
+\until }
+
+We also handle the `on_message()` event for received messages and print the
+message out as in the `Hello World!` examples. However we add some logic to
+allow the receiver to wait for a given number of messages, then to close the
+connection and exit. We also add some logic to check for and ignore duplicates,
+using a simple sequential id scheme.
+
+\skip on_message
+\until }
+
+Direct Send and Receive
+-----------------------
+
+Sending between these two examples requires an intermediary broker since neither
+accepts incoming connections. AMQP allows us to send messages directly between
+two processes. In that case one or other of the processes needs to accept
+incoming connections. Let's create a modified version of the receiving example
+that does this with \ref direct_recv.cpp
+
+\dontinclude direct_recv.cpp
+
+There are only two differences here. Instead of initiating a link (and
+implicitly a connection), we listen for incoming connections.
+
+
+\skip on_start
+\until }
+
+When we have received all the expected messages, we then stop listening for
+incoming connections by closing the acceptor object.
+
+\skip on_message
+\until }
+\until }
+\until }
+\until }
+
+You can use the \ref simple_send.cpp example to send to this receiver
+directly. (Note: you will need to stop any broker that is listening on the 5672
+port, or else change the port used by specifying a different address to each
+example via the -a command line switch).
+
+We can also modify the sender to allow the original receiver to connect to it,
+in \ref direct_send.cpp. Again that just requires two modifications:
+
+\dontinclude direct_send.cpp
+
+As with the modified receiver, instead of initiating establishment of a
+link, we listen for incoming connections.
+
+\skip on_start
+\until }
+
+When we have received confirmation of all the messages we sent, we can
+close the acceptor in order to exit.
+
+\skip on_delivery_accept
+\until }
+\until }
+
+To try this modified sender, run the original \ref simple_recv.cpp against it.
+
+The symmetry in the underlying AMQP that enables this is quite unique and
+elegant, and in reflecting this the proton API provides a flexible toolkit for
+implementing all sorts of interesting intermediaries (\ref broker.hpp and \ref
+broker.cpp provide a simple broker for testing purposes is an example of this).
+
+Request/Response
+----------------
+
+A common pattern is to send a request message and expect a response message in
+return. AMQP has special support for this pattern. Let's have a look at a simple
+example. We'll start with \ref server.cpp, the program that will process the
+request and send the response. Note that we are still using a broker in this
+example.
+
+Our server will provide a very simple service: it will respond with the
+body of the request converted to uppercase.
+
+\dontinclude server.cpp
+\skip class server
+\until };
+
+The code here is not too different from the simple receiver example. When we
+receive a request in `on_message` however, we look at the
+`proton::message::reply_to` address and create a sender with that address for
+the response. We'll cache the senders incase we get further requests with the
+same `reply_to`.
+
+Now let's create a simple \ref client.cpp to test this service out.
+
+\dontinclude client.cpp
+
+Our client takes a list of strings to send as requests
+
+\skipline client(
+
+Since we will be sending and receiving, we create a sender and a receiver in
+`on_start`. Our receiver has a blank address and sets the `dynamic` flag to
+true, which means we expect the remote end (broker or server) to assign a unique
+address for us.
+
+\skip on_start
+\until }
+
+Now a function to send the next request from our list of requests. We set the
+reply_to address to be the dynamically assigned address of our receiver.
+
+\skip send_request
+\until }
+
+We need to use the address assigned by the broker as the `reply_to` address of
+our requests, so we can't send them until our receiver has been set up. To do
+that, we add an `on_link_open()` method to our handler class, and if the link
+associated with event is the receiver, we use that as the trigger to send our
+first request.
+
+\skip on_link_open
+\until }
+
+When we receive a reply, we send the next request.
+
+\skip on_message
+\until }
+\until }
+\until }
+
+Direct Request/Response
+-----------------------
+
+We can avoid the intermediary process by writing a server that accepts
+connections directly, \ref server_direct.cpp. It involves the following changes
+to our original server:
+
+\dontinclude server_direct.cpp
+
+Our server must generate a unique reply-to addresses for links from the
+client that request a dynamic address (previously this was done by the broker.)
+We use a simple counter.
+
+\skip generate_address
+\until }
+
+Next we need to handle incoming requests for links with dynamic addresses from
+the client. We give the link a unique address and record it in our `senders`
+map.
+
+\skip on_link_open
+\until }
+
+Note we are interested in *sender* links above because we are implementing the
+server. A *receiver* link created on the client corresponds to a *sender* link
+on the server.
+
+Finally when we receive a message we look up its `reply_to` in our senders map and send the reply.
+
+\skip on_message
+\until }
+\until }
+\until }
+
+Connection Engine
+-----------------
+
+The `proton::connection_engine` is an alternative to the container. For simple
+applications with a single connection, its use is about the same as the the
+`proton::container`, but it allows more flexibility for multi-threaded
+applications or applications with unusual IO requirements.
+
+\dontinclude engine/helloworld.cpp
+
+We'll look at the \ref engine/helloworld.cpp example step-by-step to see how it differs
+from the container \ref helloworld.cpp version.
+
+First we include the `proton::io::socket_engine` class, which is a `proton::connection_engine`
+that uses socket IO.
+
+\skipline proton/io.hpp
+
+Our `hello_world` class differs only in the `on_start()` method. Instead of
+calling `container.connect()`, we simply call `proton::connection::open` to open the
+engine's' connection:
+
+\skip on_start
+\until }
+
+Our `main` function only differs in that it creates and runs a `socket_engine`
+instead of a `container`.
+
+\skip main
+\until }
+\until }
+\until }
+
+*/
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/docs/tutorial.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/docs/tutorial.hpp b/proton-c/bindings/cpp/docs/tutorial.hpp
deleted file mode 100644
index dcfbe05..0000000
--- a/proton-c/bindings/cpp/docs/tutorial.hpp
+++ /dev/null
@@ -1,428 +0,0 @@
-// -*-markdown-*-
-// NOTE: doxygen can include markdown pages directly but there seems to be a bug
-// that shows messed-up line numbers in \skip \until code extracts so this file
-// is markdown wrapped in a C++ comment - which works.
-
-/**\page tutorial Tutorial
-
-This is a brief tutorial that will walk you through the fundamentals of building
-messaging applications in incremental steps. There are further examples, in
-addition the ones mentioned in the tutorial.
-
-Some of the examples require an AMQP *broker* that can receive, store and send
-messages. \ref broker.hpp and \ref broker.cpp define a simple example
-broker. Run without arguments it listens on `0.0.0.0:5672`, the standard AMQP
-port on all network interfaces. To use a different port or network interface:
-
- broker -a <host>:<port>
-
-Instead of the example broker, you can use any AMQP 1.0 compliant broker. You
-must configure your broker to have a queue (or topic) named "examples".
-
-The `helloworld` examples take an optional URL argument. The other examples take
-an option `-a URL`. A URL looks like:
-
- HOST:PORT/ADDRESS
-
-It usually defaults to `127.0.0.1:5672/examples`, but you can change this if
-your broker is on a different host or port, or you want to use a different queue
-or topic name (the ADDRESS part of the URL). URL details are at `proton::url`
-
-The first part of the tutorial uses the `proton::container`, later we will
-show some of the same examples implemented using the `proton::connection_engine`.
-Most of the code is the same for either approach.
-
-Hello World!
-------------
-
-\dontinclude helloworld.cpp
-
-Tradition dictates that we start with hello world! This example sends a message
-to a broker and the receives the same message back to demonstrate sending and
-receiving. In a realistic system the sender and receiver would normally be in
-different processes. The complete example is \ref helloworld.cpp
-
-We will include the following classes: `proton::container` runs an event loop
-which dispatches events to a `proton::handler`. This allows a *reactive*
-style of programming which is well suited to messaging applications. `proton::url` is a simple parser for the URL format mentioned above.
-
-\skip proton/container
-\until proton/url
-
-We will define a class `hello_world` which is a subclass of
-`proton::handler` and over-rides functions to handle the events
-of interest in sending and receiving a message.
-
-\skip class hello_world
-\until {}
-
-`on_start()` is called when the event loop first starts. We handle that by
-establishing a connection and creating a sender and a receiver.
-
-\skip on_start
-\until }
-
-`on_sendable()` is called when message can be transferred over the associated
-sender link to the remote peer. We create a `proton::message`, set the message
-body to `"Hello World!"` and send the message. Then we close the sender as we only
-want to send one message. Closing the sender will prevent further calls to
-`on_sendable()`.
-
-\skip on_sendable
-\until }
-
-`on_message()` is called when a message is received. We just print the body of
-the message and close the connection, as we only want one message
-
-\skip on_message
-\until }
-
-The message body is a `proton::value`, see the documentation for more on how to
-extract the message body as type-safe C++ values.
-
-Our `main` function creates an instance of the `hello_world` handler and a
-proton::container using that handler. Calling `proton::container::run` sets
-things in motion and returns when we close the connection as there is nothing
-further to do. It may throw an exception, which will be a subclass of
-`proton::error`. That in turn is a subclass of `std::exception`.
-
-\skip main
-\until }
-\until }
-\until }
-
-Hello World, Direct!
---------------------
-
-\dontinclude helloworld_direct.cpp
-
-Though often used in conjunction with a broker, AMQP does not *require* this. It
-also allows senders and receivers to communicate directly if desired.
-
-We will modify our example to send a message directly to itself. This is a bit
-contrived but illustrates both sides of the direct send/receive scenario. Full
-code at \ref helloworld_direct.cpp
-
-The first difference, is that rather than creating a receiver on the same
-connection as our sender, we listen for incoming connections by invoking the
-`proton::container::listen()` method on the container.
-
-\skip on_start
-\until }
-
-As we only need then to initiate one link, the sender, we can do that by
-passing in a url rather than an existing connection, and the connection
-will also be automatically established for us.
-
-We send the message in response to the `on_sendable()` callback and
-print the message out in response to the `on_message()` callback exactly
-as before.
-
-\skip on_sendable
-\until }
-\until }
-
-However we also handle two new events. We now close the connection from
-the senders side once the message has been accepted.
-The acceptance of the message is an indication of successful transfer to the
-peer. We are notified of that event through the `on_delivery_accept()`
-callback.
-
-\skip on_delivery_accept
-\until }
-
-Then, once the connection has been closed, of which we are
-notified through the `on_connection_close()` callback, we stop accepting incoming
-connections at which point there is no work to be done and the
-event loop exits, and the run() method will return.
-
-\skip on_connection_close
-\until }
-
-So now we have our example working without a broker involved!
-
-Note that for this example we pick an "unusual" port 8888 since we are talking
-to ourselves rather than a broker.
-
-\skipline url =
-
-Asynchronous Send and Receive
------------------------------
-
-Of course, these `HelloWorld!` examples are very artificial, communicating as
-they do over a network connection but with the same process. A more realistic
-example involves communication between separate processes (which could indeed be
-running on completely separate machines).
-
-Let's separate the sender from the receiver, and transfer more than a single
-message between them.
-
-We'll start with a simple sender \ref simple_send.cpp.
-
-\dontinclude simple_send.cpp
-
-As with the previous example, we define the application logic in a class that
-handles events. Because we are transferring more than one message, we need to
-keep track of how many we have sent. We'll use a `sent` member variable for
-that. The `total` member variable will hold the number of messages we want to
-send.
-
-\skip class simple_send
-\until total
-
-As before, we use the `on_start()` event to establish our sender link over which
-we will transfer messages.
-
-\skip on_start
-\until }
-
-AMQP defines a credit-based flow control mechanism. Flow control allows
-the receiver to control how many messages it is prepared to receive at a
-given time and thus prevents any component being overwhelmed by the
-number of messages it is sent.
-
-In the `on_sendable()` callback, we check that our sender has credit
-before sending messages. We also check that we haven't already sent the
-required number of messages.
-
-\skip on_sendable
-\until }
-\until }
-
-The `proton::sender::send()` call above is asynchronous. When it returns the
-message has not yet actually been transferred across the network to the
-receiver. By handling the `on_accepted()` event, we can get notified when the
-receiver has received and accepted the message. In our example we use this event
-to track the confirmation of the messages we have sent. We only close the
-connection and exit when the receiver has received all the messages we wanted to
-send.
-
-\skip on_delivery_accept
-\until }
-\until }
-
-If we are disconnected after a message is sent and before it has been
-confirmed by the receiver, it is said to be `in doubt`. We don't know
-whether or not it was received. In this example, we will handle that by
-resending any in-doubt messages. This is known as an 'at-least-once'
-guarantee, since each message should eventually be received at least
-once, though a given message may be received more than once (i.e.
-duplicates are possible). In the `on_disconnected()` callback, we reset
-the sent count to reflect only those that have been confirmed. The
-library will automatically try to reconnect for us, and when our sender
-is sendable again, we can restart from the point we know the receiver
-got to.
-
-\skip on_disconnect
-\until }
-
-\dontinclude simple_recv.cpp
-
-Now let's look at the corresponding receiver \ref simple_recv.cpp
-
-This time we'll use an `expected` member variable for for the number of messages we expect and
-a `received` variable to count how many we have received so far.
-
-\skip class simple_recv
-\until received
-
-We handle `on_start()` by creating our receiver, much like we
-did for the sender.
-
-\skip on_start
-\until }
-
-We also handle the `on_message()` event for received messages and print the
-message out as in the `Hello World!` examples. However we add some logic to
-allow the receiver to wait for a given number of messages, then to close the
-connection and exit. We also add some logic to check for and ignore duplicates,
-using a simple sequential id scheme.
-
-\skip on_message
-\until }
-
-Direct Send and Receive
------------------------
-
-Sending between these two examples requires an intermediary broker since neither
-accepts incoming connections. AMQP allows us to send messages directly between
-two processes. In that case one or other of the processes needs to accept
-incoming connections. Let's create a modified version of the receiving example
-that does this with \ref direct_recv.cpp
-
-\dontinclude direct_recv.cpp
-
-There are only two differences here. Instead of initiating a link (and
-implicitly a connection), we listen for incoming connections.
-
-
-\skip on_start
-\until }
-
-When we have received all the expected messages, we then stop listening for
-incoming connections by closing the acceptor object.
-
-\skip on_message
-\until }
-\until }
-\until }
-\until }
-
-You can use the \ref simple_send.cpp example to send to this receiver
-directly. (Note: you will need to stop any broker that is listening on the 5672
-port, or else change the port used by specifying a different address to each
-example via the -a command line switch).
-
-We can also modify the sender to allow the original receiver to connect to it,
-in \ref direct_send.cpp. Again that just requires two modifications:
-
-\dontinclude direct_send.cpp
-
-As with the modified receiver, instead of initiating establishment of a
-link, we listen for incoming connections.
-
-\skip on_start
-\until }
-
-When we have received confirmation of all the messages we sent, we can
-close the acceptor in order to exit.
-
-\skip on_delivery_accept
-\until }
-\until }
-
-To try this modified sender, run the original \ref simple_recv.cpp against it.
-
-The symmetry in the underlying AMQP that enables this is quite unique and
-elegant, and in reflecting this the proton API provides a flexible toolkit for
-implementing all sorts of interesting intermediaries (\ref broker.hpp and \ref
-broker.cpp provide a simple broker for testing purposes is an example of this).
-
-Request/Response
-----------------
-
-A common pattern is to send a request message and expect a response message in
-return. AMQP has special support for this pattern. Let's have a look at a simple
-example. We'll start with \ref server.cpp, the program that will process the
-request and send the response. Note that we are still using a broker in this
-example.
-
-Our server will provide a very simple service: it will respond with the
-body of the request converted to uppercase.
-
-\dontinclude server.cpp
-\skip class server
-\until };
-
-The code here is not too different from the simple receiver example. When we
-receive a request in `on_message` however, we look at the
-`proton::message::reply_to` address and create a sender with that address for
-the response. We'll cache the senders incase we get further requests with the
-same `reply_to`.
-
-Now let's create a simple \ref client.cpp to test this service out.
-
-\dontinclude client.cpp
-
-Our client takes a list of strings to send as requests
-
-\skipline client(
-
-Since we will be sending and receiving, we create a sender and a receiver in
-`on_start`. Our receiver has a blank address and sets the `dynamic` flag to
-true, which means we expect the remote end (broker or server) to assign a unique
-address for us.
-
-\skip on_start
-\until }
-
-Now a function to send the next request from our list of requests. We set the
-reply_to address to be the dynamically assigned address of our receiver.
-
-\skip send_request
-\until }
-
-We need to use the address assigned by the broker as the `reply_to` address of
-our requests, so we can't send them until our receiver has been set up. To do
-that, we add an `on_link_open()` method to our handler class, and if the link
-associated with event is the receiver, we use that as the trigger to send our
-first request.
-
-\skip on_link_open
-\until }
-
-When we receive a reply, we send the next request.
-
-\skip on_message
-\until }
-\until }
-\until }
-
-Direct Request/Response
------------------------
-
-We can avoid the intermediary process by writing a server that accepts
-connections directly, \ref server_direct.cpp. It involves the following changes
-to our original server:
-
-\dontinclude server_direct.cpp
-
-Our server must generate a unique reply-to addresses for links from the
-client that request a dynamic address (previously this was done by the broker.)
-We use a simple counter.
-
-\skip generate_address
-\until }
-
-Next we need to handle incoming requests for links with dynamic addresses from
-the client. We give the link a unique address and record it in our `senders`
-map.
-
-\skip on_link_open
-\until }
-
-Note we are interested in *sender* links above because we are implementing the
-server. A *receiver* link created on the client corresponds to a *sender* link
-on the server.
-
-Finally when we receive a message we look up its `reply_to` in our senders map and send the reply.
-
-\skip on_message
-\until }
-\until }
-\until }
-
-Connection Engine
------------------
-
-The `proton::connection_engine` is an alternative to the container. For simple
-applications with a single connection, its use is about the same as the the
-`proton::container`, but it allows more flexibility for multi-threaded
-applications or applications with unusual IO requirements.
-
-\dontinclude engine/helloworld.cpp
-
-We'll look at the \ref engine/helloworld.cpp example step-by-step to see how it differs
-from the container \ref helloworld.cpp version.
-
-First we include the `proton::io::socket_engine` class, which is a `proton::connection_engine`
-that uses socket IO.
-
-\skipline proton/io.hpp
-
-Our `hello_world` class differs only in the `on_start()` method. Instead of
-calling `container.connect()`, we simply call `proton::connection::open` to open the
-engine's' connection:
-
-\skip on_start
-\until }
-
-Our `main` function only differs in that it creates and runs a `socket_engine`
-instead of a `container`.
-
-\skip main
-\until }
-\until }
-\until }
-
-*/
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/docs/user.doxygen.in
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/docs/user.doxygen.in b/proton-c/bindings/cpp/docs/user.doxygen.in
index e76337a..26b1784 100644
--- a/proton-c/bindings/cpp/docs/user.doxygen.in
+++ b/proton-c/bindings/cpp/docs/user.doxygen.in
@@ -25,13 +25,13 @@ OUTPUT_DIRECTORY = .
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
+ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = YES
JAVADOC_AUTOBRIEF = YES
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
BUILTIN_STL_SUPPORT = YES
INLINE_SIMPLE_STRUCTS = YES
-EXTRACT_LOCAL_CLASSES = NO
HIDE_UNDOC_CLASSES = YES
HIDE_COMPOUND_REFERENCE = YES
HIDE_SCOPE_NAMES = YES
@@ -44,6 +44,7 @@ ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
PREDEFINED = protected=private PN_CPP_EXTERN=
+EXCLUDE_SYMBOLS = internal internal::*
# Configuration options related to warning and progress messages
@@ -52,14 +53,17 @@ WARNINGS = YES
# Configuration options related to the input files
-INPUT = @CMAKE_SOURCE_DIR@/proton-c/bindings/cpp/include @CMAKE_SOURCE_DIR@/proton-c/bindings/cpp/docs @CMAKE_SOURCE_DIR@/examples/cpp/README.hpp
-FILE_PATTERNS = *.hpp *.md
+INPUT = @CMAKE_SOURCE_DIR@/proton-c/bindings/cpp/include @CMAKE_SOURCE_DIR@/proton-c/bindings/cpp/docs @CMAKE_SOURCE_DIR@/examples/cpp/README.dox
+FILE_PATTERNS = *.hpp *.md *.dox
+FULL_PATH_NAMES = YES
RECURSIVE = YES
+STRIP_FROM_PATH = @CMAKE_SOURCE_DIR@/proton-c/bindings/cpp/include
EXAMPLE_PATH = @CMAKE_SOURCE_DIR@/examples/cpp
EXAMPLE_RECURSIVE = YES
# View and list options
+GENERATE_TREEVIEW = YES
GENERATE_TODOLIST = NO
GENERATE_TESTLIST = NO
GENERATE_BUGLIST = NO
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/amqp.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/amqp.hpp b/proton-c/bindings/cpp/include/proton/amqp.hpp
index 2ca122f..990bf06 100644
--- a/proton-c/bindings/cpp/include/proton/amqp.hpp
+++ b/proton-c/bindings/cpp/include/proton/amqp.hpp
@@ -25,7 +25,8 @@
namespace proton {
-
+/// AMQP typedefs for C++ types
+///
/// This namespace contains typedefs to associate AMQP scalar type names with
/// the corresponding C++ types. These are provided as a convenience for those
/// familiar with AMQP, you do not need to use them, you can use the C++ types
@@ -38,31 +39,31 @@ namespace amqp {
///@name Typedefs for AMQP numeric types.
///@{
-///@ Boolean true or false.
+
+/// Boolean true or false.
typedef bool boolean_type;
-///@ 8-bit unsigned byte
+/// 8-bit unsigned byte
typedef uint8_t ubyte_type;
-///@ 8-bit signed byte
+/// 8-bit signed byte
typedef int8_t byte_type;
-///@ 16-bit unsigned short integer
+/// 16-bit unsigned short integer
typedef uint16_t ushort_type;
-///@ 16-bit signed short integer
+/// 16-bit signed short integer
typedef int16_t short_type;
-///@ 32-bit unsigned integer
+/// 32-bit unsigned integer
typedef uint32_t uint_type;
-///@ 32-bit signed integer
+/// 32-bit signed integer
typedef int32_t int_type;
-///@ 64-bit unsigned long integer
+/// 64-bit unsigned long integer
typedef uint64_t ulong_type;
-///@ 64-bit signed long integer
+/// 64-bit signed long integer
typedef int64_t long_type;
-///@ 32-bit unicode code point
+/// 32-bit unicode code point
typedef wchar_t char_type;
-///@ 32-bit binary floating point
+/// 32-bit binary floating point
typedef float float_type;
-///@ 64-bit binary floating point
+/// 64-bit binary floating point
typedef double double_type;
-///@}
/// An AMQP string is unicode UTF-8 encoded.
typedef std::string string_type;
@@ -79,15 +80,14 @@ typedef proton::timestamp timestamp_type;
/// A 16-byte universally unique identifier.
typedef proton::uuid uuid_type;
-///@name AMQP decimal floating point types.
-///
-/// These are not usable as arithmetic types in C++. You can pass them on over
-/// AMQP or convert the raw bytes using a decimal support library. @see proton::decimal.
-/// @{
+/// 32 bit decimal floating point
typedef proton::decimal32 decimal32_type;
+
+/// 64 bit decimal floating point
typedef proton::decimal64 decimal64_type;
+
+/// 128 bit decimal floating point
typedef proton::decimal128 decimal128_type;
-///@}
}}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 61b6434..acea44e 100644
--- a/proton-c/bindings/cpp/include/proton/annotation_key.hpp
+++ b/proton-c/bindings/cpp/include/proton/annotation_key.hpp
@@ -20,7 +20,7 @@
* under the License.
*/
-#include <proton/scalar.hpp>
+#include <proton/scalar_base.hpp>
#include <proton/symbol.hpp>
namespace proton {
@@ -28,39 +28,46 @@ namespace proton {
/// 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 {
+class annotation_key : public scalar_base {
public:
+ using scalar_base::type;
+
/// An empty annotation key has a uint64_t == 0 value.
- annotation_key() { scalar_ = uint64_t(0); }
- annotation_key(const annotation_key& x) { scalar_ = x; }
- annotation_key& operator=(const annotation_key& x) { scalar_ = x; return *this; }
+ annotation_key() { put_(uint64_t(0)); }
- annotation_key(uint64_t x) { scalar_ = x; }
- annotation_key(const symbol& x) { scalar_ = x; }
+ /// Construct from any type that can be assigned
+ template <class T> annotation_key(const T& x) { *this = x; }
+ ///@name Assign from a uint64_t or symbol.
+ ///@{
+ annotation_key& operator=(uint64_t x) { put_(x); return *this; }
+ annotation_key& operator=(const symbol& x) { put_(x); return *this; }
+ ///@}
///@name Extra conversions for strings, treated as amqp::SYMBOL.
///@{
- annotation_key(const std::string& x) { scalar_ = symbol(x); }
- annotation_key(const char *x) {scalar_ = symbol(x); }
+ annotation_key& operator=(const std::string& x) { put_(symbol(x)); return *this; }
+ annotation_key& operator=(const char *x) { put_(symbol(x)); return *this; }
///@}
- annotation_key& operator=(uint64_t x) { scalar_ = x; return *this; }
- annotation_key& operator=(const symbol& x) { scalar_ = x; return *this; }
-
- /// @name Get methods
- ///
- /// @{
- void get(uint64_t& x) const { scalar_.get(x); }
- void get(symbol& x) const { scalar_.get(x); }
- /// @}
-
- /// Return the value as type T.
- template<class T> T get() const { T x; get(x); return x; }
-
+ ///@cond INTERNAL
friend class message;
friend class codec::decoder;
+ ///@endcond
};
+///@cond internal
+template <class T> T get(const annotation_key& x);
+///@endcond
+
+/// Get the uint64_t value or throw conversion_error. @related annotation_key
+template<> inline uint64_t get<uint64_t>(const annotation_key& x) { return internal::get<uint64_t>(x); }
+/// Get the @ref symbol value or throw conversion_error. @related annotation_key
+template<> inline symbol get<symbol>(const annotation_key& x) { return internal::get<symbol>(x); }
+/// Get the @ref binary value or throw conversion_error. @related annotation_key
+
+/// @copydoc scalar::coerce
+/// @related annotation_key
+template<class T> T coerce(const annotation_key& x) { return internal::coerce<T>(x); }
}
#endif // ANNOTATION_KEY_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/binary.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/binary.hpp b/proton-c/bindings/cpp/include/proton/binary.hpp
index e907f47..a72ac75 100644
--- a/proton-c/bindings/cpp/include/proton/binary.hpp
+++ b/proton-c/bindings/cpp/include/proton/binary.hpp
@@ -28,22 +28,24 @@
namespace proton {
/// Arbitrary binary data.
-class binary : public std::vector<char> {
+class binary : public std::vector<uint8_t> {
public:
- typedef std::vector<char> byte_vector;
-
- explicit binary() : byte_vector() {}
- explicit binary(size_t n) : byte_vector(n) {}
- explicit binary(size_t n, char x) : byte_vector(n, x) {}
- template <class Iter> binary(Iter first, Iter last) : byte_vector(first, last) {}
- explicit binary(const std::string& s) : byte_vector(s.begin(), s.end()) {}
-
- std::string str() const { return std::string(begin(), end()); }
-
- binary& operator=(const binary& x) { byte_vector::operator=(x); return *this; }
+ ///@name Constructors @{
+ explicit binary() : std::vector<value_type>() {}
+ explicit binary(size_t n) : std::vector<value_type>(n) {}
+ explicit binary(size_t n, value_type x) : std::vector<value_type>(n, x) {}
+ explicit binary(const std::string& s) : std::vector<value_type>(s.begin(), s.end()) {}
+ template <class Iter> binary(Iter first, Iter last) : std::vector<value_type>(first, last) {}
+ ///@}
+
+ /// Convert to std::string
+ operator std::string() const { return std::string(begin(), end()); }
+
+ /// Assignment
binary& operator=(const std::string& x) { assign(x.begin(), x.end()); return *this; }
};
+/// Print binary value
PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const binary&);
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/byte_array.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/byte_array.hpp b/proton-c/bindings/cpp/include/proton/byte_array.hpp
index c2757fa..fe3f864 100644
--- a/proton-c/bindings/cpp/include/proton/byte_array.hpp
+++ b/proton-c/bindings/cpp/include/proton/byte_array.hpp
@@ -23,6 +23,7 @@
#include <proton/comparable.hpp>
#include <algorithm>
+#include <iterator>
namespace proton {
@@ -30,32 +31,51 @@ namespace proton {
/// as an array of bytes.
template <size_t N> class byte_array : private comparable<byte_array<N> > {
public:
- typedef char value_type;
+ ///@name Sequence container typedefs
+ ///@{
+ typedef uint8_t value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef value_type* iterator;
+ typedef const value_type* const_iterator;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ ///@}
- /// Initially all 0.
+ /// 0-initialized byte array
byte_array() { std::fill(bytes_, bytes_+N, '\0'); }
- /// Returns N
+ /// Size of the array
static size_t size() { return N; }
- uint8_t* begin() { return bytes_; }
- uint8_t* end() { return bytes_+N; }
- uint8_t& operator[](size_t i) { return bytes_[i]; }
+ ///@name Array operators
+ ///@{
+ value_type* begin() { return bytes_; }
+ value_type* end() { return bytes_+N; }
+ value_type& operator[](size_t i) { return bytes_[i]; }
- const uint8_t* begin() const { return bytes_; }
- const uint8_t* end() const { return bytes_+N; }
- const uint8_t& operator[](size_t i) const { return bytes_[i]; }
+ const value_type* begin() const { return bytes_; }
+ const value_type* end() const { return bytes_+N; }
+ const value_type& operator[](size_t i) const { return bytes_[i]; }
+ ///@}
- friend bool operator==(const byte_array& x, const byte_array& y) {
- return std::equal(x.begin(), x.end(), y.begin());
- }
+ ///@name Comparison operators
+ ///@{
+ friend bool operator==(const byte_array& x, const byte_array& y) {
+ return std::equal(x.begin(), x.end(), y.begin());
+ }
- friend bool operator<(const byte_array& x, const byte_array& y) {
- return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
- }
+ friend bool operator<(const byte_array& x, const byte_array& y) {
+ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+ }
+ ///@}
private:
- uint8_t bytes_[N];
+ value_type bytes_[N];
};
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/comparable.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/comparable.hpp b/proton-c/bindings/cpp/include/proton/comparable.hpp
index 8bf0e47..cca0e62 100644
--- a/proton-c/bindings/cpp/include/proton/comparable.hpp
+++ b/proton-c/bindings/cpp/include/proton/comparable.hpp
@@ -22,6 +22,8 @@
namespace proton {
+///@cond INTERNAL
+
/// Base class for comparable types with operator< and
/// operator==. Provides remaining operators.
template <class T> class comparable {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 e6946c7..0b1a947 100644
--- a/proton-c/bindings/cpp/include/proton/connection_engine.hpp
+++ b/proton-c/bindings/cpp/include/proton/connection_engine.hpp
@@ -125,7 +125,7 @@ PN_CPP_CLASS_EXTERN connection_engine {
/// Thrown by io_read and io_write functions to indicate an error.
struct PN_CPP_CLASS_EXTERN io_error : public error {
- PN_CPP_EXTERN explicit io_error(const std::string&);
+ PN_CPP_EXTERN explicit io_error(const std::string&); ///< Construct with message
};
protected:
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 3d39154..2dadd51 100644
--- a/proton-c/bindings/cpp/include/proton/data.hpp
+++ b/proton-c/bindings/cpp/include/proton/data.hpp
@@ -24,55 +24,62 @@
#include <proton/types_fwd.hpp>
#include <proton/type_id.hpp>
+///@file
+
struct pn_data_t;
namespace proton {
class value;
+///@defgroup codec Internal details of AMQP encoding.
+///
+/// You can use these classes on an experimental basis to create your own AMQP
+/// encodings for C++ types, but they may change in the future. For examples of use
+/// see the built-in encodings, for example in proton/vector.hpp or proton/map.hpp
+/// @ingroup codec
namespace codec {
/// Wrapper for a proton data object.
class data : public internal::object<pn_data_t> {
public:
+ /// Wrap an existing proton-C data object.
data(pn_data_t* d=0) : internal::object<pn_data_t>(d) {}
+ /// Create a new data object.
PN_CPP_EXTERN static data create();
- // Copy the contents of another data object.
+ /// Copy the contents of another data object.
PN_CPP_EXTERN void copy(const data&);
- /** Clear the data. */
+ /// Clear the data.
PN_CPP_EXTERN void clear();
- /** Rewind current position to the start */
+ /// Rewind current position to the start.
PN_CPP_EXTERN void rewind();
- /** True if there are no values. */
+ /// True if there are no values.
PN_CPP_EXTERN bool empty() const;
- /** Return the data cursor position */
- PN_CPP_EXTERN void* point() const;
-
- /** Restore the cursor position to a previously saved position */
- PN_CPP_EXTERN void restore(void* h);
-
- PN_CPP_EXTERN void narrow();
-
- PN_CPP_EXTERN void widen();
-
+ /// Append the contents of another data object.
PN_CPP_EXTERN int append(data src);
+ /// Append up to limit items from data object.
PN_CPP_EXTERN int appendn(data src, int limit);
+ protected:
+ PN_CPP_EXTERN void* point() const;
+ PN_CPP_EXTERN void restore(void* h);
+ PN_CPP_EXTERN void narrow();
+ PN_CPP_EXTERN void widen();
PN_CPP_EXTERN bool next();
-
PN_CPP_EXTERN bool prev();
+ friend struct state_guard;
friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const data&);
};
-/// state_guard saves the state and restores it in dtor unless cancel() is called.
+// state_guard saves the state and restores it in dtor unless cancel() is called.
struct state_guard {
data& data_;
void* point_;
@@ -83,13 +90,6 @@ struct state_guard {
void cancel() { cancel_ = true; }
};
-/// Narrow the data object, widen it in dtor.
-struct narrow_guard {
- data& data_;
- narrow_guard(data& d) : data_(d) { data_.narrow(); }
- ~narrow_guard() { data_.widen(); }
-};
-
// Start encoding a complex type.
struct start {
start(type_id type_=NULL_TYPE, type_id element_=NULL_TYPE,
@@ -107,10 +107,11 @@ struct start {
PN_CPP_EXTERN static start described() { return start(DESCRIBED, NULL_TYPE, true); }
};
-/// Finish inserting or extracting a complex type.
+// Finish inserting or extracting a complex type.
struct finish {};
} // codec
+
} // proton
-#endif // PROTON_DATA_HPP
+#endif /*!PROTON_DATA_HPP*/
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/decimal.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/decimal.hpp b/proton-c/bindings/cpp/include/proton/decimal.hpp
index ddb8ea8..dada944 100644
--- a/proton-c/bindings/cpp/include/proton/decimal.hpp
+++ b/proton-c/bindings/cpp/include/proton/decimal.hpp
@@ -49,13 +49,16 @@ class decimal64 : public byte_array<8> {};
/// 128-bit decimal floating point.
class decimal128 : public byte_array<16> {};
+///@}
+/// Print decimal values
+///@{
PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const decimal32&);
PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const decimal64&);
PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const decimal128&);
-
///@}
+
}
#endif // DECIMAL_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 9a835c0..e6fc78b 100644
--- a/proton-c/bindings/cpp/include/proton/decoder.hpp
+++ b/proton-c/bindings/cpp/include/proton/decoder.hpp
@@ -20,10 +20,12 @@
*/
#include <proton/data.hpp>
+#include <proton/types_fwd.hpp>
#include <proton/type_traits.hpp>
#include <utility>
+// Proton namespace
namespace proton {
class annotation_key;
@@ -32,19 +34,23 @@ class scalar;
class value;
class value_base;
+/// @ingroup codec
namespace codec {
/// Stream-like decoder from AMQP bytes to C++ values.
///
-/// Internal use only, see proton::value, proton::scalar and proton::amqp
+/// Internal use only, see proton::value, proton::scalar and \ref types
/// for the recommended ways to manage AMQP data.
class decoder : public data {
public:
- ///@internal
- explicit decoder(const data& d) : data(d) {}
+
+ /// Wrap Proton-C data object.
+ /// The exact flag if set means decode only when there is an exact match
+ /// between the AMQP and C++ type. If not set then perform automatic conversions.
+ explicit decoder(const data& d, bool exact=false) : data(d), exact_(exact) {}
/// Attach decoder to a proton::value. The decoder is rewound to the start of the data.
- PN_CPP_EXTERN explicit decoder(const value_base&);
+ PN_CPP_EXTERN explicit decoder(const value_base&, bool exact=false);
/// Decode AMQP data from a buffer and add it to the end of the decoders stream. */
PN_CPP_EXTERN void decode(const char* buffer, size_t size);
@@ -59,11 +65,9 @@ class decoder : public data {
/// @throw conversion_error if no more values. @see decoder::more().
PN_CPP_EXTERN type_id next_type();
- /** @name Extract simple types
- * Overloads to extract simple types.
- * @throw conversion_error if the decoder is empty or has an incompatible type.
- * @{
- */
+ /// @name Extract built-in types
+ /// @throw conversion_error if the decoder is empty or has an incompatible type.
+ /// @{
PN_CPP_EXTERN decoder& operator>>(bool&);
PN_CPP_EXTERN decoder& operator>>(uint8_t&);
PN_CPP_EXTERN decoder& operator>>(int8_t&);
@@ -96,10 +100,10 @@ class decoder : public data {
/// Call finish() to "exit" the container and move on to the next value.
PN_CPP_EXTERN decoder& operator>>(start&);
- // Finish decoding a container type, and move on to the next value in the stream.
+ /// Finish decoding a container type, and move on to the next value in the stream.
PN_CPP_EXTERN decoder& operator>>(const finish&);
- // XXX doc
+ ///@cond INTERNAL
template <class T> struct sequence_ref { T& ref; sequence_ref(T& r) : ref(r) {} };
template <class T> struct associative_ref { T& ref; associative_ref(T& r) : ref(r) {} };
template <class T> struct pair_sequence_ref { T& ref; pair_sequence_ref(T& r) : ref(r) {} };
@@ -107,6 +111,7 @@ class decoder : public data {
template <class T> static sequence_ref<T> sequence(T& x) { return sequence_ref<T>(x); }
template <class T> static associative_ref<T> associative(T& x) { return associative_ref<T>(x); }
template <class T> static pair_sequence_ref<T> pair_sequence(T& x) { return pair_sequence_ref<T>(x); }
+ ///@endcond
/** Extract any AMQP sequence (ARRAY, LIST or MAP) to a C++ sequence
* container of T if the elements types are convertible to T. A MAP is
@@ -124,6 +129,7 @@ class decoder : public data {
/** Extract an AMQP MAP to a C++ associative container */
template <class T> decoder& operator>>(associative_ref<T> r) {
+ using namespace internal;
start s;
*this >> s;
assert_type_equal(MAP, s.type);
@@ -140,6 +146,7 @@ class decoder : public data {
/// Extract an AMQP MAP to a C++ push_back sequence of pairs
/// preserving encoded order.
template <class T> decoder& operator>>(pair_sequence_ref<T> r) {
+ using namespace internal;
start s;
*this >> s;
assert_type_equal(MAP, s.type);
@@ -154,30 +161,32 @@ class decoder : public data {
return *this;
}
- /// Extract and return a value.
- template <class T> T extract() { T x; *this >> x; return x; }
-
private:
type_id pre_get();
template <class T, class U> decoder& extract(T& x, U (*get)(pn_data_t*));
+ bool exact_;
friend class message;
};
+template<class T> T get(decoder& d) {
+ assert_type_equal(internal::type_id_of<T>::value, d.next_type());
+ T x;
+ d >> x;
+ return x;
+}
+
// operator >> for integer types that are not covered by the standard overrides.
-template <class T> typename codec::enable_unknown_integer<T, decoder&>::type
+template <class T> typename internal::enable_if<internal::is_unknown_integer<T>::value, decoder&>::type
operator>>(decoder& d, T& i) {
+ using namespace internal;
typename integer_type<sizeof(T), is_signed<T>::value>::type v;
d >> v; // Extract as a known integer type
i = v; // C++ conversion to the target type.
return d;
}
-///@cond INTERNAL
-
-} // internal
+} // codec
} // proton
-/// @endcond
-
#endif // PROTON_DECODER_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/deque.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/deque.hpp b/proton-c/bindings/cpp/include/proton/deque.hpp
index 18d142d..7d0b278 100644
--- a/proton-c/bindings/cpp/include/proton/deque.hpp
+++ b/proton-c/bindings/cpp/include/proton/deque.hpp
@@ -31,7 +31,7 @@ namespace codec {
/// std::deque<T> for most T is encoded as an amqp::ARRAY (same type elements)
template <class T, class A>
encoder& operator<<(encoder& e, const std::deque<T, A>& x) {
- return e << encoder::array(x, type_id_of<T>::value);
+ return e << encoder::array(x, internal::type_id_of<T>::value);
}
/// std::deque<value> encodes as amqp::LIST (mixed type elements)
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/duration.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/duration.hpp b/proton-c/bindings/cpp/include/proton/duration.hpp
index 51f7a46..9d41d2d 100644
--- a/proton-c/bindings/cpp/include/proton/duration.hpp
+++ b/proton-c/bindings/cpp/include/proton/duration.hpp
@@ -33,11 +33,13 @@ namespace proton {
/// A span of time in milliseconds.
class duration : private comparable<duration> {
public:
- typedef uint64_t numeric_type;
- explicit duration(numeric_type ms = 0) : ms_(ms) {}
- duration& operator=(numeric_type ms) { ms_ = ms; return *this; }
- numeric_type milliseconds() const { return ms_; }
- numeric_type ms() const { return ms_; }
+ typedef uint64_t numeric_type; ///< Numeric type used to store milliseconds
+
+ explicit duration(numeric_type ms = 0) : ms_(ms) {} ///< Construct from milliseconds
+ duration& operator=(numeric_type ms) { ms_ = ms; return *this; } ///< Assign
+
+ numeric_type milliseconds() const { return ms_; } ///< Return milliseconds
+ numeric_type ms() const { return ms_; } ///< Return milliseconds
PN_CPP_EXTERN static const duration FOREVER; ///< Wait for ever
PN_CPP_EXTERN static const duration IMMEDIATE; ///< Don't wait at all
@@ -48,8 +50,11 @@ class duration : private comparable<duration> {
numeric_type ms_;
};
+/// Print duration
PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, duration);
+///@name Comparison and arithmetic operators
+///@{
inline bool operator<(duration x, duration y) { return x.ms() < y.ms(); }
inline bool operator==(duration x, duration y) { return x.ms() == y.ms(); }
@@ -57,7 +62,7 @@ inline duration operator+(duration x, duration y) { return duration(x.ms() + y.m
inline duration operator-(duration x, duration y) { return duration(x.ms() - y.ms()); }
inline duration operator*(duration d, uint64_t n) { return duration(d.ms()*n); }
inline duration operator*(uint64_t n, duration d) { return d * n; }
-
+///@}
}
#endif // PROTON_CPP_DURATION_H
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/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 c76c9ce..b9d4461 100644
--- a/proton-c/bindings/cpp/include/proton/encoder.hpp
+++ b/proton-c/bindings/cpp/include/proton/encoder.hpp
@@ -1,5 +1,5 @@
-#ifndef ENCODER_H
-#define ENCODER_H
+#ifndef PROTON_ENCODER_HPP
+#define PROTON_ENCODER_HPP
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -21,23 +21,24 @@
*/
#include <proton/data.hpp>
+#include <proton/types_fwd.hpp>
#include <proton/type_traits.hpp>
namespace proton {
-class scalar;
-class value;
+class scalar_base;
class value_base;
+/// @ingroup codec
namespace codec {
/// Stream-like encoder from AMQP bytes to C++ values.
///
-/// Internal use only, see proton::value, proton::scalar and proton::amqp
+/// Internal use only, see proton::value, proton::scalar and \ref types
/// for the recommended ways to manage AMQP data.
class encoder : public data {
public:
- ///@internal
+ /// Wrap Proton-C data object.
explicit encoder(const data& d) : data(d) {}
/// Encoder into v. Clears any current value in v.
@@ -63,6 +64,8 @@ class encoder : public data {
/** Encode the current values into a std::string. Clears the encoder. */
PN_CPP_EXTERN std::string encode();
+ /// @name Insert built-in types
+ /// @{
PN_CPP_EXTERN encoder& operator<<(bool);
PN_CPP_EXTERN encoder& operator<<(uint8_t);
PN_CPP_EXTERN encoder& operator<<(int8_t);
@@ -83,17 +86,24 @@ class encoder : public data {
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&);
+ PN_CPP_EXTERN encoder& operator<<(const scalar_base&);
PN_CPP_EXTERN encoder& operator<<(const null&);
+ ///@}
- /// Inserts proton::value.
+ /// Insert a proton::value.
+ /// @internal NOTE insert value_base, not value to avoid recursive implicit conversions.
PN_CPP_EXTERN encoder& operator<<(const value_base&);
+ /// Start a complex type
PN_CPP_EXTERN encoder& operator<<(const start&);
/// Finish a complex type
PN_CPP_EXTERN encoder& operator<<(const finish&);
- // XXX doc
+ ///@cond INTERNAL
+
+ // Undefined template to prevent pointers being implicitly converted to bool.
+ template <class T> void* operator<<(const T*);
+
template <class T> struct list_cref { T& ref; list_cref(T& r) : ref(r) {} };
template <class T> struct map_cref { T& ref; map_cref(T& r) : ref(r) {} };
@@ -135,26 +145,47 @@ class encoder : public data {
*this << finish();
return *this;
}
+ ///@endcond
private:
template<class T, class U> encoder& insert(const T& x, int (*put)(pn_data_t*, U));
void check(long result);
};
-///@internal
-/// Invalid template to prevent pointers being implicitly converted to bool.
-template <class T> void* operator<<(encoder&, const T*);
-// Treat char* as string
+/// Treat char* as string
inline encoder& operator<<(encoder& e, const char* s) { return e << std::string(s); }
-// operator << for integer types that are not covered by the standard overrides.
-template <class T> typename codec::enable_unknown_integer<T, encoder&>::type
+/// operator << for integer types that are not covered by the standard overrides.
+template <class T> typename internal::enable_if<internal::is_unknown_integer<T>::value, encoder&>::type
operator<<(encoder& e, T i) {
+ using namespace internal;
return e << static_cast<typename integer_type<sizeof(T), is_signed<T>::value>::type>(i);
}
-} // internal
+///@cond INTERNAL
+namespace is_encodable_impl { // Protected the world from wildcard operator<<
+
+using namespace internal;
+
+sfinae::no operator<<(sfinae::wildcard, sfinae::wildcard); // Fallback
+
+template<typename T> struct is_encodable : public sfinae {
+ 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);
+};
+// Avoid recursion
+template <> struct is_encodable<value> : public true_type {};
+
+} // namespace is_encodable_impl
+
+using is_encodable_impl::is_encodable;
+///@endcond
+
+} // codec
} // proton
-#endif // ENCODER_H
+#endif /*!PROTON_ENCODER_HPP*/
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d70dab5d/proton-c/bindings/cpp/include/proton/endpoint.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/endpoint.hpp b/proton-c/bindings/cpp/include/proton/endpoint.hpp
index 705ce7d..d59e093 100644
--- a/proton-c/bindings/cpp/include/proton/endpoint.hpp
+++ b/proton-c/bindings/cpp/include/proton/endpoint.hpp
@@ -75,6 +75,7 @@ PN_CPP_CLASS_EXTERN endpoint {
#endif
};
+///@cond INTERNAL
namespace internal {
template <class T, class D> class iter_base {
@@ -86,7 +87,7 @@ template <class T, class D> class iter_base {
D operator++(int) { D x(*this); ++(*this); return x; }
bool operator==(const iter_base<T, D>& x) const { return obj_ == x.obj_; }
bool operator!=(const iter_base<T, D>& x) const { return obj_ != x.obj_; }
-
+ ///@}
protected:
explicit iter_base(T p = 0) : obj_(p) {}
T obj_;
@@ -105,6 +106,8 @@ template<class I> class iter_range {
};
} // namespace internal
+///@endcond
+
} // namespace proton
#endif // PROTON_CPP_H
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[4/4] qpid-proton git commit: PROTON-1159: Merge with trunk
Posted by kp...@apache.org.
PROTON-1159: Merge with trunk
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/e15bcdd0
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/e15bcdd0
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/e15bcdd0
Branch: refs/heads/kvdr-PROTON-1159
Commit: e15bcdd097f5db718a0ca8204e734ad5727787f2
Parents: a8b63a1 d70dab5
Author: Kim van der Riet <kp...@apache.org>
Authored: Thu Mar 17 11:33:57 2016 -0400
Committer: Kim van der Riet <kp...@apache.org>
Committed: Thu Mar 17 11:33:57 2016 -0400
----------------------------------------------------------------------
examples/cpp/README.dox | 198 +++++++++
examples/cpp/README.hpp | 198 ---------
examples/cpp/direct_recv.cpp | 8 +-
examples/cpp/encode_decode.cpp | 13 +-
examples/cpp/engine/server.cpp | 2 +-
examples/cpp/server.cpp | 2 +-
examples/cpp/server_direct.cpp | 12 +-
proton-c/bindings/cpp/CMakeLists.txt | 2 +-
proton-c/bindings/cpp/docs/CMakeLists.txt | 1 +
proton-c/bindings/cpp/docs/tutorial.dox | 428 +++++++++++++++++++
proton-c/bindings/cpp/docs/tutorial.hpp | 428 -------------------
proton-c/bindings/cpp/docs/user.doxygen.in | 10 +-
proton-c/bindings/cpp/include/proton/amqp.hpp | 40 +-
.../cpp/include/proton/annotation_key.hpp | 51 ++-
proton-c/bindings/cpp/include/proton/binary.hpp | 26 +-
.../bindings/cpp/include/proton/byte_array.hpp | 52 ++-
.../bindings/cpp/include/proton/comparable.hpp | 2 +
.../cpp/include/proton/connection_engine.hpp | 2 +-
proton-c/bindings/cpp/include/proton/data.hpp | 51 +--
.../bindings/cpp/include/proton/decimal.hpp | 5 +-
.../bindings/cpp/include/proton/decoder.hpp | 49 ++-
proton-c/bindings/cpp/include/proton/deque.hpp | 2 +-
.../bindings/cpp/include/proton/duration.hpp | 17 +-
.../bindings/cpp/include/proton/encoder.hpp | 65 ++-
.../bindings/cpp/include/proton/endpoint.hpp | 5 +-
proton-c/bindings/cpp/include/proton/error.hpp | 6 +-
.../cpp/include/proton/forward_list.hpp | 2 +-
proton-c/bindings/cpp/include/proton/io.hpp | 3 +-
proton-c/bindings/cpp/include/proton/link.hpp | 5 +
proton-c/bindings/cpp/include/proton/list.hpp | 2 +-
.../bindings/cpp/include/proton/message.hpp | 6 +-
.../bindings/cpp/include/proton/message_id.hpp | 62 ++-
proton-c/bindings/cpp/include/proton/scalar.hpp | 217 ++--------
.../bindings/cpp/include/proton/scalar_base.hpp | 181 ++++++++
.../bindings/cpp/include/proton/session.hpp | 4 +-
proton-c/bindings/cpp/include/proton/symbol.hpp | 4 +
.../bindings/cpp/include/proton/timestamp.hpp | 18 +-
.../bindings/cpp/include/proton/type_id.hpp | 23 +-
.../bindings/cpp/include/proton/type_traits.hpp | 108 ++---
proton-c/bindings/cpp/include/proton/types.hpp | 88 +++-
.../bindings/cpp/include/proton/types_fwd.hpp | 11 +-
proton-c/bindings/cpp/include/proton/url.hpp | 2 +-
proton-c/bindings/cpp/include/proton/value.hpp | 106 ++---
proton-c/bindings/cpp/include/proton/vector.hpp | 2 +-
proton-c/bindings/cpp/src/decoder.cpp | 127 +++---
proton-c/bindings/cpp/src/encoder.cpp | 21 +-
proton-c/bindings/cpp/src/interop_test.cpp | 21 -
proton-c/bindings/cpp/src/message.cpp | 4 +-
proton-c/bindings/cpp/src/message_test.cpp | 16 +-
proton-c/bindings/cpp/src/scalar.cpp | 263 ------------
proton-c/bindings/cpp/src/scalar_base.cpp | 158 +++++++
proton-c/bindings/cpp/src/scalar_test.cpp | 15 +-
proton-c/bindings/cpp/src/ssl.cpp | 2 +-
proton-c/bindings/cpp/src/test_bits.hpp | 7 +
proton-c/bindings/cpp/src/types_internal.hpp | 15 +-
proton-c/bindings/cpp/src/value.cpp | 27 +-
proton-c/bindings/cpp/src/value_test.cpp | 46 +-
tests/tools/apps/cpp/reactor_send.cpp | 2 +-
58 files changed, 1688 insertions(+), 1555 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e15bcdd0/proton-c/bindings/cpp/include/proton/byte_array.hpp
----------------------------------------------------------------------
diff --cc proton-c/bindings/cpp/include/proton/byte_array.hpp
index 9ae123f,fe3f864..831283f
--- a/proton-c/bindings/cpp/include/proton/byte_array.hpp
+++ b/proton-c/bindings/cpp/include/proton/byte_array.hpp
@@@ -23,8 -23,7 +23,9 @@@
#include <proton/comparable.hpp>
#include <algorithm>
+#include <iomanip>
+#include <iostream>
+ #include <iterator>
namespace proton {
@@@ -32,40 -31,51 +33,59 @@@
/// as an array of bytes.
template <size_t N> class byte_array : private comparable<byte_array<N> > {
public:
- typedef char value_type;
+ ///@name Sequence container typedefs
+ ///@{
+ typedef uint8_t value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef value_type* iterator;
+ typedef const value_type* const_iterator;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ ///@}
- /// Initially all 0.
+ /// 0-initialized byte array
byte_array() { std::fill(bytes_, bytes_+N, '\0'); }
- /// Returns N
+ /// Size of the array
static size_t size() { return N; }
- uint8_t* begin() { return bytes_; }
- uint8_t* end() { return bytes_+N; }
- uint8_t& operator[](size_t i) { return bytes_[i]; }
+ ///@name Array operators
+ ///@{
+ value_type* begin() { return bytes_; }
+ value_type* end() { return bytes_+N; }
+ value_type& operator[](size_t i) { return bytes_[i]; }
- const uint8_t* begin() const { return bytes_; }
- const uint8_t* end() const { return bytes_+N; }
- const uint8_t& operator[](size_t i) const { return bytes_[i]; }
+ const value_type* begin() const { return bytes_; }
+ const value_type* end() const { return bytes_+N; }
+ const value_type& operator[](size_t i) const { return bytes_[i]; }
+ ///@}
- friend bool operator==(const byte_array& x, const byte_array& y) {
- return std::equal(x.begin(), x.end(), y.begin());
- }
+ ///@name Comparison operators
+ ///@{
+ friend bool operator==(const byte_array& x, const byte_array& y) {
+ return std::equal(x.begin(), x.end(), y.begin());
+ }
- friend bool operator<(const byte_array& x, const byte_array& y) {
- return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
- }
+ friend bool operator<(const byte_array& x, const byte_array& y) {
+ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+ }
+ ///@}
+ friend std::ostream& operator<<(std::ostream& o, const byte_array& b) {
+ o << "0x" << std::hex;
+ for (int i=0; i<b.size(); ++i) {
+ o << std::setfill('0') << std::setw(2) << ((int)b[i] & 0xff);
+ }
+ return o << std::dec;
+ }
+
private:
- uint8_t bytes_[N];
+ value_type bytes_[N];
};
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[2/4] qpid-proton git commit: PROTON-1138: c++: get<>/coerce<> API
and documentation.
Posted by kp...@apache.org.
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