]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/json/value_stack.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / json / value_stack.hpp
CommitLineData
20effc67
TL
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_VALUE_STACK_HPP
11#define BOOST_JSON_VALUE_STACK_HPP
12
13#include <boost/json/detail/config.hpp>
14#include <boost/json/error.hpp>
15#include <boost/json/storage_ptr.hpp>
16#include <boost/json/value.hpp>
17#include <stddef.h>
18
19BOOST_JSON_NS_BEGIN
20
21//----------------------------------------------------------
22
23/** A stack of @ref value elements, for building a document.
24
25 This stack of @ref value allows iterative
26 construction of a JSON document in memory.
27 The implementation uses temporary internal
28 storage to buffer elements so that arrays, objects,
29 and strings in the document are constructed using a
30 single memory allocation. This improves performance
31 and makes efficient use of the @ref memory_resource
32 used to create the resulting @ref value.
33
34 Temporary storage used by the implementation
35 initially comes from an optional memory buffer
36 owned by the caller. If that storage is exhausted,
37 then memory is obtained dynamically from the
38 @ref memory_resource provided on construction.
39
40 @par Usage
41
42 Construct the stack with an optional initial
43 temporary buffer, and a @ref storage_ptr to use for
44 more storage when the initial buffer is exhausted.
45 Then to build a @ref value, first call @ref reset
46 and optionally specify the @ref memory_resource
47 which will be used for the value. Then push elements
48 onto the stack by calling the corresponding functions.
49 After the document has been fully created, call
50 @ref release to acquire ownership of the top-level
51 @ref value.
52
53 @par Performance
54
55 The initial buffer and any dynamically allocated
56 temporary buffers are retained until the stack
57 is destroyed. This improves performance when using
58 a single stack instance to produce multiple
59 values.
60
61 @par Example
62
63 The following code constructs a @ref value which
64 when serialized produces a JSON object with three
65 elements. It uses a local buffer for the temporary
66 storage, and a separate local buffer for the storage
67 of the resulting value. No memory is dynamically
68 allocated; this shows how to construct a value
69 without using the heap.
70
71 @code
72
73 // This example builds a json::value without any dynamic memory allocations:
74
75 // Construct the value stack using a local buffer
76 unsigned char temp[4096];
77 value_stack st( storage_ptr(), temp, sizeof(temp) );
78
79 // Create a static resource with a local initial buffer
80 unsigned char buf[4096];
81 static_resource mr( buf, sizeof(buf) );
82
83 // All values on the stack will use `mr`
84 st.reset(&mr);
85
86 // Push the key/value pair "a":1.
87 st.push_key("a");
88 st.push_int64(1);
89
90 // Push "b":null
91 st.push_key("b");
92 st.push_null();
93
94 // Push "c":"hello"
95 st.push_key("c");
96 st.push_string("hello");
97
98 // Pop the three key/value pairs and push an object with those three values.
99 st.push_object(3);
100
101 // Pop the object from the stack and take ownership.
102 value jv = st.release();
103
104 assert( serialize(jv) == "{\"a\":1,\"b\":null,\"c\":\"hello\"}" );
105
106 // At this point we could re-use the stack by calling reset
107
108 @endcode
109
110 @par Thread Safety
111
112 Distinct instances may be accessed concurrently.
113 Non-const member functions of a shared instance
114 may not be called concurrently with any other
115 member functions of that instance.
116*/
117class value_stack
118{
119 class stack
120 {
121 enum
122 {
123 min_size_ = 16
124 };
125
126 storage_ptr sp_;
127 void* temp_;
128 value* begin_;
129 value* top_;
130 value* end_;
131 // string starts at top_+1
132 std::size_t chars_ = 0;
133 bool run_dtors_ = true;
134
135 public:
136 inline ~stack();
137 inline stack(
138 storage_ptr sp,
139 void* temp, std::size_t size) noexcept;
140 inline void run_dtors(bool b) noexcept;
141 inline std::size_t size() const noexcept;
142 inline bool has_chars();
143
144 inline void clear() noexcept;
145 inline void maybe_grow();
146 inline void grow_one();
147 inline void grow(std::size_t nchars);
148
149 inline void append(string_view s);
150 inline string_view release_string() noexcept;
151 inline value* release(std::size_t n) noexcept;
152 template<class... Args> value& push(Args&&... args);
153 template<class Unchecked> void exchange(Unchecked&& u);
154 };
155
156 stack st_;
157 storage_ptr sp_;
158
159public:
160 /// Copy constructor (deleted)
161 value_stack(
162 value_stack const&) = delete;
163
164 /// Copy assignment (deleted)
165 value_stack& operator=(
166 value_stack const&) = delete;
167
168 /** Destructor.
169
170 All dynamically allocated memory and
171 partial or complete elements is freed.
172
173 @par Complexity
174 Linear in the size of partial results.
175
176 @par Exception Safety
177 No-throw guarantee.
178 */
179 BOOST_JSON_DECL
180 ~value_stack();
181
182 /** Constructor.
183
184 Constructs an empty stack. Before any
185 @ref value can be built, the function
186 @ref reset must be called.
187
188 The `sp` parameter is only used to allocate
189 intermediate storage; it will not be used
190 for the @ref value returned by @ref release.
191
192 @param sp A pointer to the @ref memory_resource
193 to use for intermediate storage allocations. If
194 this argument is omitted, the default memory
195 resource is used.
196
197 @param temp_buffer A pointer to a caller-owned
198 buffer which will be used to store temporary
199 data used while building the value. If this
200 pointer is null, the builder will use the
201 storage pointer to allocate temporary data.
202
203 @param temp_size The number of valid bytes of
204 storage pointed to by `temp_buffer`.
205 */
206 BOOST_JSON_DECL
207 value_stack(
208 storage_ptr sp = {},
209 unsigned char* temp_buffer = nullptr,
210 std::size_t temp_size = 0) noexcept;
211
212 /** Prepare to build a new document.
213
214 This function must be called before constructing
215 a new top-level @ref value. Any previously existing
216 partial or complete elements are destroyed, but
217 internal dynamically allocated memory is preserved
218 which may be reused to build new values.
219
220 @par Exception Safety
221
222 No-throw guarantee.
223
224 @param sp A pointer to the @ref memory_resource
225 to use for top-level @ref value and all child
226 values. The stack will acquire shared ownership
227 of the memory resource until @ref release or
228 @ref reset is called, or when the stack is
229 destroyed.
230 */
231 BOOST_JSON_DECL
232 void
233 reset(storage_ptr sp = {}) noexcept;
234
235 /** Return the top-level @ref value.
236
237 This function transfers ownership of the
238 constructed top-level value to the caller.
239 The behavior is undefined if there is not
240 a single, top-level element.
241
242 @par Exception Safety
243
244 No-throw guarantee.
245
246 @return A __value__ holding the result.
247 Ownership of this value is transferred
248 to the caller. Ownership of the memory
249 resource used in the last call to @ref reset
250 is released.
251 */
252 BOOST_JSON_DECL
253 value
254 release() noexcept;
255
256 //--------------------------------------------
257
258 /** Push an array formed by popping `n` values from the stack.
259
260 This function pushes an @ref array value
261 onto the stack. The array is formed by first
262 popping the top `n` values from the stack.
263 If the stack contains fewer than `n` values,
264 or if any of the top `n` values on the stack
265 is a key, the behavior is undefined.
266
267 @par Example
268
269 The following statements produce an array
270 with the contents 1, 2, 3:
271
272 @code
273
274 value_stack st;
275
276 // reset must be called first or else the behavior is undefined
277 st.reset();
278
279 // Place three values on the stack
280 st.push_int64( 1 );
281 st.push_int64( 2 );
282 st.push_int64( 3 );
283
284 // Remove the 3 values, and push an array with those 3 elements on the stack
285 st.push_array( 3 );
286
287 // Pop the object from the stack and take ownership.
288 value jv = st.release();
289
290 assert( serialize(jv) == "[1,2,3]" );
291
292 // At this point, reset must be called again to use the stack
293
294 @endcode
295
296 @param n The number of values to pop from the
297 top of the stack to form the array.
298 */
299 BOOST_JSON_DECL
300 void
301 push_array(std::size_t n);
302
303 /** Push an object formed by popping `n` key/value pairs from the stack.
304
305 This function pushes an @ref object value
306 onto the stack. The object is formed by first
307 popping the top `n` key/value pairs from the
308 stack. If the stack contains fewer than `n`
309 key/value pairs, or if any of the top `n` key/value
310 pairs on the stack does not consist of exactly one
311 key followed by one value, the behavior is undefined.
312
313 @note
314
315 A key/value pair is formed by pushing a key, and then
316 pushing a value.
317
318 @par Example
319
320 The following code creates an object on the stack
321 with a single element, where key is "x" and value
322 is true:
323
324 @code
325
326 value_stack st;
327
328 // reset must be called first or else the behavior is undefined
329 st.reset();
330
331 // Place a key/value pair onto the stack
332 st.push_key( "x" );
333 st.push_bool( true );
334
335 // Replace the key/value pair with an object containing a single element
336 st.push_object( 1 );
337
338 // Pop the object from the stack and take ownership.
339 value jv = st.release();
340
341 assert( serialize(jv) == "{\"x\",true}" );
342
343 // At this point, reset must be called again to use the stack
344
345 @endcode
346
347 @par Duplicate Keys
348
349 If there are object elements with duplicate keys;
350 that is, if multiple elements in an object have
351 keys that compare equal, only the last equivalent
352 element will be inserted.
353
354 @param n The number of key/value pairs to pop from the
355 top of the stack to form the array.
356 */
357 BOOST_JSON_DECL
358 void
359 push_object(std::size_t n);
360
361 /** Push part of a key or string onto the stack.
362
363 This function pushes the characters in `s` onto
364 the stack, appending to any existing characters
365 or creating new characters as needed. Once a
366 string part is placed onto the stack, the only
367 valid stack operations are:
368
369 @li @ref push_chars to append additional
370 characters to the key or string being built,
371
372 @li @ref push_key or @ref push_string to
373 finish building the key or string and place
374 the value onto the stack.
375
376 @par Exception Safety
377
378 Basic guarantee.
379 Calls to `memory_resource::allocate` may throw.
380
381 @param s The characters to append. This may be empty.
382 */
383 BOOST_JSON_DECL
384 void
385 push_chars(
386 string_view s);
387
388 /** Push a key onto the stack.
389
390 This function notionally removes all the
391 characters currently on the stack, then
392 pushes a @ref value containing a key onto
393 the stack formed by appending `s` to the
394 removed characters.
395
396 @par Exception Safety
397
398 Basic guarantee.
399 Calls to `memory_resource::allocate` may throw.
400
401 @param s The characters to append. This may be empty.
402 */
403 BOOST_JSON_DECL
404 void
405 push_key(
406 string_view s);
407
408 /** Place a string value onto the stack.
409
410 This function notionally removes all the
411 characters currently on the stack, then
412 pushes a @ref value containing a @ref string
413 onto the stack formed by appending `s` to the
414 removed characters.
415
416 @par Exception Safety
417
418 Basic guarantee.
419 Calls to `memory_resource::allocate` may throw.
420
421 @param s The characters to append. This may be empty.
422 */
423 BOOST_JSON_DECL
424 void
425 push_string(
426 string_view s);
427
428 /** Push a number onto the stack
429
430 This function pushes a number value onto the stack.
431
432 @par Exception Safety
433
434 Basic guarantee.
435 Calls to `memory_resource::allocate` may throw.
436
437 @param i The number to insert.
438 */
439 BOOST_JSON_DECL
440 void
441 push_int64(
442 int64_t i);
443
444 /** Push a number onto the stack
445
446 This function pushes a number value onto the stack.
447
448 @par Exception Safety
449
450 Basic guarantee.
451 Calls to `memory_resource::allocate` may throw.
452
453 @param u The number to insert.
454 */
455 BOOST_JSON_DECL
456 void
457 push_uint64(
458 uint64_t u);
459
460 /** Push a number onto the stack
461
462 This function pushes a number value onto the stack.
463
464 @par Exception Safety
465
466 Basic guarantee.
467 Calls to `memory_resource::allocate` may throw.
468
469 @param d The number to insert.
470 */
471 BOOST_JSON_DECL
472 void
473 push_double(
474 double d);
475
476 /** Push a `bool` onto the stack
477
478 This function pushes a boolean value onto the stack.
479
480 @par Exception Safety
481
482 Basic guarantee.
483 Calls to `memory_resource::allocate` may throw.
484
485 @param b The boolean to insert.
486 */
487 BOOST_JSON_DECL
488 void
489 push_bool(
490 bool b);
491
492 /** Push a null onto the stack
493
494 This function pushes a boolean value onto the stack.
495
496 @par Exception Safety
497
498 Basic guarantee.
499 Calls to `memory_resource::allocate` may throw.
500 */
501 BOOST_JSON_DECL
502 void
503 push_null();
504};
505
506BOOST_JSON_NS_END
507
508#endif