Coverage Report

Created: 2023-09-25 06:13

/src/msgpack-c/include/msgpack/v1/adaptor/ext.hpp
Line
Count
Source (jump to first uncovered line)
1
//
2
// MessagePack for C++ static resolution routine
3
//
4
// Copyright (C) 2015-2016 KONDO Takatoshi
5
//
6
//    Distributed under the Boost Software License, Version 1.0.
7
//    (See accompanying file LICENSE_1_0.txt or copy at
8
//    http://www.boost.org/LICENSE_1_0.txt)
9
//
10
#ifndef MSGPACK_V1_TYPE_EXT_HPP
11
#define MSGPACK_V1_TYPE_EXT_HPP
12
13
#include "msgpack/v1/adaptor/ext_decl.hpp"
14
#include "msgpack/adaptor/check_container_size.hpp"
15
#include <cstring>
16
#include <string>
17
18
namespace msgpack {
19
20
/// @cond
21
MSGPACK_API_VERSION_NAMESPACE(v1) {
22
/// @endcond
23
24
namespace type {
25
26
class ext {
27
public:
28
0
    ext() : m_data(1, 0) {}
29
0
    ext(int8_t t, const char* p, uint32_t s) {
30
0
        msgpack::detail::check_container_size_for_ext<sizeof(std::size_t)>(s);
31
0
        m_data.reserve(static_cast<std::size_t>(s) + 1);
32
0
        m_data.push_back(static_cast<char>(t));
33
0
        m_data.insert(m_data.end(), p, p + s);
34
0
    }
35
0
    ext(int8_t t, uint32_t s) {
36
0
        msgpack::detail::check_container_size_for_ext<sizeof(std::size_t)>(s);
37
0
        m_data.resize(static_cast<std::size_t>(s) + 1);
38
0
        m_data[0] = static_cast<char>(t);
39
0
    }
40
    explicit ext(ext_ref const&);
41
0
    int8_t type() const {
42
0
        return static_cast<int8_t>(m_data[0]);
43
0
    }
44
0
    const char* data() const {
45
0
        return &m_data[0] + 1;
46
0
    }
47
0
    char* data() {
48
0
        return &m_data[0] + 1;
49
0
    }
50
0
    uint32_t size() const {
51
0
        return static_cast<uint32_t>(m_data.size()) - 1;
52
0
    }
53
0
    bool operator== (const ext& x) const {
54
0
        return m_data == x.m_data;
55
0
    }
56
57
0
    bool operator!= (const ext& x) const {
58
0
        return !(*this == x);
59
0
    }
60
61
0
    bool operator< (const ext& x) const {
62
0
        return m_data < x.m_data;
63
0
    }
64
65
0
    bool operator> (const ext& x) const {
66
0
        return m_data > x.m_data;
67
0
    }
68
private:
69
    std::vector<char> m_data;
70
    friend class ext_ref;
71
};
72
73
} // namespace type
74
75
namespace adaptor {
76
77
template <>
78
struct convert<msgpack::type::ext> {
79
0
    msgpack::object const& operator()(msgpack::object const& o, msgpack::type::ext& v) const {
80
0
        if(o.type != msgpack::type::EXT) {
81
0
            throw msgpack::type_error();
82
0
        }
83
0
        v = msgpack::type::ext(o.via.ext.type(), o.via.ext.data(), o.via.ext.size);
84
0
        return o;
85
0
    }
86
};
87
88
template <>
89
struct pack<msgpack::type::ext> {
90
    template <typename Stream>
91
    msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const msgpack::type::ext& v) const {
92
        // size limit has already been checked at ext's constructor
93
        uint32_t size = v.size();
94
        o.pack_ext(size, v.type());
95
        o.pack_ext_body(v.data(), size);
96
        return o;
97
    }
98
};
99
100
template <>
101
struct object_with_zone<msgpack::type::ext> {
102
0
    void operator()(msgpack::object::with_zone& o, const msgpack::type::ext& v) const {
103
0
        // size limit has already been checked at ext's constructor
104
0
        uint32_t size = v.size();
105
0
        o.type = msgpack::type::EXT;
106
0
        char* ptr = static_cast<char*>(o.zone.allocate_align(size + 1, MSGPACK_ZONE_ALIGNOF(char)));
107
0
        o.via.ext.ptr = ptr;
108
0
        o.via.ext.size = size;
109
0
        ptr[0] = static_cast<char>(v.type());
110
0
        std::memcpy(ptr + 1, v.data(), size);
111
0
    }
112
};
113
114
} // namespace adaptor
115
116
namespace type {
117
118
class ext_ref {
119
public:
120
    // ext_ref should be default constructible to support 'convert'.
121
    // A default constructed ext_ref object::m_ptr doesn't have the buffer to point to.
122
    // In order to avoid nullptr checking branches, m_ptr points to m_size.
123
    // So type() returns unspecified but valid value. It might be a zero because m_size
124
    // is initialized as zero, but shouldn't assume that.
125
0
    ext_ref() : m_ptr(static_cast<char*>(static_cast<void*>(&m_size))), m_size(0) {}
126
    ext_ref(const char* p, uint32_t s) :
127
        m_ptr(s == 0 ? static_cast<char*>(static_cast<void*>(&m_size)) : p),
128
0
        m_size(s == 0 ? 0 : s - 1) {
129
0
        msgpack::detail::check_container_size_for_ext<sizeof(std::size_t)>(s);
130
0
    }
131
132
    // size limit has already been checked at ext's constructor
133
0
    ext_ref(ext const& x) : m_ptr(&x.m_data[0]), m_size(x.size()) {}
134
135
0
    const char* data() const {
136
0
        return m_ptr + 1;
137
0
    }
138
139
0
    uint32_t size() const {
140
0
        return m_size;
141
0
    }
142
143
0
    int8_t type() const {
144
0
        return static_cast<int8_t>(m_ptr[0]);
145
0
    }
146
147
0
    std::string str() const {
148
0
        return std::string(m_ptr + 1, m_size);
149
0
    }
150
151
0
    bool operator== (const ext_ref& x) const {
152
0
        return m_size == x.m_size && std::memcmp(m_ptr, x.m_ptr, m_size) == 0;
153
0
    }
154
155
0
    bool operator!= (const ext_ref& x) const {
156
0
        return !(*this == x);
157
0
    }
158
159
0
    bool operator< (const ext_ref& x) const {
160
0
        if (m_size < x.m_size) return true;
161
0
        if (m_size > x.m_size) return false;
162
0
        return std::memcmp(m_ptr, x.m_ptr, m_size) < 0;
163
0
    }
164
165
0
    bool operator> (const ext_ref& x) const {
166
0
        if (m_size > x.m_size) return true;
167
0
        if (m_size < x.m_size) return false;
168
0
        return std::memcmp(m_ptr, x.m_ptr, m_size) > 0;
169
0
    }
170
171
private:
172
    const char* m_ptr;
173
    uint32_t m_size;
174
    friend struct adaptor::object<msgpack::type::ext_ref>;
175
};
176
177
inline ext::ext(ext_ref const& x) {
178
    // size limit has already been checked at ext_ref's constructor
179
    m_data.reserve(x.size() + 1);
180
181
    m_data.push_back(static_cast<char>(x.type()));
182
    m_data.insert(m_data.end(), x.data(), x.data() + x.size());
183
}
184
185
} // namespace type
186
187
namespace adaptor {
188
189
template <>
190
struct convert<msgpack::type::ext_ref> {
191
0
    msgpack::object const& operator()(msgpack::object const& o, msgpack::type::ext_ref& v) const {
192
0
        if(o.type != msgpack::type::EXT) { throw msgpack::type_error(); }
193
0
        v = msgpack::type::ext_ref(o.via.ext.ptr, o.via.ext.size + 1);
194
0
        return o;
195
0
    }
196
};
197
198
template <>
199
struct pack<msgpack::type::ext_ref> {
200
    template <typename Stream>
201
    msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const msgpack::type::ext_ref& v) const {
202
        // size limit has already been checked at ext_ref's constructor
203
        uint32_t size = v.size();
204
        o.pack_ext(size, v.type());
205
        o.pack_ext_body(v.data(), size);
206
        return o;
207
    }
208
};
209
210
template <>
211
struct object<msgpack::type::ext_ref> {
212
0
    void operator()(msgpack::object& o, const msgpack::type::ext_ref& v) const {
213
0
        // size limit has already been checked at ext_ref's constructor
214
0
        uint32_t size = v.size();
215
0
        o.type = msgpack::type::EXT;
216
0
        o.via.ext.ptr = v.m_ptr;
217
0
        o.via.ext.size = size;
218
0
    }
219
};
220
221
template <>
222
struct object_with_zone<msgpack::type::ext_ref> {
223
0
    void operator()(msgpack::object::with_zone& o, const msgpack::type::ext_ref& v) const {
224
0
        static_cast<msgpack::object&>(o) << v;
225
0
    }
226
};
227
228
} // namespace adaptor
229
230
/// @cond
231
} // MSGPACK_API_VERSION_NAMESPACE(v1)
232
/// @endcond
233
234
} // namespace msgpack
235
236
#endif // MSGPACK_V1_TYPE_EXT_HPP