#ifndef PROTON_CODEC_ENCODER_HPP #define PROTON_CODEC_ENCODER_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 "../internal/data.hpp" #include "../internal/type_traits.hpp" #include "../types_fwd.hpp" #include "./common.hpp" #include /// @file /// @copybrief proton::codec::encoder namespace proton { class scalar_base; namespace internal{ class value_base; } namespace codec { /// **Unsettled API** - A stream-like encoder from C++ values to AMQP /// bytes. /// /// For internal use only. /// /// @see @ref types_page for the recommended ways to manage AMQP data class encoder : public internal::data { public: /// Wrap Proton-C data object. explicit encoder(const data& d) : data(d) {} /// Encoder into v. Clears any current value in v. PN_CPP_EXTERN explicit encoder(internal::value_base& v); /// Encode the current values into buffer and update size to reflect the /// number of bytes encoded. /// /// Clears the encoder. /// /// @return if buffer == 0 or size is too small, then return false /// and size to the required size. Otherwise, return true and set /// size to the number of bytes encoded. PN_CPP_EXTERN bool encode(char* buffer, size_t& size); /// Encode the current values into a std::string and resize the /// string if necessary. Clears the encoder. PN_CPP_EXTERN void encode(std::string&); /// 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); PN_CPP_EXTERN encoder& operator<<(uint16_t); PN_CPP_EXTERN encoder& operator<<(int16_t); PN_CPP_EXTERN encoder& operator<<(uint32_t); PN_CPP_EXTERN encoder& operator<<(int32_t); PN_CPP_EXTERN encoder& operator<<(wchar_t); PN_CPP_EXTERN encoder& operator<<(uint64_t); PN_CPP_EXTERN encoder& operator<<(int64_t); PN_CPP_EXTERN encoder& operator<<(timestamp); PN_CPP_EXTERN encoder& operator<<(float); PN_CPP_EXTERN encoder& operator<<(double); PN_CPP_EXTERN encoder& operator<<(decimal32); PN_CPP_EXTERN encoder& operator<<(decimal64); PN_CPP_EXTERN encoder& operator<<(decimal128); PN_CPP_EXTERN encoder& operator<<(const uuid&); PN_CPP_EXTERN encoder& operator<<(const std::string&); PN_CPP_EXTERN encoder& operator<<(const symbol&); PN_CPP_EXTERN encoder& operator<<(const binary&); PN_CPP_EXTERN encoder& operator<<(const scalar_base&); PN_CPP_EXTERN encoder& operator<<(const null&); #if PN_CPP_HAS_NULLPTR PN_CPP_EXTERN encoder& operator<<(decltype(nullptr)); #endif /// @} /// Insert a proton::value. /// /// @internal NOTE insert value_base, not value to avoid recursive /// implicit conversions. PN_CPP_EXTERN encoder& operator<<(const internal::value_base&); /// Start a complex type PN_CPP_EXTERN encoder& operator<<(const start&); /// Finish a complex type PN_CPP_EXTERN encoder& operator<<(const finish&); /// @cond INTERNAL // Undefined template to prevent pointers being implicitly converted to bool. template void* operator<<(const T*); template struct list_cref { T& ref; list_cref(T& r) : ref(r) {} }; template struct map_cref { T& ref; map_cref(T& r) : ref(r) {} }; template struct array_cref { start array_start; T& ref; array_cref(T& r, type_id el, bool described) : array_start(ARRAY, el, described), ref(r) {} }; template static list_cref list(T& x) { return list_cref(x); } template static map_cref map(T& x) { return map_cref(x); } template static array_cref array(T& x, type_id element, bool described=false) { return array_cref(x, element, described); } template encoder& operator<<(const map_cref& x) { internal::state_guard sg(*this); *this << start::map(); for (typename T::const_iterator i = x.ref.begin(); i != x.ref.end(); ++i) *this << i->first << i->second; *this << finish(); return *this; } template encoder& operator<<(const list_cref& x) { internal::state_guard sg(*this); *this << start::list(); for (typename T::const_iterator i = x.ref.begin(); i != x.ref.end(); ++i) *this << *i; *this << finish(); return *this; } template encoder& operator<<(const array_cref& x) { internal::state_guard sg(*this); *this << x.array_start; for (typename T::const_iterator i = x.ref.begin(); i != x.ref.end(); ++i) *this << *i; *this << finish(); return *this; } /// @endcond private: template encoder& insert(const T& x, int (*put)(pn_data_t*, U)); void check(long result); }; /// 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 typename internal::enable_if::value, encoder&>::type operator<<(encoder& e, T i) { using namespace internal; return e << static_cast::value>::type>(i); } /// @cond INTERNAL namespace is_encodable_impl { // Protect the world from fallback operator<< using namespace internal; sfinae::no operator<<(encoder const&, const sfinae::any_t &); // Fallback template 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 : public true_type {}; } // is_encodable_impl using is_encodable_impl::is_encodable; // Metafunction to test if a class looks like an encodable map from K to T. template struct is_encodable_map : public internal::false_type {}; template struct is_encodable_map< M, K, T, typename internal::enable_if< internal::is_same::value && internal::is_same::value && is_encodable::value >::type > : public internal::true_type {}; /// @endcond } // codec } // proton #endif /// PROTON_CODEC_ENCODER_HPP