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 +
    return try_as_object() & [key](object& jo) { return jo.try_at(key); };
532 -
    if( !r )
 
533 -
        return r.error();
 
534 -
    return r->try_at(key);
 
535  
}
532  
}
536  

533  

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

540  

546  
boost::system::result<value&>
541  
boost::system::result<value&>
547  
value::try_at(std::size_t pos) noexcept
542  
value::try_at(std::size_t pos) noexcept
548  
{
543  
{
549 -
    auto r = try_as_array();
544 +
    return try_as_array() & [pos](array& ja) { return ja.try_at(pos); };
550 -
    if( !r )
 
551 -
        return r.error();
 
552 -
    return r->try_at(pos);
 
553  
}
545  
}
554  

546  

555  
boost::system::result<value const&>
547  
boost::system::result<value const&>
556  
value::try_at(std::size_t pos) const noexcept
548  
value::try_at(std::size_t pos) const noexcept
557  
{
549  
{
558 -
    auto r = try_as_array();
550 +
    return try_as_array() & [pos](array const& ja) { return ja.try_at(pos); };
559 -
    if( !r )
 
560 -
        return r.error();
 
561 -
    return r->try_at(pos);
 
562  
}
551  
}
563  

552  

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

558  

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

564  

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

570  

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

576  

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

582  

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

588  

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

594  

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

600  

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

606  

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

612  

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

618  

630  
//----------------------------------------------------------
619  
//----------------------------------------------------------
631  
//
620  
//
632  
// Modifiers
621  
// Modifiers
633  
//
622  
//
634  
//----------------------------------------------------------
623  
//----------------------------------------------------------
635  

624  

636  
string&
625  
string&
637  
value::
626  
value::
638  
emplace_string() noexcept
627  
emplace_string() noexcept
639  
{
628  
{
640  
    return *::new(&str_) string(destroy());
629  
    return *::new(&str_) string(destroy());
641  
}
630  
}
642  

631  

643  
array&
632  
array&
644  
value::
633  
value::
645  
emplace_array() noexcept
634  
emplace_array() noexcept
646  
{
635  
{
647  
    return *::new(&arr_) array(destroy());
636  
    return *::new(&arr_) array(destroy());
648  
}
637  
}
649  

638  

650  
object&
639  
object&
651  
value::
640  
value::
652  
emplace_object() noexcept
641  
emplace_object() noexcept
653  
{
642  
{
654  
    return *::new(&obj_) object(destroy());
643  
    return *::new(&obj_) object(destroy());
655  
}
644  
}
656  

645  

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

665  

677  
    // copy
666  
    // copy
678  
    value temp1(
667  
    value temp1(
679  
        std::move(*this),
668  
        std::move(*this),
680  
        other.storage());
669  
        other.storage());
681  
    value temp2(
670  
    value temp2(
682  
        std::move(other),
671  
        std::move(other),
683  
        this->storage());
672  
        this->storage());
684  
    other.~value();
673  
    other.~value();
685  
    ::new(&other) value(pilfer(temp1));
674  
    ::new(&other) value(pilfer(temp1));
686  
    this->~value();
675  
    this->~value();
687  
    ::new(this) value(pilfer(temp2));
676  
    ::new(this) value(pilfer(temp2));
688  
}
677  
}
689  

678  

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

685  

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

690  

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

694  

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

698  

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

709  

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

723  

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

731  

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

738  

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

743  

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

755  

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

770  

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

775  

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

779  

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

789  

801  
//----------------------------------------------------------
790  
//----------------------------------------------------------
802  
//
791  
//
803  
// private
792  
// private
804  
//
793  
//
805  
//----------------------------------------------------------
794  
//----------------------------------------------------------
806  

795  

807  
storage_ptr
796  
storage_ptr
808  
value::
797  
value::
809  
destroy() noexcept
798  
destroy() noexcept
810  
{
799  
{
811  
    switch(kind())
800  
    switch(kind())
812  
    {
801  
    {
813  
    case json::kind::null:
802  
    case json::kind::null:
814  
    case json::kind::bool_:
803  
    case json::kind::bool_:
815  
    case json::kind::int64:
804  
    case json::kind::int64:
816  
    case json::kind::uint64:
805  
    case json::kind::uint64:
817  
    case json::kind::double_:
806  
    case json::kind::double_:
818  
        break;
807  
        break;
819  

808  

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

815  

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

822  

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

829  

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

833  

845  
bool
834  
bool
846  
value::
835  
value::
847  
equal(value const& other) const noexcept
836  
equal(value const& other) const noexcept
848  
{
837  
{
849  
    switch(kind())
838  
    switch(kind())
850  
    {
839  
    {
851  
    default: // unreachable()?
840  
    default: // unreachable()?
852  
    case json::kind::null:
841  
    case json::kind::null:
853  
        return other.kind() == json::kind::null;
842  
        return other.kind() == json::kind::null;
854  

843  

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

848  

860  
    case json::kind::int64:
849  
    case json::kind::int64:
861  
        switch(other.kind())
850  
        switch(other.kind())
862  
        {
851  
        {
863  
        case json::kind::int64:
852  
        case json::kind::int64:
864  
            return get_int64() == other.get_int64();
853  
            return get_int64() == other.get_int64();
865  
        case json::kind::uint64:
854  
        case json::kind::uint64:
866  
            if(get_int64() < 0)
855  
            if(get_int64() < 0)
867  
                return false;
856  
                return false;
868  
            return static_cast<std::uint64_t>(
857  
            return static_cast<std::uint64_t>(
869  
                get_int64()) == other.get_uint64();
858  
                get_int64()) == other.get_uint64();
870  
        default:
859  
        default:
871  
            return false;
860  
            return false;
872  
        }
861  
        }
873  

862  

874  
    case json::kind::uint64:
863  
    case json::kind::uint64:
875  
        switch(other.kind())
864  
        switch(other.kind())
876  
        {
865  
        {
877  
        case json::kind::uint64:
866  
        case json::kind::uint64:
878  
            return get_uint64() == other.get_uint64();
867  
            return get_uint64() == other.get_uint64();
879  
        case json::kind::int64:
868  
        case json::kind::int64:
880  
            if(other.get_int64() < 0)
869  
            if(other.get_int64() < 0)
881  
                return false;
870  
                return false;
882  
            return static_cast<std::uint64_t>(
871  
            return static_cast<std::uint64_t>(
883  
                other.get_int64()) == get_uint64();
872  
                other.get_int64()) == get_uint64();
884  
        default:
873  
        default:
885  
            return false;
874  
            return false;
886  
        }
875  
        }
887  

876  

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

881  

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

886  

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

891  

903  
    case json::kind::object:
892  
    case json::kind::object:
904  
        return
893  
        return
905  
            other.kind() == json::kind::object &&
894  
            other.kind() == json::kind::object &&
906  
            get_object() == other.get_object();
895  
            get_object() == other.get_object();
907  
    }
896  
    }
908  
}
897  
}
909  

898  

910  
//----------------------------------------------------------
899  
//----------------------------------------------------------
911  
//
900  
//
912  
// key_value_pair
901  
// key_value_pair
913  
//
902  
//
914  
//----------------------------------------------------------
903  
//----------------------------------------------------------
915  

904  

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

909  

921  
key_value_pair::
910  
key_value_pair::
922  
key_value_pair(
911  
key_value_pair(
923  
    pilfered<json::value> key,
912  
    pilfered<json::value> key,
924  
    pilfered<json::value> value) noexcept
913  
    pilfered<json::value> value) noexcept
925  
    : value_(value)
914  
    : value_(value)
926  
{
915  
{
927  
    std::size_t len;
916  
    std::size_t len;
928  
    key_ = access::release_key(key.get(), len);
917  
    key_ = access::release_key(key.get(), len);
929  
    len_ = static_cast<std::uint32_t>(len);
918  
    len_ = static_cast<std::uint32_t>(len);
930  
}
919  
}
931  

920  

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

937  

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

939  

951  
namespace detail
940  
namespace detail
952  
{
941  
{
953  

942  

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

947  

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

950  

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

954  

966  
} // namespace detail
955  
} // namespace detail
967  
} // namespace json
956  
} // namespace json
968  
} // namespace boost
957  
} // namespace boost
969  

958  

970  
//----------------------------------------------------------
959  
//----------------------------------------------------------
971  
//
960  
//
972  
// std::hash specialization
961  
// std::hash specialization
973  
//
962  
//
974  
//----------------------------------------------------------
963  
//----------------------------------------------------------
975  

964  

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

971  

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

973  

985  
#endif
974  
#endif