You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2016/03/11 22:45:52 UTC
[2/4] qpid-proton git commit: PROTON-1138: c++: Encode/decode of
complex types
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/include/proton/unordered_map.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/unordered_map.hpp b/proton-c/bindings/cpp/include/proton/unordered_map.hpp
new file mode 100644
index 0000000..43a84d1
--- /dev/null
+++ b/proton-c/bindings/cpp/include/proton/unordered_map.hpp
@@ -0,0 +1,40 @@
+#ifndef PROTON_UNORDERED_MAP_HPP
+#define PROTON_UNORDERED_MAP_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 <unordered_map>
+#include <proton/encoder.hpp>
+#include <proton/decoder.hpp>
+
+namespace proton {
+namespace codec {
+
+/// Encode std::unordered_map<K, T> as amqp::UNORDERED_MAP.
+template <class K, class T, class C, class A>
+encoder& operator<<(encoder& e, const std::unordered_map<K, T, C, A>& m) { return e << encoder::map(m); }
+
+/// Decode to std::unordered_map<K, T> from amqp::UNORDERED_MAP.
+template <class K, class T, class C, class A>
+decoder& operator>>(decoder& d, std::unordered_map<K, T, C, A>& m) { return d >> decoder::associative(m); }
+
+} // internal
+} // proton
+
+#endif // PROTON_UNORDERED_MAP_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/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 a5e7ad0..c863971 100644
--- a/proton-c/bindings/cpp/include/proton/url.hpp
+++ b/proton-c/bindings/cpp/include/proton/url.hpp
@@ -20,8 +20,8 @@
* under the License.
*/
-#include "proton/types.hpp"
-#include "proton/error.hpp"
+#include <proton/types_fwd.hpp>
+#include <proton/error.hpp>
#include <iosfwd>
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/include/proton/uuid.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/uuid.hpp b/proton-c/bindings/cpp/include/proton/uuid.hpp
index ec95b34..b1ad316 100644
--- a/proton-c/bindings/cpp/include/proton/uuid.hpp
+++ b/proton-c/bindings/cpp/include/proton/uuid.hpp
@@ -30,9 +30,9 @@ namespace proton {
/// A 16-byte universally unique identifier.
class uuid : public byte_array<16> {
public:
- /// Return a uuid copied from bytes, bytes must point to at least sizeof(uuid) bytes.
+ /// Return a uuid copied from bytes, bytes must point to at least 16 bytes.
/// If bytes==0 the UUID is zero initialized.
- PN_CPP_EXTERN static uuid make(const char* bytes=0);
+ PN_CPP_EXTERN static uuid copy(const char* bytes=0);
/// Return a simple randomly-generated UUID. Used by the proton library to
/// generate default UUIDs. For specific security, performance or
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/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 4c51bf3..359aaeb 100644
--- a/proton-c/bindings/cpp/include/proton/value.hpp
+++ b/proton-c/bindings/cpp/include/proton/value.hpp
@@ -1,5 +1,5 @@
-#ifndef VALUE_H
-#define VALUE_H
+#ifndef PROTON_VALUE_HPP
+#define PROTON_VALUE_HPP
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,20 +20,18 @@
* under the License.
*/
-#include "proton/data.hpp"
-#include "proton/types.hpp"
-#include "proton/timestamp.hpp"
-#include "proton/uuid.hpp"
+#include <proton/encoder.hpp>
+#include <proton/decoder.hpp>
+#include <proton/type_traits.hpp>
+#include <proton/types_fwd.hpp>
+
+#include <iosfwd>
namespace proton {
-/// A holder for an AMQP value.
-///
-/// A proton::value can hold any AMQP data value, simple or compound.
-/// It has assignment and conversion operators to convert its contents
-/// easily to and from native C++ types.
+/// A holder for any single AMQP value, simple or complex (can be list, array, map etc.)
///
-/// The conversions for scalar types are documented in proton::amqp.
+/// @see proton::amqp for conversions rules between C++ and AMQP types.
///
class value : private comparable<value> {
public:
@@ -44,17 +42,29 @@ class value : private comparable<value> {
/// 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 proton::amqp for allowed types.
- /// Ignore the default parameter, it restricts the template to match only allowed types.
- template <class T> value(const T& x, typename enable_amqp_type<T>::type* = 0) { encode() << x; }
+ 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&);
- PN_CPP_EXTERN value& operator=(const value&);
+ /// 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) {
+ codec::encoder e(*this);
+ e << x;
+ return *this;
+ }
/// Reset the value to null
PN_CPP_EXTERN void clear();
@@ -72,16 +82,7 @@ class value : private comparable<value> {
/// @{
/// Get the value.
- template<class T> void get(T &t) const { decode() >> t; }
-
- /// Get an AMQP map as any type T that satisfies the map concept.
- template<class T> void get_map(T& t) const { decode() >> internal::to_map(t); }
-
- /// Get a map as a as any type T that is a sequence pair-like types with first and second.
- template<class T> void get_pairs(T& t) const { decode() >> internal::to_pairs(t); }
-
- /// Get an AMQP array or list as type T that satisfies the sequence concept. */
- template<class T> void get_sequence(T& t) const { decode() >> internal::to_sequence(t); }
+ template<class T> void get(T &t) const { codec::decoder d(*this); d >> t; }
PN_CPP_EXTERN void get(null&) const;
/// @}
@@ -104,24 +105,19 @@ class value : private comparable<value> {
friend PN_CPP_EXTERN void swap(value&, value&);
friend PN_CPP_EXTERN bool operator==(const value& x, const value& y);
friend PN_CPP_EXTERN bool operator<(const value& x, const value& y);
- friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream& o, const value& dv);
-
- ///@cond INTERNAL
- PN_CPP_EXTERN internal::encoder encode();
- PN_CPP_EXTERN internal::decoder decode() const;
- PN_CPP_EXTERN explicit value(pn_data_t*); ///< Copies the data
- ///@endcond
+ friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream& o, codec::exact_cref<value>);
private:
-
- mutable class internal::data data_;
- internal::data& data() const; // On-demand access.
+ codec::data& data() const;
+ mutable class codec::data data_;
friend class message;
- friend class internal::encoder;
- friend class internal::decoder;
+ friend class codec::encoder;
+ friend class codec::decoder;
};
-}
+template<class T> T get(codec::exact_cref<value> v) { T x; v.ref.get(x); return x; }
+
+} // proton
-#endif // VALUE_H
+#endif // PROTON_VALUE_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/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
new file mode 100644
index 0000000..350960d
--- /dev/null
+++ b/proton-c/bindings/cpp/include/proton/vector.hpp
@@ -0,0 +1,55 @@
+#ifndef PROTON_VECTOR_HPP
+#define PROTON_VECTOR_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 <vector>
+#include <utility>
+
+#include <proton/encoder.hpp>
+#include <proton/decoder.hpp>
+
+namespace proton {
+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);
+}
+
+/// Encode std::vector<value> encode as amqp::LIST (mixed type elements)
+template <class A> encoder& operator<<(encoder& e, const std::vector<value, A>& x) { return e << encoder::list(x); }
+
+/// Encode std::vector<scalar> as amqp::LIST (mixed type elements)
+template <class A> encoder& operator<<(encoder& e, const std::vector<scalar, A>& x) { return e << encoder::list(x); }
+
+/// Encode std::deque<std::pair<k,t> > as amqp::MAP, preserves order of entries.
+template <class A, class K, class T>
+encoder& operator<<(encoder& e, const std::vector<std::pair<K,T>, A>& x) { return e << encoder::map(x); }
+
+/// Decode to std::vector<T> from an amqp::LIST or amqp::ARRAY.
+template <class T, class A> decoder& operator>>(decoder& d, std::vector<T, A>& x) { return d >> decoder::sequence(x); }
+
+/// Decode to std::vector<std::pair<K, T> from an amqp::MAP.
+template <class A, class K, class T> decoder& operator>>(decoder& d, std::vector<std::pair<K, T> , A>& x) { return d >> decoder::pair_sequence(x); }
+
+} // internal
+} // proton
+
+#endif // PROTON_VECTOR_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/src/codec_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/codec_test.cpp b/proton-c/bindings/cpp/src/codec_test.cpp
index e3b45d7..ec5cf9a 100644
--- a/proton-c/bindings/cpp/src/codec_test.cpp
+++ b/proton-c/bindings/cpp/src/codec_test.cpp
@@ -13,7 +13,7 @@
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
-nn * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * "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.
@@ -22,26 +22,19 @@ nn * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#include "test_bits.hpp"
#include <proton/types.hpp>
-#include <proton/binary.hpp>
-#include <proton/decimal.hpp>
-#include <proton/decoder.hpp>
-#include <proton/encoder.hpp>
-#include <proton/symbol.hpp>
-#include <proton/value.hpp>
-#include <proton/scalar.hpp>
-#include <proton/annotation_key.hpp>
-#include <proton/message_id.hpp>
+#include <proton/data.hpp>
using namespace test;
using namespace proton;
template <class T> void simple_type_test(const T& x) {
- ASSERT(internal::is_encodable<T>::value);
- ASSERT(internal::is_decodable<T>::value);
+ ASSERT(codec::is_encodable<T>::value);
value v;
- v.encode() << x;
+ codec::encoder e(v);
+ e << x;
T y;
- v.decode() >> y;
+ codec::decoder d(v);
+ d >> y;
ASSERT_EQUAL(x, y);
}
@@ -51,8 +44,7 @@ template <class T> T make_fill(const char c) {
}
template <class T> void uncodable_type_test() {
- ASSERT(!internal::is_encodable<T>::value);
- ASSERT(!internal::is_decodable<T>::value);
+ ASSERT(!codec::is_encodable<T>::value);
}
int main(int, char**) {
@@ -75,8 +67,7 @@ int main(int, char**) {
RUN_TEST(failed, simple_type_test(make_fill<decimal32>(0)));
RUN_TEST(failed, simple_type_test(make_fill<decimal64>(0)));
RUN_TEST(failed, simple_type_test(make_fill<decimal128>(0)));
- // FIXME aconway 2016-03-07:
- // RUN_TEST(failed, simple_type_test(uuid::copy("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff")));
+ RUN_TEST(failed, simple_type_test(uuid::copy("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff")));
RUN_TEST(failed, simple_type_test(std::string("xxx")));
RUN_TEST(failed, simple_type_test(symbol("aaa")));
RUN_TEST(failed, simple_type_test(binary("aaa")));
@@ -108,13 +99,15 @@ int main(int, char**) {
value v(23); // Make sure we can take a non-const ref also
RUN_TEST(failed, simple_type_test(v));
RUN_TEST(failed, simple_type_test(scalar(23)));
- RUN_TEST(failed, simple_type_test(static_cast<annotation_key>(42)));
- RUN_TEST(failed, simple_type_test(static_cast<message_id>(42)));
+ RUN_TEST(failed, simple_type_test(annotation_key(42)));
+ RUN_TEST(failed, simple_type_test(message_id(42)));
// Make sure we reject uncodable types
RUN_TEST(failed, (uncodable_type_test<std::pair<int, float> >()));
RUN_TEST(failed, (uncodable_type_test<std::pair<scalar, value> >()));
RUN_TEST(failed, (uncodable_type_test<std::basic_string<wchar_t> >()));
+ RUN_TEST(failed, (uncodable_type_test<codec::data>()));
+ RUN_TEST(failed, (uncodable_type_test<pn_data_t*>()));
return failed;
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/src/data.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/data.cpp b/proton-c/bindings/cpp/src/data.cpp
index a714cf6..5bbf743 100644
--- a/proton-c/bindings/cpp/src/data.cpp
+++ b/proton-c/bindings/cpp/src/data.cpp
@@ -19,28 +19,35 @@
#include "proton_bits.hpp"
-#include "proton/amqp.hpp"
-#include "proton/binary.hpp"
-#include "proton/data.hpp"
-#include "proton/decimal.hpp"
-#include "proton/symbol.hpp"
+#include <proton/binary.hpp>
+#include <proton/data.hpp>
+#include <proton/decimal.hpp>
+#include <proton/encoder.hpp>
+#include <proton/message_id.hpp>
+#include <proton/symbol.hpp>
+#include <proton/timestamp.hpp>
+#include <proton/value.hpp>
#include <proton/codec.h>
#include <ostream>
namespace proton {
-namespace internal {
+namespace codec {
-data& data::copy(const data& x) { ::pn_data_copy(pn_object(), x.pn_object()); return *this; }
+data data::create() { return internal::take_ownership(pn_data(0)).get(); }
+
+void data::copy(const data& x) { ::pn_data_copy(pn_object(), x.pn_object()); }
void data::clear() { ::pn_data_clear(pn_object()); }
+void data::rewind() { ::pn_data_rewind(pn_object()); }
+
bool data::empty() const { return ::pn_data_size(pn_object()) == 0; }
-uintptr_t data::point() const { return uintptr_t(pn_data_point(pn_object())); }
+void* data::point() const { return pn_data_point(pn_object()); }
-void data::restore(uintptr_t h) { pn_data_restore(pn_object(), pn_handle_t(h)); }
+void data::restore(void* h) { pn_data_restore(pn_object(), pn_handle_t(h)); }
void data::narrow() { pn_data_narrow(pn_object()); }
@@ -50,123 +57,15 @@ int data::append(data src) { return pn_data_append(pn_object(), src.pn_object())
int data::appendn(data src, int limit) { return pn_data_appendn(pn_object(), src.pn_object(), limit);}
-bool data::next() const { return pn_data_next(pn_object()); }
-
+bool data::next() { return pn_data_next(pn_object()); }
-namespace {
-struct save_state {
- data data_;
- uintptr_t handle;
- save_state(data d) : data_(d), handle(data_.point()) {}
- ~save_state() { if (!!data_) data_.restore(handle); }
-};
-}
+bool data::prev() { return pn_data_prev(pn_object()); }
std::ostream& operator<<(std::ostream& o, const data& d) {
- save_state s(d.pn_object());
- d.decoder().rewind();
+ state_guard sg(const_cast<data&>(d));
+ const_cast<data&>(d).rewind();
return o << inspectable(d.pn_object());
}
-data data::create() { return internal::take_ownership(pn_data(0)); }
-
-class encoder data::encoder() { return internal::encoder(pn_object()); }
-class decoder data::decoder() { return internal:: decoder(pn_object()); }
-
-type_id data::type() const { return decoder().type(); }
-
-namespace {
-
-// Compare nodes, return -1 if a<b, 0 if a==b, +1 if a>b
-// Forward-declare so we can use it recursively.
-int compare_next(data& a, data& b);
-
-template <class T> int compare(const T& a, const T& b) {
- if (a < b) return -1;
- else if (a > b) return +1;
- else return 0;
-}
-
-int compare_container(data& a, data& b) {
- scope sa(a.decoder()), sb(b.decoder());
- // Compare described vs. not-described.
- int cmp = compare(sa.is_described, sb.is_described);
- if (cmp) return cmp;
- // Lexical sort (including descriptor if there is one)
- size_t min_size = std::min(sa.size, sb.size) + size_t(sa.is_described);
- for (size_t i = 0; i < min_size; ++i) {
- cmp = compare_next(a, b);
- if (cmp) return cmp;
- }
- return compare(sa.size, sb.size);
-}
-
-template <class T> int compare_simple(data& a, data& b) {
- T va = T();
- T vb = T();
- a.decoder() >> va;
- b.decoder() >> vb;
- return compare(va, vb);
-}
-
-int compare_next(data& a, data& b) {
- // Sort by type_id first.
- type_id ta = a.type(), tb = b.type();
- int cmp = compare(ta, tb);
- if (cmp) return cmp;
-
- switch (ta) {
- case NULL_TYPE: return 0;
- case ARRAY:
- case LIST:
- case MAP:
- case DESCRIBED:
- return compare_container(a, b);
- case BOOLEAN: return compare_simple<bool>(a, b);
- case UBYTE: return compare_simple<amqp::ubyte_type>(a, b);
- case BYTE: return compare_simple<amqp::byte_type>(a, b);
- case USHORT: return compare_simple<amqp::ushort_type>(a, b);
- case SHORT: return compare_simple<amqp::short_type>(a, b);
- case UINT: return compare_simple<amqp::uint_type>(a, b);
- case INT: return compare_simple<amqp::int_type>(a, b);
- case CHAR: return compare_simple<amqp::char_type>(a, b);
- case ULONG: return compare_simple<amqp::ulong_type>(a, b);
- case LONG: return compare_simple<amqp::long_type>(a, b);
- case TIMESTAMP: return compare_simple<timestamp>(a, b);
- case FLOAT: return compare_simple<amqp::float_type>(a, b);
- case DOUBLE: return compare_simple<amqp::double_type>(a, b);
- case DECIMAL32: return compare_simple<decimal32>(a, b);
- case DECIMAL64: return compare_simple<decimal64>(a, b);
- case DECIMAL128: return compare_simple<decimal128>(a, b);
- case UUID: return compare_simple<uuid>(a, b);
- case BINARY: return compare_simple<amqp::binary_type>(a, b);
- case STRING: return compare_simple<amqp::string_type>(a, b);
- case SYMBOL: return compare_simple<amqp::symbol_type>(a, b);
- }
- // Invalid but equal type_id, treat as equal.
- return 0;
-}
-
-int compare(data& a, data& b) {
- save_state s1(a);
- save_state s2(b);
- a.decoder().rewind();
- b.decoder().rewind();
- while (a.decoder().more() && b.decoder().more()) {
- int cmp = compare_next(a, b);
- if (cmp != 0) return cmp;
- }
- if (b.decoder().more()) return -1;
- if (a.decoder().more()) return 1;
- return 0;
-}
-} // namespace
-
-bool data::equal(const data& x) const {
- return compare(const_cast<data&>(*this), const_cast<data&>(x)) == 0;
-}
-bool data::less(const data& x) const {
- return compare(const_cast<data&>(*this), const_cast<data&>(x)) < 0;
-}
-}
-}
+} // codec
+} // proton
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/src/decimal.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/decimal.cpp b/proton-c/bindings/cpp/src/decimal.cpp
index 65279f4..93fe84c 100644
--- a/proton-c/bindings/cpp/src/decimal.cpp
+++ b/proton-c/bindings/cpp/src/decimal.cpp
@@ -22,6 +22,6 @@
namespace proton {
std::ostream& operator<<(std::ostream& o, const decimal32& ) { return o << "<decimal32>"; }
-std::ostream& operator<<(std::ostream& o, const decimal64& ) { return o << "<decimal32>"; }
-std::ostream& operator<<(std::ostream& o, const decimal128& ) { return o << "<decimal32>"; }
+std::ostream& operator<<(std::ostream& o, const decimal64& ) { return o << "<decimal64>"; }
+std::ostream& operator<<(std::ostream& o, const decimal128& ) { return o << "<decimal128>"; }
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/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 f517e36..e724003 100644
--- a/proton-c/bindings/cpp/src/decoder.cpp
+++ b/proton-c/bindings/cpp/src/decoder.cpp
@@ -17,128 +17,99 @@
* under the License.
*/
-#include "proton/data.hpp"
-#include "proton/decoder.hpp"
-#include "proton/decimal.hpp"
-#include "proton/value.hpp"
-#include "proton/message_id.hpp"
-#include "proton/annotation_key.hpp"
-#include "proton/amqp.hpp"
-#include "proton_bits.hpp"
+#include <proton/annotation_key.hpp>
+#include <proton/binary.hpp>
+#include <proton/data.hpp>
+#include <proton/decimal.hpp>
+#include <proton/encoder.hpp>
+#include <proton/message_id.hpp>
+#include <proton/symbol.hpp>
+#include <proton/timestamp.hpp>
+#include <proton/value.hpp>
+#include "proton_bits.hpp"
#include "types_internal.hpp"
#include "msg.hpp"
#include <proton/codec.h>
namespace proton {
-namespace internal {
+namespace codec {
/**@file
*
* Note the pn_data_t "current" node is always pointing *before* the next value
* to be returned by the decoder.
- *
*/
-namespace {
-struct save_state {
- pn_data_t* data;
- pn_handle_t handle;
- save_state(pn_data_t* d) : data(d), handle(pn_data_point(d)) {}
- ~save_state() { if (data) pn_data_restore(data, handle); }
- void cancel() { data = 0; }
-};
-
-struct narrow {
- data data_;
- narrow(data d) : data_(d) { data_.narrow(); }
- ~narrow() { data_.widen(); }
-};
+decoder::decoder(exact_cref<value> v) : data(v.ref.data()) { rewind(); }
+
+namespace {
template <class T> T check(T result) {
if (result < 0)
- throw conversion_error("" + error_str(result));
+ throw conversion_error(error_str(result));
return result;
}
-
}
void decoder::decode(const char* i, size_t size) {
- save_state ss(pn_object());
+ state_guard sg(*this);
const char* end = i + size;
- while (i < end) {
+ while (i < end)
i += check(pn_data_decode(pn_object(), i, size_t(end - i)));
- }
}
-void decoder::decode(const std::string& buffer) {
- decode(buffer.data(), buffer.size());
-}
-
-bool decoder::more() const {
- save_state ss(pn_object());
- return pn_data_next(pn_object());
-}
-
-void decoder::rewind() { ::pn_data_rewind(pn_object()); }
-
-void decoder::backup() { ::pn_data_prev(pn_object()); }
-
-void decoder::skip() { ::pn_data_next(pn_object()); }
-
-namespace {
+void decoder::decode(const std::string& s) { decode(s.data(), s.size()); }
-void bad_type(type_id want, type_id got) {
- if (want != got) throw make_conversion_error(want, got);
+bool decoder::more() {
+ state_guard sg(*this);
+ return next();
}
-type_id pre_get(pn_data_t* data) {
- if (!pn_data_next(data)) throw conversion_error("no more data");
- type_id t = type_id(pn_data_type(data));
+type_id decoder::pre_get() {
+ if (!next()) throw conversion_error("no more data");
+ type_id t = type_id(pn_data_type(pn_object()));
if (t < 0) throw conversion_error("invalid data");
return t;
}
+namespace {
+
template <class T, class U> void assign(T& x, const U& y) { x = y; }
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); }
-// Simple extract with no type conversion.
-template <class T, class U> void extract(pn_data_t* data, T& x, U (*get)(pn_data_t*)) {
- save_state ss(data);
- bad_type(type_id_of<T>::value, pre_get(data));
- assign(x, get(data));
- ss.cancel(); // No error, no rewind
-}
+} // namespace
-}
-void decoder::check_type(type_id want) {
- type_id got = type();
- if (want != got) bad_type(want, got);
+// Simple extract with no type conversion.
+template <class T, class U> void decoder::extract(T& x, U (*get)(pn_data_t*)) {
+ state_guard sg(*this);
+ assert_type_equal(type_id_of<T>::value, pre_get());
+ assign(x, get(pn_object()));
+ sg.cancel(); // No error, cancel the reset.
}
-type_id decoder::type() const {
- save_state ss(pn_object());
- return pre_get(pn_object());
+type_id decoder::next_type() {
+ state_guard sg(*this);
+ return pre_get();
}
-decoder decoder::operator>>(start& s) {
- pn_data_t* d = pn_object();
- save_state ss(d);
- s.type = pre_get(d);
+decoder& decoder::operator>>(start& s) {
+ state_guard sg(*this);
+ s.type = pre_get();
switch (s.type) {
case ARRAY:
- s.size = pn_data_get_array(d);
- s.element = type_id(pn_data_get_array_type(d)); s.is_described = pn_data_is_array_described(d);
+ s.size = pn_data_get_array(pn_object());
+ s.element = type_id(pn_data_get_array_type(pn_object())); s.is_described = pn_data_is_array_described(pn_object());
break;
case LIST:
- s.size = pn_data_get_list(d);
+ s.size = pn_data_get_list(pn_object());
break;
case MAP:
- s.size = pn_data_get_map(d);
+ s.size = pn_data_get_map(pn_object());
break;
case DESCRIBED:
s.is_described = true;
@@ -147,41 +118,36 @@ decoder decoder::operator>>(start& s) {
default:
throw conversion_error(MSG("" << s.type << " is not a container type"));
}
- pn_data_enter(d);
- ss.cancel();
+ pn_data_enter(pn_object());
+ sg.cancel();
return *this;
}
-// FIXME aconway 2016-03-08: remove
-decoder decoder::operator>>(struct finish) { pn_data_exit(pn_object()); return *this; }
-
-decoder decoder::operator>>(struct skip) { pn_data_next(pn_object()); return *this; }
-
-decoder decoder::operator>>(struct assert_type a) { bad_type(a.type, type()); return *this; }
-
-decoder decoder::operator>>(struct rewind) { rewind(); return *this; }
+decoder& decoder::operator>>(const finish&) {
+ pn_data_exit(pn_object());
+ return *this;
+}
-decoder decoder::operator>>(null&) {
- save_state ss(pn_object());
- bad_type(NULL_TYPE, pre_get(pn_object()));
+decoder& decoder::operator>>(null&) {
+ state_guard sg(*this);
+ assert_type_equal(NULL_TYPE, pre_get());
return *this;
}
-decoder decoder::operator>>(value& v) {
- data mine(pn_object());
- if (mine == v.data_)
+decoder& decoder::operator>>(value& v) {
+ if (*this == v.data_)
throw conversion_error("extract into self");
v.clear();
{
- narrow n(pn_object());
- check(v.data().appendn(mine, 1));
+ narrow_guard n(*this);
+ check(v.data().appendn(pn_object(), 1));
}
- if (!mine.next()) throw conversion_error("no more data");
+ next();
return *this;
}
-decoder decoder::operator>>(message_id& x) {
- switch (type()) {
+decoder& decoder::operator>>(message_id& x) {
+ switch (next_type()) {
case ULONG:
case UUID:
case BINARY:
@@ -189,209 +155,190 @@ decoder decoder::operator>>(message_id& x) {
return *this >> x.scalar_;
default:
throw conversion_error(
- msg() << "expected one of ulong, uuid, binary or string but found " << type());
+ msg() << "expected one of ulong, uuid, binary or string but found " << next_type());
};
}
-decoder decoder::operator>>(annotation_key& x) {
- switch (type()) {
+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(type()));
+ throw conversion_error("expected one of ulong or symbol but found " + type_name(next_type()));
};
}
-decoder decoder::operator>>(scalar& x) {
- save_state ss(pn_object());
- type_id got = pre_get(pn_object());
+decoder& decoder::operator>>(scalar& x) {
+ state_guard sg(*this);
+ type_id got = pre_get();
if (!type_id_is_scalar(got))
throw conversion_error("expected scalar, found "+type_name(got));
x.set(pn_data_get_atom(pn_object()));
- ss.cancel(); // No error, no rewind
+ sg.cancel(); // No error, no rewind
return *this;
}
-decoder decoder::operator>>(amqp::boolean_type &x) {
- extract(pn_object(), x, pn_data_get_bool);
+decoder& decoder::operator>>(bool &x) {
+ extract(x, pn_data_get_bool);
return *this;
}
-decoder decoder::operator>>(amqp::ubyte_type &x) {
- pn_data_t* d = pn_object();
- save_state ss(d);
- switch (pre_get(d)) {
- case UBYTE: x = pn_data_get_ubyte(d); break;
- default: bad_type(UBYTE, type_id(type_id(pn_data_type(d))));
+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()))));
}
- ss.cancel();
+ sg.cancel();
return *this;
}
-decoder decoder::operator>>(amqp::byte_type &x) {
- pn_data_t* d = pn_object();
- save_state ss(d);
- switch (pre_get(d)) {
- case BYTE: x = pn_data_get_byte(d); break;
- default: bad_type(BYTE, type_id(type_id(pn_data_type(d))));
+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()))));
}
- ss.cancel();
+ sg.cancel();
return *this;
}
-decoder decoder::operator>>(amqp::ushort_type &x) {
- pn_data_t* d = pn_object();
- save_state ss(d);
- switch (pre_get(d)) {
- case UBYTE: x = pn_data_get_ubyte(d); break;
- case USHORT: x = pn_data_get_ushort(d); break;
- default: bad_type(USHORT, type_id(type_id(pn_data_type(d))));
+decoder& decoder::operator>>(uint16_t &x) {
+ state_guard sg(*this);
+ switch (pre_get()) {
+ 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()))));
}
- ss.cancel();
+ sg.cancel();
return *this;
}
-decoder decoder::operator>>(amqp::short_type &x) {
- pn_data_t* d = pn_object();
- save_state ss(d);
- switch (pre_get(d)) {
- case BYTE: x = pn_data_get_byte(d); break;
- case SHORT: x = pn_data_get_short(d); break;
- default: bad_type(SHORT, type_id(pn_data_type(d)));
+decoder& decoder::operator>>(int16_t &x) {
+ state_guard sg(*this);
+ switch (pre_get()) {
+ 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())));
}
- ss.cancel();
+ sg.cancel();
return *this;
}
-decoder decoder::operator>>(amqp::uint_type &x) {
- pn_data_t* d = pn_object();
- save_state ss(d);
- switch (pre_get(d)) {
- case UBYTE: x = pn_data_get_ubyte(d); break;
- case USHORT: x = pn_data_get_ushort(d); break;
- case UINT: x = pn_data_get_uint(d); break;
- default: bad_type(UINT, type_id(pn_data_type(d)));
+decoder& decoder::operator>>(uint32_t &x) {
+ state_guard sg(*this);
+ switch (pre_get()) {
+ 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())));
}
- ss.cancel();
+ sg.cancel();
return *this;
}
-decoder decoder::operator>>(amqp::int_type &x) {
- pn_data_t* d = pn_object();
- save_state ss(d);
- switch (pre_get(d)) {
- case BYTE: x = pn_data_get_byte(d); break;
- case SHORT: x = pn_data_get_short(d); break;
- case INT: x = pn_data_get_int(d); break;
- default: bad_type(INT, type_id(pn_data_type(d)));
+decoder& decoder::operator>>(int32_t &x) {
+ state_guard sg(*this);
+ switch (pre_get()) {
+ 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())));
}
- ss.cancel();
+ sg.cancel();
return *this;
}
-decoder decoder::operator>>(amqp::ulong_type &x) {
- pn_data_t* d = pn_object();
- save_state ss(d);
- switch (pre_get(d)) {
- case UBYTE: x = pn_data_get_ubyte(d); break;
- case USHORT: x = pn_data_get_ushort(d); break;
- case UINT: x = pn_data_get_uint(d); break;
- case ULONG: x = pn_data_get_ulong(d); break;
- default: bad_type(ULONG, type_id(pn_data_type(d)));
+decoder& decoder::operator>>(uint64_t &x) {
+ state_guard sg(*this);
+ switch (pre_get()) {
+ 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())));
}
- ss.cancel();
+ sg.cancel();
return *this;
}
-decoder decoder::operator>>(amqp::long_type &x) {
- pn_data_t* d = pn_object();
- save_state ss(d);
- switch (pre_get(d)) {
- case BYTE: x = pn_data_get_byte(d); break;
- case SHORT: x = pn_data_get_short(d); break;
- case INT: x = pn_data_get_int(d); break;
- case LONG: x = pn_data_get_long(d); break;
- default: bad_type(LONG, type_id(pn_data_type(d)));
+decoder& decoder::operator>>(int64_t &x) {
+ state_guard sg(*this);
+ switch (pre_get()) {
+ 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())));
}
- ss.cancel();
+ sg.cancel();
return *this;
}
-decoder decoder::operator>>(amqp::char_type &x) {
- extract(pn_object(), x, pn_data_get_char);
+decoder& decoder::operator>>(wchar_t &x) {
+ extract(x, pn_data_get_char);
return *this;
}
-decoder decoder::operator>>(timestamp &x) {
- extract(pn_object(), x, pn_data_get_timestamp);
+decoder& decoder::operator>>(timestamp &x) {
+ extract(x, pn_data_get_timestamp);
return *this;
}
-decoder decoder::operator>>(amqp::float_type &x) {
- pn_data_t* d = pn_object();
- save_state ss(d);
- switch (pre_get(d)) {
- case FLOAT: x = pn_data_get_float(d); break;
- case DOUBLE: x = float(pn_data_get_double(d)); break;
- default: bad_type(FLOAT, type_id(pn_data_type(d)));
+decoder& decoder::operator>>(float &x) {
+ state_guard sg(*this);
+ switch (pre_get()) {
+ 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())));
}
- ss.cancel();
+ sg.cancel();
return *this;
}
-decoder decoder::operator>>(amqp::double_type &x) {
- pn_data_t* d = pn_object();
- save_state ss(d);
- switch (pre_get(d)) {
- case FLOAT: x = pn_data_get_float(d); break;
- case DOUBLE: x = pn_data_get_double(d); break;
- default: bad_type(DOUBLE, type_id(pn_data_type(d)));
+decoder& decoder::operator>>(double &x) {
+ state_guard sg(*this);
+ switch (pre_get()) {
+ 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())));
}
- ss.cancel();
+ sg.cancel();
return *this;
}
-decoder decoder::operator>>(decimal32 &x) {
- extract(pn_object(), x, pn_data_get_decimal32);
+decoder& decoder::operator>>(decimal32 &x) {
+ extract(x, pn_data_get_decimal32);
return *this;
}
-decoder decoder::operator>>(decimal64 &x) {
- extract(pn_object(), x, pn_data_get_decimal64);
+decoder& decoder::operator>>(decimal64 &x) {
+ extract(x, pn_data_get_decimal64);
return *this;
}
-decoder decoder::operator>>(decimal128 &x) {
- extract(pn_object(), x, pn_data_get_decimal128);
+decoder& decoder::operator>>(decimal128 &x) {
+ extract(x, pn_data_get_decimal128);
return *this;
}
-decoder decoder::operator>>(uuid &x) {
- extract(pn_object(), x, pn_data_get_uuid);
+decoder& decoder::operator>>(uuid &x) {
+ extract(x, pn_data_get_uuid);
return *this;
}
-decoder decoder::operator>>(std::string &x) {
- pn_data_t* d = pn_object();
- save_state ss(d);
- switch (pre_get(d)) {
- case STRING: x = str(pn_data_get_string(d)); break;
- case BINARY: x = str(pn_data_get_binary(d)); break;
- case SYMBOL: x = str(pn_data_get_symbol(d)); break;
- default: bad_type(STRING, type_id(pn_data_type(d)));
+decoder& decoder::operator>>(std::string &x) {
+ state_guard sg(*this);
+ switch (pre_get()) {
+ case STRING: x = str(pn_data_get_string(pn_object())); break;
+ case BINARY: x = str(pn_data_get_binary(pn_object())); break;
+ case SYMBOL: x = str(pn_data_get_symbol(pn_object())); break;
+ default: assert_type_equal(STRING, type_id(pn_data_type(pn_object())));
}
- ss.cancel();
+ sg.cancel();
return *this;
}
-void assert_map_scope(const scope& s) {
- if (s.type != MAP)
- throw conversion_error("cannot decode "+type_name(s.type)+" as map");
- if (s.size % 2 != 0)
- throw conversion_error("odd number of elements in map");
-}
-
-
-} // internal
+} // codec
} // proton
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/src/duration.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/duration.cpp b/proton-c/bindings/cpp/src/duration.cpp
index 6becb99..15c3369 100644
--- a/proton-c/bindings/cpp/src/duration.cpp
+++ b/proton-c/bindings/cpp/src/duration.cpp
@@ -31,12 +31,6 @@ const duration duration::IMMEDIATE(0);
const duration duration::SECOND(1000);
const duration duration::MINUTE(SECOND * 60);
-std::ostream& operator<<(std::ostream& o, timestamp ts) {
- return o << "timestamp:" << ts.ms() << "ms";
-}
-
-std::ostream& operator<<(std::ostream& o, duration d) {
- return o << d.ms() << "ms";
-}
+std::ostream& operator<<(std::ostream& o, duration d) { return o << d.ms(); }
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/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 7db2a99..a8322c8 100644
--- a/proton-c/bindings/cpp/src/encoder.cpp
+++ b/proton-c/bindings/cpp/src/encoder.cpp
@@ -17,44 +17,39 @@
* under the License.
*/
-#include "proton/amqp.hpp"
-#include "proton/annotation_key.hpp"
-#include "proton/binary.hpp"
-#include "proton/data.hpp"
-#include "proton/decimal.hpp"
-#include "proton/encoder.hpp"
-#include "proton/message_id.hpp"
-#include "proton/symbol.hpp"
-#include "proton/value.hpp"
-
#include "proton_bits.hpp"
#include "types_internal.hpp"
#include "msg.hpp"
+#include <proton/annotation_key.hpp>
+#include <proton/binary.hpp>
+#include <proton/data.hpp>
+#include <proton/decimal.hpp>
+#include <proton/encoder.hpp>
+#include <proton/message_id.hpp>
+#include <proton/symbol.hpp>
+#include <proton/timestamp.hpp>
+#include <proton/value.hpp>
+
#include <proton/codec.h>
#include <algorithm>
namespace proton {
-namespace internal {
+namespace codec {
-namespace {
-struct save_state {
- pn_data_t* data;
- pn_handle_t handle;
- save_state(pn_data_t* d) : data(d), handle(pn_data_point(d)) {}
- ~save_state() { if (data) pn_data_restore(data, handle); }
- void cancel() { data = 0; }
-};
-
-void check(long result, pn_data_t* data) {
+void encoder::check(long result) {
if (result < 0)
- throw conversion_error(error_str(pn_data_error(data), result));
+ throw conversion_error(error_str(pn_data_error(pn_object()), result));
}
+
+
+encoder::encoder(value& v) : data(v.data()) {
+ clear();
}
bool encoder::encode(char* buffer, size_t& size) {
- save_state ss(pn_object()); // In case of error
+ state_guard sg(*this); // In case of error
ssize_t result = pn_data_encode(pn_object(), buffer, size);
if (result == PN_OVERFLOW) {
result = pn_data_encoded_size(pn_object());
@@ -63,9 +58,9 @@ bool encoder::encode(char* buffer, size_t& size) {
return false;
}
}
- check(result, pn_object());
+ check(result);
size = size_t(result);
- ss.cancel(); // Don't restore state, all is well.
+ sg.cancel(); // Don't restore state, all is well.
pn_data_clear(pn_object());
return true;
}
@@ -85,7 +80,7 @@ std::string encoder::encode() {
return s;
}
-encoder encoder::operator<<(const start& s) {
+encoder& encoder::operator<<(const start& s) {
switch (s.type) {
case ARRAY: pn_data_put_array(pn_object(), s.is_described, pn_type_t(s.element)); break;
case MAP: pn_data_put_map(pn_object()); break;
@@ -98,7 +93,7 @@ encoder encoder::operator<<(const start& s) {
return *this;
}
-encoder encoder::operator<<(const finish&) {
+encoder& encoder::operator<<(const finish&) {
pn_data_exit(pn_object());
return *this;
}
@@ -111,63 +106,51 @@ template <> pn_decimal32_t convert(const decimal32 &x) { pn_decimal32_t y; byte_
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>
-encoder do_put(encoder e, pn_data_t* data, const T& x, int (*put)(pn_data_t*, U)) {
- save_state ss(data); // Save state in case of error.
- check(put(data, convert<U>(x)), data);
- ss.cancel(); // Don't restore state, all is good.
- return e;
-}
+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)); }
+int pn_data_put_amqp_symbol(pn_data_t *d, const symbol& x) { return pn_data_put_symbol(d, pn_bytes(x)); }
+} // namespace
-int pn_data_put_amqp_string(pn_data_t *d, const amqp::string_type& x) { return pn_data_put_string(d, pn_bytes(x)); }
-int pn_data_put_amqp_binary(pn_data_t *d, const amqp::binary_type& x) { return pn_data_put_binary(d, pn_bytes(x)); }
-int pn_data_put_amqp_symbol(pn_data_t *d, const amqp::symbol_type& x) { return pn_data_put_symbol(d, pn_bytes(x)); }
-}
-
-encoder encoder::operator<<(bool x) { return do_put(*this, pn_object(), x, pn_data_put_bool); }
-encoder encoder::operator<<(uint8_t x) { return do_put(*this, pn_object(), x, pn_data_put_ubyte); }
-encoder encoder::operator<<(int8_t x) { return do_put(*this, pn_object(), x, pn_data_put_byte); }
-encoder encoder::operator<<(uint16_t x) { return do_put(*this, pn_object(), x, pn_data_put_ushort); }
-encoder encoder::operator<<(int16_t x) { return do_put(*this, pn_object(), x, pn_data_put_short); }
-encoder encoder::operator<<(uint32_t x) { return do_put(*this, pn_object(), x, pn_data_put_uint); }
-encoder encoder::operator<<(int32_t x) { return do_put(*this, pn_object(), x, pn_data_put_int); }
-encoder encoder::operator<<(wchar_t x) { return do_put(*this, pn_object(), x, pn_data_put_char); }
-encoder encoder::operator<<(uint64_t x) { return do_put(*this, pn_object(), x, pn_data_put_ulong); }
-encoder encoder::operator<<(int64_t x) { return do_put(*this, pn_object(), x, pn_data_put_long); }
-encoder encoder::operator<<(timestamp x) { return do_put(*this, pn_object(), x.ms(), pn_data_put_timestamp); }
-encoder encoder::operator<<(float x) { return do_put(*this, pn_object(), x, pn_data_put_float); }
-encoder encoder::operator<<(double x) { return do_put(*this, pn_object(), x, pn_data_put_double); }
-encoder encoder::operator<<(decimal32 x) { return do_put(*this, pn_object(), x, pn_data_put_decimal32); }
-encoder encoder::operator<<(decimal64 x) { return do_put(*this, pn_object(), x, pn_data_put_decimal64); }
-encoder encoder::operator<<(decimal128 x) { return do_put(*this, pn_object(), x, pn_data_put_decimal128); }
-encoder encoder::operator<<(const uuid& x) { return do_put(*this, pn_object(), x, pn_data_put_uuid); }
-encoder encoder::operator<<(const std::string& x) { return do_put(*this, pn_object(), x, pn_data_put_amqp_string); }
-encoder encoder::operator<<(const symbol& x) { return do_put(*this, pn_object(), x, pn_data_put_amqp_symbol); }
-encoder encoder::operator<<(const binary& x) { return do_put(*this, pn_object(), x, pn_data_put_amqp_binary); }
-
-encoder encoder::operator<<(const scalar& x) { return do_put(*this, pn_object(), x.atom_, pn_data_put_atom); }
-
-encoder encoder::operator<<(const null&) {
- save_state ss(pn_object()); // Save state in case of error.
- check(pn_data_put_null(pn_object()), pn_object());
- ss.cancel(); // Don't restore state, all is good.
+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)));
+ sg.cancel(); // Don't restore state, all is good.
return *this;
}
-void encoder::insert(const value& v) {
- data mine(pn_object());
- if (mine == v.data_)
+encoder& encoder::operator<<(bool x) { return insert(x, pn_data_put_bool); }
+encoder& encoder::operator<<(uint8_t x) { return insert(x, pn_data_put_ubyte); }
+encoder& encoder::operator<<(int8_t x) { return insert(x, pn_data_put_byte); }
+encoder& encoder::operator<<(uint16_t x) { return insert(x, pn_data_put_ushort); }
+encoder& encoder::operator<<(int16_t x) { return insert(x, pn_data_put_short); }
+encoder& encoder::operator<<(uint32_t x) { return insert(x, pn_data_put_uint); }
+encoder& encoder::operator<<(int32_t x) { return insert(x, pn_data_put_int); }
+encoder& encoder::operator<<(wchar_t x) { return insert(x, pn_data_put_char); }
+encoder& encoder::operator<<(uint64_t x) { return insert(x, pn_data_put_ulong); }
+encoder& encoder::operator<<(int64_t x) { return insert(x, pn_data_put_long); }
+encoder& encoder::operator<<(timestamp x) { return insert(x.ms(), pn_data_put_timestamp); }
+encoder& encoder::operator<<(float x) { return insert(x, pn_data_put_float); }
+encoder& encoder::operator<<(double x) { return insert(x, pn_data_put_double); }
+encoder& encoder::operator<<(decimal32 x) { return insert(x, pn_data_put_decimal32); }
+encoder& encoder::operator<<(decimal64 x) { return insert(x, pn_data_put_decimal64); }
+encoder& encoder::operator<<(decimal128 x) { return insert(x, pn_data_put_decimal128); }
+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 scalar& x) { return insert(x.atom_, pn_data_put_atom); }
+
+encoder& encoder::operator<<(exact_cref<value> x) {
+ if (*this == x.ref.data_)
throw conversion_error("cannot insert into self");
- if (v.empty()) {
+ if (x.ref.empty())
pn_data_put_null(pn_object());
- } else {
- v.decode(); // Rewind
- check(mine.append(v.data()), pn_object());
- }
+ decoder d(x.ref); // Rewind
+ check(append(d));
+ return *this;
}
-std::ostream& operator<<(std::ostream& o, const encoder& e) {
- return o << data(e.pn_object());
-}
-}
-}
+} // codec
+} // proton
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/src/engine_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/engine_test.cpp b/proton-c/bindings/cpp/src/engine_test.cpp
index d386d6d..a10842a 100644
--- a/proton-c/bindings/cpp/src/engine_test.cpp
+++ b/proton-c/bindings/cpp/src/engine_test.cpp
@@ -23,7 +23,7 @@
#include <proton/connection_engine.hpp>
#include <proton/handler.hpp>
#include <proton/event.hpp>
-#include <proton/types.hpp>
+#include <proton/types_fwd.hpp>
#include <proton/link.hpp>
#include <deque>
#include <algorithm>
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/src/id_generator.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/id_generator.hpp b/proton-c/bindings/cpp/src/id_generator.hpp
index 867d827..f3df1e8 100644
--- a/proton-c/bindings/cpp/src/id_generator.hpp
+++ b/proton-c/bindings/cpp/src/id_generator.hpp
@@ -18,7 +18,7 @@
*/
///@internal
-#include "proton/types.hpp"
+#include "proton/types_fwd.hpp"
#ifndef ID_GENERATOR_HPP
#define ID_GENERATOR_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/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 083e0bc..b05c098 100644
--- a/proton-c/bindings/cpp/src/interop_test.cpp
+++ b/proton-c/bindings/cpp/src/interop_test.cpp
@@ -19,8 +19,8 @@
#include "proton/decoder.hpp"
#include "proton/encoder.hpp"
+#include "proton/error.hpp"
#include "proton/value.hpp"
-#include "proton/amqp.hpp"
#include "test_bits.hpp"
#include <string>
#include <sstream>
@@ -30,7 +30,7 @@
using namespace std;
using namespace proton;
-using namespace proton::internal;
+using namespace proton::codec;
using namespace test;
std::string tests_dir;
@@ -43,23 +43,25 @@ string read(string filename) {
}
template <class T> T get(decoder& d) {
+ assert_type_equal(type_id_of<T>::value, d.next_type());
T v;
- d >> assert_type(type_id_of<T>::value) >> v;
+ d >> v;
return v;
}
// Test data ostream operator
void test_data_ostream() {
value dv;
- dv.decode().decode(read("primitives"));
+ decoder d(dv);
+ d.decode(read("primitives"));
ASSERT_EQUAL("true, false, 42, 42, -42, 12345, -12345, 12345, -12345, 0.125, 0.125", str(dv));
}
// Test extracting to exact AMQP types works corectly, extrating to invalid types fails.
void test_decoder_primitves_exact() {
value dv;
- dv.decode().decode(read("primitives"));
- decoder d(dv.decode());
+ decoder d(dv);
+ d.decode(read("primitives"));
ASSERT(d.more());
try { get< ::int8_t>(d); FAIL("got bool as byte"); } catch(conversion_error){}
ASSERT_EQUAL(true, get<bool>(d));
@@ -84,7 +86,7 @@ void test_decoder_primitves_exact() {
// Test inserting primitive sand encoding as AMQP.
void test_encoder_primitives() {
value dv;
- encoder e = dv.encode();
+ encoder e(dv);
e << true << false;
e << ::uint8_t(42);
e << ::uint16_t(42) << ::int16_t(-42);
@@ -100,11 +102,11 @@ void test_encoder_primitives() {
void test_value_conversions() {
value v;
ASSERT_EQUAL(true, (v=true).get<bool>());
- ASSERT_EQUAL(2, (v=amqp::byte_type(2)).get<int>());
- ASSERT_EQUAL(3, (v=amqp::byte_type(3)).get<long>());
- ASSERT_EQUAL(3, (v=amqp::byte_type(3)).get<long>());
- ASSERT_EQUAL(1.0, (v=amqp::float_type(1.0)).get<double>());
- ASSERT_EQUAL(1.0, (v=amqp::double_type(1.0)).get<float>());
+ 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) {}
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/src/link_options.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/link_options.cpp b/proton-c/bindings/cpp/src/link_options.cpp
index dd0febb..534a6b6 100644
--- a/proton-c/bindings/cpp/src/link_options.cpp
+++ b/proton-c/bindings/cpp/src/link_options.cpp
@@ -108,13 +108,13 @@ class link_options::impl {
if (lifetime_policy.set) lp = lifetime_policy_symbol(lifetime_policy.value);
if (!sender && distribution_mode.set) dm = distribution_mode_symbol(distribution_mode.value);
if (lp.size() || dm.size()) {
- internal::encoder enc = t.node_properties().encode();
- enc << internal::start::map();
+ codec::encoder enc(t.node_properties());
+ enc << codec::start::map();
if (dm.size())
enc << symbol("supported-dist-modes") << std::string(dm);
if (lp.size())
- enc << symbol("lifetime-policy") << internal::start::described()
- << symbol(lp) << internal::start::list() << internal::finish();
+ enc << symbol("lifetime-policy") << codec::start::described()
+ << symbol(lp) << codec::start::list() << codec::finish();
}
}
}
@@ -126,9 +126,9 @@ class link_options::impl {
l.local_source().expiry_policy(terminus::EXPIRE_NEVER);
}
if (selector.set && selector.value.size()) {
- internal::encoder enc = l.local_source().filter().encode();
- enc << internal::start::map() << symbol("selector") << internal::start::described()
- << symbol("apache.org:selector-filter:string") << binary(selector.value) << internal::finish();
+ codec::encoder enc(l.local_source().filter());
+ enc << codec::start::map() << symbol("selector") << codec::start::described()
+ << symbol("apache.org:selector-filter:string") << binary(selector.value) << codec::finish();
}
}
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/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 2b793f8..6d95256 100644
--- a/proton-c/bindings/cpp/src/message.cpp
+++ b/proton-c/bindings/cpp/src/message.cpp
@@ -19,16 +19,17 @@
*
*/
-#include "proton/data.hpp"
-#include "proton/message.hpp"
+#include "proton/delivery.hpp"
#include "proton/error.hpp"
#include "proton/link.hpp"
-#include "proton/delivery.hpp"
-#include "proton/message.h"
-#include "proton/sender.hpp"
-#include "proton/receiver.hpp"
+#include "proton/message.hpp"
#include "proton/message_id.hpp"
-#include "proton/delivery.h"
+#include "proton/receiver.hpp"
+#include "proton/sender.hpp"
+#include "proton/timestamp.hpp"
+
+#include "proton/message.h"
+
#include "msg.hpp"
#include "proton_bits.hpp"
#include "types_internal.hpp"
@@ -46,8 +47,10 @@ message::message(const message &m) : pn_msg_(0) { *this = m; }
message::message(message &&m) : pn_msg_(0) { swap(*this, m); }
#endif
+message::message(const value& x) : pn_msg_(0) { body() = x; }
+
message::~message() {
- body_.data_ = internal::data(0); // Must release body before pn_message_free
+ body_.data_ = codec::data(0); // Must release body before pn_message_free
pn_message_free(pn_msg_);
}
@@ -126,7 +129,8 @@ std::string message::reply_to() const {
}
void message::correlation_id(const message_id& id) {
- internal::data(pn_message_correlation_id(pn_msg())).copy(id.scalar_);
+ codec::encoder e(pn_message_correlation_id(pn_msg()));
+ e << id.scalar_;
}
message_id message::correlation_id() const {
@@ -187,6 +191,8 @@ bool message::inferred() const { return pn_message_is_inferred(pn_msg()); }
void message::inferred(bool b) { pn_message_set_inferred(pn_msg(), b); }
+void message::body(const value& x) { body() = x; }
+
const value& message::body() const { pn_msg(); return body_; }
value& message::body() { pn_msg(); return body_; }
@@ -197,9 +203,10 @@ value& message::body() { pn_msg(); return body_; }
// Decode a map on demand
template<class M> M& get_map(pn_message_t* msg, pn_data_t* (*get)(pn_message_t*), M& map) {
- internal::data d(get(msg));
+ codec::decoder d(get(msg));
if (map.empty() && !d.empty()) {
- d.decoder() >> internal::rewind() >> map;
+ d.rewind();
+ d >> map;
d.clear(); // The map member is now the authority.
}
return map;
@@ -207,10 +214,10 @@ template<class M> M& get_map(pn_message_t* msg, pn_data_t* (*get)(pn_message_t*)
// Encode a map if necessary.
template<class M> M& put_map(pn_message_t* msg, pn_data_t* (*get)(pn_message_t*), M& map) {
- internal::data d(get(msg));
- if (d.empty() && !map.empty()) {
- d.encoder() << map;
- map.clear(); // The encoded pn_data_t is now the authority.
+ codec::encoder e(get(msg));
+ if (e.empty() && !map.empty()) {
+ e << map;
+ map.clear(); // The encoded pn_data_t is now the authority.
}
return map;
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/src/msg.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/msg.hpp b/proton-c/bindings/cpp/src/msg.hpp
index 66c01cb..b24b25c 100644
--- a/proton-c/bindings/cpp/src/msg.hpp
+++ b/proton-c/bindings/cpp/src/msg.hpp
@@ -43,7 +43,7 @@ struct msg {
msg(const msg& m) : os(m.str()) {}
std::string str() const { return os.str(); }
operator std::string() const { return str(); }
- template <class T> msg& operator<<(const T& t) { os <<t; return *this; }
+ template <class T> msg& operator<<(const T& t) { os << t; return *this; }
};
inline std::ostream& operator<<(std::ostream& o, const msg& m) { return o << m.str(); }
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/src/posix/io.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/posix/io.cpp b/proton-c/bindings/cpp/src/posix/io.cpp
index a85972a..be9db44 100644
--- a/proton-c/bindings/cpp/src/posix/io.cpp
+++ b/proton-c/bindings/cpp/src/posix/io.cpp
@@ -18,10 +18,12 @@
*/
#include "msg.hpp"
+
#include <proton/io.hpp>
#include <proton/url.hpp>
#include <errno.h>
+#include <string.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/socket.h>
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/src/reactor.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/reactor.hpp b/proton-c/bindings/cpp/src/reactor.hpp
index 6022e7e..3aac8f8 100644
--- a/proton-c/bindings/cpp/src/reactor.hpp
+++ b/proton-c/bindings/cpp/src/reactor.hpp
@@ -28,6 +28,7 @@
#include "proton/timestamp.hpp"
struct pn_reactor_t;
+struct pn_handler_t;
struct pn_io_t;
namespace proton {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/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
index 04e5318..2cda8af 100644
--- a/proton-c/bindings/cpp/src/scalar.cpp
+++ b/proton-c/bindings/cpp/src/scalar.cpp
@@ -43,6 +43,7 @@ scalar& scalar::operator=(const scalar& x) {
}
type_id scalar::type() const { return type_id(atom_.type); }
+
bool scalar::empty() const { return type() == NULL_TYPE; }
void scalar::set(const std::string& x, pn_type_t t) {
@@ -58,6 +59,28 @@ void scalar::set(const pn_atom_t& atom) {
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; }
@@ -193,7 +216,7 @@ template <class T, class F> T type_switch(const scalar& a, F f) {
case STRING: return f(a.get<std::string>());
case SYMBOL: return f(a.get<symbol>());
default:
- throw error("bad scalar type");
+ throw std::logic_error("bad proton::scalar type");
}
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/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 2949dcb..9b2df1f 100644
--- a/proton-c/bindings/cpp/src/scalar_test.cpp
+++ b/proton-c/bindings/cpp/src/scalar_test.cpp
@@ -19,8 +19,8 @@
#include "test_bits.hpp"
-#include "proton/amqp.hpp"
#include "proton/binary.hpp"
+#include "proton/error.hpp"
#include "proton/type_traits.hpp"
#include <proton/scalar.hpp>
@@ -126,25 +126,25 @@ template <class T> T make(const char c) { T x; std::fill(x.begin(), x.end(), c);
int main(int, char**) {
int failed = 0;
RUN_TEST(failed, type_test(false, BOOLEAN, true));
- RUN_TEST(failed, type_test(amqp::ubyte_type(42), UBYTE, amqp::ubyte_type(50)));
- RUN_TEST(failed, type_test(amqp::byte_type('x'), BYTE, amqp::byte_type('y')));
- RUN_TEST(failed, type_test(amqp::ushort_type(4242), USHORT, amqp::ushort_type(5252)));
- RUN_TEST(failed, type_test(amqp::short_type(-4242), SHORT, amqp::short_type(3)));
- RUN_TEST(failed, type_test(amqp::uint_type(4242), UINT, amqp::uint_type(5252)));
- RUN_TEST(failed, type_test(amqp::int_type(-4242), INT, amqp::int_type(3)));
- RUN_TEST(failed, type_test(amqp::ulong_type(4242), ULONG, amqp::ulong_type(5252)));
- RUN_TEST(failed, type_test(amqp::long_type(-4242), LONG, amqp::long_type(3)));
+ RUN_TEST(failed, type_test(uint8_t(42), UBYTE, uint8_t(50)));
+ RUN_TEST(failed, type_test(int8_t('x'), BYTE, int8_t('y')));
+ RUN_TEST(failed, type_test(uint16_t(4242), USHORT, uint16_t(5252)));
+ RUN_TEST(failed, type_test(int16_t(-4242), SHORT, int16_t(3)));
+ RUN_TEST(failed, type_test(uint32_t(4242), UINT, uint32_t(5252)));
+ RUN_TEST(failed, type_test(int32_t(-4242), INT, int32_t(3)));
+ RUN_TEST(failed, type_test(uint64_t(4242), ULONG, uint64_t(5252)));
+ RUN_TEST(failed, type_test(int64_t(-4242), LONG, int64_t(3)));
RUN_TEST(failed, type_test(wchar_t(23), CHAR, wchar_t(24)));
- RUN_TEST(failed, type_test(amqp::float_type(1.234), FLOAT, amqp::float_type(2.345)));
- RUN_TEST(failed, type_test(amqp::double_type(11.2233), DOUBLE, amqp::double_type(12)));
+ RUN_TEST(failed, type_test(float(1.234), FLOAT, float(2.345)));
+ RUN_TEST(failed, type_test(double(11.2233), DOUBLE, double(12)));
RUN_TEST(failed, type_test(timestamp(0), TIMESTAMP, timestamp(1)));
RUN_TEST(failed, type_test(make<decimal32>(0), DECIMAL32, make<decimal32>(1)));
RUN_TEST(failed, type_test(make<decimal64>(0), DECIMAL64, make<decimal64>(1)));
RUN_TEST(failed, type_test(make<decimal128>(0), DECIMAL128, make<decimal128>(1)));
- RUN_TEST(failed, type_test(uuid::make("a"), UUID, uuid::make("x")));
- RUN_TEST(failed, type_test(amqp::string_type("aaa"), STRING, amqp::string_type("aaaa")));
- RUN_TEST(failed, type_test(amqp::symbol_type("aaa"), SYMBOL, amqp::symbol_type("aaaa")));
- RUN_TEST(failed, type_test(amqp::binary_type("aaa"), BINARY, amqp::binary_type("aaaa")));
+ RUN_TEST(failed, type_test(uuid::copy("a"), UUID, uuid::copy("x")));
+ RUN_TEST(failed, type_test(std::string("aaa"), STRING, std::string("aaaa")));
+ RUN_TEST(failed, type_test(symbol("aaa"), SYMBOL, symbol("aaaa")));
+ RUN_TEST(failed, type_test(binary("aaa"), BINARY, binary("aaaa")));
RUN_TEST(failed, type_test(std::string("xxx"), STRING, std::string("yyy")));
RUN_TEST(failed, encode_decode_test());
RUN_TEST(failed, message_id_test());
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/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 f6297da..d45739c 100644
--- a/proton-c/bindings/cpp/src/test_bits.hpp
+++ b/proton-c/bindings/cpp/src/test_bits.hpp
@@ -19,13 +19,13 @@
* under the License.
*/
+#include "msg.hpp"
+#include <proton/types.hpp>
+
#include <stdexcept>
#include <iostream>
-#include <vector>
-#include <deque>
#include <iterator>
#include <sstream>
-#include "msg.hpp"
namespace test {
@@ -59,15 +59,17 @@ template<class T> std::string str(const T& x) { std::ostringstream s; s << x; re
template <class T> struct many : public std::vector<T> {
many() {}
template<class S> explicit many(const S& s) : std::vector<T>(s.begin(), s.end()) {}
- many operator+(const T& t) { many<T> l(*this); l.push_back(t); return l; }
+ many& operator+=(const T& t) { this->push_back(t); return *this; }
+ many& operator<<(const T& t) { return *this += t; }
+ many operator+(const T& t) { many<T> l(*this); return l += t; }
};
template <class T, class S> bool operator==(const many<T>& m, const S& s) {
- return S(m.begin(), m.end()) == s;
+ return m.size() == s.size() && S(m.begin(), m.end()) == s;
}
template <class T, class S> bool operator==(const S& s, const many<T>& m) {
- return S(m.begin(), m.end()) == s;
+ return m.size() == s.size() && S(m.begin(), m.end()) == s;
}
template <class T> std::ostream& operator<<(std::ostream& o, const many<T>& m) {
@@ -87,9 +89,27 @@ template <class T> std::ostream& operator<<(std::ostream& o, const std::deque<T>
return o << test::many<T>(s);
}
+template <class T> std::ostream& operator<<(std::ostream& o, const std::list<T>& s) {
+ return o << test::many<T>(s);
+}
+
+template <class K, class T> std::ostream& operator<<(std::ostream& o, const std::map<K, T>& x) {
+ return o << test::many<std::pair<K, T> >(x);
+}
+
template <class U, class V> std::ostream& operator<<(std::ostream& o, const std::pair<U, V>& p) {
return o << "( " << p.first << " , " << p.second << " )";
}
+
+#if PN_CPP_HAS_CPP11
+template <class K, class T> std::ostream& operator<<(std::ostream& o, const std::unordered_map<K, T>& x) {
+ return o << test::many<std::pair<const K, T> >(x);
+}
+
+template <class T> std::ostream& operator<<(std::ostream& o, const std::forward_list<T>& s) {
+ return o << test::many<T>(s);
+}
+#endif
}
#endif // TEST_BITS_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/src/timestamp.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/timestamp.cpp b/proton-c/bindings/cpp/src/timestamp.cpp
index 67ce39b..523b29e 100644
--- a/proton-c/bindings/cpp/src/timestamp.cpp
+++ b/proton-c/bindings/cpp/src/timestamp.cpp
@@ -19,9 +19,14 @@
#include <proton/timestamp.hpp>
#include <proton/types.h>
+#include <iostream>
namespace proton {
+
timestamp timestamp::now() {
return timestamp(pn_timestamp_now());
}
+
+std::ostream& operator<<(std::ostream& o, timestamp ts) { return o << ts.ms(); }
+
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/src/transport.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/transport.cpp b/proton-c/bindings/cpp/src/transport.cpp
index dc608bf..8883806 100644
--- a/proton-c/bindings/cpp/src/transport.cpp
+++ b/proton-c/bindings/cpp/src/transport.cpp
@@ -18,13 +18,18 @@
* under the License.
*
*/
+
+#include "proton/error.hpp"
#include "proton/transport.hpp"
#include "proton/condition.hpp"
#include "proton/connection.hpp"
#include "proton/ssl.hpp"
#include "proton/sasl.hpp"
-#include "msg.hpp"
#include "proton/transport.h"
+#include "proton/error.h"
+
+#include "msg.hpp"
+
namespace proton {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/src/type_id.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/type_id.cpp b/proton-c/bindings/cpp/src/type_id.cpp
new file mode 100644
index 0000000..57f950a
--- /dev/null
+++ b/proton-c/bindings/cpp/src/type_id.cpp
@@ -0,0 +1,65 @@
+/*
+ * 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 "types_internal.hpp"
+
+#include <proton/type_id.hpp>
+
+#include <ostream>
+
+namespace proton {
+
+std::string type_name(type_id t) {
+ switch (t) {
+ case NULL_TYPE: return "null";
+ case BOOLEAN: return "boolean";
+ case UBYTE: return "ubyte";
+ case BYTE: return "byte";
+ case USHORT: return "ushort";
+ case SHORT: return "short";
+ case UINT: return "uint";
+ case INT: return "int";
+ case CHAR: return "char";
+ case ULONG: return "ulong";
+ case LONG: return "long";
+ case TIMESTAMP: return "timestamp";
+ case FLOAT: return "float";
+ case DOUBLE: return "double";
+ case DECIMAL32: return "decimal32";
+ case DECIMAL64: return "decimal64";
+ case DECIMAL128: return "decimal128";
+ case UUID: return "uuid";
+ case BINARY: return "binary";
+ case STRING: return "string";
+ case SYMBOL: return "symbol";
+ case DESCRIBED: return "described";
+ case ARRAY: return "array";
+ case LIST: return "list";
+ case MAP: return "map";
+ }
+ return "unknown";
+}
+
+std::ostream& operator<<(std::ostream& o, type_id t) { return o << type_name(t); }
+
+void assert_type_equal(type_id want, type_id got) {
+ if (want != got) throw make_conversion_error(want, got);
+}
+
+} // proton
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/proton-c/bindings/cpp/src/types.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/types.cpp b/proton-c/bindings/cpp/src/types.cpp
deleted file mode 100644
index f64d0b6..0000000
--- a/proton-c/bindings/cpp/src/types.cpp
+++ /dev/null
@@ -1,81 +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 <proton/types.hpp>
-#include <proton/type_traits.hpp>
-#include <proton/codec.h>
-#include <ostream>
-#include <iomanip>
-#include <algorithm>
-#include <sstream>
-
-namespace proton {
-
-std::string type_name(type_id t) {
- switch (t) {
- case NULL_TYPE: return "null";
- case BOOLEAN: return "boolean";
- case UBYTE: return "ubyte";
- case BYTE: return "byte";
- case USHORT: return "ushort";
- case SHORT: return "short";
- case UINT: return "uint";
- case INT: return "int";
- case CHAR: return "char";
- case ULONG: return "ulong";
- case LONG: return "long";
- case TIMESTAMP: return "timestamp";
- case FLOAT: return "float";
- case DOUBLE: return "double";
- case DECIMAL32: return "decimal32";
- case DECIMAL64: return "decimal64";
- case DECIMAL128: return "decimal128";
- case UUID: return "uuid";
- case BINARY: return "binary";
- case STRING: return "string";
- case SYMBOL: return "symbol";
- case DESCRIBED: return "described";
- case ARRAY: return "array";
- case LIST: return "list";
- case MAP: return "map";
- }
- return "unknown";
-}
-
-bool type_id_is_signed_int(type_id t) { return t == BYTE || t == SHORT || t == INT || t == LONG; }
-bool type_id_is_unsigned_int(type_id t) { return t == UBYTE || t == USHORT || t == UINT || t == ULONG; }
-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); }
-bool type_id_is_floating_point(type_id t) { return t == FLOAT || t == DOUBLE; }
-bool type_id_is_decimal(type_id t) { return t == DECIMAL32 || t == DECIMAL64 || t == DECIMAL128; }
-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); }
-bool type_id_is_string_like(type_id t) { return t == BINARY || t == STRING || t == SYMBOL; }
-bool type_id_is_container(type_id t) { return t == LIST || t == MAP || t == ARRAY || t == DESCRIBED; }
-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; }
-
-
-std::ostream& operator<<(std::ostream& o, type_id t) { return o << type_name(t); }
-
-namespace internal {
-start::start(type_id t, type_id e, bool d, size_t s) : type(t), element(e), is_described(d), size(s) {}
-start start::array(type_id element, bool described) { return start(ARRAY, element, described); }
-start start::list() { return start(LIST); }
-start start::map() { return start(MAP); }
-start start::described() { return start(DESCRIBED, NULL_TYPE, true); }
-}
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/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 1c0de8a..3cf775c 100644
--- a/proton-c/bindings/cpp/src/types_internal.hpp
+++ b/proton-c/bindings/cpp/src/types_internal.hpp
@@ -30,7 +30,7 @@ namespace proton {
/// Byte copy between two objects, only enabled if their sizes are equal.
template <class T, class U>
-typename internal::enable_if<sizeof(T) == sizeof(U)>::type byte_copy(T &to, const U &from) {
+typename codec::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));
}
@@ -52,6 +52,16 @@ inline pn_bytes_t pn_bytes(const std::string& s) {
/// Convert pn_bytes_t to str
inline std::string str(const pn_bytes_t& b) { return std::string(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/4fa5fa41/proton-c/bindings/cpp/src/uuid.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/uuid.cpp b/proton-c/bindings/cpp/src/uuid.cpp
index 9e64cca..f224df7 100644
--- a/proton-c/bindings/cpp/src/uuid.cpp
+++ b/proton-c/bindings/cpp/src/uuid.cpp
@@ -17,7 +17,8 @@
* under the License.
*/
-#include "proton/uuid.hpp"
+#include <proton/uuid.hpp>
+#include <proton/types_fwd.hpp>
#include <cstdlib>
#include <ctime>
@@ -56,7 +57,7 @@ struct ios_guard {
};
}
-uuid uuid::make(const char* bytes) {
+uuid uuid::copy(const char* bytes) {
uuid u;
if (bytes)
std::copy(bytes, bytes + u.size(), u.begin());
@@ -87,12 +88,13 @@ std::ostream& operator<<(std::ostream& o, const uuid& u) {
ios_guard restore_flags(o);
o << std::hex << std::setfill('0');
static const int segments[] = {4,2,2,2,6}; // 1 byte is 2 hex chars.
- const char *p = u.begin();
+ const uint8_t *p = reinterpret_cast<const uint8_t*>(u.begin());
for (size_t i = 0; i < sizeof(segments)/sizeof(segments[0]); ++i) {
if (i > 0)
o << '-';
- for (int j = 0; j < segments[i]; ++j)
+ for (int j = 0; j < segments[i]; ++j) {
o << std::setw(2) << int(*(p++));
+ }
}
return o;
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4fa5fa41/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 dda20f2..44d696d 100644
--- a/proton-c/bindings/cpp/src/value.cpp
+++ b/proton-c/bindings/cpp/src/value.cpp
@@ -20,19 +20,23 @@
#include "proton_bits.hpp"
#include "proton/data.hpp"
#include "proton/value.hpp"
+#include "proton/types.hpp"
#include "proton/scalar.hpp"
+#include "proton/error.hpp"
#include <ostream>
namespace proton {
+using namespace codec;
+
value::value() {}
value::value(const null&) {}
value::value(const value& x) { *this = x; }
-value::value(pn_data_t* p) { if (p) data().copy(internal::data(p)); }
-
+value::value(const codec::data& x) { if (!x.empty()) data().copy(x); }
#if PN_CPP_HAS_CPP11
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; }
@@ -53,39 +57,135 @@ void value::clear() { if (!!data_) data_.clear(); }
bool value::empty() const { return !data_ || data_.empty(); }
+type_id value::type() const {
+ if (empty()) return NULL_TYPE;
+ decoder d(*this);
+ return d.next_type();
+}
+
// On demand
-internal::data& value::data() const {
- if (!data_) data_ = internal::data::create(); return data_;
+codec::data& value::data() const {
+ if (!data_)
+ data_ = codec::data::create();
+ return data_;
}
-internal::encoder value::encode() { clear(); return data().encoder(); }
+namespace {
+
+// Compare nodes, return -1 if a<b, 0 if a==b, +1 if a>b
+// Forward-declare so we can use it recursively.
+int compare_next(decoder& a, decoder& b);
-internal::decoder value::decode() const { return data().decoder() >> internal::rewind(); }
+template <class T> int compare(const T& a, const T& b) {
+ if (a < b) return -1;
+ else if (a > b) return +1;
+ else return 0;
+}
+
+int compare_container(decoder& a, decoder& b) {
+ start sa, sb;
+ a >> sa;
+ b >> sb;
+ // Compare described vs. not-described.
+ int cmp = compare(sa.is_described, sb.is_described);
+ if (cmp) return cmp;
+ // Lexical sort (including descriptor if there is one)
+ size_t min_size = std::min(sa.size, sb.size) + size_t(sa.is_described);
+ for (size_t i = 0; i < min_size; ++i) {
+ cmp = compare_next(a, b);
+ if (cmp) return cmp;
+ }
+ return compare(sa.size, sb.size);
+}
+
+template <class T> int compare_simple(decoder& a, decoder& b) {
+ T va = T();
+ T vb = T();
+ a >> va;
+ b >> vb;
+ return compare(va, vb);
+}
+
+int compare_next(decoder& a, decoder& b) {
+ // Sort by type_id first.
+ type_id ta = a.next_type(), tb = b.next_type();
+ int cmp = compare(ta, tb);
+ if (cmp) return cmp;
+
+ switch (ta) {
+ case NULL_TYPE: return 0;
+ case ARRAY:
+ case LIST:
+ case MAP:
+ case DESCRIBED:
+ return compare_container(a, b);
+ case BOOLEAN: return compare_simple<bool>(a, b);
+ case UBYTE: return compare_simple<uint8_t>(a, b);
+ case BYTE: return compare_simple<int8_t>(a, b);
+ case USHORT: return compare_simple<uint16_t>(a, b);
+ case SHORT: return compare_simple<int16_t>(a, b);
+ case UINT: return compare_simple<uint32_t>(a, b);
+ case INT: return compare_simple<int32_t>(a, b);
+ case ULONG: return compare_simple<uint64_t>(a, b);
+ case LONG: return compare_simple<int64_t>(a, b);
+ case CHAR: return compare_simple<wchar_t>(a, b);
+ case TIMESTAMP: return compare_simple<timestamp>(a, b);
+ case FLOAT: return compare_simple<float>(a, b);
+ case DOUBLE: return compare_simple<double>(a, b);
+ case DECIMAL32: return compare_simple<decimal32>(a, b);
+ case DECIMAL64: return compare_simple<decimal64>(a, b);
+ case DECIMAL128: return compare_simple<decimal128>(a, b);
+ case UUID: return compare_simple<uuid>(a, b);
+ case BINARY: return compare_simple<binary>(a, b);
+ case STRING: return compare_simple<std::string>(a, b);
+ case SYMBOL: return compare_simple<symbol>(a, b);
+ }
+ // Invalid but equal type_id, treat as equal.
+ return 0;
+}
+
+int compare(const value& x, const value& y) {
+ decoder a(x), b(y);
+ state_guard s1(a), s2(b);
+ a.rewind();
+ b.rewind();
+ while (a.more() && b.more()) {
+ int cmp = compare_next(a, b);
+ if (cmp != 0) return cmp;
+ }
+ if (b.more()) return -1;
+ if (a.more()) return 1;
+ return 0;
+}
-type_id value::type() const { return empty() ? NULL_TYPE : decode().type(); }
+} // namespace
bool operator==(const value& x, const value& y) {
if (x.empty() && y.empty()) return true;
if (x.empty() || y.empty()) return false;
- return x.data().equal(y.data());
+ return compare(x, y) == 0;
}
bool operator<(const value& x, const value& y) {
if (x.empty() && y.empty()) return false;
if (x.empty()) return true; // empty is < !empty
- return x.data().less(y.data());
+ return compare(x, y) < 0;
}
-std::ostream& operator<<(std::ostream& o, const value& v) {
- if (v.empty())
+std::ostream& operator<<(std::ostream& o, exact_cref<value> v) {
+ if (v.ref.empty())
return o << "<null>";
- // pn_inspect prints strings with quotes which is not normal in C++.
- switch (v.type()) {
+ switch (v.ref.type()) {
case STRING:
- case SYMBOL:
- return o << v.get<std::string>();
+ case SYMBOL: return o << get<std::string>(v.ref);
+ case DECIMAL32: return o << get<decimal32>(v.ref);
+ case DECIMAL64: return o << get<decimal64>(v.ref);
+ case DECIMAL128: return o << get<decimal128>(v.ref);
+ case UUID: return o << get<uuid>(v.ref);
+ case TIMESTAMP: return o << get<timestamp>(v.ref);
default:
- return o << v.data();
+ // Use pn_inspect for other types.
+ return o << decoder(v.ref);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org