GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: parser.hpp
Date: 2025-12-23 17:38:58
Exec Total Coverage
Lines: 29 29 100.0%
Functions: 11 11 100.0%
Branches: 0 0 -%

Line Branch Exec Source
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_PARSER_HPP
11 #define BOOST_JSON_PARSER_HPP
12
13 #include <boost/json/detail/config.hpp>
14 #include <boost/json/basic_parser.hpp>
15 #include <boost/json/storage_ptr.hpp>
16 #include <boost/json/value.hpp>
17 #include <boost/json/detail/handler.hpp>
18 #include <type_traits>
19 #include <cstddef>
20
21 namespace boost {
22 namespace json {
23
24 //----------------------------------------------------------
25
26 /** A DOM parser for JSON contained in a single buffer.
27
28 This class is used to parse a JSON text contained in a single character
29 buffer, into a @ref value container.
30
31 @par Usage
32 To use the parser first construct it, then optionally call @ref reset to
33 specify a @ref storage_ptr to use for the resulting @ref value. Then call
34 @ref write to parse a character buffer containing a complete JSON text. If
35 the parse is successful, call @ref release to take ownership of the value:
36 @code
37 parser p; // construct a parser
38 size_t n = p.write( "[1,2,3]" ); // parse a complete JSON text
39 assert( n == 7 ); // all characters consumed
40 value jv = p.release(); // take ownership of the value
41 @endcode
42
43 @par Extra Data
44 When the character buffer provided as input contains additional data that
45 is not part of the complete JSON text, an error is returned. The @ref
46 write_some function is an alternative which allows the parse to finish
47 early, without consuming all the characters in the buffer. This allows
48 parsing of a buffer containing multiple individual JSON texts or containing
49 different protocol data:
50 @code
51 parser p; // construct a parser
52 size_t n = p.write_some( "[1,2,3] null" ); // parse a complete JSON text
53 assert( n == 8 ); // only some characters consumed
54 value jv = p.release(); // take ownership of the value
55 @endcode
56
57 @par Temporary Storage
58 The parser may dynamically allocate temporary storage as needed to
59 accommodate the nesting level of the JSON text being parsed. Temporary
60 storage is first obtained from an optional, caller-owned buffer specified
61 upon construction. When that is exhausted, the next allocation uses the
62 @ref boost::container::pmr::memory_resource passed to the constructor; if
63 no such argument is specified, the default memory resource is used.
64 Temporary storage is freed only when the parser is destroyed; The
65 performance of parsing multiple JSON texts may be improved by reusing the
66 same parser instance.
67
68 It is important to note that the `boost::container::pmr::memory_resource`
69 supplied upon construction is used for temporary storage only, and not for
70 allocating the elements which make up the parsed value. That other memory
71 resource is optionally supplied in each call to @ref reset.
72
73 @par Duplicate Keys
74 If there are object elements with duplicate keys; that is, if multiple
75 elements in an object have keys that compare equal, only the last
76 equivalent element will be inserted.
77
78 @par Non-Standard JSON
79 The @ref parse_options structure optionally provided upon construction is
80 used to customize some parameters of the parser, including which
81 non-standard JSON extensions should be allowed. A default-constructed parse
82 options allows only standard JSON.
83
84 @par Thread Safety
85 Distinct instances may be accessed concurrently. Non-const member functions
86 of a shared instance may not be called concurrently with any other member
87 functions of that instance.
88
89 @see @ref parse, @ref stream_parser.
90 */
91 class parser
92 {
93 basic_parser<detail::handler> p_;
94
95 public:
96 /** Assignment operator.
97
98 This type is neither copyable nor movable. The operator is deleted.
99 */
100 parser& operator=(
101 parser const&) = delete;
102
103 /** Destructor.
104
105 All dynamically allocated memory, including
106 any incomplete parsing results, is freed.
107
108 @par Complexity
109 Linear in the size of partial results.
110
111 @par Exception Safety
112 No-throw guarantee.
113 */
114 2001563 ~parser() = default;
115
116 /** Constructors.
117
118 Construct a new parser.
119
120 The parser will only support standard JSON if overloads **(1)**
121 or **(2)** are used. Otherwise the parser will support extensions
122 specified by the parameter `opt`.
123
124 The parsed value will use the \<\<default_memory_resource,default
125 memory resource\>\> for storage. To use a different resource, call @ref
126 reset after construction.
127
128 The main difference between the overloads is in what the constructed
129 parser will use for temporary storage:
130
131 @li **(1)** the constructed parser uses the default memory resource for
132 temporary storage.
133
134 @li **(2)**, **(3)** the constructed parser uses the memory resource of
135 `sp` for temporary storage.
136
137 @li **(4)**, **(6)** the constructed parser first uses the caller-owned
138 storage `[buffer, buffer + size)` for temporary storage, falling back
139 to the memory resource of `sp` if needed.
140
141 @li **(5)**, **(7)** the constructed parser first uses the caller-owned
142 storage `[buffer, buffer + N)` for temporary storage, falling back to
143 the memory resource of `sp` if needed.
144
145 @note Ownership of `buffer` is not transferred. The caller is
146 responsible for ensuring the lifetime of the storage pointed to by
147 `buffer` extends until the parser is destroyed.
148
149 Overload **(8)** is the copy constructor. The type is neither copyable
150 nor movable, so the overload is deleted.
151
152 @par Complexity
153 Constant.
154
155 @par Exception Safety
156 No-throw guarantee.
157
158 @{
159 */
160 53 parser() noexcept
161 53 : parser({}, {})
162 {
163 53 }
164
165 /** Overload
166
167 @param sp The memory resource to use for temporary storage.
168 */
169 explicit
170 1 parser(storage_ptr sp) noexcept
171 1 : parser(std::move(sp), {})
172 {
173 1 }
174
175 /** Overload
176
177 @param opt The parsing options to use.
178 @param sp
179 */
180 BOOST_JSON_DECL
181 parser(
182 storage_ptr sp,
183 parse_options const& opt) noexcept;
184
185 /** Overload
186
187 @param buffer A pointer to valid storage.
188 @param size The number of valid bytes in `buffer`.
189 @param sp
190 @param opt
191 */
192 BOOST_JSON_DECL
193 parser(
194 storage_ptr sp,
195 parse_options const& opt,
196 unsigned char* buffer,
197 std::size_t size) noexcept;
198
199 /** Overload
200
201 @tparam N The number of valid bytes in `buffer`.
202 @param sp
203 @param opt
204 @param buffer
205 */
206 template<std::size_t N>
207 2001506 parser(
208 storage_ptr sp,
209 parse_options const& opt,
210 unsigned char(&buffer)[N]) noexcept
211 2001506 : parser(std::move(sp),
212 2001506 opt, &buffer[0], N)
213 {
214 2001506 }
215
216 #if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
217 /** Overload
218
219 @param buffer
220 @param size
221 @param sp
222 @param opt
223 */
224 parser(
225 storage_ptr sp,
226 parse_options const& opt,
227 std::byte* buffer,
228 std::size_t size) noexcept
229 : parser(sp, opt, reinterpret_cast<
230 unsigned char*>(buffer), size)
231 {
232 }
233
234 /** Overload
235
236 @tparam N
237 @param sp
238 @param opt
239 @param buffer
240 */
241 template<std::size_t N>
242 parser(
243 storage_ptr sp,
244 parse_options const& opt,
245 std::byte(&buffer)[N]) noexcept
246 : parser(std::move(sp),
247 opt, &buffer[0], N)
248 {
249 }
250 #endif
251
252 #ifndef BOOST_JSON_DOCS
253 // Safety net for accidental buffer overflows
254 template<std::size_t N>
255 parser(
256 storage_ptr sp,
257 parse_options const& opt,
258 unsigned char(&buffer)[N],
259 std::size_t n) noexcept
260 : parser(std::move(sp),
261 opt, &buffer[0], n)
262 {
263 // If this goes off, check your parameters
264 // closely, chances are you passed an array
265 // thinking it was a pointer.
266 BOOST_ASSERT(n <= N);
267 }
268
269 #ifdef __cpp_lib_byte
270 // Safety net for accidental buffer overflows
271 template<std::size_t N>
272 parser(
273 storage_ptr sp,
274 parse_options const& opt,
275 std::byte(&buffer)[N], std::size_t n) noexcept
276 : parser(std::move(sp),
277 opt, &buffer[0], n)
278 {
279 // If this goes off, check your parameters
280 // closely, chances are you passed an array
281 // thinking it was a pointer.
282 BOOST_ASSERT(n <= N);
283 }
284 #endif
285 #endif
286
287 /// Overload
288 parser(
289 parser const&) = delete;
290 /// @}
291
292
293 /** Reset the parser for a new JSON text.
294
295 This function is used to reset the parser to
296 prepare it for parsing a new complete JSON text.
297 Any previous partial results are destroyed.
298
299 @par Complexity
300 Constant or linear in the size of any previous
301 partial parsing results.
302
303 @par Exception Safety
304 No-throw guarantee.
305
306 @param sp A pointer to the @ref boost::container::pmr::memory_resource
307 to use for the resulting @ref value. The parser will acquire shared
308 ownership.
309 */
310 BOOST_JSON_DECL
311 void
312 reset(storage_ptr sp = {}) noexcept;
313
314 /** Parse a buffer containing a complete JSON text.
315
316 This function parses a complete JSON text contained in the specified
317 character buffer. Additional characters past the end of the complete
318 JSON text are ignored. The function returns the actual number of
319 characters parsed, which may be less than the size of the input. This
320 allows parsing of a buffer containing multiple individual JSON texts or
321 containing different protocol data:
322
323 @par Example
324 @code
325 parser p; // construct a parser
326 size_t n = p.write_some( "[1,2,3] null" ); // parse a complete JSON text
327 assert( n == 8 ); // only some characters consumed
328 value jv = p.release(); // take ownership of the value
329 @endcode
330
331 Overloads **(1)**, **(2)**, **(4)**, and **(5)** report errors by
332 setting `ec`. Overloads **(3)** and **(6)** report errors by throwing
333 exceptions.
334
335 @par Complexity
336 @li **(1)**--**(3)** linear in `size`.
337 @li **(4)**--**(6)** linear in `s.size()`.
338
339 @par Exception Safety
340 Basic guarantee. Calls to `memory_resource::allocate` may throw. Upon
341 error or exception, subsequent calls will fail until @ref reset is
342 called to parse a new JSON text.
343
344 @return The number of characters consumed from the buffer.
345
346 @param data A pointer to a buffer of `size` characters to parse.
347 @param size The number of characters pointed to by `data`.
348 @param ec Set to the error, if any occurred.
349
350 @{
351 */
352 BOOST_JSON_DECL
353 std::size_t
354 write_some(
355 char const* data,
356 std::size_t size,
357 system::error_code& ec);
358
359 BOOST_JSON_DECL
360 std::size_t
361 write_some(
362 char const* data,
363 std::size_t size,
364 std::error_code& ec);
365
366 /** Overload
367
368 @param data
369 @param size
370 */
371 BOOST_JSON_DECL
372 std::size_t
373 write_some(
374 char const* data,
375 std::size_t size);
376
377 /** Overload
378
379 @param s The character string to parse.
380 @param ec
381 */
382 std::size_t
383 2 write_some(
384 string_view s,
385 system::error_code& ec)
386 {
387 2 return write_some(
388 2 s.data(), s.size(), ec);
389 }
390
391 /** Overload
392
393 @param s
394 @param ec
395 */
396 std::size_t
397 2 write_some(
398 string_view s,
399 std::error_code& ec)
400 {
401 2 return write_some(
402 2 s.data(), s.size(), ec);
403 }
404
405 /** Overload
406
407 @param s
408 */
409 std::size_t
410 4 write_some(
411 string_view s)
412 {
413 4 return write_some(
414 2 s.data(), s.size());
415 }
416 /// @}
417
418 /** Parse a buffer containing a complete JSON text.
419
420 This function parses a complete JSON text contained in the specified
421 character buffer. The entire buffer must be consumed; if there are
422 additional characters past the end of the complete JSON text, the parse
423 fails and an error is returned.
424
425 @par Example
426 @code
427 parser p; // construct a parser
428 size_t n = p.write( "[1,2,3]" ); // parse a complete JSON text
429 assert( n == 7 ); // all characters consumed
430 value jv = p.release(); // take ownership of the value
431 @endcode
432
433 Overloads **(1)**, **(2)**, **(4)**, and **(5)** report errors by
434 setting `ec`. Overloads **(3)** and **(6)** report errors by throwing
435 exceptions.
436
437 @par Complexity
438 @li **(1)**--**(3)** linear in `size`.
439 @li **(4)**--**(6)** linear in `s.size()`.
440
441 @par Exception Safety
442 Basic guarantee. Calls to `memory_resource::allocate` may throw. Upon
443 error or exception, subsequent calls will fail until @ref reset is
444 called to parse a new JSON text.
445
446 @return The number of characters consumed from the buffer.
447
448 @param data A pointer to a buffer of `size` characters to parse.
449 @param size The number of characters pointed to by `data`.
450 @param ec Set to the error, if any occurred.
451
452 @{
453 */
454 BOOST_JSON_DECL
455 std::size_t
456 write(
457 char const* data,
458 std::size_t size,
459 system::error_code& ec);
460
461 BOOST_JSON_DECL
462 std::size_t
463 write(
464 char const* data,
465 std::size_t size,
466 std::error_code& ec);
467
468 /** Overload
469
470 @throw `boost::system::system_error` Thrown on error.
471 */
472 BOOST_JSON_DECL
473 std::size_t
474 write(
475 char const* data,
476 std::size_t size);
477
478 /** Overload
479
480 @param s The character string to parse.
481 @param ec
482 */
483 std::size_t
484 2001508 write(
485 string_view s,
486 system::error_code& ec)
487 {
488 2001508 return write(
489 2001507 s.data(), s.size(), ec);
490 }
491
492 /** Overload
493
494 @param s
495 @param ec
496 */
497 std::size_t
498 3 write(
499 string_view s,
500 std::error_code& ec)
501 {
502 3 return write(
503 3 s.data(), s.size(), ec);
504 }
505
506 /** Overload
507
508 @param s
509 */
510 std::size_t
511 8 write(
512 string_view s)
513 {
514 8 return write(
515 4 s.data(), s.size());
516 }
517 /// @}
518
519 /** Return the parsed JSON text as a @ref value.
520
521 This returns the parsed value, or throws an exception if the parsing is
522 incomplete or failed. It is necessary to call @ref reset after calling
523 this function in order to parse another JSON text.
524
525 @par Complexity
526 Constant.
527
528 @return The parsed value. Ownership of this value is transferred to the
529 caller.
530
531 @throw boost::system::system_error A complete JSON text hasn't been
532 parsed, or parsing failed.
533 */
534 BOOST_JSON_DECL
535 value
536 release();
537 };
538
539 } // namespace json
540 } // namespace boost
541
542 #endif
543