mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-04-27 10:26:01 +02:00
Added EXT type supporting classes.
This commit is contained in:
parent
17900625d0
commit
ff14be8fdb
@ -121,6 +121,7 @@ IF (MSGPACK_ENABLE_CXX)
|
||||
include/msgpack/adaptor/detail/cpp03_msgpack_tuple.hpp
|
||||
include/msgpack/adaptor/detail/cpp11_define.hpp
|
||||
include/msgpack/adaptor/detail/cpp11_msgpack_tuple.hpp
|
||||
include/msgpack/adaptor/ext.hpp
|
||||
include/msgpack/adaptor/fixint.hpp
|
||||
include/msgpack/adaptor/float.hpp
|
||||
include/msgpack/adaptor/int.hpp
|
||||
|
@ -47,6 +47,16 @@ template <>
|
||||
inline void check_container_size<4>(std::size_t /*size*/) {
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
inline void check_container_size_for_ext(std::size_t size) {
|
||||
if (size > 0xffffffff) throw container_size_overflow("container size overflow");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void check_container_size_for_ext<4>(std::size_t size) {
|
||||
if (size > 0xfffffffe) throw container_size_overflow("container size overflow");
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
|
245
include/msgpack/adaptor/ext.hpp
Normal file
245
include/msgpack/adaptor/ext.hpp
Normal file
@ -0,0 +1,245 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2015 KONDO Takatoshi
|
||||
//
|
||||
// Licensed 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.
|
||||
//
|
||||
#ifndef MSGPACK_TYPE_EXT_HPP
|
||||
#define MSGPACK_TYPE_EXT_HPP
|
||||
|
||||
#include "msgpack/versioning.hpp"
|
||||
#include "msgpack/adaptor/adaptor_base.hpp"
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
/// @cond
|
||||
MSGPACK_API_VERSION_NAMESPACE(v1) {
|
||||
/// @endcond
|
||||
|
||||
namespace type {
|
||||
class ext_ref;
|
||||
|
||||
class ext {
|
||||
public:
|
||||
ext() : m_data(1, 0) {}
|
||||
ext(int8_t t, const char* p, uint32_t s) {
|
||||
detail::check_container_size_for_ext<sizeof(std::size_t)>(s);
|
||||
m_data.reserve(static_cast<std::size_t>(s) + 1);
|
||||
m_data.push_back(static_cast<char>(t));
|
||||
m_data.insert(m_data.end(), p, p + s);
|
||||
}
|
||||
ext(int8_t t, uint32_t s) {
|
||||
detail::check_container_size_for_ext<sizeof(std::size_t)>(s);
|
||||
m_data.resize(static_cast<std::size_t>(s) + 1);
|
||||
m_data[0] = static_cast<char>(t);
|
||||
}
|
||||
ext(ext_ref const&);
|
||||
int8_t type() const {
|
||||
return static_cast<int8_t>(m_data[0]);
|
||||
}
|
||||
const char* data() const {
|
||||
return &m_data[1];
|
||||
}
|
||||
char* data() {
|
||||
return &m_data[1];
|
||||
}
|
||||
uint32_t size() const {
|
||||
return m_data.size() - 1;
|
||||
}
|
||||
bool operator== (const ext& x) const {
|
||||
return m_data == x.m_data;
|
||||
}
|
||||
|
||||
bool operator!= (const ext& x) const {
|
||||
return !(*this == x);
|
||||
}
|
||||
|
||||
bool operator< (const ext& x) const {
|
||||
return m_data < x.m_data;
|
||||
}
|
||||
|
||||
bool operator> (const ext& x) const {
|
||||
return m_data > x.m_data;
|
||||
}
|
||||
private:
|
||||
std::vector<char> m_data;
|
||||
friend class ext_ref;
|
||||
};
|
||||
|
||||
} // namespace type
|
||||
|
||||
namespace adaptor {
|
||||
|
||||
template <>
|
||||
struct convert<msgpack::type::ext> {
|
||||
msgpack::object const& operator()(msgpack::object const& o, msgpack::type::ext& v) const {
|
||||
if(o.type != msgpack::type::EXT) {
|
||||
throw msgpack::type_error();
|
||||
}
|
||||
v = msgpack::type::ext(o.via.ext.type(), o.via.ext.data(), o.via.ext.size);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct pack<msgpack::type::ext> {
|
||||
template <typename Stream>
|
||||
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const msgpack::type::ext& v) const {
|
||||
// size limit has aleady been checked at ext's constructor
|
||||
uint32_t size = v.size();
|
||||
o.pack_ext(size, v.type());
|
||||
o.pack_ext_body(v.data(), size);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct object_with_zone<msgpack::type::ext> {
|
||||
void operator()(msgpack::object::with_zone& o, const msgpack::type::ext& v) const {
|
||||
// size limit has aleady been checked at ext's constructor
|
||||
uint32_t size = v.size();
|
||||
o.type = msgpack::type::EXT;
|
||||
char* ptr = static_cast<char*>(o.zone.allocate_align(size + 1));
|
||||
o.via.ext.ptr = ptr;
|
||||
o.via.ext.size = size;
|
||||
ptr[0] = static_cast<char>(v.type());
|
||||
std::memcpy(ptr + 1, v.data(), size);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace adaptor
|
||||
|
||||
namespace type {
|
||||
|
||||
class ext_ref {
|
||||
public:
|
||||
// ext_ref should be default constructible to support 'convert'.
|
||||
// A default constructed ext_ref object::m_ptr doesn't have the buffer to point to.
|
||||
// In order to avoid nullptr checking branches, m_ptr points to m_size.
|
||||
// So type() returns unspecified but valid value. It might be a zero because m_size
|
||||
// is initialized as zero, but shoudn't assume that.
|
||||
ext_ref() : m_ptr(static_cast<char*>(static_cast<void*>(&m_size))), m_size(0) {}
|
||||
ext_ref(const char* p, uint32_t s) :
|
||||
m_ptr(s == 0 ? static_cast<char*>(static_cast<void*>(&m_size)) : p),
|
||||
m_size(s == 0 ? 0 : s - 1) {
|
||||
detail::check_container_size_for_ext<sizeof(std::size_t)>(s);
|
||||
}
|
||||
|
||||
// size limit has aleady been checked at ext's constructor
|
||||
ext_ref(ext const& x) : m_ptr(&x.m_data[0]), m_size(x.size()) {}
|
||||
|
||||
const char* data() const {
|
||||
return m_ptr + 1;
|
||||
}
|
||||
|
||||
uint32_t size() const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
int8_t type() const {
|
||||
return static_cast<int8_t>(m_ptr[0]);
|
||||
}
|
||||
|
||||
std::string str() const {
|
||||
return std::string(m_ptr + 1, m_size);
|
||||
}
|
||||
|
||||
bool operator== (const ext_ref& x) const {
|
||||
return m_size == x.m_size && std::memcmp(m_ptr, x.m_ptr, m_size) == 0;
|
||||
}
|
||||
|
||||
bool operator!= (const ext_ref& x) const {
|
||||
return !(*this == x);
|
||||
}
|
||||
|
||||
bool operator< (const ext_ref& x) const {
|
||||
if (m_size < x.m_size) return true;
|
||||
if (m_size > x.m_size) return false;
|
||||
return std::memcmp(m_ptr, x.m_ptr, m_size) < 0;
|
||||
}
|
||||
|
||||
bool operator> (const ext_ref& x) const {
|
||||
if (m_size > x.m_size) return true;
|
||||
if (m_size < x.m_size) return false;
|
||||
return std::memcmp(m_ptr, x.m_ptr, m_size) > 0;
|
||||
}
|
||||
private:
|
||||
const char* m_ptr;
|
||||
uint32_t m_size;
|
||||
friend struct msgpack::adaptor::object<msgpack::type::ext_ref>;
|
||||
};
|
||||
|
||||
ext::ext(ext_ref const& x) {
|
||||
// size limit has aleady been checked at ext_ref's constructor
|
||||
m_data.reserve(x.size() + 1);
|
||||
|
||||
m_data.push_back(x.type());
|
||||
m_data.insert(m_data.end(), x.data(), x.data() + x.size());
|
||||
}
|
||||
|
||||
} // namespace type
|
||||
|
||||
namespace adaptor {
|
||||
|
||||
template <>
|
||||
struct convert<msgpack::type::ext_ref> {
|
||||
msgpack::object const& operator()(msgpack::object const& o, msgpack::type::ext_ref& v) const {
|
||||
if(o.type != msgpack::type::EXT) { throw msgpack::type_error(); }
|
||||
v = msgpack::type::ext_ref(o.via.ext.ptr, o.via.ext.size + 1);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct pack<msgpack::type::ext_ref> {
|
||||
template <typename Stream>
|
||||
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const msgpack::type::ext_ref& v) const {
|
||||
// size limit has aleady been checked at ext_ref's constructor
|
||||
uint32_t size = v.size();
|
||||
o.pack_ext(size, v.type());
|
||||
o.pack_ext_body(v.data(), size);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct object<msgpack::type::ext_ref> {
|
||||
void operator()(msgpack::object& o, const msgpack::type::ext_ref& v) const {
|
||||
// size limit has aleady been checked at ext_ref's constructor
|
||||
uint32_t size = v.size();
|
||||
o.type = msgpack::type::EXT;
|
||||
o.via.ext.ptr = v.m_ptr;
|
||||
o.via.ext.size = size;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct object_with_zone<msgpack::type::ext_ref> {
|
||||
void operator()(msgpack::object::with_zone& o, const msgpack::type::ext_ref& v) const {
|
||||
static_cast<msgpack::object&>(o) << v;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace adaptor
|
||||
|
||||
/// @cond
|
||||
} // MSGPACK_API_VERSION_NAMESPACE(v1)
|
||||
/// @endcond
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif // MSGPACK_TYPE_EXT_HPP
|
@ -2,6 +2,7 @@
|
||||
#include "adaptor/bool.hpp"
|
||||
#include "adaptor/char_ptr.hpp"
|
||||
#include "adaptor/deque.hpp"
|
||||
#include "adaptor/ext.hpp"
|
||||
#include "adaptor/fixint.hpp"
|
||||
#include "adaptor/float.hpp"
|
||||
#include "adaptor/int.hpp"
|
||||
|
@ -72,6 +72,7 @@ nobase_include_HEADERS += \
|
||||
../include/msgpack/adaptor/detail/cpp03_msgpack_tuple.hpp \
|
||||
../include/msgpack/adaptor/detail/cpp11_define.hpp \
|
||||
../include/msgpack/adaptor/detail/cpp11_msgpack_tuple.hpp \
|
||||
../include/msgpack/adaptor/ext.hpp \
|
||||
../include/msgpack/adaptor/fixint.hpp \
|
||||
../include/msgpack/adaptor/float.hpp \
|
||||
../include/msgpack/adaptor/int.hpp \
|
||||
|
@ -452,7 +452,7 @@ TEST(MSGPACK, simple_buffer_fixext_4byte_65536)
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::packer<msgpack::sbuffer> packer(sbuf);
|
||||
char buf[size];
|
||||
for (int i = 0; i != size; ++i) buf[i] = static_cast<char>(i);
|
||||
for (std::size_t i = 0; i != size; ++i) buf[i] = static_cast<char>(i);
|
||||
packer.pack_ext(sizeof(buf), 77);
|
||||
packer.pack_ext_body(buf, sizeof(buf));
|
||||
|
||||
@ -464,6 +464,85 @@ TEST(MSGPACK, simple_buffer_fixext_4byte_65536)
|
||||
std::equal(buf, buf + sizeof(buf), ret.get().via.ext.data()));
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_ext_convert)
|
||||
{
|
||||
std::size_t const size = 65536;
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::packer<msgpack::sbuffer> packer(sbuf);
|
||||
char buf[size];
|
||||
for (std::size_t i = 0; i != size; ++i) buf[i] = static_cast<char>(i);
|
||||
packer.pack_ext(sizeof(buf), 77);
|
||||
packer.pack_ext_body(buf, sizeof(buf));
|
||||
|
||||
msgpack::unpacked ret;
|
||||
msgpack::unpack(ret, sbuf.data(), sbuf.size());
|
||||
msgpack::type::ext e;
|
||||
ret.get().convert(e);
|
||||
EXPECT_EQ(size, e.size());
|
||||
EXPECT_EQ(77, e.type());
|
||||
EXPECT_TRUE(
|
||||
std::equal(buf, buf + sizeof(buf), e.data()));
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_ext_pack_convert)
|
||||
{
|
||||
std::size_t const size = 65536;
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::type::ext val1(77, size);
|
||||
char* buf = val1.data();
|
||||
for (std::size_t i = 0; i != size; ++i) buf[i] = static_cast<char>(i);
|
||||
msgpack::pack(sbuf, val1);
|
||||
|
||||
msgpack::unpacked ret;
|
||||
msgpack::unpack(ret, sbuf.data(), sbuf.size());
|
||||
msgpack::type::ext val2;
|
||||
ret.get().convert(val2);
|
||||
EXPECT_EQ(size, val2.size());
|
||||
EXPECT_EQ(77, val2.type());
|
||||
EXPECT_TRUE(
|
||||
std::equal(buf, buf + sizeof(buf), val2.data()));
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_ext_ref_convert)
|
||||
{
|
||||
std::size_t const size = 65536;
|
||||
msgpack::sbuffer sbuf;
|
||||
msgpack::packer<msgpack::sbuffer> packer(sbuf);
|
||||
char buf[size];
|
||||
for (std::size_t i = 0; i != size; ++i) buf[i] = static_cast<char>(i);
|
||||
packer.pack_ext(sizeof(buf), 77);
|
||||
packer.pack_ext_body(buf, sizeof(buf));
|
||||
|
||||
msgpack::unpacked ret;
|
||||
msgpack::unpack(ret, sbuf.data(), sbuf.size());
|
||||
msgpack::type::ext_ref er;
|
||||
ret.get().convert(er);
|
||||
EXPECT_EQ(size, er.size());
|
||||
EXPECT_EQ(77, er.type());
|
||||
EXPECT_TRUE(
|
||||
std::equal(buf, buf + sizeof(buf), er.data()));
|
||||
}
|
||||
|
||||
TEST(MSGPACK, simple_buffer_ext_ref_pack_convert)
|
||||
{
|
||||
std::size_t const buf_size = 65536;
|
||||
std::size_t const data_size = buf_size - 1;
|
||||
msgpack::sbuffer sbuf;
|
||||
char buf[buf_size];
|
||||
buf[0] = static_cast<char>(77);
|
||||
for (std::size_t i = 0; i != data_size; ++i) buf[i + 1] = static_cast<char>(i);
|
||||
msgpack::pack(sbuf, msgpack::type::ext_ref(buf, buf_size));
|
||||
|
||||
msgpack::unpacked ret;
|
||||
msgpack::unpack(ret, sbuf.data(), sbuf.size());
|
||||
msgpack::type::ext_ref val2;
|
||||
ret.get().convert(val2);
|
||||
EXPECT_EQ(data_size, val2.size());
|
||||
EXPECT_EQ(77, val2.type());
|
||||
EXPECT_TRUE(
|
||||
std::equal(&buf[1], &buf[buf_size], val2.data()));
|
||||
}
|
||||
|
||||
TEST(MSGPACK_STL, simple_buffer_string)
|
||||
{
|
||||
for (unsigned int k = 0; k < kLoop; k++) {
|
||||
|
@ -864,3 +864,51 @@ TEST(object_with_zone, tuple_empty)
|
||||
}
|
||||
|
||||
#endif // !defined(MSGPACK_USE_CPP03)
|
||||
|
||||
TEST(object_with_zone, ext_empty)
|
||||
{
|
||||
msgpack::type::ext v;
|
||||
msgpack::zone z;
|
||||
msgpack::object obj(v, z);
|
||||
EXPECT_EQ(obj.as<msgpack::type::ext>(), v);
|
||||
EXPECT_EQ(obj.as<msgpack::type::ext_ref>(), v);
|
||||
}
|
||||
|
||||
TEST(object_with_zone, ext)
|
||||
{
|
||||
msgpack::type::ext v(42, 10);
|
||||
for (int i = 0; i < 10; ++i) v.data()[i] = i;
|
||||
msgpack::zone z;
|
||||
msgpack::object obj(v, z);
|
||||
EXPECT_EQ(obj.as<msgpack::type::ext>(), v);
|
||||
EXPECT_EQ(obj.as<msgpack::type::ext_ref>(), v);
|
||||
}
|
||||
|
||||
TEST(object_with_zone, ext_from_buf)
|
||||
{
|
||||
char const buf[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
msgpack::type::ext v(42, buf, sizeof(buf));
|
||||
msgpack::zone z;
|
||||
msgpack::object obj(v, z);
|
||||
EXPECT_EQ(obj.as<msgpack::type::ext>(), v);
|
||||
EXPECT_EQ(obj.as<msgpack::type::ext_ref>(), v);
|
||||
}
|
||||
|
||||
TEST(object_with_zone, ext_ref_empty)
|
||||
{
|
||||
msgpack::type::ext_ref v;
|
||||
msgpack::zone z;
|
||||
msgpack::object obj(v, z);
|
||||
EXPECT_EQ(obj.as<msgpack::type::ext>(), v);
|
||||
EXPECT_EQ(obj.as<msgpack::type::ext_ref>(), v);
|
||||
}
|
||||
|
||||
TEST(object_with_zone, ext_ref_from_buf)
|
||||
{
|
||||
char const buf[] = { 77, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
msgpack::type::ext_ref v(buf, sizeof(buf));
|
||||
msgpack::zone z;
|
||||
msgpack::object obj(v, z);
|
||||
EXPECT_EQ(obj.as<msgpack::type::ext>(), v);
|
||||
EXPECT_EQ(obj.as<msgpack::type::ext_ref>(), v);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user