]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/json/impl/value.ipp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / json / impl / value.ipp
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 //
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)
6 //
7 // Official repository: https://github.com/boostorg/json
8 //
9
10 #ifndef BOOST_JSON_IMPL_VALUE_IPP
11 #define BOOST_JSON_IMPL_VALUE_IPP
12
13 #include <boost/json/value.hpp>
14 #include <cstring>
15 #include <limits>
16 #include <new>
17 #include <utility>
18
19 BOOST_JSON_NS_BEGIN
20
21 value::
22 ~value()
23 {
24 switch(kind())
25 {
26 case json::kind::null:
27 case json::kind::bool_:
28 case json::kind::int64:
29 case json::kind::uint64:
30 case json::kind::double_:
31 sca_.~scalar();
32 break;
33
34 case json::kind::string:
35 str_.~string();
36 break;
37
38 case json::kind::array:
39 arr_.~array();
40 break;
41
42 case json::kind::object:
43 obj_.~object();
44 break;
45 }
46 }
47
48 value::
49 value(
50 value const& other,
51 storage_ptr sp)
52 {
53 switch(other.kind())
54 {
55 case json::kind::null:
56 ::new(&sca_) scalar(
57 std::move(sp));
58 break;
59
60 case json::kind::bool_:
61 ::new(&sca_) scalar(
62 other.sca_.b,
63 std::move(sp));
64 break;
65
66 case json::kind::int64:
67 ::new(&sca_) scalar(
68 other.sca_.i,
69 std::move(sp));
70 break;
71
72 case json::kind::uint64:
73 ::new(&sca_) scalar(
74 other.sca_.u,
75 std::move(sp));
76 break;
77
78 case json::kind::double_:
79 ::new(&sca_) scalar(
80 other.sca_.d,
81 std::move(sp));
82 break;
83
84 case json::kind::string:
85 ::new(&str_) string(
86 other.str_,
87 std::move(sp));
88 break;
89
90 case json::kind::array:
91 ::new(&arr_) array(
92 other.arr_,
93 std::move(sp));
94 break;
95
96 case json::kind::object:
97 ::new(&obj_) object(
98 other.obj_,
99 std::move(sp));
100 break;
101 }
102 }
103
104 value::
105 value(value&& other) noexcept
106 {
107 relocate(this, other);
108 ::new(&other.sca_) scalar(sp_);
109 }
110
111 value::
112 value(
113 value&& other,
114 storage_ptr sp)
115 {
116 switch(other.kind())
117 {
118 case json::kind::null:
119 ::new(&sca_) scalar(
120 std::move(sp));
121 break;
122
123 case json::kind::bool_:
124 ::new(&sca_) scalar(
125 other.sca_.b, std::move(sp));
126 break;
127
128 case json::kind::int64:
129 ::new(&sca_) scalar(
130 other.sca_.i, std::move(sp));
131 break;
132
133 case json::kind::uint64:
134 ::new(&sca_) scalar(
135 other.sca_.u, std::move(sp));
136 break;
137
138 case json::kind::double_:
139 ::new(&sca_) scalar(
140 other.sca_.d, std::move(sp));
141 break;
142
143 case json::kind::string:
144 ::new(&str_) string(
145 std::move(other.str_),
146 std::move(sp));
147 break;
148
149 case json::kind::array:
150 ::new(&arr_) array(
151 std::move(other.arr_),
152 std::move(sp));
153 break;
154
155 case json::kind::object:
156 ::new(&obj_) object(
157 std::move(other.obj_),
158 std::move(sp));
159 break;
160 }
161 }
162
163 //----------------------------------------------------------
164 //
165 // Conversion
166 //
167 //----------------------------------------------------------
168
169 value::
170 value(
171 std::initializer_list<value_ref> init,
172 storage_ptr sp)
173 {
174 if(value_ref::maybe_object(init))
175 ::new(&obj_) object(
176 value_ref::make_object(
177 init, std::move(sp)));
178 else
179 ::new(&arr_) array(
180 value_ref::make_array(
181 init, std::move(sp)));
182 }
183
184 //----------------------------------------------------------
185 //
186 // Assignment
187 //
188 //----------------------------------------------------------
189
190 value&
191 value::
192 operator=(value const& other)
193 {
194 value(other,
195 storage()).swap(*this);
196 return *this;
197 }
198
199 value&
200 value::
201 operator=(value&& other)
202 {
203 value(std::move(other),
204 storage()).swap(*this);
205 return *this;
206 }
207
208 value&
209 value::
210 operator=(
211 std::initializer_list<value_ref> init)
212 {
213 value(init,
214 storage()).swap(*this);
215 return *this;
216 }
217
218 value&
219 value::
220 operator=(string_view s)
221 {
222 value(s, storage()).swap(*this);
223 return *this;
224 }
225
226 value&
227 value::
228 operator=(char const* s)
229 {
230 value(s, storage()).swap(*this);
231 return *this;
232 }
233
234 value&
235 value::
236 operator=(string const& str)
237 {
238 value(str, storage()).swap(*this);
239 return *this;
240 }
241
242 value&
243 value::
244 operator=(string&& str)
245 {
246 value(std::move(str),
247 storage()).swap(*this);
248 return *this;
249 }
250
251 value&
252 value::
253 operator=(array const& arr)
254 {
255 value(arr, storage()).swap(*this);
256 return *this;
257 }
258
259 value&
260 value::
261 operator=(array&& arr)
262 {
263 value(std::move(arr),
264 storage()).swap(*this);
265 return *this;
266 }
267
268 value&
269 value::
270 operator=(object const& obj)
271 {
272 value(obj, storage()).swap(*this);
273 return *this;
274 }
275
276 value&
277 value::
278 operator=(object&& obj)
279 {
280 value(std::move(obj),
281 storage()).swap(*this);
282 return *this;
283 }
284
285 //----------------------------------------------------------
286 //
287 // Modifiers
288 //
289 //----------------------------------------------------------
290
291 string&
292 value::
293 emplace_string() noexcept
294 {
295 return *::new(&str_) string(destroy());
296 }
297
298 array&
299 value::
300 emplace_array() noexcept
301 {
302 return *::new(&arr_) array(destroy());
303 }
304
305 object&
306 value::
307 emplace_object() noexcept
308 {
309 return *::new(&obj_) object(destroy());
310 }
311
312 void
313 value::
314 swap(value& other)
315 {
316 if(*storage() == *other.storage())
317 {
318 // fast path
319 union U
320 {
321 value tmp;
322 U(){}
323 ~U(){}
324 };
325 U u;
326 relocate(&u.tmp, *this);
327 relocate(this, other);
328 relocate(&other, u.tmp);
329 return;
330 }
331
332 // copy
333 value temp1(
334 std::move(*this),
335 other.storage());
336 value temp2(
337 std::move(other),
338 this->storage());
339 other.~value();
340 ::new(&other) value(pilfer(temp1));
341 this->~value();
342 ::new(this) value(pilfer(temp2));
343 }
344
345 //----------------------------------------------------------
346 //
347 // private
348 //
349 //----------------------------------------------------------
350
351 storage_ptr
352 value::
353 destroy() noexcept
354 {
355 switch(kind())
356 {
357 case json::kind::null:
358 case json::kind::bool_:
359 case json::kind::int64:
360 case json::kind::uint64:
361 case json::kind::double_:
362 break;
363
364 case json::kind::string:
365 {
366 auto sp = str_.storage();
367 str_.~string();
368 return sp;
369 }
370
371 case json::kind::array:
372 {
373 auto sp = arr_.storage();
374 arr_.~array();
375 return sp;
376 }
377
378 case json::kind::object:
379 {
380 auto sp = obj_.storage();
381 obj_.~object();
382 return sp;
383 }
384
385 }
386 return std::move(sp_);
387 }
388
389 bool
390 value::
391 equal(value const& other) const noexcept
392 {
393 switch(kind())
394 {
395 default: // unreachable()?
396 case json::kind::null:
397 return other.kind() == json::kind::null;
398
399 case json::kind::bool_:
400 return
401 other.kind() == json::kind::bool_ &&
402 get_bool() == other.get_bool();
403
404 case json::kind::int64:
405 switch(other.kind())
406 {
407 case json::kind::int64:
408 return get_int64() == other.get_int64();
409 case json::kind::uint64:
410 if(get_int64() < 0)
411 return false;
412 return static_cast<std::uint64_t>(
413 get_int64()) == other.get_uint64();
414 default:
415 return false;
416 }
417
418 case json::kind::uint64:
419 switch(other.kind())
420 {
421 case json::kind::uint64:
422 return get_uint64() == other.get_uint64();
423 case json::kind::int64:
424 if(other.get_int64() < 0)
425 return false;
426 return static_cast<std::uint64_t>(
427 other.get_int64()) == get_uint64();
428 default:
429 return false;
430 }
431
432 case json::kind::double_:
433 return
434 other.kind() == json::kind::double_ &&
435 get_double() == other.get_double();
436
437 case json::kind::string:
438 return
439 other.kind() == json::kind::string &&
440 get_string() == other.get_string();
441
442 case json::kind::array:
443 return
444 other.kind() == json::kind::array &&
445 get_array() == other.get_array();
446
447 case json::kind::object:
448 return
449 other.kind() == json::kind::object &&
450 get_object() == other.get_object();
451 }
452 }
453
454 //----------------------------------------------------------
455 //
456 // key_value_pair
457 //
458 //----------------------------------------------------------
459
460 // empty keys point here
461 BOOST_JSON_REQUIRE_CONST_INIT
462 char const
463 key_value_pair::empty_[1] = { 0 };
464
465 key_value_pair::
466 key_value_pair(
467 pilfered<json::value> key,
468 pilfered<json::value> value) noexcept
469 : value_(value)
470 {
471 std::size_t len;
472 key_ = access::release_key(key.get(), len);
473 len_ = static_cast<std::uint32_t>(len);
474 }
475
476 key_value_pair::
477 key_value_pair(
478 key_value_pair const& other,
479 storage_ptr sp)
480 : value_(other.value_, std::move(sp))
481 {
482 auto p = reinterpret_cast<
483 char*>(value_.storage()->
484 allocate(other.len_ + 1,
485 alignof(char)));
486 std::memcpy(
487 p, other.key_, other.len_);
488 len_ = other.len_;
489 p[len_] = 0;
490 key_ = p;
491 }
492
493 //----------------------------------------------------------
494
495 BOOST_JSON_NS_END
496
497 #endif