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_>
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 +
  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);
441   456  
442   // intentionally private 457   // intentionally private
443   std::size_t 458   std::size_t
HITCBC 444   8565077 depth() const noexcept 459   8590001 depth() const noexcept
445   { 460   {
HITCBC 446   8565077 return opt_.max_depth - depth_; 461   8590001 return opt_.max_depth - depth_;
447   } 462   }
448   463  
449   public: 464   public:
450   /** Destructor. 465   /** Destructor.
451   466  
452   All dynamically allocated internal memory is freed. 467   All dynamically allocated internal memory is freed.
453   468  
454   @par Effects 469   @par Effects
455   @code 470   @code
456   handler().~Handler() 471   handler().~Handler()
457   @endcode 472   @endcode
458   473  
459   @par Complexity 474   @par Complexity
460   Same as `~Handler()`. 475   Same as `~Handler()`.
461   476  
462   @par Exception Safety 477   @par Exception Safety
463   Same as `~Handler()`. 478   Same as `~Handler()`.
464   */ 479   */
HITCBC 465   2165011 ~basic_parser() = default; 480   2218617 ~basic_parser() = default;
466   481  
467   /** Constructors. 482   /** Constructors.
468   483  
469   Overload **(1)** constructs the parser with the specified options, with 484   Overload **(1)** constructs the parser with the specified options, with
470   any additional arguments forwarded to the handler's constructor. 485   any additional arguments forwarded to the handler's constructor.
471   486  
472   `basic_parser` is not copyable or movable, so the copy constructor is 487   `basic_parser` is not copyable or movable, so the copy constructor is
473   deleted. 488   deleted.
474   489  
475   @par Complexity 490   @par Complexity
476   Same as `Handler( std::forward< Args >( args )... )`. 491   Same as `Handler( std::forward< Args >( args )... )`.
477   492  
478   @par Exception Safety 493   @par Exception Safety
479   Same as `Handler( std::forward< Args >( args )... )`. 494   Same as `Handler( std::forward< Args >( args )... )`.
480   495  
481   @param opt Configuration settings for the parser. If this structure is 496   @param opt Configuration settings for the parser. If this structure is
482   default constructed, the parser will accept only standard JSON. 497   default constructed, the parser will accept only standard JSON.
483   @param args Optional additional arguments forwarded to the handler's 498   @param args Optional additional arguments forwarded to the handler's
484   constructor. 499   constructor.
485   500  
486   @{ 501   @{
487   */ 502   */
488   template<class... Args> 503   template<class... Args>
489   explicit 504   explicit
490   basic_parser( 505   basic_parser(
491   parse_options const& opt, 506   parse_options const& opt,
492   Args&&... args); 507   Args&&... args);
493   508  
494   /// Overload 509   /// Overload
495   basic_parser( 510   basic_parser(
496   basic_parser const&) = delete; 511   basic_parser const&) = delete;
497   /// @} 512   /// @}
498   513  
499   /** Assignment. 514   /** Assignment.
500   515  
501   This type cannot be copied or moved. The copy assignment is deleted. 516   This type cannot be copied or moved. The copy assignment is deleted.
502   */ 517   */
503   basic_parser& operator=( 518   basic_parser& operator=(
504   basic_parser const&) = delete; 519   basic_parser const&) = delete;
505   520  
506   /** Return a reference to the handler. 521   /** Return a reference to the handler.
507   522  
508   This function provides access to the constructed 523   This function provides access to the constructed
509   instance of the handler owned by the parser. 524   instance of the handler owned by the parser.
510   525  
511   @par Complexity 526   @par Complexity
512   Constant. 527   Constant.
513   528  
514   @par Exception Safety 529   @par Exception Safety
515   No-throw guarantee. 530   No-throw guarantee.
516   531  
517   @{ 532   @{
518   */ 533   */
519   Handler& 534   Handler&
HITCBC 520   6311043 handler() noexcept 535   6365737 handler() noexcept
521   { 536   {
HITCBC 522   6311043 return h_; 537   6365737 return h_;
523   } 538   }
524   539  
525   Handler const& 540   Handler const&
HITCBC 526   24 handler() const noexcept 541   24 handler() const noexcept
527   { 542   {
HITCBC 528   24 return h_; 543   24 return h_;
529   } 544   }
530   /// @} 545   /// @}
531   546  
532   /** Return the last error. 547   /** Return the last error.
533   548  
534   This returns the last error code which 549   This returns the last error code which
535   was generated in the most recent call 550   was generated in the most recent call
536   to @ref write_some. 551   to @ref write_some.
537   552  
538   @par Complexity 553   @par Complexity
539   Constant. 554   Constant.
540   555  
541   @par Exception Safety 556   @par Exception Safety
542   No-throw guarantee. 557   No-throw guarantee.
543   */ 558   */
544   system::error_code 559   system::error_code
HITCBC 545   11 last_error() const noexcept 560   11 last_error() const noexcept
546   { 561   {
HITCBC 547   11 return ec_; 562   11 return ec_;
548   } 563   }
549   564  
550   /** Check if a complete JSON text has been parsed. 565   /** Check if a complete JSON text has been parsed.
551   566  
552   This function returns `true` when all of these conditions are met: 567   This function returns `true` when all of these conditions are met:
553   568  
554   @li A complete serialized JSON text has been presented to the parser, 569   @li A complete serialized JSON text has been presented to the parser,
555   and 570   and
556   @li No error or exception has occurred since the parser was 571   @li No error or exception has occurred since the parser was
557   constructed, or since the last call to @ref reset. 572   constructed, or since the last call to @ref reset.
558   573  
559   @par Complexity 574   @par Complexity
560   Constant. 575   Constant.
561   576  
562   @par Exception Safety 577   @par Exception Safety
563   No-throw guarantee. 578   No-throw guarantee.
564   */ 579   */
565   bool 580   bool
HITCBC 566   4078247 done() const noexcept 581   4078949 done() const noexcept
567   { 582   {
HITCBC 568   4078247 return done_; 583   4078949 return done_;
569   } 584   }
570   585  
571   /** Reset the state, to parse a new document. 586   /** Reset the state, to parse a new document.
572   587  
573   This function discards the current parsing 588   This function discards the current parsing
574   state, to prepare for parsing a new document. 589   state, to prepare for parsing a new document.
575   Dynamically allocated temporary memory used 590   Dynamically allocated temporary memory used
576   by the implementation is not deallocated. 591   by the implementation is not deallocated.
577   592  
578   @par Complexity 593   @par Complexity
579   Constant. 594   Constant.
580   595  
581   @par Exception Safety 596   @par Exception Safety
582   No-throw guarantee. 597   No-throw guarantee.
583   */ 598   */
584   void 599   void
585   reset() noexcept; 600   reset() noexcept;
586   601  
587   /** Indicate a parsing failure. 602   /** Indicate a parsing failure.
588   603  
589   This changes the state of the parser to indicate that the parse has 604   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 605   failed. A parser implementation can use this to fail the parser if
591   needed due to external inputs. 606   needed due to external inputs.
592   607  
593   @attention 608   @attention
594   If `! ec.failed()`, an implementation-defined error code that indicates 609   If `! ec.failed()`, an implementation-defined error code that indicates
595   failure will be stored instead. 610   failure will be stored instead.
596   611  
597   @par Complexity 612   @par Complexity
598   Constant. 613   Constant.
599   614  
600   @par Exception Safety 615   @par Exception Safety
601   No-throw guarantee. 616   No-throw guarantee.
602   617  
603   @param ec The error code to set. 618   @param ec The error code to set.
604   */ 619   */
605   void 620   void
606   fail(system::error_code ec) noexcept; 621   fail(system::error_code ec) noexcept;
607   622  
608   /** Parse some of input characters as JSON, incrementally. 623   /** Parse some of input characters as JSON, incrementally.
609   624  
610   This function parses the JSON text in the specified buffer, calling the 625   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 626   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 627   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. 628   of the current JSON if any characters were already parsed.
614   629  
615   The characters in the buffer are processed starting from the beginning, 630   The characters in the buffer are processed starting from the beginning,
616   until one of the following conditions is met: 631   until one of the following conditions is met:
617   632  
618   @li All of the characters in the buffer have been parsed, or 633   @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 634   @li Some of the characters in the buffer have been parsed and the JSON
620   is complete, or 635   is complete, or
621   @li A parsing error occurs. 636   @li A parsing error occurs.
622   637  
623   The supplied buffer does not need to contain the entire JSON. 638   The supplied buffer does not need to contain the entire JSON.
624   Subsequent calls can provide more serialized data, allowing JSON to be 639   Subsequent calls can provide more serialized data, allowing JSON to be
625   processed incrementally. The end of the serialized JSON can be 640   processed incrementally. The end of the serialized JSON can be
626   indicated by passing `more = false`. 641   indicated by passing `more = false`.
627   642  
628   @par Complexity 643   @par Complexity
629   Linear in `size`. 644   Linear in `size`.
630   645  
631   @par Exception Safety 646   @par Exception Safety
632   Basic guarantee. Calls to the handler may throw. 647   Basic guarantee. Calls to the handler may throw.
633   648  
634   Upon error or exception, subsequent calls will fail until @ref reset 649   Upon error or exception, subsequent calls will fail until @ref reset
635   is called to parse a new JSON. 650   is called to parse a new JSON.
636   651  
637   @return The number of characters successfully 652   @return The number of characters successfully
638   parsed, which may be smaller than `size`. 653   parsed, which may be smaller than `size`.
639   654  
640   @param more `true` if there are possibly more buffers in the current 655   @param more `true` if there are possibly more buffers in the current
641   JSON, otherwise `false`. 656   JSON, otherwise `false`.
642   657  
643   @param data A pointer to a buffer of `size` characters to parse. 658   @param data A pointer to a buffer of `size` characters to parse.
644   659  
645   @param size The number of characters pointed to by `data`. 660   @param size The number of characters pointed to by `data`.
646   661  
647   @param ec Set to the error, if any occurred. 662   @param ec Set to the error, if any occurred.
648   663  
649   @{ 664   @{
650   */ 665   */
651   std::size_t 666   std::size_t
652   write_some( 667   write_some(
653   bool more, 668   bool more,
654   char const* data, 669   char const* data,
655   std::size_t size, 670   std::size_t size,
656   system::error_code& ec); 671   system::error_code& ec);
657   672  
658   std::size_t 673   std::size_t
659   write_some( 674   write_some(
660   bool more, 675   bool more,
661   char const* data, 676   char const* data,
662   std::size_t size, 677   std::size_t size,
663   std::error_code& ec); 678   std::error_code& ec);
664   /// @} 679   /// @}
665   }; 680   };
666   681  
667   } // namespace json 682   } // namespace json
668   } // namespace boost 683   } // namespace boost
669   684  
670   #endif 685   #endif