messagepack implementation for embedded systems (mbed / arduino)

Dependents:   hello_message_pack

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ext.hpp Source File

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