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