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