messagepack implementation for embedded systems (mbed / arduino)
Dependents: hello_message_pack
ext.hpp
00001 // 00002 // MessagePack for C++ static resolution routine 00003 // 00004 // Copyright (C) 2015 KONDO Takatoshi 00005 // 00006 // Distributed under the Boost Software License, Version 1.0. 00007 // (See accompanying file LICENSE_1_0.txt or copy at 00008 // http://www.boost.org/LICENSE_1_0.txt) 00009 // 00010 #ifndef MSGPACK_TYPE_EXT_HPP 00011 #define MSGPACK_TYPE_EXT_HPP 00012 00013 #include "msgpack/versioning.hpp" 00014 #include "msgpack/adaptor/adaptor_base.hpp" 00015 #include <cstring> 00016 #include <string> 00017 #include <cassert> 00018 00019 namespace msgpack { 00020 00021 /// @cond 00022 MSGPACK_API_VERSION_NAMESPACE(v1) { 00023 /// @endcond 00024 00025 namespace type { 00026 class ext_ref; 00027 00028 class ext { 00029 public: 00030 ext() : m_data(1, 0) {} 00031 ext(int8_t t, const char* p, uint32_t s) { 00032 detail::check_container_size_for_ext<sizeof(std::size_t)>(s); 00033 m_data.reserve(static_cast<std::size_t>(s) + 1); 00034 m_data.push_back(static_cast<char>(t)); 00035 m_data.insert(m_data.end(), p, p + s); 00036 } 00037 ext(int8_t t, uint32_t s) { 00038 detail::check_container_size_for_ext<sizeof(std::size_t)>(s); 00039 m_data.resize(static_cast<std::size_t>(s) + 1); 00040 m_data[0] = static_cast<char>(t); 00041 } 00042 ext(ext_ref const&); 00043 int8_t type() const { 00044 return static_cast<int8_t>(m_data[0]); 00045 } 00046 const char* data() const { 00047 return &m_data[1]; 00048 } 00049 char* data() { 00050 return &m_data[1]; 00051 } 00052 uint32_t size() const { 00053 return static_cast<uint32_t>(m_data.size()) - 1; 00054 } 00055 bool operator== (const ext& x) const { 00056 return m_data == x.m_data; 00057 } 00058 00059 bool operator!= (const ext& x) const { 00060 return !(*this == x); 00061 } 00062 00063 bool operator< (const ext& x) const { 00064 return m_data < x.m_data; 00065 } 00066 00067 bool operator> (const ext& x) const { 00068 return m_data > x.m_data; 00069 } 00070 private: 00071 std::vector<char> m_data; 00072 friend class ext_ref; 00073 }; 00074 00075 } // namespace type 00076 00077 namespace adaptor { 00078 00079 template <> 00080 struct convert<msgpack::type::ext> { 00081 msgpack::object const& operator()(msgpack::object const& o, msgpack::type::ext& v) const { 00082 if(o.type != msgpack::type::EXT) { 00083 // throw msgpack::type_error(); 00084 } 00085 v = msgpack::type::ext(o.via.ext.type(), o.via.ext.data(), o.via.ext.size); 00086 return o; 00087 } 00088 }; 00089 00090 template <> 00091 struct pack<msgpack::type::ext> { 00092 template <typename Stream> 00093 msgpack::packer<Stream> & operator()(msgpack::packer<Stream> & o, const msgpack::type::ext& v) const { 00094 // size limit has already been checked at ext's constructor 00095 uint32_t size = v.size(); 00096 o.pack_ext(size, v.type()); 00097 o.pack_ext_body(v.data(), size); 00098 return o; 00099 } 00100 }; 00101 00102 template <> 00103 struct object_with_zone<msgpack::type::ext> { 00104 void operator()(msgpack::object::with_zone& o, const msgpack::type::ext& v) const { 00105 // size limit has already been checked at ext's constructor 00106 uint32_t size = v.size(); 00107 o.type = msgpack::type::EXT; 00108 char* ptr = static_cast<char*>(o.zone.allocate_align(size + 1)); 00109 o.via.ext.ptr = ptr; 00110 o.via.ext.size = size; 00111 ptr[0] = static_cast<char>(v.type()); 00112 std::memcpy(ptr + 1, v.data(), size); 00113 } 00114 }; 00115 00116 } // namespace adaptor 00117 00118 namespace type { 00119 00120 class ext_ref { 00121 public: 00122 // ext_ref should be default constructible to support 'convert'. 00123 // A default constructed ext_ref object::m_ptr doesn't have the buffer to point to. 00124 // In order to avoid nullptr checking branches, m_ptr points to m_size. 00125 // So type() returns unspecified but valid value. It might be a zero because m_size 00126 // is initialized as zero, but shouldn't assume that. 00127 ext_ref() : m_ptr(static_cast<char*>(static_cast<void*>(&m_size))), m_size(0) {} 00128 ext_ref(const char* p, uint32_t s) : 00129 m_ptr(s == 0 ? static_cast<char*>(static_cast<void*>(&m_size)) : p), 00130 m_size(s == 0 ? 0 : s - 1) { 00131 detail::check_container_size_for_ext<sizeof(std::size_t)>(s); 00132 } 00133 00134 // size limit has already been checked at ext's constructor 00135 ext_ref(ext const& x) : m_ptr(&x.m_data[0]), m_size(x.size()) {} 00136 00137 const char* data() const { 00138 return m_ptr + 1; 00139 } 00140 00141 uint32_t size() const { 00142 return m_size; 00143 } 00144 00145 int8_t type() const { 00146 return static_cast<int8_t>(m_ptr[0]); 00147 } 00148 00149 std::string str() const { 00150 return std::string(m_ptr + 1, m_size); 00151 } 00152 00153 bool operator== (const ext_ref& x) const { 00154 return m_size == x.m_size && std::memcmp(m_ptr, x.m_ptr, m_size) == 0; 00155 } 00156 00157 bool operator!= (const ext_ref& x) const { 00158 return !(*this == x); 00159 } 00160 00161 bool operator< (const ext_ref& x) const { 00162 if (m_size < x.m_size) return true; 00163 if (m_size > x.m_size) return false; 00164 return std::memcmp(m_ptr, x.m_ptr, m_size) < 0; 00165 } 00166 00167 bool operator> (const ext_ref& x) const { 00168 if (m_size > x.m_size) return true; 00169 if (m_size < x.m_size) return false; 00170 return std::memcmp(m_ptr, x.m_ptr, m_size) > 0; 00171 } 00172 private: 00173 const char* m_ptr; 00174 uint32_t m_size; 00175 friend struct msgpack::adaptor::object<msgpack::type::ext_ref>; 00176 }; 00177 00178 inline ext::ext(ext_ref const& x) { 00179 // size limit has already been checked at ext_ref's constructor 00180 m_data.reserve(x.size() + 1); 00181 00182 m_data.push_back(x.type()); 00183 m_data.insert(m_data.end(), x.data(), x.data() + x.size()); 00184 } 00185 00186 } // namespace type 00187 00188 namespace adaptor { 00189 00190 template <> 00191 struct convert<msgpack::type::ext_ref> { 00192 msgpack::object const& operator()(msgpack::object const& o, msgpack::type::ext_ref& v) const { 00193 if(o.type != msgpack::type::EXT) { 00194 // throw msgpack::type_error(); 00195 } 00196 v = msgpack::type::ext_ref(o.via.ext.ptr, o.via.ext.size + 1); 00197 return o; 00198 } 00199 }; 00200 00201 template <> 00202 struct pack<msgpack::type::ext_ref> { 00203 template <typename Stream> 00204 msgpack::packer<Stream> & operator()(msgpack::packer<Stream> & o, const msgpack::type::ext_ref& v) const { 00205 // size limit has already been checked at ext_ref's constructor 00206 uint32_t size = v.size(); 00207 o.pack_ext(size, v.type()); 00208 o.pack_ext_body(v.data(), size); 00209 return o; 00210 } 00211 }; 00212 00213 template <> 00214 struct object<msgpack::type::ext_ref> { 00215 void operator()(msgpack::object& o, const msgpack::type::ext_ref& v) const { 00216 // size limit has already been checked at ext_ref's constructor 00217 uint32_t size = v.size(); 00218 o.type = msgpack::type::EXT; 00219 o.via.ext.ptr = v.m_ptr; 00220 o.via.ext.size = size; 00221 } 00222 }; 00223 00224 template <> 00225 struct object_with_zone<msgpack::type::ext_ref> { 00226 void operator()(msgpack::object::with_zone& o, const msgpack::type::ext_ref& v) const { 00227 static_cast<msgpack::object&>(o) << v; 00228 } 00229 }; 00230 00231 } // namespace adaptor 00232 00233 /// @cond 00234 } // MSGPACK_API_VERSION_NAMESPACE(v1) 00235 /// @endcond 00236 00237 } // namespace msgpack 00238 00239 #endif // MSGPACK_TYPE_EXT_HPP
Generated on Tue Jul 12 2022 22:51:45 by 1.7.2