DAW JSON Link
daw_json_parse_options.h
Go to the documentation of this file.
1 // Copyright (c) Darrell Wright
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
5 //
6 // Official repository: https://github.com/beached/daw_json_link
7 //
8 
9 #pragma once
10 
11 #include "version.h"
12 
13 #include "daw_json_option_bits.h"
14 
15 #include <daw/cpp_17.h>
16 #include <daw/daw_attributes.h>
17 #include <daw/daw_traits.h>
18 
19 #include <ciso646>
20 #include <climits>
21 #include <cstddef>
22 #include <cstdint>
23 #include <utility>
24 
25 namespace daw::json {
26  inline namespace DAW_JSON_VER {
27  /***
28  * Allow for different optimizations. Currently only the compile_time path
29  * is fully supported. The others may offer faster parsing. The default is
30  * compile_time, it provides constexpr parsing and generally is faster
31  * currently.
32  */
33  enum class ExecModeTypes : unsigned {
35  runtime, /* testing */
36  simd /* testing */
37  }; // 2bits
38 
39  namespace json_details {
40  template<>
41  inline constexpr unsigned json_option_bits_width<ExecModeTypes> = 2;
42 
43  template<>
46  } // namespace json_details
47 
48  /***
49  * Input is a zero terminated string. If this cannot be detected, you can
50  * specify it here. Offers some optimization possibilities in the parser.
51  * Default is no, to try and detect, but use the safer assumption that the
52  * buffer does not end in zero.
53  */
54  enum class ZeroTerminatedString : unsigned { no, yes }; // 1bit
55  namespace json_details {
56  template<>
58  1;
59 
60  template<>
63  } // namespace json_details
64 
65  /***
66  * Allow comments in JSON. The supported modes are none, C++ style
67  * comments, and # hash style comments. Default is none, no comments
68  * allowed
69  */
70  enum class PolicyCommentTypes : unsigned { none, cpp, hash }; // 2bits
71  namespace json_details {
72  template<>
73  inline constexpr unsigned json_option_bits_width<PolicyCommentTypes> = 2;
74 
75  template<>
78  } // namespace json_details
79  /***
80  * Enable all structure, buffer, and type checking. The default is yes, but
81  * no still does some checking and can be faster.
82  */
83  enum class CheckedParseMode : unsigned { yes, no }; // 1bit
84  namespace json_details {
85  template<>
86  inline constexpr unsigned json_option_bits_width<CheckedParseMode> = 1;
87 
88  template<>
91  } // namespace json_details
92 
93  /***
94  * When document is minified, it is assumed that there is no whitespace in
95  * the document. Not all policies support this.
96  */
97  enum class MinifiedDocument : unsigned { no, yes }; // 1 bit
98  namespace json_details {
99  template<>
100  inline constexpr unsigned json_option_bits_width<MinifiedDocument> = 1;
101 
102  template<>
105  } // namespace json_details
106 
107  /***
108  * Allow the escape character '\' in names. This forces a slower parser and
109  * is generally not needed. The default is no, and the end of string
110  * matching only needs to look for a `"`, not skip `\"` in names.
111  */
112  enum class AllowEscapedNames : unsigned { no, yes }; // 1bit
113  namespace json_details {
114  template<>
115  inline constexpr unsigned json_option_bits_width<AllowEscapedNames> = 1;
116 
117  template<>
120  } // namespace json_details
121 
122  /***
123  * Testing
124  * Use precise IEEE754 parsing of real numbers. The default is no, and
125  * results is much faster parsing with very small errors of 0-2ulp.
126  */
127  enum class IEEE754Precise : unsigned { no, yes }; // 1bit
128  namespace json_details {
129  template<>
130  inline constexpr unsigned json_option_bits_width<IEEE754Precise> = 1;
131 
132  template<>
135  } // namespace json_details
136 
137  /***
138  * If the hashes of all members being looked are unique, the lookup of names
139  * as they are found in the document stops at hash checking by default. You
140  * can force a full string check by setting to yes.
141  */
142  enum class ForceFullNameCheck : unsigned { no, yes }; // 1bit
143  namespace json_details {
144  template<>
145  inline constexpr unsigned json_option_bits_width<ForceFullNameCheck> = 1;
146 
147  template<>
150  } // namespace json_details
151  /***
152  * Set the default parser policy to require all JSON members in the parsed
153  * object be mapped. See also, the ignore_unknown_members and
154  * exact_class_mapping traits to set overrides
155  */
156  enum class UseExactMappingsByDefault : unsigned { no, yes }; // 1bit
157  namespace json_details {
158  template<>
159  inline constexpr unsigned
161 
162  template<>
163  inline constexpr auto
166  } // namespace json_details
167 
168  /***
169  * Continue checking that the data is whitespace or empty after the end of
170  * top level object is parsed from from_json
171  */
172  enum class MustVerifyEndOfDataIsValid : unsigned { no, yes };
173  namespace json_details {
174  template<>
175  inline constexpr unsigned
177 
178  template<>
179  inline constexpr auto
182  } // namespace json_details
183 
184  /***
185  * When enabled, the parser can temporarily set a character to the desired
186  * token. This allows for safe searching without bounds checking. If the
187  * buffer is not mutable, it will not be enabled.
188  */
189  enum class TemporarilyMutateBuffer : unsigned { no, yes }; // 1bit
190  namespace json_details {
191  template<>
192  inline constexpr unsigned
194 
195  template<>
198  } // namespace json_details
199 
200  /***
201  * Exclude characters under 0x20 that are not explicitly allowed.
202  */
203  enum class ExcludeSpecialEscapes : unsigned { no, yes }; // 1bit
204  namespace json_details {
205  template<>
207  1;
208 
209  template<>
212  } // namespace json_details
213  /* *****************************************
214  * Implementation details
215  */
216  namespace json_details {
217  using policy_list = typename option_list_impl<
222 
223  template<typename Policy, typename Policies>
224  inline constexpr unsigned basic_policy_bits_start =
226  std::make_index_sequence<pack_size_v<Policies>>{ } );
227 
228  template<typename Policy>
229  inline constexpr unsigned policy_bits_start =
230  basic_policy_bits_start<Policy, policy_list>;
231 
232  template<typename Policy>
233  constexpr void set_bits_in( json_options_t &value, Policy e ) {
234  static_assert( is_option_flag<Policy>,
235  "Only registered policy types are allowed" );
236  auto new_bits = static_cast<unsigned>( e );
237  constexpr unsigned mask = (1U << json_option_bits_width<Policy>)-1U;
238  new_bits &= mask;
239  new_bits <<= policy_bits_start<Policy>;
240  value &= ~mask;
241  value |= new_bits;
242  }
243 
244  template<typename Policy, typename... Policies>
245  constexpr json_options_t set_bits( json_options_t value, Policy pol,
246  Policies... pols ) {
247  static_assert( ( is_option_flag<Policies> and ... ),
248  "Only registered policy types are allowed" );
249 
250  auto new_bits = static_cast<unsigned>( pol );
251  constexpr unsigned mask = ( (1U << json_option_bits_width<Policy>)-1U );
252  new_bits &= mask;
253  new_bits <<= policy_bits_start<Policy>;
254  value &= ~( mask << policy_bits_start<Policy> );
255  value |= new_bits;
256  if constexpr( sizeof...( Policies ) > 0 ) {
257  if constexpr( sizeof...( pols ) > 0 ) {
258  return set_bits( value, pols... );
259  } else {
260  return value;
261  }
262  } else {
263  return value;
264  }
265  }
266 
267  template<typename Policy>
268  constexpr json_options_t set_bits_for( Policy e ) {
269  static_assert( is_option_flag<Policy>,
270  "Only registered policy types are allowed" );
271  auto new_bits = static_cast<json_options_t>( e );
272  new_bits <<= policy_bits_start<Policy>;
273  return new_bits;
274  }
275 
276  template<typename>
278 
279  template<typename... Policies>
280  struct default_policy_flag_t<pack_list<Policies...>> {
281  static constexpr json_options_t value =
282  ( set_bits_for<Policies>( default_json_option_value<Policies> ) |
283  ... );
284  };
285 
286  /***
287  * The defaults for all known policies encoded as a json_options_t
288  */
289  inline static constexpr json_options_t default_policy_flag =
291 
292  template<typename Policy, typename Result = Policy>
293  constexpr Result get_bits_for( json_options_t value ) {
294  static_assert( is_option_flag<Policy>,
295  "Only registered policy types are allowed" );
296  constexpr unsigned mask = ( 1U << (policy_bits_start<Policy> +
297  json_option_bits_width<Policy>)) -
298  1U;
299  value &= mask;
300  value >>= policy_bits_start<Policy>;
301  return static_cast<Result>( Policy{ value } );
302  }
303  } // namespace json_details
304  // ***********************************************
305 
306  /***
307  * Create the parser options flag for BasicParsePolicy
308  * @tparam Policies Policy types that satisfy the `is_policy_flag` trait.
309  * @param policies A list of parser options to change from the defaults.
310  * @return A json_options_t that encodes the options for the parser
311  */
312  template<typename... Policies>
314  parse_options( Policies... policies ) {
315  static_assert( ( json_details::is_option_flag<Policies> and ... ),
316  "Only registered policy types are allowed" );
317  auto result = json_details::default_policy_flag;
318  if constexpr( sizeof...( Policies ) > 0 ) {
319  result |= ( json_details::set_bits_for( policies ) | ... );
320  }
321  return result;
322  }
323  } // namespace DAW_JSON_VER
324 } // namespace daw::json
constexpr auto default_json_option_value< PolicyCommentTypes >
Definition: daw_json_parse_options.h:76
typename option_list_impl< ExecModeTypes, ZeroTerminatedString, PolicyCommentTypes, CheckedParseMode, AllowEscapedNames, IEEE754Precise, ForceFullNameCheck, MinifiedDocument, UseExactMappingsByDefault, TemporarilyMutateBuffer, MustVerifyEndOfDataIsValid, ExcludeSpecialEscapes >::type policy_list
Definition: daw_json_parse_options.h:221
constexpr unsigned basic_policy_bits_start
Definition: daw_json_parse_options.h:224
static constexpr json_options_t set_bits_for(JsonOptionList< OptionList... >, Option e)
Definition: daw_json_option_bits.h:161
constexpr auto default_json_option_value< UseExactMappingsByDefault >
Definition: daw_json_parse_options.h:164
constexpr auto default_json_option_value< MinifiedDocument >
Definition: daw_json_parse_options.h:103
constexpr auto default_json_option_value< ExecModeTypes >
Definition: daw_json_parse_options.h:44
constexpr auto default_json_option_value< IEEE754Precise >
Definition: daw_json_parse_options.h:133
constexpr auto default_json_option_value< MustVerifyEndOfDataIsValid >
Definition: daw_json_parse_options.h:180
constexpr unsigned json_option_bits_width< ExcludeSpecialEscapes >
Definition: daw_json_parse_options.h:206
constexpr json_options_t set_bits(JsonOptionList< OptionList... >, json_options_t value, Option pol, Options... pols)
Definition: daw_json_option_bits.h:138
constexpr unsigned json_option_bits_width< UseExactMappingsByDefault >
Definition: daw_json_parse_options.h:160
constexpr auto default_json_option_value< CheckedParseMode >
Definition: daw_json_parse_options.h:89
constexpr auto default_json_option_value< TemporarilyMutateBuffer >
Definition: daw_json_parse_options.h:196
constexpr auto default_json_option_value< ForceFullNameCheck >
Definition: daw_json_parse_options.h:148
constexpr unsigned json_option_bits_width< CheckedParseMode >
Definition: daw_json_parse_options.h:86
constexpr unsigned json_option_bits_width< ExecModeTypes >
Definition: daw_json_parse_options.h:41
std::uint32_t json_options_t
Definition: daw_json_option_bits.h:23
constexpr unsigned json_option_bits_width< MinifiedDocument >
Definition: daw_json_parse_options.h:100
static constexpr json_options_t default_policy_flag
Definition: daw_json_parse_options.h:289
constexpr unsigned json_option_bits_width< IEEE754Precise >
Definition: daw_json_parse_options.h:130
constexpr unsigned json_option_bits_width< TemporarilyMutateBuffer >
Definition: daw_json_parse_options.h:193
constexpr unsigned json_option_bits_width< ForceFullNameCheck >
Definition: daw_json_parse_options.h:145
constexpr unsigned json_option_bits_width< PolicyCommentTypes >
Definition: daw_json_parse_options.h:73
constexpr auto default_json_option_value< AllowEscapedNames >
Definition: daw_json_parse_options.h:118
constexpr void set_bits_in(JsonOptionList< OptionList... >, json_options_t &value, Option e)
Definition: daw_json_option_bits.h:124
constexpr auto default_json_option_value< ZeroTerminatedString >
Definition: daw_json_parse_options.h:61
constexpr Result get_bits_for(JsonOptionList< OptionList... >, json_options_t value)
Definition: daw_json_option_bits.h:167
constexpr unsigned json_option_bits_width< ZeroTerminatedString >
Definition: daw_json_parse_options.h:57
constexpr unsigned json_option_bits_width< MustVerifyEndOfDataIsValid >
Definition: daw_json_parse_options.h:176
constexpr unsigned policy_bits_start
Definition: daw_json_parse_options.h:229
constexpr auto default_json_option_value< ExcludeSpecialEscapes >
Definition: daw_json_parse_options.h:210
constexpr unsigned json_option_bits_width< AllowEscapedNames >
Definition: daw_json_parse_options.h:115
UseExactMappingsByDefault
Definition: daw_json_parse_options.h:156
constexpr json_details::json_options_t parse_options(Policies... policies)
Definition: daw_json_parse_options.h:314
ForceFullNameCheck
Definition: daw_json_parse_options.h:142
IEEE754Precise
Definition: daw_json_parse_options.h:127
CheckedParseMode
Definition: daw_json_parse_options.h:83
ExecModeTypes
Definition: daw_json_parse_options.h:33
MustVerifyEndOfDataIsValid
Definition: daw_json_parse_options.h:172
PolicyCommentTypes
Definition: daw_json_parse_options.h:70
AllowEscapedNames
Definition: daw_json_parse_options.h:112
MinifiedDocument
Definition: daw_json_parse_options.h:97
ExcludeSpecialEscapes
Definition: daw_json_parse_options.h:203
ZeroTerminatedString
Definition: daw_json_parse_options.h:54
TemporarilyMutateBuffer
Definition: daw_json_parse_options.h:189
Definition: daw_from_json.h:22
Definition: daw_json_parse_options.h:277
Definition: daw_json_option_bits.h:58
#define DAW_JSON_VER
Definition: version.h:11