Coverage Report

Created: 2023-09-25 06:13

/src/msgpack-c/include/msgpack/v1/object.hpp
Line
Count
Source (jump to first uncovered line)
1
//
2
// MessagePack for C++ static resolution routine
3
//
4
// Copyright (C) 2008-2014 FURUHASHI Sadayuki and 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_OBJECT_HPP
11
#define MSGPACK_V1_OBJECT_HPP
12
13
#include "msgpack/object_decl.hpp"
14
#include "msgpack/adaptor/check_container_size.hpp"
15
16
#include <cstring>
17
#include <stdexcept>
18
#include <typeinfo>
19
#include <limits>
20
#include <ostream>
21
#include <typeinfo>
22
#include <iomanip>
23
24
namespace msgpack {
25
26
/// @cond
27
MSGPACK_API_VERSION_NAMESPACE(v1) {
28
/// @endcond
29
30
struct object_kv {
31
    msgpack::object key;
32
    msgpack::object val;
33
};
34
35
struct object::with_zone : msgpack::object {
36
0
    with_zone(msgpack::zone& z) : zone(z) { }
37
    msgpack::zone& zone;
38
private:
39
    with_zone();
40
};
41
42
43
/// The class holds object and zone
44
class object_handle {
45
public:
46
    /// Constructor that creates nil object and null zone.
47
0
    object_handle() {}
48
49
    /// Constructor that creates an object_handle holding object `obj` and zone `z`.
50
    /**
51
     * @param obj object
52
     * @param z zone
53
     */
54
    object_handle(
55
        msgpack::object const& obj,
56
#if defined(MSGPACK_USE_CPP03)
57
        msgpack::unique_ptr<msgpack::zone> z
58
#else  // defined(MSGPACK_USE_CPP03)
59
        msgpack::unique_ptr<msgpack::zone>&& z
60
#endif // defined(MSGPACK_USE_CPP03)
61
    ) :
62
1.19k
        m_obj(obj), m_zone(msgpack::move(z)) { }
63
64
    void set(msgpack::object const& obj)
65
0
        { m_obj = obj; }
66
67
    /// Get object reference
68
    /**
69
     * @return object
70
     */
71
    const msgpack::object& get() const
72
1.19k
        { return m_obj; }
73
74
    /**
75
     * @return object (to mimic smart pointers).
76
     */
77
    const msgpack::object& operator*() const
78
0
        { return get(); }
79
80
    /**
81
     * @return the address of the object (to mimic smart pointers).
82
     */
83
    const msgpack::object* operator->() const
84
0
        { return &get(); }
85
86
    /// Get unique_ptr reference of zone.
87
    /**
88
     * @return unique_ptr reference of zone
89
     */
90
    msgpack::unique_ptr<msgpack::zone>& zone()
91
0
        { return m_zone; }
92
93
    /// Get unique_ptr const reference of zone.
94
    /**
95
     * @return unique_ptr const reference of zone
96
     */
97
    const msgpack::unique_ptr<msgpack::zone>& zone() const
98
0
        { return m_zone; }
99
100
#if defined(MSGPACK_USE_CPP03)
101
    struct object_handle_ref {
102
        object_handle_ref(object_handle* oh):m_oh(oh) {}
103
        object_handle* m_oh;
104
    };
105
106
    object_handle(object_handle& other):
107
        m_obj(other.m_obj),
108
        m_zone(msgpack::move(other.m_zone)) {
109
    }
110
111
    object_handle(object_handle_ref ref):
112
        m_obj(ref.m_oh->m_obj),
113
        m_zone(msgpack::move(ref.m_oh->m_zone)) {
114
    }
115
116
    object_handle& operator=(object_handle& other) {
117
        m_obj = other.m_obj;
118
        m_zone = msgpack::move(other.m_zone);
119
        return *this;
120
    }
121
122
    object_handle& operator=(object_handle_ref ref) {
123
        m_obj = ref.m_oh->m_obj;
124
        m_zone = msgpack::move(ref.m_oh->m_zone);
125
        return *this;
126
    }
127
128
    operator object_handle_ref() {
129
        return object_handle_ref(this);
130
    }
131
#endif // defined(MSGPACK_USE_CPP03)
132
133
private:
134
    msgpack::object m_obj;
135
    msgpack::unique_ptr<msgpack::zone> m_zone;
136
};
137
138
namespace detail {
139
140
template <std::size_t N>
141
inline std::size_t add_ext_type_size(std::size_t size) {
142
    return size + 1;
143
}
144
145
template <>
146
0
inline std::size_t add_ext_type_size<4>(std::size_t size) {
147
0
    return size == 0xffffffff ? size : size + 1;
148
0
}
149
150
} // namespace detail
151
class object_parser {
152
private:
153
    enum next_ret {
154
        cont,
155
        finish,
156
        abort
157
    };
158
    struct elem {
159
        elem(msgpack::object const* p, std::size_t r)
160
83.8k
            : rest(r), is_map(false), is_key(false) {
161
83.8k
            as.obj_ptr = p;
162
83.8k
        }
163
164
        elem(msgpack::object_kv const* p, std::size_t r)
165
128k
            : rest(r), is_map(true), is_key(true) {
166
128k
            as.kv_ptr = p;
167
128k
        }
168
169
1.27M
        msgpack::object const& get() const {
170
1.27M
            if (is_map) {
171
873k
                if (is_key) {
172
436k
                    return as.kv_ptr->key;
173
436k
                }
174
436k
                else {
175
436k
                    return as.kv_ptr->val;
176
436k
                }
177
873k
            }
178
396k
            else {
179
396k
                return *as.obj_ptr;
180
396k
            }
181
1.27M
        }
182
183
        template <typename Visitor>
184
1.29M
        next_ret next(Visitor& v) {
185
1.29M
            if (rest == 0) {
186
28.1k
                if (is_map) {
187
12.8k
                    if (!v.end_map()) return abort;
188
12.8k
                }
189
15.2k
                else {
190
15.2k
                    if (!v.end_array()) return abort;
191
15.2k
                }
192
28.1k
                return finish;
193
28.1k
            }
194
1.27M
            else {
195
1.27M
                if (is_map) {
196
873k
                    if (is_key) {
197
436k
                        if (!v.end_map_key()) return abort;
198
436k
                        if (!v.start_map_value()) return abort;
199
436k
                        is_key = false;
200
436k
                    }
201
436k
                    else {
202
436k
                        if (!v.end_map_value()) return abort;
203
436k
                        --rest;
204
436k
                        if (rest == 0) {
205
115k
                            if (!v.end_map()) return abort;
206
115k
                            return finish;
207
115k
                        }
208
321k
                        if (!v.start_map_key()) return abort;
209
321k
                        ++as.kv_ptr;
210
321k
                        is_key = true;
211
321k
                    }
212
873k
                }
213
396k
                else {
214
396k
                    if (!v.end_array_item()) return abort;
215
396k
                    --rest;
216
396k
                    if (rest == 0) {
217
68.5k
                        if (!v.end_array()) return abort;
218
68.5k
                        return finish;
219
68.5k
                    }
220
328k
                    if (!v.start_array_item()) return abort;
221
328k
                    ++as.obj_ptr;
222
328k
                }
223
1.08M
                return cont;
224
1.27M
            }
225
1.29M
        }
msgpack::v1::object_parser::next_ret msgpack::v1::object_parser::elem::next<msgpack::v1::object_pack_visitor<msgpack::v1::sbuffer> >(msgpack::v1::object_pack_visitor<msgpack::v1::sbuffer>&)
Line
Count
Source
184
1.29M
        next_ret next(Visitor& v) {
185
1.29M
            if (rest == 0) {
186
28.1k
                if (is_map) {
187
12.8k
                    if (!v.end_map()) return abort;
188
12.8k
                }
189
15.2k
                else {
190
15.2k
                    if (!v.end_array()) return abort;
191
15.2k
                }
192
28.1k
                return finish;
193
28.1k
            }
194
1.27M
            else {
195
1.27M
                if (is_map) {
196
873k
                    if (is_key) {
197
436k
                        if (!v.end_map_key()) return abort;
198
436k
                        if (!v.start_map_value()) return abort;
199
436k
                        is_key = false;
200
436k
                    }
201
436k
                    else {
202
436k
                        if (!v.end_map_value()) return abort;
203
436k
                        --rest;
204
436k
                        if (rest == 0) {
205
115k
                            if (!v.end_map()) return abort;
206
115k
                            return finish;
207
115k
                        }
208
321k
                        if (!v.start_map_key()) return abort;
209
321k
                        ++as.kv_ptr;
210
321k
                        is_key = true;
211
321k
                    }
212
873k
                }
213
396k
                else {
214
396k
                    if (!v.end_array_item()) return abort;
215
396k
                    --rest;
216
396k
                    if (rest == 0) {
217
68.5k
                        if (!v.end_array()) return abort;
218
68.5k
                        return finish;
219
68.5k
                    }
220
328k
                    if (!v.start_array_item()) return abort;
221
328k
                    ++as.obj_ptr;
222
328k
                }
223
1.08M
                return cont;
224
1.27M
            }
225
1.29M
        }
Unexecuted instantiation: msgpack::v1::object_parser::next_ret msgpack::v1::object_parser::elem::next<msgpack::v1::aligned_zone_size_visitor>(msgpack::v1::aligned_zone_size_visitor&)
Unexecuted instantiation: msgpack::v1::object_parser::next_ret msgpack::v1::object_parser::elem::next<msgpack::v1::adaptor::object_with_zone<msgpack::v2::object, void>::object_with_zone_visitor>(msgpack::v1::adaptor::object_with_zone<msgpack::v2::object, void>::object_with_zone_visitor&)
Unexecuted instantiation: msgpack::v1::object_parser::next_ret msgpack::v1::object_parser::elem::next<msgpack::v1::object_equal_visitor>(msgpack::v1::object_equal_visitor&)
Unexecuted instantiation: msgpack::v1::object_parser::next_ret msgpack::v1::object_parser::elem::next<msgpack::v1::object_stringize_visitor>(msgpack::v1::object_stringize_visitor&)
226
227
        union {
228
            msgpack::object const* obj_ptr;
229
            msgpack::object_kv const* kv_ptr;
230
        } as;
231
        std::size_t rest;
232
        bool is_map;
233
        bool is_key;
234
    };
235
public:
236
1.19k
    explicit object_parser(msgpack::object const& obj):m_current(&obj) {}
237
    template <typename Visitor>
238
1.19k
    void parse(Visitor& v) {
239
1.27M
        while (true) {
240
1.27M
            bool start_collection = false;
241
1.27M
            switch(m_current->type) {
242
3.06k
            case msgpack::type::NIL:
243
3.06k
                if (!v.visit_nil()) return;
244
3.06k
                break;
245
5.96k
            case msgpack::type::BOOLEAN:
246
5.96k
                if (!v.visit_boolean(m_current->via.boolean)) return;
247
5.96k
                break;
248
431k
            case msgpack::type::POSITIVE_INTEGER:
249
431k
                if (!v.visit_positive_integer(m_current->via.u64)) return;
250
431k
                break;
251
431k
            case msgpack::type::NEGATIVE_INTEGER:
252
105k
                if (!v.visit_negative_integer(m_current->via.i64)) return;
253
105k
                break;
254
461k
            case msgpack::type::FLOAT32:
255
461k
                if (!v.visit_float32(static_cast<float>(m_current->via.f64))) return;
256
461k
                break;
257
461k
            case msgpack::type::FLOAT64:
258
17.3k
                if (!v.visit_float64(m_current->via.f64)) return;
259
17.3k
                break;
260
17.3k
            case msgpack::type::STR:
261
14.7k
                if (!v.visit_str(m_current->via.str.ptr, m_current->via.str.size)) return;
262
14.7k
                break;
263
14.7k
            case msgpack::type::BIN:
264
2.35k
                if (!v.visit_bin(m_current->via.bin.ptr, m_current->via.bin.size)) return;
265
2.35k
                break;
266
17.4k
            case msgpack::type::EXT:
267
17.4k
                msgpack::detail::check_container_size<sizeof(std::size_t)>(m_current->via.ext.size);
268
17.4k
                if (!v.visit_ext(m_current->via.ext.ptr, m_current->via.ext.size + 1)) return;
269
17.4k
                break;
270
83.8k
            case msgpack::type::ARRAY:
271
83.8k
                if (!v.start_array(m_current->via.array.size)) return;
272
83.8k
                m_ctx.push_back(elem(m_current->via.array.ptr, m_current->via.array.size));
273
83.8k
                start_collection = m_current->via.array.size != 0;
274
83.8k
                if (start_collection) {
275
68.5k
                    if (!v.start_array_item()) return;
276
68.5k
                }
277
83.8k
                break;
278
128k
            case msgpack::type::MAP:
279
128k
                if (!v.start_map(m_current->via.map.size)) return;
280
128k
                m_ctx.push_back(elem(m_current->via.map.ptr, m_current->via.map.size));
281
128k
                start_collection = m_current->via.map.size != 0;
282
128k
                if (start_collection) {
283
115k
                    if (!v.start_map_key()) return;
284
115k
                }
285
128k
                break;
286
128k
            default:
287
0
                throw msgpack::type_error();
288
0
                break;
289
1.27M
            }
290
1.27M
            if (m_ctx.empty()) return;
291
1.27M
            if (!start_collection) {
292
1.29M
                while (true) {
293
1.29M
                    next_ret r = m_ctx.back().next(v);
294
1.29M
                    if (r == finish) {
295
211k
                        m_ctx.pop_back();
296
211k
                        if (m_ctx.empty()) return;
297
211k
                    }
298
1.08M
                    else if (r == cont) {
299
1.08M
                        break;
300
1.08M
                    }
301
0
                    else {
302
                        // abort
303
0
                        return;
304
0
                    }
305
1.29M
                }
306
1.08M
            }
307
1.27M
            m_current = &m_ctx.back().get();
308
1.27M
        }
309
1.19k
    }
void msgpack::v1::object_parser::parse<msgpack::v1::object_pack_visitor<msgpack::v1::sbuffer> >(msgpack::v1::object_pack_visitor<msgpack::v1::sbuffer>&)
Line
Count
Source
238
1.19k
    void parse(Visitor& v) {
239
1.27M
        while (true) {
240
1.27M
            bool start_collection = false;
241
1.27M
            switch(m_current->type) {
242
3.06k
            case msgpack::type::NIL:
243
3.06k
                if (!v.visit_nil()) return;
244
3.06k
                break;
245
5.96k
            case msgpack::type::BOOLEAN:
246
5.96k
                if (!v.visit_boolean(m_current->via.boolean)) return;
247
5.96k
                break;
248
431k
            case msgpack::type::POSITIVE_INTEGER:
249
431k
                if (!v.visit_positive_integer(m_current->via.u64)) return;
250
431k
                break;
251
431k
            case msgpack::type::NEGATIVE_INTEGER:
252
105k
                if (!v.visit_negative_integer(m_current->via.i64)) return;
253
105k
                break;
254
461k
            case msgpack::type::FLOAT32:
255
461k
                if (!v.visit_float32(static_cast<float>(m_current->via.f64))) return;
256
461k
                break;
257
461k
            case msgpack::type::FLOAT64:
258
17.3k
                if (!v.visit_float64(m_current->via.f64)) return;
259
17.3k
                break;
260
17.3k
            case msgpack::type::STR:
261
14.7k
                if (!v.visit_str(m_current->via.str.ptr, m_current->via.str.size)) return;
262
14.7k
                break;
263
14.7k
            case msgpack::type::BIN:
264
2.35k
                if (!v.visit_bin(m_current->via.bin.ptr, m_current->via.bin.size)) return;
265
2.35k
                break;
266
17.4k
            case msgpack::type::EXT:
267
17.4k
                msgpack::detail::check_container_size<sizeof(std::size_t)>(m_current->via.ext.size);
268
17.4k
                if (!v.visit_ext(m_current->via.ext.ptr, m_current->via.ext.size + 1)) return;
269
17.4k
                break;
270
83.8k
            case msgpack::type::ARRAY:
271
83.8k
                if (!v.start_array(m_current->via.array.size)) return;
272
83.8k
                m_ctx.push_back(elem(m_current->via.array.ptr, m_current->via.array.size));
273
83.8k
                start_collection = m_current->via.array.size != 0;
274
83.8k
                if (start_collection) {
275
68.5k
                    if (!v.start_array_item()) return;
276
68.5k
                }
277
83.8k
                break;
278
128k
            case msgpack::type::MAP:
279
128k
                if (!v.start_map(m_current->via.map.size)) return;
280
128k
                m_ctx.push_back(elem(m_current->via.map.ptr, m_current->via.map.size));
281
128k
                start_collection = m_current->via.map.size != 0;
282
128k
                if (start_collection) {
283
115k
                    if (!v.start_map_key()) return;
284
115k
                }
285
128k
                break;
286
128k
            default:
287
0
                throw msgpack::type_error();
288
0
                break;
289
1.27M
            }
290
1.27M
            if (m_ctx.empty()) return;
291
1.27M
            if (!start_collection) {
292
1.29M
                while (true) {
293
1.29M
                    next_ret r = m_ctx.back().next(v);
294
1.29M
                    if (r == finish) {
295
211k
                        m_ctx.pop_back();
296
211k
                        if (m_ctx.empty()) return;
297
211k
                    }
298
1.08M
                    else if (r == cont) {
299
1.08M
                        break;
300
1.08M
                    }
301
0
                    else {
302
                        // abort
303
0
                        return;
304
0
                    }
305
1.29M
                }
306
1.08M
            }
307
1.27M
            m_current = &m_ctx.back().get();
308
1.27M
        }
309
1.19k
    }
Unexecuted instantiation: void msgpack::v1::object_parser::parse<msgpack::v1::aligned_zone_size_visitor>(msgpack::v1::aligned_zone_size_visitor&)
Unexecuted instantiation: void msgpack::v1::object_parser::parse<msgpack::v1::adaptor::object_with_zone<msgpack::v2::object, void>::object_with_zone_visitor>(msgpack::v1::adaptor::object_with_zone<msgpack::v2::object, void>::object_with_zone_visitor&)
Unexecuted instantiation: void msgpack::v1::object_parser::parse<msgpack::v1::object_equal_visitor>(msgpack::v1::object_equal_visitor&)
Unexecuted instantiation: void msgpack::v1::object_parser::parse<msgpack::v1::object_stringize_visitor>(msgpack::v1::object_stringize_visitor&)
310
private:
311
    msgpack::object const* m_current;
312
    std::vector<elem> m_ctx;
313
};
314
315
template <typename Stream>
316
struct object_pack_visitor {
317
    explicit object_pack_visitor(msgpack::packer<Stream>& pk)
318
1.19k
        :m_packer(pk) {}
319
3.06k
    bool visit_nil() {
320
3.06k
        m_packer.pack_nil();
321
3.06k
        return true;
322
3.06k
    }
323
5.96k
    bool visit_boolean(bool v) {
324
5.96k
        if (v) m_packer.pack_true();
325
1.18k
        else m_packer.pack_false();
326
5.96k
        return true;
327
5.96k
    }
328
431k
    bool visit_positive_integer(uint64_t v) {
329
431k
        m_packer.pack_uint64(v);
330
431k
        return true;
331
431k
    }
332
105k
    bool visit_negative_integer(int64_t v) {
333
105k
        m_packer.pack_int64(v);
334
105k
        return true;
335
105k
    }
336
461k
    bool visit_float32(float v) {
337
461k
        m_packer.pack_float(v);
338
461k
        return true;
339
461k
    }
340
17.3k
    bool visit_float64(double v) {
341
17.3k
        m_packer.pack_double(v);
342
17.3k
        return true;
343
17.3k
    }
344
14.7k
    bool visit_str(const char* v, uint32_t size) {
345
14.7k
        m_packer.pack_str(size);
346
14.7k
        m_packer.pack_str_body(v, size);
347
14.7k
        return true;
348
14.7k
    }
349
2.35k
    bool visit_bin(const char* v, uint32_t size) {
350
2.35k
        m_packer.pack_bin(size);
351
2.35k
        m_packer.pack_bin_body(v, size);
352
2.35k
        return true;
353
2.35k
    }
354
17.4k
    bool visit_ext(const char* v, uint32_t size) {
355
17.4k
        m_packer.pack_ext(size - 1, static_cast<int8_t>(*v));
356
17.4k
        m_packer.pack_ext_body(v + 1, size - 1);
357
17.4k
        return true;
358
17.4k
    }
359
83.8k
    bool start_array(uint32_t num_elements) {
360
83.8k
        m_packer.pack_array(num_elements);
361
83.8k
        return true;
362
83.8k
    }
363
396k
    bool start_array_item() {
364
396k
        return true;
365
396k
    }
366
396k
    bool end_array_item() {
367
396k
        return true;
368
396k
    }
369
83.8k
    bool end_array() {
370
83.8k
        return true;
371
83.8k
    }
372
128k
    bool start_map(uint32_t num_kv_pairs) {
373
128k
        m_packer.pack_map(num_kv_pairs);
374
128k
        return true;
375
128k
    }
376
436k
    bool start_map_key() {
377
436k
        return true;
378
436k
    }
379
436k
    bool end_map_key() {
380
436k
        return true;
381
436k
    }
382
436k
    bool start_map_value() {
383
436k
        return true;
384
436k
    }
385
436k
    bool end_map_value() {
386
436k
        return true;
387
436k
    }
388
128k
    bool end_map() {
389
128k
        return true;
390
128k
    }
391
private:
392
    msgpack::packer<Stream>& m_packer;
393
};
394
395
396
struct object_stringize_visitor {
397
    explicit object_stringize_visitor(std::ostream& os)
398
0
        :m_os(os) {}
399
0
    bool visit_nil() {
400
0
        m_os << "null";
401
0
        return true;
402
0
    }
403
0
    bool visit_boolean(bool v) {
404
0
        if (v) m_os << "true";
405
0
        else m_os << "false";
406
0
        return true;
407
0
    }
408
0
    bool visit_positive_integer(uint64_t v) {
409
0
        m_os << v;
410
0
        return true;
411
0
    }
412
0
    bool visit_negative_integer(int64_t v) {
413
0
        m_os << v;
414
0
        return true;
415
0
    }
416
0
    bool visit_float32(float v) {
417
0
        m_os << v;
418
0
        return true;
419
0
    }
420
0
    bool visit_float64(double v) {
421
0
        m_os << v;
422
0
        return true;
423
0
    }
424
0
    bool visit_str(const char* v, uint32_t size) {
425
0
        m_os << '"';
426
0
        for (uint32_t i = 0; i < size; ++i) {
427
0
            char c = v[i];
428
0
            switch (c) {
429
0
            case '\\':
430
0
                m_os << "\\\\";
431
0
                break;
432
0
            case '"':
433
0
                m_os << "\\\"";
434
0
                break;
435
0
            case '/':
436
0
                m_os << "\\/";
437
0
                break;
438
0
            case '\b':
439
0
                m_os << "\\b";
440
0
                break;
441
0
            case '\f':
442
0
                m_os << "\\f";
443
0
                break;
444
0
            case '\n':
445
0
                m_os << "\\n";
446
0
                break;
447
0
            case '\r':
448
0
                m_os << "\\r";
449
0
                break;
450
0
            case '\t':
451
0
                m_os << "\\t";
452
0
                break;
453
0
            default: {
454
0
                unsigned int code = static_cast<unsigned int>(c);
455
0
                if (code < 0x20 || code == 0x7f) {
456
0
                    std::ios::fmtflags flags(m_os.flags());
457
0
                    m_os << "\\u" << std::hex << std::setw(4) << std::setfill('0') << (code & 0xff);
458
0
                    m_os.flags(flags);
459
0
                }
460
0
                else {
461
0
                    m_os << c;
462
0
                }
463
0
            } break;
464
0
            }
465
0
        }
466
0
        m_os << '"';
467
0
        return true;
468
0
    }
469
0
    bool visit_bin(const char* /*v*/, uint32_t size) {
470
0
        m_os << "\"BIN(size:" << size << ")\"";
471
0
        return true;
472
0
    }
473
0
    bool visit_ext(const char* v, uint32_t size) {
474
0
        if (size == 0) {
475
0
            m_os << "\"EXT(size:0)\"";
476
0
        }
477
0
        else {
478
0
            m_os << "\"EXT(type:" << static_cast<int>(v[0]) << ",size:" << size - 1 << ")\"";
479
0
        }
480
0
        return true;
481
0
    }
482
0
    bool start_array(uint32_t num_elements) {
483
0
        m_current_size.push_back(num_elements);
484
0
        m_os << "[";
485
0
        return true;
486
0
    }
487
0
    bool start_array_item() {
488
0
        return true;
489
0
    }
490
0
    bool end_array_item() {
491
0
        --m_current_size.back();
492
0
        if (m_current_size.back() != 0) {
493
0
            m_os << ",";
494
0
        }
495
0
        return true;
496
0
    }
497
0
    bool end_array() {
498
0
        m_current_size.pop_back();
499
0
        m_os << "]";
500
0
        return true;
501
0
    }
502
0
    bool start_map(uint32_t num_kv_pairs) {
503
0
        m_current_size.push_back(num_kv_pairs);
504
0
        m_os << "{";
505
0
        return true;
506
0
    }
507
0
    bool start_map_key() {
508
0
        return true;
509
0
    }
510
0
    bool end_map_key() {
511
0
        m_os << ":";
512
0
        return true;
513
0
    }
514
0
    bool start_map_value() {
515
0
        return true;
516
0
    }
517
0
    bool end_map_value() {
518
0
        --m_current_size.back();
519
0
        if (m_current_size.back() != 0) {
520
0
            m_os << ",";
521
0
        }
522
0
        return true;
523
0
    }
524
0
    bool end_map() {
525
0
        m_current_size.pop_back();
526
0
        m_os << "}";
527
0
        return true;
528
0
    }
529
private:
530
    std::ostream& m_os;
531
    std::vector<uint32_t> m_current_size;
532
};
533
534
struct aligned_zone_size_visitor {
535
    explicit aligned_zone_size_visitor(std::size_t& s)
536
0
        :m_size(s) {}
537
0
    bool visit_nil() {
538
0
        return true;
539
0
    }
540
0
    bool visit_boolean(bool) {
541
0
        return true;
542
0
    }
543
0
    bool visit_positive_integer(uint64_t) {
544
0
        return true;
545
0
    }
546
0
    bool visit_negative_integer(int64_t) {
547
0
        return true;
548
0
    }
549
0
    bool visit_float32(float) {
550
0
        return true;
551
0
    }
552
0
    bool visit_float64(double) {
553
0
        return true;
554
0
    }
555
0
    bool visit_str(const char*, uint32_t size) {
556
0
        m_size += msgpack::aligned_size(size, MSGPACK_ZONE_ALIGNOF(char));
557
0
        return true;
558
0
    }
559
0
    bool visit_bin(const char*, uint32_t size) {
560
0
        m_size += msgpack::aligned_size(size, MSGPACK_ZONE_ALIGNOF(char));
561
0
        return true;
562
0
    }
563
0
    bool visit_ext(const char*, uint32_t size) {
564
0
        m_size += msgpack::aligned_size(size, MSGPACK_ZONE_ALIGNOF(char));
565
0
        return true;
566
0
    }
567
0
    bool start_array(uint32_t num_elements) {
568
0
        m_size += msgpack::aligned_size(
569
0
            sizeof(msgpack::object) * num_elements,
570
0
            MSGPACK_ZONE_ALIGNOF(msgpack::object));
571
0
        return true;
572
0
    }
573
0
    bool start_array_item() {
574
0
        return true;
575
0
    }
576
0
    bool end_array_item() {
577
0
        return true;
578
0
    }
579
0
    bool end_array() {
580
0
        return true;
581
0
    }
582
0
    bool start_map(uint32_t num_kv_pairs) {
583
0
        m_size += msgpack::aligned_size(
584
0
            sizeof(msgpack::object_kv) * num_kv_pairs,
585
0
            MSGPACK_ZONE_ALIGNOF(msgpack::object_kv));
586
0
        return true;
587
0
    }
588
0
    bool start_map_key() {
589
0
        return true;
590
0
    }
591
0
    bool end_map_key() {
592
0
        return true;
593
0
    }
594
0
    bool start_map_value() {
595
0
        return true;
596
0
    }
597
0
    bool end_map_value() {
598
0
        return true;
599
0
    }
600
0
    bool end_map() {
601
0
        return true;
602
0
    }
603
private:
604
    std::size_t& m_size;
605
};
606
607
0
inline std::size_t aligned_zone_size(msgpack::object const& obj) {
608
0
    std::size_t s = 0;
609
0
    aligned_zone_size_visitor vis(s);
610
0
    msgpack::object_parser(obj).parse(vis);
611
0
    return s;
612
0
}
613
614
/// clone object
615
/**
616
 * Clone (deep copy) object.
617
 * The copied object is located on newly allocated zone.
618
 * @param obj copy source object
619
 *
620
 * @return object_handle that holds deep copied object and zone.
621
 */
622
0
inline object_handle clone(msgpack::object const& obj) {
623
0
    std::size_t size = msgpack::aligned_zone_size(obj);
624
0
    msgpack::unique_ptr<msgpack::zone> z(size == 0 ? MSGPACK_NULLPTR : new msgpack::zone(size));
625
0
    msgpack::object newobj = z.get() ? msgpack::object(obj, *z) : obj;
626
0
    return object_handle(newobj, msgpack::move(z));
627
0
}
628
629
template <typename T>
630
inline object::implicit_type::operator T() { return obj.as<T>(); }
631
632
namespace detail {
633
template <typename Stream, typename T>
634
struct packer_serializer {
635
    static msgpack::packer<Stream>& pack(msgpack::packer<Stream>& o, const T& v) {
636
        v.msgpack_pack(o);
637
        return o;
638
    }
639
};
640
} // namespace detail
641
642
// Adaptor functors' member functions definitions.
643
template <typename T, typename Enabler>
644
inline
645
msgpack::object const&
646
adaptor::convert<T, Enabler>::operator()(msgpack::object const& o, T& v) const {
647
    v.msgpack_unpack(o.convert());
648
    return o;
649
}
650
651
template <typename T, typename Enabler>
652
template <typename Stream>
653
inline
654
msgpack::packer<Stream>&
655
adaptor::pack<T, Enabler>::operator()(msgpack::packer<Stream>& o, T const& v) const {
656
    return msgpack::detail::packer_serializer<Stream, T>::pack(o, v);
657
}
658
659
template <typename T, typename Enabler>
660
inline
661
void
662
adaptor::object_with_zone<T, Enabler>::operator()(msgpack::object::with_zone& o, T const& v) const {
663
    v.msgpack_object(static_cast<msgpack::object*>(&o), o.zone);
664
}
665
666
// Adaptor functor specialization to object
667
namespace adaptor {
668
669
template <>
670
struct convert<msgpack::object> {
671
0
    msgpack::object const& operator()(msgpack::object const& o, msgpack::object& v) const {
672
0
        v = o;
673
0
        return o;
674
0
    }
675
};
676
677
template <>
678
struct pack<msgpack::object> {
679
    template <typename Stream>
680
1.19k
    msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, msgpack::object const& v) const {
681
1.19k
        object_pack_visitor<Stream> vis(o);
682
1.19k
        msgpack::object_parser(v).parse(vis);
683
1.19k
        return o;
684
1.19k
    }
685
};
686
687
template <>
688
struct object_with_zone<msgpack::object> {
689
0
    void operator()(msgpack::object::with_zone& o, msgpack::object const& v) const {
690
0
        object_with_zone_visitor vis(o);
691
0
        msgpack::object_parser(v).parse(vis);
692
0
    }
693
private:
694
    struct object_with_zone_visitor {
695
        explicit object_with_zone_visitor(msgpack::object::with_zone& owz)
696
0
            :m_zone(owz.zone), m_ptr(&owz) {
697
0
            m_objs.push_back(&owz);
698
0
        }
699
0
        bool visit_nil() {
700
0
            m_ptr->type = msgpack::type::NIL;
701
0
            return true;
702
0
        }
703
0
        bool visit_boolean(bool v) {
704
0
            m_ptr->type = msgpack::type::BOOLEAN;
705
0
            m_ptr->via.boolean = v;
706
0
            return true;
707
0
        }
708
0
        bool visit_positive_integer(uint64_t v) {
709
0
            m_ptr->type = msgpack::type::POSITIVE_INTEGER;
710
0
            m_ptr->via.u64 = v;
711
0
            return true;
712
0
        }
713
0
        bool visit_negative_integer(int64_t v) {
714
0
            m_ptr->type = msgpack::type::NEGATIVE_INTEGER;
715
0
            m_ptr->via.i64 = v;
716
0
            return true;
717
0
        }
718
0
        bool visit_float32(float v) {
719
0
            m_ptr->type = msgpack::type::FLOAT32;
720
0
            m_ptr->via.f64 = v;
721
0
            return true;
722
0
        }
723
0
        bool visit_float64(double v) {
724
0
            m_ptr->type = msgpack::type::FLOAT64;
725
0
            m_ptr->via.f64 = v;
726
0
            return true;
727
0
        }
728
0
        bool visit_str(const char* v, uint32_t size) {
729
0
            m_ptr->type = msgpack::type::STR;
730
0
            m_ptr->via.str.size = size;
731
0
            char* ptr = static_cast<char*>(m_zone.allocate_align(size, MSGPACK_ZONE_ALIGNOF(char)));
732
0
            m_ptr->via.str.ptr = ptr;
733
0
            std::memcpy(ptr, v, size);
734
0
            return true;
735
0
        }
736
0
        bool visit_bin(const char* v, uint32_t size) {
737
0
            m_ptr->type = msgpack::type::BIN;
738
0
            m_ptr->via.bin.size = size;
739
0
            char* ptr = static_cast<char*>(m_zone.allocate_align(size, MSGPACK_ZONE_ALIGNOF(char)));
740
0
            m_ptr->via.bin.ptr = ptr;
741
0
            std::memcpy(ptr, v, size);
742
0
            return true;
743
0
        }
744
0
        bool visit_ext(const char* v, uint32_t size) {
745
0
            m_ptr->type = msgpack::type::EXT;
746
0
747
0
            // v contains type but length(size) doesn't count the type byte.
748
0
            // See https://github.com/msgpack/msgpack/blob/master/spec.md#ext-format-family
749
0
            m_ptr->via.ext.size = size - 1;
750
0
751
0
            char* ptr = static_cast<char*>(m_zone.allocate_align(size, MSGPACK_ZONE_ALIGNOF(char)));
752
0
            m_ptr->via.ext.ptr = ptr;
753
0
            std::memcpy(ptr, v, size);
754
0
            return true;
755
0
        }
756
0
        bool start_array(uint32_t num_elements) {
757
0
            m_ptr->type = msgpack::type::ARRAY;
758
0
            m_ptr->via.array.ptr = static_cast<msgpack::object*>(
759
0
                m_zone.allocate_align(
760
0
                    sizeof(msgpack::object) * num_elements, MSGPACK_ZONE_ALIGNOF(msgpack::object)));
761
0
            m_ptr->via.array.size = num_elements;
762
0
            m_objs.push_back(elem(m_ptr->via.array.ptr));
763
0
            return true;
764
0
        }
765
0
        bool start_array_item() {
766
0
            m_ptr = m_objs.back().get_item();
767
0
            return true;
768
0
        }
769
0
        bool end_array_item() {
770
0
            ++m_objs.back().as.obj;
771
0
            return true;
772
0
        }
773
0
        bool end_array() {
774
0
            m_objs.pop_back();
775
0
            return true;
776
0
        }
777
0
        bool start_map(uint32_t num_kv_pairs) {
778
0
            m_ptr->type = msgpack::type::MAP;
779
0
            m_ptr->via.map.ptr = (msgpack::object_kv*)m_zone.allocate_align(
780
0
                sizeof(msgpack::object_kv) * num_kv_pairs, MSGPACK_ZONE_ALIGNOF(msgpack::object_kv));
781
0
            m_ptr->via.map.size = num_kv_pairs;
782
0
            m_objs.push_back(elem(m_ptr->via.map.ptr));
783
0
            return true;
784
0
        }
785
0
        bool start_map_key() {
786
0
            m_ptr = m_objs.back().get_key();
787
0
            return true;
788
0
        }
789
0
        bool end_map_key() {
790
0
            return true;
791
0
        }
792
0
        bool start_map_value() {
793
0
            m_ptr = m_objs.back().get_val();
794
0
            return true;
795
0
        }
796
0
        bool end_map_value() {
797
0
            ++m_objs.back().as.kv;
798
0
            return true;
799
0
        }
800
0
        bool end_map() {
801
0
            m_objs.pop_back();
802
0
            return true;
803
0
        }
804
    private:
805
        struct elem {
806
            elem(msgpack::object* obj)
807
0
                :is_obj(true) {
808
0
                as.obj = obj;
809
0
            }
810
            elem(msgpack::object_kv* kv)
811
0
                :is_obj(false) {
812
0
                as.kv = kv;
813
0
            }
814
0
            msgpack::object* get_item() {
815
0
                return as.obj;
816
0
            }
817
0
            msgpack::object* get_key() {
818
0
                return &as.kv->key;
819
0
            }
820
0
            msgpack::object* get_val() {
821
0
                return &as.kv->val;
822
0
            }
823
            union {
824
                msgpack::object* obj;
825
                msgpack::object_kv* kv;
826
            } as;
827
            bool is_obj;
828
        };
829
        std::vector<elem> m_objs;
830
        msgpack::zone& m_zone;
831
        msgpack::object* m_ptr;
832
    };
833
};
834
835
// Adaptor functor specialization to object::with_zone
836
837
template <>
838
struct object_with_zone<msgpack::object::with_zone> {
839
    void operator()(
840
        msgpack::object::with_zone& o,
841
0
        msgpack::object::with_zone const& v) const {
842
0
        o << static_cast<msgpack::object const&>(v);
843
0
    }
844
};
845
846
847
} // namespace adaptor
848
849
850
// obsolete
851
template <typename Type>
852
class define : public Type {
853
public:
854
    typedef Type msgpack_type;
855
    typedef define<Type> define_type;
856
    define() {}
857
    define(const msgpack_type& v) : msgpack_type(v) {}
858
859
    template <typename Packer>
860
    void msgpack_pack(Packer& o) const
861
    {
862
        msgpack::operator<<(o, static_cast<const msgpack_type&>(*this));
863
    }
864
865
    void msgpack_unpack(object const& o)
866
    {
867
        msgpack::operator>>(o, static_cast<msgpack_type&>(*this));
868
    }
869
};
870
871
// deconvert operator
872
873
template <typename Stream>
874
template <typename T>
875
inline msgpack::packer<Stream>& packer<Stream>::pack(const T& v)
876
1.19k
{
877
1.19k
    msgpack::operator<<(*this, v);
878
1.19k
    return *this;
879
1.19k
}
880
881
struct object_equal_visitor {
882
    object_equal_visitor(msgpack::object const& obj, bool& result)
883
0
        :m_ptr(&obj), m_result(result) {}
884
0
    bool visit_nil() {
885
0
        if (m_ptr->type != msgpack::type::NIL) {
886
0
            m_result = false;
887
0
            return false;
888
0
        }
889
0
        return true;
890
0
    }
891
0
    bool visit_boolean(bool v) {
892
0
        if (m_ptr->type != msgpack::type::BOOLEAN || m_ptr->via.boolean != v) {
893
0
            m_result = false;
894
0
            return false;
895
0
        }
896
0
        return true;
897
0
    }
898
0
    bool visit_positive_integer(uint64_t v) {
899
0
        if (m_ptr->type != msgpack::type::POSITIVE_INTEGER || m_ptr->via.u64 != v) {
900
0
            m_result = false;
901
0
            return false;
902
0
        }
903
0
        return true;
904
0
    }
905
0
    bool visit_negative_integer(int64_t v) {
906
0
        if (m_ptr->type != msgpack::type::NEGATIVE_INTEGER || m_ptr->via.i64 != v) {
907
0
            m_result = false;
908
0
            return false;
909
0
        }
910
0
        return true;
911
0
    }
912
0
    bool visit_float32(float v) {
913
0
        if (m_ptr->type != msgpack::type::FLOAT32 || m_ptr->via.f64 != v) {
914
0
            m_result = false;
915
0
            return false;
916
0
        }
917
0
        return true;
918
0
    }
919
0
    bool visit_float64(double v) {
920
0
        if (m_ptr->type != msgpack::type::FLOAT64 || m_ptr->via.f64 != v) {
921
0
            m_result = false;
922
0
            return false;
923
0
        }
924
0
        return true;
925
0
    }
926
0
    bool visit_str(const char* v, uint32_t size) {
927
0
        if (m_ptr->type != msgpack::type::STR ||
928
0
            m_ptr->via.str.size != size ||
929
0
            std::memcmp(m_ptr->via.str.ptr, v, size) != 0) {
930
0
            m_result = false;
931
0
            return false;
932
0
        }
933
0
        return true;
934
0
    }
935
0
    bool visit_bin(const char* v, uint32_t size) {
936
0
        if (m_ptr->type != msgpack::type::BIN ||
937
0
            m_ptr->via.bin.size != size ||
938
0
            std::memcmp(m_ptr->via.bin.ptr, v, size) != 0) {
939
0
            m_result = false;
940
0
            return false;
941
0
        }
942
0
        return true;
943
0
    }
944
0
    bool visit_ext(const char* v, uint32_t size) {
945
0
        if (m_ptr->type != msgpack::type::EXT ||
946
0
            m_ptr->via.ext.size != size - 1 ||
947
0
            std::memcmp(m_ptr->via.ext.ptr, v, size) != 0) {
948
0
            m_result = false;
949
0
            return false;
950
0
        }
951
0
        return true;
952
0
    }
953
0
    bool start_array(uint32_t num_elements) {
954
0
        if (m_ptr->type != msgpack::type::ARRAY ||
955
0
            m_ptr->via.array.size != num_elements) {
956
0
            m_result = false;
957
0
            return false;
958
0
        }
959
0
        m_objs.push_back(elem(m_ptr->via.array.ptr));
960
0
        return true;
961
0
    }
962
0
    bool start_array_item() {
963
0
        m_ptr = m_objs.back().get_item();
964
0
        return true;
965
0
    }
966
0
    bool end_array_item() {
967
0
        ++m_objs.back().as.obj;
968
0
        return true;
969
0
    }
970
0
    bool end_array() {
971
0
        m_objs.pop_back();
972
0
        return true;
973
0
    }
974
0
    bool start_map(uint32_t num_kv_pairs) {
975
0
        if (m_ptr->type != msgpack::type::MAP ||
976
0
            m_ptr->via.array.size != num_kv_pairs) {
977
0
            m_result = false;
978
0
            return false;
979
0
        }
980
0
        m_objs.push_back(elem(m_ptr->via.map.ptr));
981
0
        return true;
982
0
    }
983
0
    bool start_map_key() {
984
0
        m_ptr = m_objs.back().get_key();
985
0
        return true;
986
0
    }
987
0
    bool end_map_key() {
988
0
        return true;
989
0
    }
990
0
    bool start_map_value() {
991
0
        m_ptr = m_objs.back().get_val();
992
0
        return true;
993
0
    }
994
0
    bool end_map_value() {
995
0
        ++m_objs.back().as.kv;
996
0
        return true;
997
0
    }
998
0
    bool end_map() {
999
0
        m_objs.pop_back();
1000
0
        return true;
1001
0
    }
1002
private:
1003
    struct elem {
1004
        elem(msgpack::object const* obj)
1005
0
            :is_obj(true) {
1006
0
            as.obj = obj;
1007
0
        }
1008
        elem(msgpack::object_kv const* kv)
1009
0
            :is_obj(false) {
1010
0
            as.kv = kv;
1011
0
        }
1012
0
        msgpack::object const* get_item() {
1013
0
            return as.obj;
1014
0
        }
1015
0
        msgpack::object const* get_key() {
1016
0
            return &as.kv->key;
1017
0
        }
1018
0
        msgpack::object const* get_val() {
1019
0
            return &as.kv->val;
1020
0
        }
1021
        union {
1022
            msgpack::object const* obj;
1023
            msgpack::object_kv const* kv;
1024
        } as;
1025
        bool is_obj;
1026
    };
1027
    std::vector<elem> m_objs;
1028
    msgpack::object const* m_ptr;
1029
    bool& m_result;
1030
};
1031
1032
inline bool operator==(const msgpack::object& x, const msgpack::object& y)
1033
0
{
1034
0
    if(x.type != y.type) { return false; }
1035
0
    bool b = true;
1036
0
    object_equal_visitor vis(y, b);
1037
0
    msgpack::object_parser(x).parse(vis);
1038
0
    return b;
1039
0
}
1040
1041
template <typename T>
1042
inline bool operator==(const msgpack::object& x, const T& y)
1043
try {
1044
    return x == msgpack::object(y);
1045
} catch (msgpack::type_error&) {
1046
    return false;
1047
}
1048
1049
inline bool operator!=(const msgpack::object& x, const msgpack::object& y)
1050
0
{ return !(x == y); }
1051
1052
template <typename T>
1053
inline bool operator==(const T& y, const msgpack::object& x)
1054
{ return x == y; }
1055
1056
template <typename T>
1057
inline bool operator!=(const msgpack::object& x, const T& y)
1058
{ return !(x == y); }
1059
1060
template <typename T>
1061
inline bool operator!=(const T& y, const msgpack::object& x)
1062
{ return x != y; }
1063
1064
1065
inline object::implicit_type object::convert() const
1066
0
{
1067
0
    return object::implicit_type(*this);
1068
0
}
1069
1070
template <typename T>
1071
inline
1072
typename msgpack::enable_if<
1073
    !msgpack::is_array<T>::value && !msgpack::is_pointer<T>::value,
1074
    T&
1075
>::type
1076
object::convert(T& v) const
1077
0
{
1078
0
    msgpack::operator>>(*this, v);
1079
0
    return v;
1080
0
}
1081
1082
template <typename T, std::size_t N>
1083
inline T(&object::convert(T(&v)[N]) const)[N]
1084
{
1085
    msgpack::operator>>(*this, v);
1086
    return v;
1087
}
1088
1089
#if !defined(MSGPACK_DISABLE_LEGACY_CONVERT)
1090
template <typename T>
1091
inline
1092
typename msgpack::enable_if<
1093
    msgpack::is_pointer<T>::value,
1094
    T
1095
>::type
1096
object::convert(T v) const
1097
{
1098
    convert(*v);
1099
    return v;
1100
}
1101
#endif // !defined(MSGPACK_DISABLE_LEGACY_CONVERT)
1102
1103
template <typename T>
1104
inline bool object::convert_if_not_nil(T& v) const
1105
{
1106
    if (is_nil()) {
1107
        return false;
1108
    }
1109
    convert(v);
1110
    return true;
1111
}
1112
1113
#if defined(MSGPACK_USE_CPP03)
1114
1115
template <typename T>
1116
inline T object::as() const
1117
{
1118
    T v;
1119
    convert(v);
1120
    return v;
1121
}
1122
1123
#else  // defined(MSGPACK_USE_CPP03)
1124
1125
template <typename T>
1126
inline typename std::enable_if<msgpack::has_as<T>::value, T>::type object::as() const {
1127
    return msgpack::adaptor::as<T>()(*this);
1128
}
1129
1130
template <typename T>
1131
0
inline typename std::enable_if<!msgpack::has_as<T>::value, T>::type object::as() const {
1132
0
    T v;
1133
0
    convert(v);
1134
0
    return v;
1135
0
}
1136
1137
#endif // defined(MSGPACK_USE_CPP03)
1138
1139
inline object::object()
1140
4.50k
{
1141
4.50k
    type = msgpack::type::NIL;
1142
4.50k
}
1143
1144
template <typename T>
1145
inline object::object(const T& v)
1146
{
1147
    *this << v;
1148
}
1149
1150
template <typename T>
1151
inline object& object::operator=(const T& v)
1152
{
1153
    *this = object(v);
1154
    return *this;
1155
}
1156
1157
template <typename T>
1158
inline object::object(const T& v, msgpack::zone& z)
1159
{
1160
    with_zone oz(z);
1161
    msgpack::operator<<(oz, v);
1162
    type = oz.type;
1163
    via = oz.via;
1164
}
1165
1166
template <typename T>
1167
inline object::object(const T& v, msgpack::zone* z)
1168
{
1169
    with_zone oz(*z);
1170
    msgpack::operator<<(oz, v);
1171
    type = oz.type;
1172
    via = oz.via;
1173
}
1174
1175
1176
// obsolete
1177
template <typename T>
1178
inline void convert(T& v, msgpack::object const& o)
1179
{
1180
    o.convert(v);
1181
}
1182
1183
// obsolete
1184
template <typename Stream, typename T>
1185
inline void pack(msgpack::packer<Stream>& o, const T& v)
1186
{
1187
    o.pack(v);
1188
}
1189
1190
// obsolete
1191
template <typename Stream, typename T>
1192
inline void pack_copy(msgpack::packer<Stream>& o, T v)
1193
{
1194
    pack(o, v);
1195
}
1196
1197
template <typename Stream>
1198
inline msgpack::packer<Stream>& operator<< (msgpack::packer<Stream>& o, const msgpack::object& v)
1199
{
1200
    object_pack_visitor<Stream> vis(o);
1201
    msgpack::object_parser(v).parse(vis);
1202
    return o;
1203
}
1204
1205
template <typename Stream>
1206
inline msgpack::packer<Stream>& operator<< (msgpack::packer<Stream>& o, const msgpack::object::with_zone& v)
1207
{
1208
    return o << static_cast<msgpack::object>(v);
1209
}
1210
1211
inline std::ostream& operator<< (std::ostream& s, const msgpack::object& v)
1212
0
{
1213
0
    object_stringize_visitor vis(s);
1214
0
    msgpack::object_parser(v).parse(vis);
1215
0
    return s;
1216
0
}
1217
1218
/// @cond
1219
}  // MSGPACK_API_VERSION_NAMESPACE(v1)
1220
/// @endcond
1221
1222
}  // namespace msgpack
1223
1224
#endif // MSGPACK_V1_OBJECT_HPP