GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: parser.hpp
Date: 2025-12-23 17:20:53
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
29 single character buffer, into a @ref value container.
30
31 @par Usage
32
33 To use the parser first construct it, then optionally
34 call @ref reset to specify a @ref storage_ptr to use
35 for the resulting @ref value. Then call @ref write
36 to parse a character buffer containing a complete
37 JSON text. If the parse is successful, call @ref release
38 to take ownership of the value:
39 @code
40 parser p; // construct a parser
41 size_t n = p.write( "[1,2,3]" ); // parse a complete JSON text
42 assert( n == 7 ); // all characters consumed
43 value jv = p.release(); // take ownership of the value
44 @endcode
45
46 @par Extra Data
47
48 When the character buffer provided as input contains
49 additional data that is not part of the complete
50 JSON text, an error is returned. The @ref write_some
51 function is an alternative which allows the parse
52 to finish early, without consuming all the characters
53 in the buffer. This allows parsing of a buffer
54 containing multiple individual JSON texts or containing
55 different protocol data:
56 @code
57 parser p; // construct a parser
58 size_t n = p.write_some( "[1,2,3] null" ); // parse a complete JSON text
59 assert( n == 8 ); // only some characters consumed
60 value jv = p.release(); // take ownership of the value
61 @endcode
62
63 @par Temporary Storage
64
65 The parser may dynamically allocate temporary
66 storage as needed to accommodate the nesting level
67 of the JSON text being parsed. Temporary storage is
68 first obtained from an optional, caller-owned
69 buffer specified upon construction. When that
70 is exhausted, the next allocation uses the
71 `boost::container::pmr::memory_resource` passed to the constructor; if
72 no such argument is specified, the default memory
73 resource is used. Temporary storage is freed only
74 when the parser is destroyed; The performance of
75 parsing multiple JSON texts may be improved by reusing
76 the same parser instance.
77 \n
78 It is important to note that the `boost::container::pmr::memory_resource`
79 supplied upon construction is used for temporary
80 storage only, and not for allocating the elements
81 which make up the parsed value. That other memory
82 resource is optionally supplied in each call
83 to @ref reset.
84
85 @par Duplicate Keys
86
87 If there are object elements with duplicate keys;
88 that is, if multiple elements in an object have
89 keys that compare equal, only the last equivalent
90 element will be inserted.
91
92 @par Non-Standard JSON
93
94 The @ref parse_options structure optionally
95 provided upon construction is used to customize
96 some parameters of the parser, including which
97 non-standard JSON extensions should be allowed.
98 A default-constructed parse options allows only
99 standard JSON.
100
101 @par Thread Safety
102
103 Distinct instances may be accessed concurrently.
104 Non-const member functions of a shared instance
105 may not be called concurrently with any other
106 member functions of that instance.
107
108 @see
109 @ref parse,
110 @ref parse_options,
111 @ref stream_parser.
112 */
113 class parser
114 {
115 basic_parser<detail::handler> p_;
116
117 public:
118 /// Copy constructor (deleted)
119 parser(
120 parser const&) = delete;
121
122 /// Copy assignment (deleted)
123 parser& operator=(
124 parser const&) = delete;
125
126 /** Destructor.
127
128 All dynamically allocated memory, including
129 any incomplete parsing results, is freed.
130
131 @par Complexity
132 Linear in the size of partial results
133
134 @par Exception Safety
135 No-throw guarantee.
136 */
137 2001563 ~parser() = default;
138
139 /** Constructor.
140
141 This constructs a new parser which first uses
142 the caller-owned storage pointed to by `buffer`
143 for temporary storage, falling back to the memory
144 resource `sp` if needed. The parser will use the
145 specified parsing options.
146 \n
147 The parsed value will use the default memory
148 resource for storage. To use a different resource,
149 call @ref reset after construction.
150
151 @par Complexity
152 Constant.
153
154 @par Exception Safety
155 No-throw guarantee.
156
157 @param sp The memory resource to use for
158 temporary storage after `buffer` is exhausted.
159
160 @param opt The parsing options to use.
161
162 @param buffer A pointer to valid memory of at least
163 `size` bytes for the parser to use for temporary storage.
164 Ownership is not transferred, the caller is responsible
165 for ensuring the lifetime of the memory pointed to by
166 `buffer` extends until the parser is destroyed.
167
168 @param size The number of valid bytes in `buffer`.
169 */
170 BOOST_JSON_DECL
171 parser(
172 storage_ptr sp,
173 parse_options const& opt,
174 unsigned char* buffer,
175 std::size_t size) noexcept;
176
177 /** Constructor.
178
179 This constructs a new parser which uses the default
180 memory resource for temporary storage, and accepts
181 only strict JSON.
182 \n
183 The parsed value will use the default memory
184 resource for storage. To use a different resource,
185 call @ref reset after construction.
186
187 @par Complexity
188 Constant.
189
190 @par Exception Safety
191 No-throw guarantee.
192 */
193 53 parser() noexcept
194 53 : parser({}, {})
195 {
196 53 }
197
198 /** Constructor.
199
200 This constructs a new parser which uses the
201 specified memory resource for temporary storage,
202 and is configured to use the specified parsing
203 options.
204 \n
205 The parsed value will use the default memory
206 resource for storage. To use a different resource,
207 call @ref reset after construction.
208
209 @par Complexity
210 Constant.
211
212 @par Exception Safety
213 No-throw guarantee.
214
215 @param sp The memory resource to use for temporary storage.
216
217 @param opt The parsing options to use.
218 */
219 BOOST_JSON_DECL
220 parser(
221 storage_ptr sp,
222 parse_options const& opt) noexcept;
223
224 /** Constructor.
225
226 This constructs a new parser which uses the
227 specified memory resource for temporary storage,
228 and accepts only strict JSON.
229 \n
230 The parsed value will use the default memory
231 resource for storage. To use a different resource,
232 call @ref reset after construction.
233
234 @par Complexity
235 Constant.
236
237 @par Exception Safety
238 No-throw guarantee.
239
240 @param sp The memory resource to use for temporary storage.
241 */
242 explicit
243 1 parser(storage_ptr sp) noexcept
244 1 : parser(std::move(sp), {})
245 {
246 1 }
247
248 /** Constructor.
249
250 This constructs a new parser which first uses the
251 caller-owned storage `buffer` for temporary storage,
252 falling back to the memory resource `sp` if needed.
253 The parser will use the specified parsing options.
254 \n
255 The parsed value will use the default memory
256 resource for storage. To use a different resource,
257 call @ref reset after construction.
258
259 @par Complexity
260 Constant.
261
262 @par Exception Safety
263 No-throw guarantee.
264
265 @param sp The memory resource to use for
266 temporary storage after `buffer` is exhausted.
267
268 @param opt The parsing options to use.
269
270 @param buffer A buffer for the parser to use for
271 temporary storage. Ownership is not transferred,
272 the caller is responsible for ensuring the lifetime
273 of `buffer` extends until the parser is destroyed.
274 */
275 template<std::size_t N>
276 2001506 parser(
277 storage_ptr sp,
278 parse_options const& opt,
279 unsigned char(&buffer)[N]) noexcept
280 2001506 : parser(std::move(sp),
281 2001506 opt, &buffer[0], N)
282 {
283 2001506 }
284
285 #if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
286 /** Constructor.
287
288 This constructs a new parser which first uses
289 the caller-owned storage pointed to by `buffer`
290 for temporary storage, falling back to the memory
291 resource `sp` if needed. The parser will use the
292 specified parsing options.
293 \n
294 The parsed value will use the default memory
295 resource for storage. To use a different resource,
296 call @ref reset after construction.
297
298 @par Complexity
299 Constant.
300
301 @par Exception Safety
302 No-throw guarantee.
303
304 @param sp The memory resource to use for
305 temporary storage after `buffer` is exhausted.
306
307 @param opt The parsing options to use.
308
309 @param buffer A pointer to valid memory of at least
310 `size` bytes for the parser to use for temporary storage.
311 Ownership is not transferred, the caller is responsible
312 for ensuring the lifetime of the memory pointed to by
313 `buffer` extends until the parser is destroyed.
314
315 @param size The number of valid bytes in `buffer`.
316 */
317 parser(
318 storage_ptr sp,
319 parse_options const& opt,
320 std::byte* buffer,
321 std::size_t size) noexcept
322 : parser(sp, opt, reinterpret_cast<
323 unsigned char*>(buffer), size)
324 {
325 }
326
327 /** Constructor.
328
329 This constructs a new parser which first uses the
330 caller-owned storage `buffer` for temporary storage,
331 falling back to the memory resource `sp` if needed.
332 The parser will use the specified parsing options.
333 \n
334 The parsed value will use the default memory
335 resource for storage. To use a different resource,
336 call @ref reset after construction.
337
338 @par Complexity
339 Constant.
340
341 @par Exception Safety
342 No-throw guarantee.
343
344 @param sp The memory resource to use for
345 temporary storage after `buffer` is exhausted.
346
347 @param opt The parsing options to use.
348
349 @param buffer A buffer for the parser to use for
350 temporary storage. Ownership is not transferred,
351 the caller is responsible for ensuring the lifetime
352 of `buffer` extends until the parser is destroyed.
353 */
354 template<std::size_t N>
355 parser(
356 storage_ptr sp,
357 parse_options const& opt,
358 std::byte(&buffer)[N]) noexcept
359 : parser(std::move(sp),
360 opt, &buffer[0], N)
361 {
362 }
363 #endif
364
365 #ifndef BOOST_JSON_DOCS
366 // Safety net for accidental buffer overflows
367 template<std::size_t N>
368 parser(
369 storage_ptr sp,
370 parse_options const& opt,
371 unsigned char(&buffer)[N],
372 std::size_t n) noexcept
373 : parser(std::move(sp),
374 opt, &buffer[0], n)
375 {
376 // If this goes off, check your parameters
377 // closely, chances are you passed an array
378 // thinking it was a pointer.
379 BOOST_ASSERT(n <= N);
380 }
381
382 #ifdef __cpp_lib_byte
383 // Safety net for accidental buffer overflows
384 template<std::size_t N>
385 parser(
386 storage_ptr sp,
387 parse_options const& opt,
388 std::byte(&buffer)[N], std::size_t n) noexcept
389 : parser(std::move(sp),
390 opt, &buffer[0], n)
391 {
392 // If this goes off, check your parameters
393 // closely, chances are you passed an array
394 // thinking it was a pointer.
395 BOOST_ASSERT(n <= N);
396 }
397 #endif
398 #endif
399
400 /** Reset the parser for a new JSON text.
401
402 This function is used to reset the parser to
403 prepare it for parsing a new complete JSON text.
404 Any previous partial results are destroyed.
405
406 @par Complexity
407 Constant or linear in the size of any previous
408 partial parsing results.
409
410 @par Exception Safety
411 No-throw guarantee.
412
413 @param sp A pointer to the `boost::container::pmr::memory_resource` to
414 use for the resulting @ref value. The parser will acquire shared
415 ownership.
416 */
417 BOOST_JSON_DECL
418 void
419 reset(storage_ptr sp = {}) noexcept;
420
421 /** Parse a buffer containing a complete JSON text.
422
423 This function parses a complete JSON text contained
424 in the specified character buffer. Additional
425 characters past the end of the complete JSON text
426 are ignored. The function returns the actual
427 number of characters parsed, which may be less
428 than the size of the input. This allows parsing
429 of a buffer containing multiple individual JSON texts
430 or containing different protocol data:
431
432 @par Example
433 @code
434 parser p; // construct a parser
435 size_t n = p.write_some( "[1,2,3] null" ); // parse a complete JSON text
436 assert( n == 8 ); // only some characters consumed
437 value jv = p.release(); // take ownership of the value
438 @endcode
439
440 @par Complexity
441 Linear in `size`.
442
443 @par Exception Safety
444 Basic guarantee.
445 Calls to `memory_resource::allocate` may throw.
446 Upon error or exception, subsequent calls will
447 fail until @ref reset is called to parse a new JSON text.
448
449 @return The number of characters consumed from
450 the buffer.
451
452 @param data A pointer to a buffer of `size`
453 characters to parse.
454
455 @param size The number of characters pointed to
456 by `data`.
457
458 @param ec Set to the error, if any occurred.
459 */
460 /** @{ */
461 BOOST_JSON_DECL
462 std::size_t
463 write_some(
464 char const* data,
465 std::size_t size,
466 system::error_code& ec);
467
468 BOOST_JSON_DECL
469 std::size_t
470 write_some(
471 char const* data,
472 std::size_t size,
473 std::error_code& ec);
474 /** @} */
475
476 /** Parse a buffer containing a complete JSON text.
477
478 This function parses a complete JSON text contained
479 in the specified character buffer. Additional
480 characters past the end of the complete JSON text
481 are ignored. The function returns the actual
482 number of characters parsed, which may be less
483 than the size of the input. This allows parsing
484 of a buffer containing multiple individual JSON texts
485 or containing different protocol data:
486
487 @par Example
488 @code
489 parser p; // construct a parser
490 size_t n = p.write_some( "[1,2,3] null" ); // parse a complete JSON text
491 assert( n == 8 ); // only some characters consumed
492 value jv = p.release(); // take ownership of the value
493 @endcode
494
495 @par Complexity
496 Linear in `size`.
497
498 @par Exception Safety
499 Basic guarantee.
500 Calls to `memory_resource::allocate` may throw.
501 Upon error or exception, subsequent calls will
502 fail until @ref reset is called to parse a new JSON text.
503
504 @return The number of characters consumed from
505 the buffer.
506
507 @param data A pointer to a buffer of `size`
508 characters to parse.
509
510 @param size The number of characters pointed to
511 by `data`.
512
513 @throw `boost::system::system_error` Thrown on error.
514 */
515 BOOST_JSON_DECL
516 std::size_t
517 write_some(
518 char const* data,
519 std::size_t size);
520
521 /** Parse a buffer containing a complete JSON text.
522
523 This function parses a complete JSON text contained
524 in the specified character buffer. Additional
525 characters past the end of the complete JSON text
526 are ignored. The function returns the actual
527 number of characters parsed, which may be less
528 than the size of the input. This allows parsing
529 of a buffer containing multiple individual JSON texts
530 or containing different protocol data:
531
532 @par Example
533 @code
534 parser p; // construct a parser
535 size_t n = p.write_some( "[1,2,3] null" ); // parse a complete JSON text
536 assert( n == 8 ); // only some characters consumed
537 value jv = p.release(); // take ownership of the value
538 @endcode
539
540 @par Complexity
541 Linear in `size`.
542
543 @par Exception Safety
544 Basic guarantee.
545 Calls to `memory_resource::allocate` may throw.
546 Upon error or exception, subsequent calls will
547 fail until @ref reset is called to parse a new JSON text.
548
549 @return The number of characters consumed from
550 the buffer.
551
552 @param s The character string to parse.
553
554 @param ec Set to the error, if any occurred.
555 */
556 /** @{ */
557 std::size_t
558 2 write_some(
559 string_view s,
560 system::error_code& ec)
561 {
562 2 return write_some(
563 2 s.data(), s.size(), ec);
564 }
565
566 std::size_t
567 2 write_some(
568 string_view s,
569 std::error_code& ec)
570 {
571 2 return write_some(
572 2 s.data(), s.size(), ec);
573 }
574 /** @} */
575
576 /** Parse a buffer containing a complete JSON text.
577
578 This function parses a complete JSON text contained
579 in the specified character buffer. Additional
580 characters past the end of the complete JSON text
581 are ignored. The function returns the actual
582 number of characters parsed, which may be less
583 than the size of the input. This allows parsing
584 of a buffer containing multiple individual JSON texts
585 or containing different protocol data:
586
587 @par Example
588 @code
589 parser p; // construct a parser
590 size_t n = p.write_some( "[1,2,3] null" ); // parse a complete JSON text
591 assert( n == 8 ); // only some characters consumed
592 value jv = p.release(); // take ownership of the value
593 @endcode
594
595 @par Complexity
596 Linear in `size`.
597
598 @par Exception Safety
599 Basic guarantee.
600 Calls to `memory_resource::allocate` may throw.
601 Upon error or exception, subsequent calls will
602 fail until @ref reset is called to parse a new JSON text.
603
604 @return The number of characters consumed from
605 the buffer.
606
607 @param s The character string to parse.
608
609 @throw `boost::system::system_error` Thrown on error.
610 */
611 std::size_t
612 4 write_some(
613 string_view s)
614 {
615 4 return write_some(
616 2 s.data(), s.size());
617 }
618
619 /** Parse a buffer containing a complete JSON text.
620
621 This function parses a complete JSON text contained
622 in the specified character buffer. The entire
623 buffer must be consumed; if there are additional
624 characters past the end of the complete JSON text,
625 the parse fails and an error is returned.
626
627 @par Example
628 @code
629 parser p; // construct a parser
630 size_t n = p.write( "[1,2,3]" ); // parse a complete JSON text
631 assert( n == 7 ); // all characters consumed
632 value jv = p.release(); // take ownership of the value
633 @endcode
634
635 @par Complexity
636 Linear in `size`.
637
638 @par Exception Safety
639 Basic guarantee.
640 Calls to `memory_resource::allocate` may throw.
641 Upon error or exception, subsequent calls will
642 fail until @ref reset is called to parse a new JSON text.
643
644 @return The number of characters consumed from
645 the buffer.
646
647 @param data A pointer to a buffer of `size`
648 characters to parse.
649
650 @param size The number of characters pointed to
651 by `data`.
652
653 @param ec Set to the error, if any occurred.
654 */
655 /** @{ */
656 BOOST_JSON_DECL
657 std::size_t
658 write(
659 char const* data,
660 std::size_t size,
661 system::error_code& ec);
662
663 BOOST_JSON_DECL
664 std::size_t
665 write(
666 char const* data,
667 std::size_t size,
668 std::error_code& ec);
669 /** @} */
670
671 /** Parse a buffer containing a complete JSON text.
672
673 This function parses a complete JSON text contained
674 in the specified character buffer. The entire
675 buffer must be consumed; if there are additional
676 characters past the end of the complete JSON text,
677 the parse fails and an error is returned.
678
679 @par Example
680 @code
681 parser p; // construct a parser
682 size_t n = p.write( "[1,2,3]" ); // parse a complete JSON text
683 assert( n == 7 ); // all characters consumed
684 value jv = p.release(); // take ownership of the value
685 @endcode
686
687 @par Complexity
688 Linear in `size`.
689
690 @par Exception Safety
691 Basic guarantee.
692 Calls to `memory_resource::allocate` may throw.
693 Upon error or exception, subsequent calls will
694 fail until @ref reset is called to parse a new JSON text.
695
696 @return The number of characters consumed from
697 the buffer.
698
699 @param data A pointer to a buffer of `size`
700 characters to parse.
701
702 @param size The number of characters pointed to
703 by `data`.
704
705 @throw `boost::system::system_error` Thrown on error.
706 */
707 BOOST_JSON_DECL
708 std::size_t
709 write(
710 char const* data,
711 std::size_t size);
712
713 /** Parse a buffer containing a complete JSON text.
714
715 This function parses a complete JSON text contained
716 in the specified character buffer. The entire
717 buffer must be consumed; if there are additional
718 characters past the end of the complete JSON text,
719 the parse fails and an error is returned.
720
721 @par Example
722 @code
723 parser p; // construct a parser
724 size_t n = p.write( "[1,2,3]" ); // parse a complete JSON text
725 assert( n == 7 ); // all characters consumed
726 value jv = p.release(); // take ownership of the value
727 @endcode
728
729 @par Complexity
730 Linear in `size`.
731
732 @par Exception Safety
733 Basic guarantee.
734 Calls to `memory_resource::allocate` may throw.
735 Upon error or exception, subsequent calls will
736 fail until @ref reset is called to parse a new JSON text.
737
738 @return The number of characters consumed from
739 the buffer.
740
741 @param s The character string to parse.
742
743 @param ec Set to the error, if any occurred.
744 */
745 /** @{ */
746 std::size_t
747 2001508 write(
748 string_view s,
749 system::error_code& ec)
750 {
751 2001508 return write(
752 2001507 s.data(), s.size(), ec);
753 }
754
755 std::size_t
756 3 write(
757 string_view s,
758 std::error_code& ec)
759 {
760 3 return write(
761 3 s.data(), s.size(), ec);
762 }
763 /** @} */
764
765 /** Parse a buffer containing a complete JSON text.
766
767 This function parses a complete JSON text contained
768 in the specified character buffer. The entire
769 buffer must be consumed; if there are additional
770 characters past the end of the complete JSON text,
771 the parse fails and an error is returned.
772
773 @par Example
774 @code
775 parser p; // construct a parser
776 size_t n = p.write( "[1,2,3]" ); // parse a complete JSON text
777 assert( n == 7 ); // all characters consumed
778 value jv = p.release(); // take ownership of the value
779 @endcode
780
781 @par Complexity
782 Linear in `size`.
783
784 @par Exception Safety
785 Basic guarantee.
786 Calls to `memory_resource::allocate` may throw.
787 Upon error or exception, subsequent calls will
788 fail until @ref reset is called to parse a new JSON text.
789
790 @return The number of characters consumed from
791 the buffer.
792
793 @param s The character string to parse.
794
795 @throw `boost::system::system_error` Thrown on error.
796 */
797 std::size_t
798 8 write(
799 string_view s)
800 {
801 8 return write(
802 4 s.data(), s.size());
803 }
804
805 /** Return the parsed JSON text as a @ref value.
806
807 This returns the parsed value, or throws
808 an exception if the parsing is incomplete or
809 failed. It is necessary to call @ref reset
810 after calling this function in order to parse
811 another JSON text.
812
813 @par Complexity
814 Constant.
815
816 @return The parsed value. Ownership of this
817 value is transferred to the caller.
818
819 @throw `boost::system::system_error` Thrown on failure.
820 */
821 BOOST_JSON_DECL
822 value
823 release();
824 };
825
826 } // namespace json
827 } // namespace boost
828
829 #endif
830