TLA Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/boostorg/json
9 : //
10 :
11 : #ifndef BOOST_JSON_BASIC_PARSER_HPP
12 : #define BOOST_JSON_BASIC_PARSER_HPP
13 :
14 : #include <boost/json/detail/config.hpp>
15 : #include <boost/json/detail/except.hpp>
16 : #include <boost/json/error.hpp>
17 : #include <boost/json/kind.hpp>
18 : #include <boost/json/parse_options.hpp>
19 : #include <boost/json/detail/stack.hpp>
20 : #include <boost/json/detail/stream.hpp>
21 : #include <boost/json/detail/utf8.hpp>
22 : #include <boost/json/detail/sbo_buffer.hpp>
23 :
24 : namespace boost {
25 : namespace json {
26 :
27 : /** An incremental SAX parser for serialized JSON.
28 :
29 : This implements a SAX-style parser, invoking a caller-supplied handler with
30 : each parsing event. To use, first declare a variable of type
31 : `basic_parser<T>` where `T` meets the handler requirements specified below.
32 : Then call @ref write_some one or more times with the input, setting
33 : `more = false` on the final buffer. The parsing events are realized through
34 : member function calls on the handler, which exists as a data member of the
35 : parser.
36 :
37 : The parser may dynamically allocate intermediate storage as needed to
38 : accommodate the nesting level of the input JSON. On subsequent invocations,
39 : the parser can cheaply re-use this memory, improving performance. This
40 : storage is freed when the parser is destroyed
41 :
42 : @par Usage
43 : To get the declaration and function definitions for this class it is
44 : necessary to include this file instead:
45 : @code
46 : #include <boost/json/basic_parser_impl.hpp>
47 : @endcode
48 :
49 : Users who wish to parse JSON into the DOM container @ref value will not use
50 : this class directly; instead they will create an instance of @ref parser or
51 : @ref stream_parser and use that instead. Alternatively, they may call the
52 : function @ref parse. This class is designed for users who wish to perform
53 : custom actions instead of building a @ref value. For example, to produce a
54 : DOM from an external library.
55 :
56 : @note
57 : By default, only conforming JSON using UTF-8 encoding is accepted. However,
58 : select non-compliant syntax can be allowed by construction using a
59 : @ref parse_options set to desired values.
60 :
61 : @par Handler
62 : The handler provided must be implemented as an object of class type which
63 : defines each of the required event member functions below. The event
64 : functions return a `bool` where `true` indicates success, and `false`
65 : indicates failure. If the member function returns `false`, it must set the
66 : error code to a suitable value. This error code will be returned by the
67 : write function to the caller.
68 :
69 : Handlers are required to declare the maximum limits on various elements. If
70 : these limits are exceeded during parsing, then parsing fails with an error.
71 :
72 : The following declaration meets the parser's handler requirements:
73 :
74 : @code
75 : struct handler
76 : {
77 : /// The maximum number of elements allowed in an array
78 : static constexpr std::size_t max_array_size = -1;
79 :
80 : /// The maximum number of elements allowed in an object
81 : static constexpr std::size_t max_object_size = -1;
82 :
83 : /// The maximum number of characters allowed in a string
84 : static constexpr std::size_t max_string_size = -1;
85 :
86 : /// The maximum number of characters allowed in a key
87 : static constexpr std::size_t max_key_size = -1;
88 :
89 : /// Called once when the JSON parsing begins.
90 : ///
91 : /// @return `true` on success.
92 : /// @param ec Set to the error, if any occurred.
93 : ///
94 : bool on_document_begin( error_code& ec );
95 :
96 : /// Called when the JSON parsing is done.
97 : ///
98 : /// @return `true` on success.
99 : /// @param ec Set to the error, if any occurred.
100 : ///
101 : bool on_document_end( error_code& ec );
102 :
103 : /// Called when the beginning of an array is encountered.
104 : ///
105 : /// @return `true` on success.
106 : /// @param ec Set to the error, if any occurred.
107 : ///
108 : bool on_array_begin( error_code& ec );
109 :
110 : /// Called when the end of the current array is encountered.
111 : ///
112 : /// @return `true` on success.
113 : /// @param n The number of elements in the array.
114 : /// @param ec Set to the error, if any occurred.
115 : ///
116 : bool on_array_end( std::size_t n, error_code& ec );
117 :
118 : /// Called when the beginning of an object is encountered.
119 : ///
120 : /// @return `true` on success.
121 : /// @param ec Set to the error, if any occurred.
122 : ///
123 : bool on_object_begin( error_code& ec );
124 :
125 : /// Called when the end of the current object is encountered.
126 : ///
127 : /// @return `true` on success.
128 : /// @param n The number of elements in the object.
129 : /// @param ec Set to the error, if any occurred.
130 : ///
131 : bool on_object_end( std::size_t n, error_code& ec );
132 :
133 : /// Called with characters corresponding to part of the current string.
134 : ///
135 : /// @return `true` on success.
136 : /// @param s The partial characters
137 : /// @param n The total size of the string thus far
138 : /// @param ec Set to the error, if any occurred.
139 : ///
140 : bool on_string_part( string_view s, std::size_t n, error_code& ec );
141 :
142 : /// Called with the last characters corresponding to the current string.
143 : ///
144 : /// @return `true` on success.
145 : /// @param s The remaining characters
146 : /// @param n The total size of the string
147 : /// @param ec Set to the error, if any occurred.
148 : ///
149 : bool on_string( string_view s, std::size_t n, error_code& ec );
150 :
151 : /// Called with characters corresponding to part of the current key.
152 : ///
153 : /// @return `true` on success.
154 : /// @param s The partial characters
155 : /// @param n The total size of the key thus far
156 : /// @param ec Set to the error, if any occurred.
157 : ///
158 : bool on_key_part( string_view s, std::size_t n, error_code& ec );
159 :
160 : /// Called with the last characters corresponding to the current key.
161 : ///
162 : /// @return `true` on success.
163 : /// @param s The remaining characters
164 : /// @param n The total size of the key
165 : /// @param ec Set to the error, if any occurred.
166 : ///
167 : bool on_key( string_view s, std::size_t n, error_code& ec );
168 :
169 : /// Called with the characters corresponding to part of the current number.
170 : ///
171 : /// @return `true` on success.
172 : /// @param s The partial characters
173 : /// @param ec Set to the error, if any occurred.
174 : ///
175 : bool on_number_part( string_view s, error_code& ec );
176 :
177 : /// Called when a signed integer is parsed.
178 : ///
179 : /// @return `true` on success.
180 : /// @param i The value
181 : /// @param s The remaining characters
182 : /// @param ec Set to the error, if any occurred.
183 : ///
184 : bool on_int64( int64_t i, string_view s, error_code& ec );
185 :
186 : /// Called when an unsigend integer is parsed.
187 : ///
188 : /// @return `true` on success.
189 : /// @param u The value
190 : /// @param s The remaining characters
191 : /// @param ec Set to the error, if any occurred.
192 : ///
193 : bool on_uint64( uint64_t u, string_view s, error_code& ec );
194 :
195 : /// Called when a double is parsed.
196 : ///
197 : /// @return `true` on success.
198 : /// @param d The value
199 : /// @param s The remaining characters
200 : /// @param ec Set to the error, if any occurred.
201 : ///
202 : bool on_double( double d, string_view s, error_code& ec );
203 :
204 : /// Called when a boolean is parsed.
205 : ///
206 : /// @return `true` on success.
207 : /// @param b The value
208 : /// @param ec Set to the error, if any occurred.
209 : ///
210 : bool on_bool( bool b, error_code& ec );
211 :
212 : /// Called when a null is parsed.
213 : ///
214 : /// @return `true` on success.
215 : /// @param ec Set to the error, if any occurred.
216 : ///
217 : bool on_null( error_code& ec );
218 :
219 : /// Called with characters corresponding to part of the current comment.
220 : ///
221 : /// @return `true` on success.
222 : /// @param s The partial characters.
223 : /// @param ec Set to the error, if any occurred.
224 : ///
225 : bool on_comment_part( string_view s, error_code& ec );
226 :
227 : /// Called with the last characters corresponding to the current comment.
228 : ///
229 : /// @return `true` on success.
230 : /// @param s The remaining characters
231 : /// @param ec Set to the error, if any occurred.
232 : ///
233 : bool on_comment( string_view s, error_code& ec );
234 : };
235 : @endcode
236 :
237 : @see
238 : @ref parse,
239 : @ref stream_parser,
240 : \<\<examples_validate, validating parser example\>\>.
241 : */
242 : template<class Handler>
243 : class basic_parser
244 : {
245 : enum class state : char
246 : {
247 : doc1, doc3,
248 : com1, com2, com3, com4,
249 : lit1,
250 : str1, str2, str3, str4,
251 : str5, str6, str7, str8,
252 : sur1, sur2, sur3,
253 : sur4, sur5, sur6,
254 : obj1, obj2, obj3, obj4,
255 : obj5, obj6, obj7, obj8,
256 : obj9, obj10, obj11,
257 : arr1, arr2, arr3,
258 : arr4, arr5, arr6,
259 : num1, num2, num3, num4,
260 : num5, num6, num7, num8,
261 : exp1, exp2, exp3,
262 : val1, val2, val3
263 : };
264 :
265 : struct number
266 : {
267 : uint64_t mant;
268 : int bias;
269 : int exp;
270 : bool frac;
271 : bool neg;
272 : };
273 :
274 : template< bool StackEmpty_, char First_ >
275 : struct parse_number_helper;
276 :
277 : // optimization: must come first
278 : Handler h_;
279 :
280 : number num_;
281 : system::error_code ec_;
282 : detail::stack st_;
283 : detail::utf8_sequence seq_;
284 : unsigned u1_;
285 : unsigned u2_;
286 : bool more_; // false for final buffer
287 : bool done_ = false; // true on complete parse
288 : bool clean_ = true; // write_some exited cleanly
289 : const char* end_;
290 : detail::sbo_buffer<16 + 16 + 1 + 1> num_buf_;
291 : parse_options opt_;
292 : // how many levels deeper the parser can go
293 : std::size_t depth_ = opt_.max_depth;
294 : unsigned char cur_lit_ = 0;
295 : unsigned char lit_offset_ = 0;
296 :
297 : inline void reserve();
298 : inline const char* sentinel();
299 : inline bool incomplete(
300 : const detail::const_stream_wrapper& cs);
301 :
302 : #ifdef __INTEL_COMPILER
303 : #pragma warning push
304 : #pragma warning disable 2196
305 : #endif
306 :
307 : BOOST_NOINLINE
308 : inline
309 : const char*
310 : suspend_or_fail(state st);
311 :
312 : BOOST_NOINLINE
313 : inline
314 : const char*
315 : suspend_or_fail(
316 : state st,
317 : std::size_t n);
318 :
319 : BOOST_NOINLINE
320 : inline
321 : const char*
322 : fail(const char* p) noexcept;
323 :
324 : BOOST_NOINLINE
325 : inline
326 : const char*
327 : fail(
328 : const char* p,
329 : error ev,
330 : source_location const* loc) noexcept;
331 :
332 : BOOST_NOINLINE
333 : inline
334 : const char*
335 : maybe_suspend(
336 : const char* p,
337 : state st);
338 :
339 : BOOST_NOINLINE
340 : inline
341 : const char*
342 : maybe_suspend(
343 : const char* p,
344 : state st,
345 : std::size_t n);
346 :
347 : BOOST_NOINLINE
348 : inline
349 : const char*
350 : maybe_suspend(
351 : const char* p,
352 : state st,
353 : const number& num);
354 :
355 : BOOST_NOINLINE
356 : inline
357 : const char*
358 : suspend(
359 : const char* p,
360 : state st);
361 :
362 : BOOST_NOINLINE
363 : inline
364 : const char*
365 : suspend(
366 : const char* p,
367 : state st,
368 : const number& num);
369 :
370 : #ifdef __INTEL_COMPILER
371 : #pragma warning pop
372 : #endif
373 :
374 : template<bool StackEmpty_/*, bool Terminal_*/>
375 : const char* parse_comment(const char* p,
376 : std::integral_constant<bool, StackEmpty_> stack_empty,
377 : /*std::integral_constant<bool, Terminal_>*/ bool terminal);
378 :
379 : template<bool StackEmpty_>
380 : const char* parse_document(const char* p,
381 : std::integral_constant<bool, StackEmpty_> stack_empty);
382 :
383 : template<bool StackEmpty_, bool AllowComments_/*,
384 : bool AllowTrailing_, bool AllowBadUTF8_*/>
385 : const char* parse_value(const char* p,
386 : std::integral_constant<bool, StackEmpty_> stack_empty,
387 : std::integral_constant<bool, AllowComments_> allow_comments,
388 : /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
389 : /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
390 : bool allow_bad_utf16);
391 :
392 : template<bool AllowComments_/*,
393 : bool AllowTrailing_, bool AllowBadUTF8_*/>
394 : const char* resume_value(const char* p,
395 : std::integral_constant<bool, AllowComments_> allow_comments,
396 : /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
397 : /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
398 : bool allow_bad_utf16);
399 :
400 : template<bool StackEmpty_, bool AllowComments_/*,
401 : bool AllowTrailing_, bool AllowBadUTF8_*/>
402 : const char* parse_object(const char* p,
403 : std::integral_constant<bool, StackEmpty_> stack_empty,
404 : std::integral_constant<bool, AllowComments_> allow_comments,
405 : /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
406 : /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
407 : bool allow_bad_utf16);
408 :
409 : template<bool StackEmpty_, bool AllowComments_/*,
410 : bool AllowTrailing_, bool AllowBadUTF8_*/>
411 : const char* parse_array(const char* p,
412 : std::integral_constant<bool, StackEmpty_> stack_empty,
413 : std::integral_constant<bool, AllowComments_> allow_comments,
414 : /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
415 : /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
416 : bool allow_bad_utf16);
417 :
418 : template<class Literal>
419 : const char* parse_literal(const char* p, Literal literal);
420 :
421 : template<bool StackEmpty_, bool IsKey_>
422 : const char* parse_string(const char* p,
423 : std::integral_constant<bool, StackEmpty_> stack_empty,
424 : std::integral_constant<bool, IsKey_> is_key,
425 : bool allow_bad_utf8,
426 : bool allow_bad_utf16);
427 :
428 : template<bool StackEmpty_>
429 : const char* parse_escaped(
430 : const char* p,
431 : std::size_t& total,
432 : std::integral_constant<bool, StackEmpty_> stack_empty,
433 : bool is_key,
434 : bool allow_bad_utf16);
435 :
436 : template<bool StackEmpty_, char First_>
437 : char const*
438 : parse_number(
439 : char const* p,
440 : std::integral_constant<bool, StackEmpty_> stack_empty,
441 : std::integral_constant<char, First_> first);
442 :
443 : template<bool StackEmpty_, char First_>
444 : char const*
445 : parse_number_precise(
446 : char const* p,
447 : std::integral_constant<bool, StackEmpty_> stack_empty,
448 : std::integral_constant<char, First_> first);
449 :
450 : template<bool StackEmpty_, char First_>
451 : char const*
452 : skip_number(
453 : char const* p,
454 : std::integral_constant<bool, StackEmpty_> stack_empty,
455 : std::integral_constant<char, First_> first);
456 :
457 : // intentionally private
458 : std::size_t
459 HIT 8590001 : depth() const noexcept
460 : {
461 8590001 : return opt_.max_depth - depth_;
462 : }
463 :
464 : public:
465 : /** Destructor.
466 :
467 : All dynamically allocated internal memory is freed.
468 :
469 : @par Effects
470 : @code
471 : handler().~Handler()
472 : @endcode
473 :
474 : @par Complexity
475 : Same as `~Handler()`.
476 :
477 : @par Exception Safety
478 : Same as `~Handler()`.
479 : */
480 2218617 : ~basic_parser() = default;
481 :
482 : /** Constructors.
483 :
484 : Overload **(1)** constructs the parser with the specified options, with
485 : any additional arguments forwarded to the handler's constructor.
486 :
487 : `basic_parser` is not copyable or movable, so the copy constructor is
488 : deleted.
489 :
490 : @par Complexity
491 : Same as `Handler( std::forward< Args >( args )... )`.
492 :
493 : @par Exception Safety
494 : Same as `Handler( std::forward< Args >( args )... )`.
495 :
496 : @param opt Configuration settings for the parser. If this structure is
497 : default constructed, the parser will accept only standard JSON.
498 : @param args Optional additional arguments forwarded to the handler's
499 : constructor.
500 :
501 : @{
502 : */
503 : template<class... Args>
504 : explicit
505 : basic_parser(
506 : parse_options const& opt,
507 : Args&&... args);
508 :
509 : /// Overload
510 : basic_parser(
511 : basic_parser const&) = delete;
512 : /// @}
513 :
514 : /** Assignment.
515 :
516 : This type cannot be copied or moved. The copy assignment is deleted.
517 : */
518 : basic_parser& operator=(
519 : basic_parser const&) = delete;
520 :
521 : /** Return a reference to the handler.
522 :
523 : This function provides access to the constructed
524 : instance of the handler owned by the parser.
525 :
526 : @par Complexity
527 : Constant.
528 :
529 : @par Exception Safety
530 : No-throw guarantee.
531 :
532 : @{
533 : */
534 : Handler&
535 6365737 : handler() noexcept
536 : {
537 6365737 : return h_;
538 : }
539 :
540 : Handler const&
541 24 : handler() const noexcept
542 : {
543 24 : return h_;
544 : }
545 : /// @}
546 :
547 : /** Return the last error.
548 :
549 : This returns the last error code which
550 : was generated in the most recent call
551 : to @ref write_some.
552 :
553 : @par Complexity
554 : Constant.
555 :
556 : @par Exception Safety
557 : No-throw guarantee.
558 : */
559 : system::error_code
560 11 : last_error() const noexcept
561 : {
562 11 : return ec_;
563 : }
564 :
565 : /** Check if a complete JSON text has been parsed.
566 :
567 : This function returns `true` when all of these conditions are met:
568 :
569 : @li A complete serialized JSON text has been presented to the parser,
570 : and
571 : @li No error or exception has occurred since the parser was
572 : constructed, or since the last call to @ref reset.
573 :
574 : @par Complexity
575 : Constant.
576 :
577 : @par Exception Safety
578 : No-throw guarantee.
579 : */
580 : bool
581 4078949 : done() const noexcept
582 : {
583 4078949 : return done_;
584 : }
585 :
586 : /** Reset the state, to parse a new document.
587 :
588 : This function discards the current parsing
589 : state, to prepare for parsing a new document.
590 : Dynamically allocated temporary memory used
591 : by the implementation is not deallocated.
592 :
593 : @par Complexity
594 : Constant.
595 :
596 : @par Exception Safety
597 : No-throw guarantee.
598 : */
599 : void
600 : reset() noexcept;
601 :
602 : /** Indicate a parsing failure.
603 :
604 : This changes the state of the parser to indicate that the parse has
605 : failed. A parser implementation can use this to fail the parser if
606 : needed due to external inputs.
607 :
608 : @attention
609 : If `! ec.failed()`, an implementation-defined error code that indicates
610 : failure will be stored instead.
611 :
612 : @par Complexity
613 : Constant.
614 :
615 : @par Exception Safety
616 : No-throw guarantee.
617 :
618 : @param ec The error code to set.
619 : */
620 : void
621 : fail(system::error_code ec) noexcept;
622 :
623 : /** Parse some of input characters as JSON, incrementally.
624 :
625 : This function parses the JSON text in the specified buffer, calling the
626 : handler to emit each SAX parsing event. The parse proceeds from the
627 : current state, which is at the beginning of a new JSON or in the middle
628 : of the current JSON if any characters were already parsed.
629 :
630 : The characters in the buffer are processed starting from the beginning,
631 : until one of the following conditions is met:
632 :
633 : @li All of the characters in the buffer have been parsed, or
634 : @li Some of the characters in the buffer have been parsed and the JSON
635 : is complete, or
636 : @li A parsing error occurs.
637 :
638 : The supplied buffer does not need to contain the entire JSON.
639 : Subsequent calls can provide more serialized data, allowing JSON to be
640 : processed incrementally. The end of the serialized JSON can be
641 : indicated by passing `more = false`.
642 :
643 : @par Complexity
644 : Linear in `size`.
645 :
646 : @par Exception Safety
647 : Basic guarantee. Calls to the handler may throw.
648 :
649 : Upon error or exception, subsequent calls will fail until @ref reset
650 : is called to parse a new JSON.
651 :
652 : @return The number of characters successfully
653 : parsed, which may be smaller than `size`.
654 :
655 : @param more `true` if there are possibly more buffers in the current
656 : JSON, otherwise `false`.
657 :
658 : @param data A pointer to a buffer of `size` characters to parse.
659 :
660 : @param size The number of characters pointed to by `data`.
661 :
662 : @param ec Set to the error, if any occurred.
663 :
664 : @{
665 : */
666 : std::size_t
667 : write_some(
668 : bool more,
669 : char const* data,
670 : std::size_t size,
671 : system::error_code& ec);
672 :
673 : std::size_t
674 : write_some(
675 : bool more,
676 : char const* data,
677 : std::size_t size,
678 : std::error_code& ec);
679 : /// @}
680 : };
681 :
682 : } // namespace json
683 : } // namespace boost
684 :
685 : #endif
|