1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/json
7  
// Official repository: https://github.com/boostorg/json
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_JSON_IMPL_VALUE_IPP
10  
#ifndef BOOST_JSON_IMPL_VALUE_IPP
11  
#define BOOST_JSON_IMPL_VALUE_IPP
11  
#define BOOST_JSON_IMPL_VALUE_IPP
12  

12  

13  
#include <boost/container_hash/hash.hpp>
13  
#include <boost/container_hash/hash.hpp>
14  
#include <boost/json/value.hpp>
14  
#include <boost/json/value.hpp>
15  
#include <boost/json/parser.hpp>
15  
#include <boost/json/parser.hpp>
16  
#include <cstring>
16  
#include <cstring>
17  
#include <istream>
17  
#include <istream>
18  
#include <limits>
18  
#include <limits>
19  
#include <new>
19  
#include <new>
20  
#include <utility>
20  
#include <utility>
21  

21  

22  
namespace boost {
22  
namespace boost {
23  
namespace json {
23  
namespace json {
24  

24  

25  
namespace
25  
namespace
26  
{
26  
{
27  

27  

28  
int parse_depth_xalloc = std::ios::xalloc();
28  
int parse_depth_xalloc = std::ios::xalloc();
29  
int parse_flags_xalloc = std::ios::xalloc();
29  
int parse_flags_xalloc = std::ios::xalloc();
30  

30  

31  
struct value_hasher
31  
struct value_hasher
32  
{
32  
{
33  
    std::size_t& seed;
33  
    std::size_t& seed;
34  

34  

35  
    template< class T >
35  
    template< class T >
36  
    void operator()( T&& t ) const noexcept
36  
    void operator()( T&& t ) const noexcept
37  
    {
37  
    {
38  
        boost::hash_combine( seed, t );
38  
        boost::hash_combine( seed, t );
39  
    }
39  
    }
40  
};
40  
};
41  

41  

42  
enum class stream_parse_flags
42  
enum class stream_parse_flags
43  
{
43  
{
44  
    allow_comments = 1 << 0,
44  
    allow_comments = 1 << 0,
45  
    allow_trailing_commas = 1 << 1,
45  
    allow_trailing_commas = 1 << 1,
46  
    allow_invalid_utf8 = 1 << 2,
46  
    allow_invalid_utf8 = 1 << 2,
47  
};
47  
};
48  

48  

49  
long
49  
long
50  
to_bitmask( parse_options const& opts )
50  
to_bitmask( parse_options const& opts )
51  
{
51  
{
52  
    using E = stream_parse_flags;
52  
    using E = stream_parse_flags;
53  
    return
53  
    return
54  
        (opts.allow_comments ?
54  
        (opts.allow_comments ?
55  
            static_cast<long>(E::allow_comments) : 0) |
55  
            static_cast<long>(E::allow_comments) : 0) |
56  
        (opts.allow_trailing_commas ?
56  
        (opts.allow_trailing_commas ?
57  
            static_cast<long>(E::allow_trailing_commas) : 0) |
57  
            static_cast<long>(E::allow_trailing_commas) : 0) |
58  
        (opts.allow_invalid_utf8 ?
58  
        (opts.allow_invalid_utf8 ?
59  
            static_cast<long>(E::allow_invalid_utf8) : 0);
59  
            static_cast<long>(E::allow_invalid_utf8) : 0);
60  
}
60  
}
61  

61  

62  
parse_options
62  
parse_options
63  
get_parse_options( std::istream& is )
63  
get_parse_options( std::istream& is )
64  
{
64  
{
65  
    long const flags = is.iword(parse_flags_xalloc);
65  
    long const flags = is.iword(parse_flags_xalloc);
66  

66  

67  
    using E = stream_parse_flags;
67  
    using E = stream_parse_flags;
68  
    parse_options opts;
68  
    parse_options opts;
69  
    opts.allow_comments =
69  
    opts.allow_comments =
70  
        flags & static_cast<long>(E::allow_comments) ? true : false;
70  
        flags & static_cast<long>(E::allow_comments) ? true : false;
71  
    opts.allow_trailing_commas =
71  
    opts.allow_trailing_commas =
72  
        flags & static_cast<long>(E::allow_trailing_commas) ? true : false;
72  
        flags & static_cast<long>(E::allow_trailing_commas) ? true : false;
73  
    opts.allow_invalid_utf8 =
73  
    opts.allow_invalid_utf8 =
74  
        flags & static_cast<long>(E::allow_invalid_utf8) ? true : false;
74  
        flags & static_cast<long>(E::allow_invalid_utf8) ? true : false;
75  
    return opts;
75  
    return opts;
76  
}
76  
}
77  

77  

78  
} // namespace
78  
} // namespace
79  

79  

80  
value::
80  
value::
81  
~value() noexcept
81  
~value() noexcept
82  
{
82  
{
83  
    switch(kind())
83  
    switch(kind())
84  
    {
84  
    {
85  
    case json::kind::null:
85  
    case json::kind::null:
86  
    case json::kind::bool_:
86  
    case json::kind::bool_:
87  
    case json::kind::int64:
87  
    case json::kind::int64:
88  
    case json::kind::uint64:
88  
    case json::kind::uint64:
89  
    case json::kind::double_:
89  
    case json::kind::double_:
90  
        sca_.~scalar();
90  
        sca_.~scalar();
91  
        break;
91  
        break;
92  

92  

93  
    case json::kind::string:
93  
    case json::kind::string:
94  
        str_.~string();
94  
        str_.~string();
95  
        break;
95  
        break;
96  

96  

97  
    case json::kind::array:
97  
    case json::kind::array:
98  
        arr_.~array();
98  
        arr_.~array();
99  
        break;
99  
        break;
100  

100  

101  
    case json::kind::object:
101  
    case json::kind::object:
102  
        obj_.~object();
102  
        obj_.~object();
103  
        break;
103  
        break;
104  
    }
104  
    }
105  
}
105  
}
106  

106  

107  
value::
107  
value::
108  
value(
108  
value(
109  
    value const& other,
109  
    value const& other,
110  
    storage_ptr sp)
110  
    storage_ptr sp)
111  
{
111  
{
112  
    switch(other.kind())
112  
    switch(other.kind())
113  
    {
113  
    {
114  
    case json::kind::null:
114  
    case json::kind::null:
115  
        ::new(&sca_) scalar(
115  
        ::new(&sca_) scalar(
116  
            std::move(sp));
116  
            std::move(sp));
117  
        break;
117  
        break;
118  

118  

119  
    case json::kind::bool_:
119  
    case json::kind::bool_:
120  
        ::new(&sca_) scalar(
120  
        ::new(&sca_) scalar(
121  
            other.sca_.b,
121  
            other.sca_.b,
122  
            std::move(sp));
122  
            std::move(sp));
123  
        break;
123  
        break;
124  

124  

125  
    case json::kind::int64:
125  
    case json::kind::int64:
126  
        ::new(&sca_) scalar(
126  
        ::new(&sca_) scalar(
127  
            other.sca_.i,
127  
            other.sca_.i,
128  
            std::move(sp));
128  
            std::move(sp));
129  
        break;
129  
        break;
130  

130  

131  
    case json::kind::uint64:
131  
    case json::kind::uint64:
132  
        ::new(&sca_) scalar(
132  
        ::new(&sca_) scalar(
133  
            other.sca_.u,
133  
            other.sca_.u,
134  
            std::move(sp));
134  
            std::move(sp));
135  
        break;
135  
        break;
136  

136  

137  
    case json::kind::double_:
137  
    case json::kind::double_:
138  
        ::new(&sca_) scalar(
138  
        ::new(&sca_) scalar(
139  
            other.sca_.d,
139  
            other.sca_.d,
140  
            std::move(sp));
140  
            std::move(sp));
141  
        break;
141  
        break;
142  

142  

143  
    case json::kind::string:
143  
    case json::kind::string:
144  
        ::new(&str_) string(
144  
        ::new(&str_) string(
145  
            other.str_,
145  
            other.str_,
146  
            std::move(sp));
146  
            std::move(sp));
147  
        break;
147  
        break;
148  

148  

149  
    case json::kind::array:
149  
    case json::kind::array:
150  
        ::new(&arr_) array(
150  
        ::new(&arr_) array(
151  
            other.arr_,
151  
            other.arr_,
152  
            std::move(sp));
152  
            std::move(sp));
153  
        break;
153  
        break;
154  

154  

155  
    case json::kind::object:
155  
    case json::kind::object:
156  
        ::new(&obj_) object(
156  
        ::new(&obj_) object(
157  
            other.obj_,
157  
            other.obj_,
158  
            std::move(sp));
158  
            std::move(sp));
159  
        break;
159  
        break;
160  
    }
160  
    }
161  
}
161  
}
162  

162  

163  
value::
163  
value::
164  
value(value&& other) noexcept
164  
value(value&& other) noexcept
165  
{
165  
{
166  
    relocate(this, other);
166  
    relocate(this, other);
167  
    ::new(&other.sca_) scalar(sp_);
167  
    ::new(&other.sca_) scalar(sp_);
168  
}
168  
}
169  

169  

170  
value::
170  
value::
171  
value(
171  
value(
172  
    value&& other,
172  
    value&& other,
173  
    storage_ptr sp)
173  
    storage_ptr sp)
174  
{
174  
{
175  
    switch(other.kind())
175  
    switch(other.kind())
176  
    {
176  
    {
177  
    case json::kind::null:
177  
    case json::kind::null:
178  
        ::new(&sca_) scalar(
178  
        ::new(&sca_) scalar(
179  
            std::move(sp));
179  
            std::move(sp));
180  
        break;
180  
        break;
181  

181  

182  
    case json::kind::bool_:
182  
    case json::kind::bool_:
183  
        ::new(&sca_) scalar(
183  
        ::new(&sca_) scalar(
184  
            other.sca_.b, std::move(sp));
184  
            other.sca_.b, std::move(sp));
185  
        break;
185  
        break;
186  

186  

187  
    case json::kind::int64:
187  
    case json::kind::int64:
188  
        ::new(&sca_) scalar(
188  
        ::new(&sca_) scalar(
189  
            other.sca_.i, std::move(sp));
189  
            other.sca_.i, std::move(sp));
190  
        break;
190  
        break;
191  

191  

192  
    case json::kind::uint64:
192  
    case json::kind::uint64:
193  
        ::new(&sca_) scalar(
193  
        ::new(&sca_) scalar(
194  
            other.sca_.u, std::move(sp));
194  
            other.sca_.u, std::move(sp));
195  
        break;
195  
        break;
196  

196  

197  
    case json::kind::double_:
197  
    case json::kind::double_:
198  
        ::new(&sca_) scalar(
198  
        ::new(&sca_) scalar(
199  
            other.sca_.d, std::move(sp));
199  
            other.sca_.d, std::move(sp));
200  
        break;
200  
        break;
201  

201  

202  
    case json::kind::string:
202  
    case json::kind::string:
203  
        ::new(&str_) string(
203  
        ::new(&str_) string(
204  
            std::move(other.str_),
204  
            std::move(other.str_),
205  
            std::move(sp));
205  
            std::move(sp));
206  
        break;
206  
        break;
207  

207  

208  
    case json::kind::array:
208  
    case json::kind::array:
209  
        ::new(&arr_) array(
209  
        ::new(&arr_) array(
210  
            std::move(other.arr_),
210  
            std::move(other.arr_),
211  
            std::move(sp));
211  
            std::move(sp));
212  
        break;
212  
        break;
213  

213  

214  
    case json::kind::object:
214  
    case json::kind::object:
215  
        ::new(&obj_) object(
215  
        ::new(&obj_) object(
216  
            std::move(other.obj_),
216  
            std::move(other.obj_),
217  
            std::move(sp));
217  
            std::move(sp));
218  
        break;
218  
        break;
219  
    }
219  
    }
220  
}
220  
}
221  

221  

222  
//----------------------------------------------------------
222  
//----------------------------------------------------------
223  
//
223  
//
224  
// Conversion
224  
// Conversion
225  
//
225  
//
226  
//----------------------------------------------------------
226  
//----------------------------------------------------------
227  

227  

228  
value::
228  
value::
229  
value(
229  
value(
230  
    std::initializer_list<value_ref> init,
230  
    std::initializer_list<value_ref> init,
231  
    storage_ptr sp)
231  
    storage_ptr sp)
232  
{
232  
{
233  
    if(value_ref::maybe_object(init))
233  
    if(value_ref::maybe_object(init))
234  
    {
234  
    {
235  
        ::new(&obj_) object(
235  
        ::new(&obj_) object(
236  
            value_ref::make_object(
236  
            value_ref::make_object(
237  
                init, std::move(sp)));
237  
                init, std::move(sp)));
238  
    }
238  
    }
239  
    else
239  
    else
240  
    {
240  
    {
241  
        if( init.size() == 1 )
241  
        if( init.size() == 1 )
242  
        {
242  
        {
243  
            ::new(&sca_) scalar();
243  
            ::new(&sca_) scalar();
244  
            value temp = init.begin()->make_value( std::move(sp) );
244  
            value temp = init.begin()->make_value( std::move(sp) );
245  
            swap(temp);
245  
            swap(temp);
246  
        }
246  
        }
247  
        else
247  
        else
248  
        {
248  
        {
249  
            ::new(&arr_) array(
249  
            ::new(&arr_) array(
250  
                value_ref::make_array(
250  
                value_ref::make_array(
251  
                    init, std::move(sp)));
251  
                    init, std::move(sp)));
252  
        }
252  
        }
253  
    }
253  
    }
254  
}
254  
}
255  

255  

256  
//----------------------------------------------------------
256  
//----------------------------------------------------------
257  
//
257  
//
258  
// Assignment
258  
// Assignment
259  
//
259  
//
260  
//----------------------------------------------------------
260  
//----------------------------------------------------------
261  

261  

262  
value&
262  
value&
263  
value::
263  
value::
264  
operator=(value const& other)
264  
operator=(value const& other)
265  
{
265  
{
266  
    value(other,
266  
    value(other,
267  
        storage()).swap(*this);
267  
        storage()).swap(*this);
268  
    return *this;
268  
    return *this;
269  
}
269  
}
270  

270  

271  
value&
271  
value&
272  
value::
272  
value::
273  
operator=(value&& other)
273  
operator=(value&& other)
274  
{
274  
{
275  
    value(std::move(other),
275  
    value(std::move(other),
276  
        storage()).swap(*this);
276  
        storage()).swap(*this);
277  
    return *this;
277  
    return *this;
278  
}
278  
}
279  

279  

280  
value&
280  
value&
281  
value::
281  
value::
282  
operator=(
282  
operator=(
283  
    std::initializer_list<value_ref> init)
283  
    std::initializer_list<value_ref> init)
284  
{
284  
{
285  
    value(init,
285  
    value(init,
286  
        storage()).swap(*this);
286  
        storage()).swap(*this);
287  
    return *this;
287  
    return *this;
288  
}
288  
}
289  

289  

290  
value&
290  
value&
291  
value::
291  
value::
292  
operator=(string_view s)
292  
operator=(string_view s)
293  
{
293  
{
294  
    value(s, storage()).swap(*this);
294  
    value(s, storage()).swap(*this);
295  
    return *this;
295  
    return *this;
296  
}
296  
}
297  

297  

298  
value&
298  
value&
299  
value::
299  
value::
300  
operator=(char const* s)
300  
operator=(char const* s)
301  
{
301  
{
302  
    value(s, storage()).swap(*this);
302  
    value(s, storage()).swap(*this);
303  
    return *this;
303  
    return *this;
304  
}
304  
}
305  

305  

306  
value&
306  
value&
307  
value::
307  
value::
308  
operator=(string const& str)
308  
operator=(string const& str)
309  
{
309  
{
310  
    value(str, storage()).swap(*this);
310  
    value(str, storage()).swap(*this);
311  
    return *this;
311  
    return *this;
312  
}
312  
}
313  

313  

314  
value&
314  
value&
315  
value::
315  
value::
316  
operator=(string&& str)
316  
operator=(string&& str)
317  
{
317  
{
318  
    value(std::move(str),
318  
    value(std::move(str),
319  
        storage()).swap(*this);
319  
        storage()).swap(*this);
320  
    return *this;
320  
    return *this;
321  
}
321  
}
322  

322  

323  
value&
323  
value&
324  
value::
324  
value::
325  
operator=(array const& arr)
325  
operator=(array const& arr)
326  
{
326  
{
327  
    value(arr, storage()).swap(*this);
327  
    value(arr, storage()).swap(*this);
328  
    return *this;
328  
    return *this;
329  
}
329  
}
330  

330  

331  
value&
331  
value&
332  
value::
332  
value::
333  
operator=(array&& arr)
333  
operator=(array&& arr)
334  
{
334  
{
335  
    value(std::move(arr),
335  
    value(std::move(arr),
336  
        storage()).swap(*this);
336  
        storage()).swap(*this);
337  
    return *this;
337  
    return *this;
338  
}
338  
}
339  

339  

340  
value&
340  
value&
341  
value::
341  
value::
342  
operator=(object const& obj)
342  
operator=(object const& obj)
343  
{
343  
{
344  
    value(obj, storage()).swap(*this);
344  
    value(obj, storage()).swap(*this);
345  
    return *this;
345  
    return *this;
346  
}
346  
}
347  

347  

348  
value&
348  
value&
349  
value::
349  
value::
350  
operator=(object&& obj)
350  
operator=(object&& obj)
351  
{
351  
{
352  
    value(std::move(obj),
352  
    value(std::move(obj),
353  
        storage()).swap(*this);
353  
        storage()).swap(*this);
354  
    return *this;
354  
    return *this;
355  
}
355  
}
356  

356  

357  
//----------------------------------------------------------
357  
//----------------------------------------------------------
358  
//
358  
//
359  
// Accessors
359  
// Accessors
360  
//
360  
//
361  
//----------------------------------------------------------
361  
//----------------------------------------------------------
362  

362  

363  
system::result<array&>
363  
system::result<array&>
364  
value::try_as_array() noexcept
364  
value::try_as_array() noexcept
365  
{
365  
{
366  
    if( is_array() )
366  
    if( is_array() )
367  
        return arr_;
367  
        return arr_;
368  

368  

369  
    system::error_code ec;
369  
    system::error_code ec;
370  
    BOOST_JSON_FAIL(ec, error::not_array);
370  
    BOOST_JSON_FAIL(ec, error::not_array);
371  
    return ec;
371  
    return ec;
372  
}
372  
}
373  

373  

374  
system::result<array const&>
374  
system::result<array const&>
375  
value::try_as_array() const noexcept
375  
value::try_as_array() const noexcept
376  
{
376  
{
377  
    if( is_array() )
377  
    if( is_array() )
378  
        return arr_;
378  
        return arr_;
379  

379  

380  
    system::error_code ec;
380  
    system::error_code ec;
381  
    BOOST_JSON_FAIL(ec, error::not_array);
381  
    BOOST_JSON_FAIL(ec, error::not_array);
382  
    return ec;
382  
    return ec;
383  
}
383  
}
384  

384  

385  
system::result<object&>
385  
system::result<object&>
386  
value::try_as_object() noexcept
386  
value::try_as_object() noexcept
387  
{
387  
{
388  
    if( is_object() )
388  
    if( is_object() )
389  
        return obj_;
389  
        return obj_;
390  

390  

391  
    system::error_code ec;
391  
    system::error_code ec;
392  
    BOOST_JSON_FAIL(ec, error::not_object);
392  
    BOOST_JSON_FAIL(ec, error::not_object);
393  
    return ec;
393  
    return ec;
394  
}
394  
}
395  

395  

396  
system::result<object const&>
396  
system::result<object const&>
397  
value::try_as_object() const noexcept
397  
value::try_as_object() const noexcept
398  
{
398  
{
399  
    if( is_object() )
399  
    if( is_object() )
400  
        return obj_;
400  
        return obj_;
401  

401  

402  
    system::error_code ec;
402  
    system::error_code ec;
403  
    BOOST_JSON_FAIL(ec, error::not_object);
403  
    BOOST_JSON_FAIL(ec, error::not_object);
404  
    return ec;
404  
    return ec;
405  
}
405  
}
406  

406  

407  
system::result<string&>
407  
system::result<string&>
408  
value::try_as_string() noexcept
408  
value::try_as_string() noexcept
409  
{
409  
{
410  
    if( is_string() )
410  
    if( is_string() )
411  
        return str_;
411  
        return str_;
412  

412  

413  
    system::error_code ec;
413  
    system::error_code ec;
414  
    BOOST_JSON_FAIL(ec, error::not_string);
414  
    BOOST_JSON_FAIL(ec, error::not_string);
415  
    return ec;
415  
    return ec;
416  
}
416  
}
417  

417  

418  
system::result<string const&>
418  
system::result<string const&>
419  
value::try_as_string() const noexcept
419  
value::try_as_string() const noexcept
420  
{
420  
{
421  
    if( is_string() )
421  
    if( is_string() )
422  
        return str_;
422  
        return str_;
423  

423  

424  
    system::error_code ec;
424  
    system::error_code ec;
425  
    BOOST_JSON_FAIL(ec, error::not_string);
425  
    BOOST_JSON_FAIL(ec, error::not_string);
426  
    return ec;
426  
    return ec;
427  
}
427  
}
428  

428  

429  
system::result<std::int64_t&>
429  
system::result<std::int64_t&>
430  
value::try_as_int64() noexcept
430  
value::try_as_int64() noexcept
431  
{
431  
{
432  
    if( is_int64() )
432  
    if( is_int64() )
433  
        return sca_.i;
433  
        return sca_.i;
434  

434  

435  
    system::error_code ec;
435  
    system::error_code ec;
436  
    BOOST_JSON_FAIL(ec, error::not_int64);
436  
    BOOST_JSON_FAIL(ec, error::not_int64);
437  
    return ec;
437  
    return ec;
438  
}
438  
}
439  

439  

440  
system::result<std::int64_t>
440  
system::result<std::int64_t>
441  
value::try_as_int64() const noexcept
441  
value::try_as_int64() const noexcept
442  
{
442  
{
443  
    if( is_int64() )
443  
    if( is_int64() )
444  
        return sca_.i;
444  
        return sca_.i;
445  

445  

446  
    system::error_code ec;
446  
    system::error_code ec;
447  
    BOOST_JSON_FAIL(ec, error::not_int64);
447  
    BOOST_JSON_FAIL(ec, error::not_int64);
448  
    return ec;
448  
    return ec;
449  
}
449  
}
450  

450  

451  
system::result<std::uint64_t&>
451  
system::result<std::uint64_t&>
452  
value::try_as_uint64() noexcept
452  
value::try_as_uint64() noexcept
453  
{
453  
{
454  
    if( is_uint64() )
454  
    if( is_uint64() )
455  
        return sca_.u;
455  
        return sca_.u;
456  

456  

457  
    system::error_code ec;
457  
    system::error_code ec;
458  
    BOOST_JSON_FAIL(ec, error::not_uint64);
458  
    BOOST_JSON_FAIL(ec, error::not_uint64);
459  
    return ec;
459  
    return ec;
460  
}
460  
}
461  

461  

462  
system::result<std::uint64_t>
462  
system::result<std::uint64_t>
463  
value::try_as_uint64() const noexcept
463  
value::try_as_uint64() const noexcept
464  
{
464  
{
465  
    if( is_uint64() )
465  
    if( is_uint64() )
466  
        return sca_.u;
466  
        return sca_.u;
467  

467  

468  
    system::error_code ec;
468  
    system::error_code ec;
469  
    BOOST_JSON_FAIL(ec, error::not_uint64);
469  
    BOOST_JSON_FAIL(ec, error::not_uint64);
470  
    return ec;
470  
    return ec;
471  
}
471  
}
472  

472  

473  
system::result<double&>
473  
system::result<double&>
474  
value::try_as_double() noexcept
474  
value::try_as_double() noexcept
475  
{
475  
{
476  
    if( is_double() )
476  
    if( is_double() )
477  
        return sca_.d;
477  
        return sca_.d;
478  

478  

479  
    system::error_code ec;
479  
    system::error_code ec;
480  
    BOOST_JSON_FAIL(ec, error::not_double);
480  
    BOOST_JSON_FAIL(ec, error::not_double);
481  
    return ec;
481  
    return ec;
482  
}
482  
}
483  

483  

484  
system::result<double>
484  
system::result<double>
485  
value::try_as_double() const noexcept
485  
value::try_as_double() const noexcept
486  
{
486  
{
487  
    if( is_double() )
487  
    if( is_double() )
488  
        return sca_.d;
488  
        return sca_.d;
489  

489  

490  
    system::error_code ec;
490  
    system::error_code ec;
491  
    BOOST_JSON_FAIL(ec, error::not_double);
491  
    BOOST_JSON_FAIL(ec, error::not_double);
492  
    return ec;
492  
    return ec;
493  
}
493  
}
494  

494  

495  
system::result<bool&>
495  
system::result<bool&>
496  
value::try_as_bool() noexcept
496  
value::try_as_bool() noexcept
497  
{
497  
{
498  
    if( is_bool() )
498  
    if( is_bool() )
499  
        return sca_.b;
499  
        return sca_.b;
500  

500  

501  
    system::error_code ec;
501  
    system::error_code ec;
502  
    BOOST_JSON_FAIL(ec, error::not_bool);
502  
    BOOST_JSON_FAIL(ec, error::not_bool);
503  
    return ec;
503  
    return ec;
504  
}
504  
}
505  

505  

506  
system::result<bool>
506  
system::result<bool>
507  
value::try_as_bool() const noexcept
507  
value::try_as_bool() const noexcept
508  
{
508  
{
509  
    if( is_bool() )
509  
    if( is_bool() )
510  
        return sca_.b;
510  
        return sca_.b;
511  

511  

512  
    system::error_code ec;
512  
    system::error_code ec;
513  
    BOOST_JSON_FAIL(ec, error::not_bool);
513  
    BOOST_JSON_FAIL(ec, error::not_bool);
514  
    return ec;
514  
    return ec;
515  
}
515  
}
516  

516  

517  
system::result<std::nullptr_t>
517  
system::result<std::nullptr_t>
518  
value::try_as_null() const noexcept
518  
value::try_as_null() const noexcept
519  
{
519  
{
520  
    if( is_null() )
520  
    if( is_null() )
521  
        return nullptr;
521  
        return nullptr;
522  

522  

523  
    system::error_code ec;
523  
    system::error_code ec;
524  
    BOOST_JSON_FAIL(ec, error::not_null);
524  
    BOOST_JSON_FAIL(ec, error::not_null);
525  
    return ec;
525  
    return ec;
526  
}
526  
}
527  

527  

528  
boost::system::result<value&>
528  
boost::system::result<value&>
529  
value::try_at(string_view key) noexcept
529  
value::try_at(string_view key) noexcept
530  
{
530  
{
531  
    auto r = try_as_object();
531  
    auto r = try_as_object();
532  
    if( !r )
532  
    if( !r )
533  
        return r.error();
533  
        return r.error();
534  
    return r->try_at(key);
534  
    return r->try_at(key);
535  
}
535  
}
536  

536  

537  
boost::system::result<value const&>
537  
boost::system::result<value const&>
538  
value::try_at(string_view key) const noexcept
538  
value::try_at(string_view key) const noexcept
539  
{
539  
{
540  
    auto r = try_as_object();
540  
    auto r = try_as_object();
541  
    if( !r )
541  
    if( !r )
542  
        return r.error();
542  
        return r.error();
543  
    return r->try_at(key);
543  
    return r->try_at(key);
544  
}
544  
}
545  

545  

546  
boost::system::result<value&>
546  
boost::system::result<value&>
547  
value::try_at(std::size_t pos) noexcept
547  
value::try_at(std::size_t pos) noexcept
548  
{
548  
{
549  
    auto r = try_as_array();
549  
    auto r = try_as_array();
550  
    if( !r )
550  
    if( !r )
551  
        return r.error();
551  
        return r.error();
552  
    return r->try_at(pos);
552  
    return r->try_at(pos);
553  
}
553  
}
554  

554  

555  
boost::system::result<value const&>
555  
boost::system::result<value const&>
556  
value::try_at(std::size_t pos) const noexcept
556  
value::try_at(std::size_t pos) const noexcept
557  
{
557  
{
558  
    auto r = try_as_array();
558  
    auto r = try_as_array();
559  
    if( !r )
559  
    if( !r )
560  
        return r.error();
560  
        return r.error();
561  
    return r->try_at(pos);
561  
    return r->try_at(pos);
562  
}
562  
}
563  

563  

564  
object const&
564  
object const&
565  
value::as_object(source_location const& loc) const&
565  
value::as_object(source_location const& loc) const&
566  
{
566  
{
567  
    return try_as_object().value(loc);
567  
    return try_as_object().value(loc);
568  
}
568  
}
569  

569  

570  
array const&
570  
array const&
571  
value::as_array(source_location const& loc) const&
571  
value::as_array(source_location const& loc) const&
572  
{
572  
{
573  
    return try_as_array().value(loc);
573  
    return try_as_array().value(loc);
574  
}
574  
}
575  

575  

576  
string const&
576  
string const&
577  
value::as_string(source_location const& loc) const&
577  
value::as_string(source_location const& loc) const&
578  
{
578  
{
579  
    return try_as_string().value(loc);
579  
    return try_as_string().value(loc);
580  
}
580  
}
581  

581  

582  
std::int64_t&
582  
std::int64_t&
583  
value::as_int64(source_location const& loc)
583  
value::as_int64(source_location const& loc)
584  
{
584  
{
585  
    return try_as_int64().value(loc);
585  
    return try_as_int64().value(loc);
586  
}
586  
}
587  

587  

588  
std::int64_t
588  
std::int64_t
589  
value::as_int64(source_location const& loc) const
589  
value::as_int64(source_location const& loc) const
590  
{
590  
{
591  
    return try_as_int64().value(loc);
591  
    return try_as_int64().value(loc);
592  
}
592  
}
593  

593  

594  
std::uint64_t&
594  
std::uint64_t&
595  
value::as_uint64(source_location const& loc)
595  
value::as_uint64(source_location const& loc)
596  
{
596  
{
597  
    return try_as_uint64().value(loc);
597  
    return try_as_uint64().value(loc);
598  
}
598  
}
599  

599  

600  
std::uint64_t
600  
std::uint64_t
601  
value::as_uint64(source_location const& loc) const
601  
value::as_uint64(source_location const& loc) const
602  
{
602  
{
603  
    return try_as_uint64().value(loc);
603  
    return try_as_uint64().value(loc);
604  
}
604  
}
605  

605  

606  
double&
606  
double&
607  
value::as_double(source_location const& loc)
607  
value::as_double(source_location const& loc)
608  
{
608  
{
609  
    return try_as_double().value(loc);
609  
    return try_as_double().value(loc);
610  
}
610  
}
611  

611  

612  
double
612  
double
613  
value::as_double(source_location const& loc) const
613  
value::as_double(source_location const& loc) const
614  
{
614  
{
615  
    return try_as_double().value(loc);
615  
    return try_as_double().value(loc);
616  
}
616  
}
617  

617  

618  
bool&
618  
bool&
619  
value::as_bool(source_location const& loc)
619  
value::as_bool(source_location const& loc)
620  
{
620  
{
621  
    return try_as_bool().value(loc);
621  
    return try_as_bool().value(loc);
622  
}
622  
}
623  

623  

624  
bool
624  
bool
625  
value::as_bool(source_location const& loc) const
625  
value::as_bool(source_location const& loc) const
626  
{
626  
{
627  
    return try_as_bool().value(loc);
627  
    return try_as_bool().value(loc);
628  
}
628  
}
629  

629  

630  
//----------------------------------------------------------
630  
//----------------------------------------------------------
631  
//
631  
//
632  
// Modifiers
632  
// Modifiers
633  
//
633  
//
634  
//----------------------------------------------------------
634  
//----------------------------------------------------------
635  

635  

636  
string&
636  
string&
637  
value::
637  
value::
638  
emplace_string() noexcept
638  
emplace_string() noexcept
639  
{
639  
{
640  
    return *::new(&str_) string(destroy());
640  
    return *::new(&str_) string(destroy());
641  
}
641  
}
642  

642  

643  
array&
643  
array&
644  
value::
644  
value::
645  
emplace_array() noexcept
645  
emplace_array() noexcept
646  
{
646  
{
647  
    return *::new(&arr_) array(destroy());
647  
    return *::new(&arr_) array(destroy());
648  
}
648  
}
649  

649  

650  
object&
650  
object&
651  
value::
651  
value::
652  
emplace_object() noexcept
652  
emplace_object() noexcept
653  
{
653  
{
654  
    return *::new(&obj_) object(destroy());
654  
    return *::new(&obj_) object(destroy());
655  
}
655  
}
656  

656  

657  
void
657  
void
658  
value::
658  
value::
659  
swap(value& other)
659  
swap(value& other)
660  
{
660  
{
661  
    if(*storage() == *other.storage())
661  
    if(*storage() == *other.storage())
662  
    {
662  
    {
663  
        // fast path
663  
        // fast path
664  
        union U
664  
        union U
665  
        {
665  
        {
666  
            value tmp;
666  
            value tmp;
667  
            U(){}
667  
            U(){}
668  
            ~U(){}
668  
            ~U(){}
669  
        };
669  
        };
670  
        U u;
670  
        U u;
671  
        relocate(&u.tmp, *this);
671  
        relocate(&u.tmp, *this);
672  
        relocate(this, other);
672  
        relocate(this, other);
673  
        relocate(&other, u.tmp);
673  
        relocate(&other, u.tmp);
674  
        return;
674  
        return;
675  
    }
675  
    }
676  

676  

677  
    // copy
677  
    // copy
678  
    value temp1(
678  
    value temp1(
679  
        std::move(*this),
679  
        std::move(*this),
680  
        other.storage());
680  
        other.storage());
681  
    value temp2(
681  
    value temp2(
682  
        std::move(other),
682  
        std::move(other),
683  
        this->storage());
683  
        this->storage());
684  
    other.~value();
684  
    other.~value();
685  
    ::new(&other) value(pilfer(temp1));
685  
    ::new(&other) value(pilfer(temp1));
686  
    this->~value();
686  
    this->~value();
687  
    ::new(this) value(pilfer(temp2));
687  
    ::new(this) value(pilfer(temp2));
688  
}
688  
}
689  

689  

690  
std::istream&
690  
std::istream&
691  
operator>>(
691  
operator>>(
692  
    std::istream& is,
692  
    std::istream& is,
693  
    value& jv)
693  
    value& jv)
694  
{
694  
{
695  
    using Traits = std::istream::traits_type;
695  
    using Traits = std::istream::traits_type;
696  

696  

697  
    // sentry prepares the stream for reading and finalizes it in destructor
697  
    // sentry prepares the stream for reading and finalizes it in destructor
698  
    std::istream::sentry sentry(is);
698  
    std::istream::sentry sentry(is);
699  
    if( !sentry )
699  
    if( !sentry )
700  
        return is;
700  
        return is;
701  

701  

702  
    parse_options opts = get_parse_options( is );
702  
    parse_options opts = get_parse_options( is );
703  
    if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) )
703  
    if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) )
704  
        opts.max_depth = depth;
704  
        opts.max_depth = depth;
705  

705  

706  
    unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
706  
    unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
707  
    stream_parser p( {}, opts, parser_buf );
707  
    stream_parser p( {}, opts, parser_buf );
708  
    p.reset( jv.storage() );
708  
    p.reset( jv.storage() );
709  

709  

710  
    char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
710  
    char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
711  
    std::streambuf& buf = *is.rdbuf();
711  
    std::streambuf& buf = *is.rdbuf();
712  
    std::ios::iostate err = std::ios::goodbit;
712  
    std::ios::iostate err = std::ios::goodbit;
713  
#ifndef BOOST_NO_EXCEPTIONS
713  
#ifndef BOOST_NO_EXCEPTIONS
714  
    try
714  
    try
715  
#endif
715  
#endif
716  
    {
716  
    {
717  
        while( true )
717  
        while( true )
718  
        {
718  
        {
719  
            system::error_code ec;
719  
            system::error_code ec;
720  

720  

721  
            // we peek the buffer; this either makes sure that there's no
721  
            // we peek the buffer; this either makes sure that there's no
722  
            // more input, or makes sure there's something in the internal
722  
            // more input, or makes sure there's something in the internal
723  
            // buffer (so in_avail will return a positive number)
723  
            // buffer (so in_avail will return a positive number)
724  
            std::istream::int_type c = is.rdbuf()->sgetc();
724  
            std::istream::int_type c = is.rdbuf()->sgetc();
725  
            // if we indeed reached EOF, we check if we parsed a full JSON
725  
            // if we indeed reached EOF, we check if we parsed a full JSON
726  
            // document; if not, we error out
726  
            // document; if not, we error out
727  
            if( Traits::eq_int_type(c, Traits::eof()) )
727  
            if( Traits::eq_int_type(c, Traits::eof()) )
728  
            {
728  
            {
729  
                err |= std::ios::eofbit;
729  
                err |= std::ios::eofbit;
730  
                p.finish(ec);
730  
                p.finish(ec);
731  
                if( ec.failed() )
731  
                if( ec.failed() )
732  
                    break;
732  
                    break;
733  
            }
733  
            }
734  

734  

735  
            // regardless of reaching EOF, we might have parsed a full JSON
735  
            // regardless of reaching EOF, we might have parsed a full JSON
736  
            // document; if so, we successfully finish
736  
            // document; if so, we successfully finish
737  
            if( p.done() )
737  
            if( p.done() )
738  
            {
738  
            {
739  
                jv = p.release();
739  
                jv = p.release();
740  
                return is;
740  
                return is;
741  
            }
741  
            }
742  

742  

743  
            // at this point we definitely have more input, specifically in
743  
            // at this point we definitely have more input, specifically in
744  
            // buf's internal buffer; we also definitely haven't parsed a whole
744  
            // buf's internal buffer; we also definitely haven't parsed a whole
745  
            // document
745  
            // document
746  
            std::streamsize available = buf.in_avail();
746  
            std::streamsize available = buf.in_avail();
747  
            // if this assert fails, the streambuf is buggy
747  
            // if this assert fails, the streambuf is buggy
748  
            BOOST_ASSERT( available > 0 );
748  
            BOOST_ASSERT( available > 0 );
749  

749  

750  
            available = ( std::min )(
750  
            available = ( std::min )(
751  
                static_cast<std::size_t>(available), sizeof(read_buf) );
751  
                static_cast<std::size_t>(available), sizeof(read_buf) );
752  
            // we read from the internal buffer of buf into our buffer
752  
            // we read from the internal buffer of buf into our buffer
753  
            available = buf.sgetn( read_buf, available );
753  
            available = buf.sgetn( read_buf, available );
754  

754  

755  
            std::size_t consumed = p.write_some(
755  
            std::size_t consumed = p.write_some(
756  
                read_buf, static_cast<std::size_t>(available), ec );
756  
                read_buf, static_cast<std::size_t>(available), ec );
757  
            // if the parser hasn't consumed the entire input we've took from
757  
            // if the parser hasn't consumed the entire input we've took from
758  
            // buf, we put the remaining data back; this should succeed,
758  
            // buf, we put the remaining data back; this should succeed,
759  
            // because we only read data from buf's internal buffer
759  
            // because we only read data from buf's internal buffer
760  
            while( consumed++ < static_cast<std::size_t>(available) )
760  
            while( consumed++ < static_cast<std::size_t>(available) )
761  
            {
761  
            {
762  
                std::istream::int_type const status = buf.sungetc();
762  
                std::istream::int_type const status = buf.sungetc();
763  
                BOOST_ASSERT( status != Traits::eof() );
763  
                BOOST_ASSERT( status != Traits::eof() );
764  
                (void)status;
764  
                (void)status;
765  
            }
765  
            }
766  

766  

767  
            if( ec.failed() )
767  
            if( ec.failed() )
768  
                break;
768  
                break;
769  
        }
769  
        }
770  
    }
770  
    }
771  
#ifndef BOOST_NO_EXCEPTIONS
771  
#ifndef BOOST_NO_EXCEPTIONS
772  
    catch(...)
772  
    catch(...)
773  
    {
773  
    {
774  
        try
774  
        try
775  
        {
775  
        {
776  
            is.setstate(std::ios::badbit);
776  
            is.setstate(std::ios::badbit);
777  
        }
777  
        }
778  
        // we ignore the exception, because we need to throw the original
778  
        // we ignore the exception, because we need to throw the original
779  
        // exception instead
779  
        // exception instead
780  
        catch( std::ios::failure const& ) { }
780  
        catch( std::ios::failure const& ) { }
781  

781  

782  
        if( is.exceptions() & std::ios::badbit )
782  
        if( is.exceptions() & std::ios::badbit )
783  
            throw;
783  
            throw;
784  
    }
784  
    }
785  
#endif
785  
#endif
786  

786  

787  
    is.setstate(err | std::ios::failbit);
787  
    is.setstate(err | std::ios::failbit);
788  
    return is;
788  
    return is;
789  
}
789  
}
790  

790  

791  
std::istream&
791  
std::istream&
792  
operator>>(
792  
operator>>(
793  
    std::istream& is,
793  
    std::istream& is,
794  
    parse_options const& opts)
794  
    parse_options const& opts)
795  
{
795  
{
796  
    is.iword(parse_flags_xalloc) = to_bitmask(opts);
796  
    is.iword(parse_flags_xalloc) = to_bitmask(opts);
797  
    is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth);
797  
    is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth);
798  
    return is;
798  
    return is;
799  
}
799  
}
800  

800  

801  
//----------------------------------------------------------
801  
//----------------------------------------------------------
802  
//
802  
//
803  
// private
803  
// private
804  
//
804  
//
805  
//----------------------------------------------------------
805  
//----------------------------------------------------------
806  

806  

807  
storage_ptr
807  
storage_ptr
808  
value::
808  
value::
809  
destroy() noexcept
809  
destroy() noexcept
810  
{
810  
{
811  
    switch(kind())
811  
    switch(kind())
812  
    {
812  
    {
813  
    case json::kind::null:
813  
    case json::kind::null:
814  
    case json::kind::bool_:
814  
    case json::kind::bool_:
815  
    case json::kind::int64:
815  
    case json::kind::int64:
816  
    case json::kind::uint64:
816  
    case json::kind::uint64:
817  
    case json::kind::double_:
817  
    case json::kind::double_:
818  
        break;
818  
        break;
819  

819  

820  
    case json::kind::string:
820  
    case json::kind::string:
821  
    {
821  
    {
822  
        auto sp = str_.storage();
822  
        auto sp = str_.storage();
823  
        str_.~string();
823  
        str_.~string();
824  
        return sp;
824  
        return sp;
825  
    }
825  
    }
826  

826  

827  
    case json::kind::array:
827  
    case json::kind::array:
828  
    {
828  
    {
829  
        auto sp = arr_.storage();
829  
        auto sp = arr_.storage();
830  
        arr_.~array();
830  
        arr_.~array();
831  
        return sp;
831  
        return sp;
832  
    }
832  
    }
833  

833  

834  
    case json::kind::object:
834  
    case json::kind::object:
835  
    {
835  
    {
836  
        auto sp = obj_.storage();
836  
        auto sp = obj_.storage();
837  
        obj_.~object();
837  
        obj_.~object();
838  
        return sp;
838  
        return sp;
839  
    }
839  
    }
840  

840  

841  
    }
841  
    }
842  
    return std::move(sp_);
842  
    return std::move(sp_);
843  
}
843  
}
844  

844  

845  
bool
845  
bool
846  
value::
846  
value::
847  
equal(value const& other) const noexcept
847  
equal(value const& other) const noexcept
848  
{
848  
{
849  
    switch(kind())
849  
    switch(kind())
850  
    {
850  
    {
851  
    default: // unreachable()?
851  
    default: // unreachable()?
852  
    case json::kind::null:
852  
    case json::kind::null:
853  
        return other.kind() == json::kind::null;
853  
        return other.kind() == json::kind::null;
854  

854  

855  
    case json::kind::bool_:
855  
    case json::kind::bool_:
856  
        return
856  
        return
857  
            other.kind() == json::kind::bool_ &&
857  
            other.kind() == json::kind::bool_ &&
858  
            get_bool() == other.get_bool();
858  
            get_bool() == other.get_bool();
859  

859  

860  
    case json::kind::int64:
860  
    case json::kind::int64:
861  
        switch(other.kind())
861  
        switch(other.kind())
862  
        {
862  
        {
863  
        case json::kind::int64:
863  
        case json::kind::int64:
864  
            return get_int64() == other.get_int64();
864  
            return get_int64() == other.get_int64();
865  
        case json::kind::uint64:
865  
        case json::kind::uint64:
866  
            if(get_int64() < 0)
866  
            if(get_int64() < 0)
867  
                return false;
867  
                return false;
868  
            return static_cast<std::uint64_t>(
868  
            return static_cast<std::uint64_t>(
869  
                get_int64()) == other.get_uint64();
869  
                get_int64()) == other.get_uint64();
870  
        default:
870  
        default:
871  
            return false;
871  
            return false;
872  
        }
872  
        }
873  

873  

874  
    case json::kind::uint64:
874  
    case json::kind::uint64:
875  
        switch(other.kind())
875  
        switch(other.kind())
876  
        {
876  
        {
877  
        case json::kind::uint64:
877  
        case json::kind::uint64:
878  
            return get_uint64() == other.get_uint64();
878  
            return get_uint64() == other.get_uint64();
879  
        case json::kind::int64:
879  
        case json::kind::int64:
880  
            if(other.get_int64() < 0)
880  
            if(other.get_int64() < 0)
881  
                return false;
881  
                return false;
882  
            return static_cast<std::uint64_t>(
882  
            return static_cast<std::uint64_t>(
883  
                other.get_int64()) == get_uint64();
883  
                other.get_int64()) == get_uint64();
884  
        default:
884  
        default:
885  
            return false;
885  
            return false;
886  
        }
886  
        }
887  

887  

888  
    case json::kind::double_:
888  
    case json::kind::double_:
889  
        return
889  
        return
890  
            other.kind() == json::kind::double_ &&
890  
            other.kind() == json::kind::double_ &&
891  
            get_double() == other.get_double();
891  
            get_double() == other.get_double();
892  

892  

893  
    case json::kind::string:
893  
    case json::kind::string:
894  
        return
894  
        return
895  
            other.kind() == json::kind::string &&
895  
            other.kind() == json::kind::string &&
896  
            get_string() == other.get_string();
896  
            get_string() == other.get_string();
897  

897  

898  
    case json::kind::array:
898  
    case json::kind::array:
899  
        return
899  
        return
900  
            other.kind() == json::kind::array &&
900  
            other.kind() == json::kind::array &&
901  
            get_array() == other.get_array();
901  
            get_array() == other.get_array();
902  

902  

903  
    case json::kind::object:
903  
    case json::kind::object:
904  
        return
904  
        return
905  
            other.kind() == json::kind::object &&
905  
            other.kind() == json::kind::object &&
906  
            get_object() == other.get_object();
906  
            get_object() == other.get_object();
907  
    }
907  
    }
908  
}
908  
}
909  

909  

910  
//----------------------------------------------------------
910  
//----------------------------------------------------------
911  
//
911  
//
912  
// key_value_pair
912  
// key_value_pair
913  
//
913  
//
914  
//----------------------------------------------------------
914  
//----------------------------------------------------------
915  

915  

916  
// empty keys point here
916  
// empty keys point here
917  
BOOST_JSON_REQUIRE_CONST_INIT
917  
BOOST_JSON_REQUIRE_CONST_INIT
918  
char const
918  
char const
919  
key_value_pair::empty_[1] = { 0 };
919  
key_value_pair::empty_[1] = { 0 };
920  

920  

921  
key_value_pair::
921  
key_value_pair::
922  
key_value_pair(
922  
key_value_pair(
923  
    pilfered<json::value> key,
923  
    pilfered<json::value> key,
924  
    pilfered<json::value> value) noexcept
924  
    pilfered<json::value> value) noexcept
925  
    : value_(value)
925  
    : value_(value)
926  
{
926  
{
927  
    std::size_t len;
927  
    std::size_t len;
928  
    key_ = access::release_key(key.get(), len);
928  
    key_ = access::release_key(key.get(), len);
929  
    len_ = static_cast<std::uint32_t>(len);
929  
    len_ = static_cast<std::uint32_t>(len);
930  
}
930  
}
931  

931  

932  
key_value_pair::
932  
key_value_pair::
933  
key_value_pair(
933  
key_value_pair(
934  
    key_value_pair const& other,
934  
    key_value_pair const& other,
935  
    storage_ptr sp)
935  
    storage_ptr sp)
936  
    : value_(other.value_, std::move(sp))
936  
    : value_(other.value_, std::move(sp))
937  
{
937  
{
938  
    auto p = reinterpret_cast<
938  
    auto p = reinterpret_cast<
939  
        char*>(value_.storage()->
939  
        char*>(value_.storage()->
940  
            allocate(other.len_ + 1,
940  
            allocate(other.len_ + 1,
941  
                alignof(char)));
941  
                alignof(char)));
942  
    std::memcpy(
942  
    std::memcpy(
943  
        p, other.key_, other.len_);
943  
        p, other.key_, other.len_);
944  
    len_ = other.len_;
944  
    len_ = other.len_;
945  
    p[len_] = 0;
945  
    p[len_] = 0;
946  
    key_ = p;
946  
    key_ = p;
947  
}
947  
}
948  

948  

949  
//----------------------------------------------------------
949  
//----------------------------------------------------------
950  

950  

951  
namespace detail
951  
namespace detail
952  
{
952  
{
953  

953  

954  
std::size_t
954  
std::size_t
955  
hash_value_impl( value const& jv ) noexcept
955  
hash_value_impl( value const& jv ) noexcept
956  
{
956  
{
957  
    std::size_t seed = 0;
957  
    std::size_t seed = 0;
958  

958  

959  
    kind const k = jv.kind();
959  
    kind const k = jv.kind();
960  
    boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 );
960  
    boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 );
961  

961  

962  
    visit( value_hasher{seed}, jv );
962  
    visit( value_hasher{seed}, jv );
963  
    return seed;
963  
    return seed;
964  
}
964  
}
965  

965  

966  
} // namespace detail
966  
} // namespace detail
967  
} // namespace json
967  
} // namespace json
968  
} // namespace boost
968  
} // namespace boost
969  

969  

970  
//----------------------------------------------------------
970  
//----------------------------------------------------------
971  
//
971  
//
972  
// std::hash specialization
972  
// std::hash specialization
973  
//
973  
//
974  
//----------------------------------------------------------
974  
//----------------------------------------------------------
975  

975  

976  
std::size_t
976  
std::size_t
977  
std::hash<::boost::json::value>::operator()(
977  
std::hash<::boost::json::value>::operator()(
978  
    ::boost::json::value const& jv) const noexcept
978  
    ::boost::json::value const& jv) const noexcept
979  
{
979  
{
980  
    return ::boost::hash< ::boost::json::value >()( jv );
980  
    return ::boost::hash< ::boost::json::value >()( jv );
981  
}
981  
}
982  

982  

983  
//----------------------------------------------------------
983  
//----------------------------------------------------------
984  

984  

985  
#endif
985  
#endif