DAW JSON Link
Loading...
Searching...
No Matches
daw_json_parse_policy.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
14#include "daw_json_assert.h"
22
23#include <daw/cpp_17.h>
24#include <daw/daw_attributes.h>
25#include <daw/daw_likely.h>
26#include <daw/daw_traits.h>
27
28#include <cassert>
29#include <cstddef>
30#include <iterator>
31#include <type_traits>
32
33namespace daw::json {
34 inline namespace DAW_JSON_VER {
45 template<json_options_t PolicyFlags = json_details::default_policy_flag,
46 typename Allocator = json_details::NoAllocator>
47 struct BasicParsePolicy : json_details::AllocatorWrapper<Allocator> {
48
49 using i_am_a_parse_policy = void;
50 static constexpr bool is_default_parse_policy =
51 PolicyFlags == json_details::default_policy_flag and
52 std::is_same_v<Allocator, json_details::NoAllocator>;
53
54 static DAW_CONSTEVAL json_options_t policy_flags( ) {
55 return PolicyFlags;
56 }
57
58 using CharT = char const;
59 using iterator = CharT *;
60
61 /***
62 * see options::CheckedParseMode
63 */
64 static constexpr bool is_unchecked_input =
65 json_details::get_bits_for<options::CheckedParseMode>( PolicyFlags ) ==
66 options::CheckedParseMode::no;
67
68 /***
69 * See options::ExecModeTypes
70 */
71 using exec_tag_t =
72 switch_t<json_details::get_bits_for<options::ExecModeTypes,
73 std::size_t>( PolicyFlags ),
75
76 static constexpr exec_tag_t exec_tag = exec_tag_t{ };
77
78 /***
79 * see options::AllowEscapedNames
80 */
81 static constexpr bool allow_escaped_names =
82 json_details::get_bits_for<options::AllowEscapedNames>( PolicyFlags ) ==
83 options::AllowEscapedNames::yes;
84
85 /***
86 * see options::ForceFullNameCheck
87 */
88 static constexpr bool force_name_equal_check =
89 json_details::get_bits_for<options::ForceFullNameCheck>(
90 PolicyFlags ) == options::ForceFullNameCheck::yes;
91
92 /***
93 * see options::ZeroTerminatedString
94 */
95 static constexpr bool is_zero_terminated_string =
96 json_details::get_bits_for<options::ZeroTerminatedString>(
97 PolicyFlags ) == options::ZeroTerminatedString::yes;
98
99 /***
100 * See options::IEEE754Precise
101 */
102 static constexpr bool precise_ieee754 =
103 json_details::get_bits_for<options::IEEE754Precise>( PolicyFlags ) ==
104 options::IEEE754Precise::yes;
105
106 /***
107 * See options::MinifiedDocument
108 */
109 static constexpr bool minified_document =
110 json_details::get_bits_for<options::MinifiedDocument>( PolicyFlags ) ==
111 options::MinifiedDocument::yes;
112
113 /***
114 * See options::ExcludeSpecialEscapes
115 */
116 static constexpr bool exclude_special_escapes =
117 json_details::get_bits_for<options::ExcludeSpecialEscapes>(
118 PolicyFlags ) == options::ExcludeSpecialEscapes::yes;
119
121 static constexpr bool allow_leading_zero_plus = true;
122
123 static constexpr bool use_exact_mappings_by_default =
124 json_details::get_bits_for<options::UseExactMappingsByDefault>(
125 PolicyFlags ) == options::UseExactMappingsByDefault::yes;
126
127 static constexpr bool must_verify_end_of_data_is_valid =
128 json_details::get_bits_for<options::MustVerifyEndOfDataIsValid>(
129 PolicyFlags ) == options::MustVerifyEndOfDataIsValid::yes;
130
131 static constexpr bool expect_long_strings =
132 json_details::get_bits_for<options::ExpectLongNames>( PolicyFlags ) ==
133 options::ExpectLongNames::yes;
134
136 switch_t<json_details::get_bits_for<options::PolicyCommentTypes,
137 std::size_t>( PolicyFlags ),
140
141 iterator first{ };
142 iterator last{ };
143 iterator class_first{ };
144 iterator class_last{ };
145 std::size_t counter = 0;
146
147 template<auto... PolicyOptions>
149 json_details::set_bits( PolicyFlags, PolicyOptions... ), Allocator>;
150
151 explicit BasicParsePolicy( ) = default;
152
153 explicit constexpr BasicParsePolicy( iterator f, iterator l )
154 : first( f )
155 , last( l )
156 , class_first( f )
157 , class_last( l ) {}
158
159 explicit constexpr BasicParsePolicy( iterator f, iterator l,
160 Allocator &alloc )
161 : json_details::AllocatorWrapper<Allocator>( alloc )
162 , first( f )
163 , last( l )
164 , class_first( f )
165 , class_last( l ) {}
166
167 explicit constexpr BasicParsePolicy( iterator f, iterator l, iterator cf,
168 iterator cl )
169 : first( f )
170 , last( l )
171 , class_first( cf )
172 , class_last( cl ) {}
173
174 explicit constexpr BasicParsePolicy( iterator f, iterator l, iterator cf,
175 iterator cl, Allocator const &alloc )
176 : json_details::AllocatorWrapper<Allocator>( alloc )
177 , first( f )
178 , last( l )
179 , class_first( cf )
180 , class_last( cl ) {}
181
182 [[nodiscard]] constexpr BasicParsePolicy
183 copy( iterator f = iterator{ }, iterator l = iterator{ },
184 iterator cf = iterator{ }, iterator cl = iterator{ } ) const {
185 BasicParsePolicy result = *this;
186 if( f ) {
187 result.first = f;
188 }
189 if( l ) {
190 result.last = l;
191 }
192 if( cf ) {
193 result.class_first = cf;
194 }
195 if( cl ) {
196 result.class_last = cl;
197 }
198 return result;
199 }
200
201 DAW_ATTRIB_INLINE constexpr decltype( auto ) get_allocator( ) const {
202 return json_details::AllocatorWrapper<Allocator>::get_allocator( );
203 }
204
205 template<typename Alloc>
207
208 template<typename Alloc>
209 [[nodiscard]] static constexpr with_allocator_type<Alloc>
211 Alloc const &alloc ) {
212 return with_allocator_type<Alloc>{ f, l, cf, cl, alloc };
213 }
214
215 [[nodiscard]] static constexpr BasicParsePolicy
217 json_details::NoAllocator const & ) {
218 return BasicParsePolicy( f, l, cf, cl );
219 }
220
221 template<typename Alloc>
222 [[nodiscard]] constexpr auto
224 if constexpr( std::is_same_v<Alloc, json_details::NoAllocator> ) {
225 return *this;
226 } else {
227 auto result = with_allocator( first, last, class_first, class_last,
228 p.get_allocator( ) );
229 result.counter = p.counter;
230 return result;
231 }
232 }
233
234 template<typename Alloc>
235 [[nodiscard]] constexpr with_allocator_type<Alloc>
236 with_allocator( Alloc const &alloc ) const {
237 auto result =
238 with_allocator( first, last, class_first, class_last, alloc );
239 result.counter = counter;
240 return result;
241 }
242
243 [[nodiscard]] DAW_ATTRIB_INLINE constexpr auto
244 with_allocator( json_details::NoAllocator const & ) const {
245 return *this;
246 }
247
250
251 template<typename Alloc>
252 [[nodiscard]] static constexpr with_allocator_type<Alloc>
253 with_allocator( iterator f, iterator l, Alloc const &alloc ) {
254 return { f, l, f, l, alloc };
255 }
256
257 template<typename Alloc>
258 [[nodiscard]] static constexpr BasicParsePolicy
260 json_details::NoAllocator const & ) {
261 return { f, l, f, l };
262 }
263
264 [[nodiscard]] DAW_ATTRIB_INLINE constexpr iterator data( ) const {
265 return first;
266 }
267
268 [[nodiscard]] DAW_ATTRIB_INLINE constexpr iterator data_end( ) const {
269 return last;
270 }
271
272 [[nodiscard]] DAW_ATTRIB_INLINE constexpr iterator begin( ) const {
273 return first;
274 }
275
276 [[nodiscard]] DAW_ATTRIB_INLINE constexpr iterator end( ) const {
277 return last;
278 }
279
280 [[nodiscard]] DAW_ATTRIB_INLINE constexpr bool empty( ) const {
281 if( not first ) {
282 return true;
283 }
284 if constexpr( is_zero_terminated_string ) {
285 return first >= last or *first == '\0';
286 } else {
287 return first >= last;
288 }
289 }
290
291 [[nodiscard]] DAW_ATTRIB_INLINE constexpr bool has_more( ) const {
292 return first < last;
293 }
294
295 template<std::size_t N>
296 constexpr bool starts_with( char const ( &rhs )[N] ) const {
297 static_assert( N > 0 );
298 if( size( ) < ( N - 1 ) ) {
299 return false;
300 }
301 bool result = true;
302 for( std::size_t n = 0; n < ( N - 1 ); ++n ) {
303 result = result & ( first[n] == rhs[n] );
304 }
305 return result;
306 }
307
308 template<char c>
309 DAW_ATTRIB_INLINE constexpr void move_to_next_of_unchecked( ) {
310 first =
311 json_details::memchr_unchecked<c, exec_tag_t, expect_long_strings>(
312 first, last );
313 }
314
315 template<char c>
316 DAW_ATTRIB_INLINE constexpr void move_to_next_of_checked( ) {
317 first =
318 json_details::memchr_checked<c, exec_tag_t, expect_long_strings>(
319 first, last );
320 }
321
322 template<char c>
323 DAW_ATTRIB_INLINE constexpr void move_to_next_of( ) {
324 if( is_unchecked_input ) {
325 move_to_next_of_unchecked<c>( );
326 } else {
327 move_to_next_of_checked<c>( );
328 }
329 }
330
331 [[nodiscard]] DAW_ATTRIB_INLINE constexpr char front( ) const {
332 return *first;
333 }
334
335 [[nodiscard]] DAW_ATTRIB_INLINE constexpr char front_checked( ) const {
336 daw_json_ensure( first < last, ErrorReason::UnexpectedEndOfData,
337 *this );
338 return *first;
339 }
340
341 [[nodiscard]] DAW_ATTRIB_INLINE constexpr std::size_t size( ) const {
342 assert( last >= first );
343 return static_cast<std::size_t>( last - first );
344 }
345
346 [[nodiscard]] constexpr bool is_null( ) const {
347 return first == nullptr;
348 }
349
350 DAW_ATTRIB_INLINE constexpr void remove_prefix( ) {
351 ++first;
352 }
353
354 DAW_ATTRIB_INLINE constexpr void remove_prefix( std::size_t n ) {
355 first += static_cast<std::ptrdiff_t>( n );
356 }
357
358 constexpr void set_class_position( ) {
359 class_first = first;
360 class_last = last;
361 }
362
363 struct class_pos_t {
366 };
367
368 constexpr void set_class_position( class_pos_t new_pos ) {
369 class_first = new_pos.f;
370 class_last = new_pos.l;
371 }
372
373 [[nodiscard]] constexpr class_pos_t get_class_position( ) const {
374 return { class_first, class_last };
375 }
376
377 constexpr void trim_left_checked( ) {
378 return CommentPolicy::trim_left_checked( *this );
379 }
380
381 constexpr void trim_left_unchecked( ) {
382 return CommentPolicy::trim_left_unchecked( *this );
383 }
384
385 [[nodiscard]] constexpr bool is_literal_end( ) const {
386 return CommentPolicy::is_literal_end( *first );
387 }
388
389 [[nodiscard]] DAW_ATTRIB_INLINE constexpr bool
391 return ( static_cast<unsigned>( static_cast<unsigned char>( *first ) ) -
392 1U ) <= 0x1FU;
393 }
394
395 [[nodiscard]] constexpr bool is_opening_bracket_checked( ) const {
396 return DAW_LIKELY( first < last ) and *first == '[';
397 }
398
399 [[nodiscard]] constexpr bool is_opening_brace_checked( ) const {
400 return DAW_LIKELY( first < last ) and *first == '{';
401 }
402
403 [[nodiscard]] constexpr bool is_closing_brace_checked( ) const {
404 return DAW_LIKELY( first < last ) and *first == '}';
405 }
406
407 [[nodiscard]] constexpr bool is_quotes_checked( ) const {
408 return DAW_LIKELY( first < last ) and *first == '"';
409 }
410
411 DAW_ATTRIB_INLINE constexpr void trim_left( ) {
412 if constexpr( is_unchecked_input ) {
413 trim_left_unchecked( );
414 } else {
415 trim_left_checked( );
416 }
417 }
418
420 trim_left_unchecked( );
421 if( *first == ',' ) {
422 ++first;
423 trim_left_unchecked( );
424 }
425 }
426
427 DAW_ATTRIB_FLATINLINE inline constexpr void
429 trim_left_checked( );
430 if constexpr( is_zero_terminated_string ) {
431 if( *first == ',' ) {
432 ++first;
433 trim_left( );
434 }
435 } else {
436 if( DAW_LIKELY( first < last ) and *first == ',' ) {
437 ++first;
438 trim_left( );
439 }
440 }
441 }
442
443 DAW_ATTRIB_INLINE constexpr void move_next_member_or_end( ) {
444 if constexpr( is_unchecked_input ) {
445 move_next_member_or_end_unchecked( );
446 } else {
447 move_next_member_or_end_checked( );
448 }
449 }
450
451 DAW_ATTRIB_INLINE constexpr void move_next_member( ) {
452 if constexpr( is_unchecked_input ) {
453 CommentPolicy::move_next_member_unchecked( *this );
454 } else {
455 // We have no guarantee that all members are available
456 move_next_member_or_end_checked( );
457 }
458 }
459
460 constexpr void move_to_next_class_member( ) {
461 CommentPolicy::template move_to_next_of<'"', '}'>( *this );
462 }
463
464 [[nodiscard]] constexpr bool is_at_next_class_member( ) const {
465 return parse_policy_details::in<'"', '}'>( *first );
466 }
467
468 [[nodiscard]] constexpr bool is_at_next_array_element( ) const {
469 return parse_policy_details::in<',', ']'>( *first );
470 }
471
472 [[nodiscard]] constexpr bool is_at_token_after_value( ) const {
473 return parse_policy_details::in<',', '}', ']'>( *first );
474 }
475
476 template<char PrimLeft>
477 [[nodiscard]] DAW_ATTRIB_INLINE constexpr BasicParsePolicy
479 return CommentPolicy::template skip_bracketed_item_checked<PrimLeft>(
480 *this );
481 }
482
483 template<char PrimLeft>
484 [[nodiscard]] DAW_ATTRIB_INLINE constexpr BasicParsePolicy
486 return CommentPolicy::template skip_bracketed_item_unchecked<PrimLeft>(
487 *this );
488 }
489
490 [[nodiscard]] DAW_ATTRIB_INLINE constexpr BasicParsePolicy skip_class( ) {
491 if constexpr( is_unchecked_input ) {
492 return skip_bracketed_item_unchecked<'{'>( );
493 } else {
494 return skip_bracketed_item_checked<'{'>( );
495 }
496 }
497
498 [[nodiscard]] DAW_ATTRIB_INLINE constexpr BasicParsePolicy skip_array( ) {
499 if constexpr( is_unchecked_input ) {
500 return skip_bracketed_item_unchecked<'['>( );
501 } else {
502 return skip_bracketed_item_checked<'['>( );
503 }
504 }
505 };
506
508
509 BasicParsePolicy( char const *, char const * ) -> BasicParsePolicy<>;
510
511 template<typename Allocator>
512 BasicParsePolicy( char const *, char const *, Allocator const & )
514
515 BasicParsePolicy( char const *, char const *, char const *, char const * )
517
518 template<typename Allocator>
519 BasicParsePolicy( char const *, char const *, char const *, char const *,
520 Allocator const & )
522
524 : BasicParsePolicy<json_details::default_policy_flag,
525 json_details::NoAllocator> {
526
527 using BasicParsePolicy::BasicParsePolicy;
528
529 constexpr DefaultParsePolicy( BasicParsePolicy const &other ) noexcept
530 : BasicParsePolicy( other ) {}
531 constexpr DefaultParsePolicy( BasicParsePolicy &&other ) noexcept
532 : BasicParsePolicy( std::move( other ) ) {}
533 };
534
535 template<json_options_t PolicyFlags = json_details::default_policy_flag,
536 typename Allocator = json_details::NoAllocator>
538 daw::conditional_t<(PolicyFlags == json_details::default_policy_flag and
539 std::is_same_v<Allocator, json_details::NoAllocator>),
542 template<typename ParsePolicy>
544 daw::conditional_t<ParsePolicy::is_default_parse_policy,
545 DefaultParsePolicy, ParsePolicy>;
546
547 namespace options {
548 /***
549 * @brief Specify parse policy flags in to_json calls. See cookbook item
550 * parse_options.md
551 */
552 template<auto... PolicyFlags>
554 static_assert(
555 json_details::are_option_flags<decltype( PolicyFlags )...>,
556 "Only registered policy types are allowed" );
557 static constexpr json_options_t value = parse_options( PolicyFlags... );
558 };
559 template<>
560 struct parse_flags_t<> {
561 static constexpr json_options_t value =
562 json_details::default_policy_flag;
563 };
564
565 namespace details {
566 template<typename... Ts>
567 std::false_type is_policy_flag( Ts... );
568
569 template<auto... PolicyFlags>
571
572 template<auto... PolicyFlags>
573 DAW_CONSTEVAL auto make_parse_flags( ) {
574 if constexpr( decltype( details::is_policy_flag(
575 PolicyFlags... ) )::value ) {
576 static_assert( sizeof...( PolicyFlags ) == 1 );
577 // We know there is only one but need to unpack
578 return ( PolicyFlags, ... );
579 } else {
580 return parse_flags_t<PolicyFlags...>{ };
581 }
582 }
583 } // namespace details
588 template<auto... PolicyFlags>
589 inline constexpr auto parse_flags =
590 details::make_parse_flags<PolicyFlags...>( );
591 } // namespace options
592
593#define DAW_JSON_CONFORMANCE_FLAGS \
594 daw::json::options::AllowEscapedNames::yes, \
595 daw::json::options::MustVerifyEndOfDataIsValid::yes, \
596 daw::json::options::IEEE754Precise::yes, \
597 daw::json::options::ExcludeSpecialEscapes::yes
598
599 inline constexpr auto ConformancePolicy =
600 options::parse_flags<DAW_JSON_CONFORMANCE_FLAGS>;
601
602 } // namespace DAW_JSON_VER
603} // namespace daw::json
#define daw_json_ensure(Bool,...)
Ensure that Bool is true. If false pass rest of args to daw_json_error.
constexpr auto parse_flags
Specify parse policy flags in to_json calls. See cookbook item parse_options.md.
daw::conditional_t<(PolicyFlags==json_details::default_policy_flag and std::is_same_v< Allocator, json_details::NoAllocator >), DefaultParsePolicy, BasicParsePolicy< PolicyFlags, Allocator > > GetParsePolicy
daw::conditional_t< ParsePolicy::is_default_parse_policy, DefaultParsePolicy, ParsePolicy > TryDefaultParsePolicy
std::bool_constant< is_zero_terminated_string_v< T > > is_zero_terminated_string
Customization point traits.
Handles the bounds and policy items for parsing execution and comments.
static constexpr BasicParsePolicy with_allocator(iterator f, iterator l, iterator cf, iterator cl, json_details::NoAllocator const &)
switch_t< json_details::get_bits_for< options::ExecModeTypes, std::size_t >(PolicyFlags), constexpr_exec_tag, runtime_exec_tag, simd_exec_tag > exec_tag_t
constexpr BasicParsePolicy(iterator f, iterator l, iterator cf, iterator cl, Allocator const &alloc)
constexpr BasicParsePolicy(iterator f, iterator l, iterator cf, iterator cl)
DAW_ATTRIB_INLINE constexpr auto with_allocator(json_details::NoAllocator const &) const
constexpr auto with_allocator(BasicParsePolicy< PolicyFlags, Alloc > p) const
static constexpr BasicParsePolicy with_allocator(iterator f, iterator l, json_details::NoAllocator const &)
constexpr BasicParsePolicy copy(iterator f=iterator{ }, iterator l=iterator{ }, iterator cf=iterator{ }, iterator cl=iterator{ }) const
constexpr BasicParsePolicy(iterator f, iterator l, Allocator &alloc)
static constexpr with_allocator_type< Alloc > with_allocator(iterator f, iterator l, Alloc const &alloc)
static constexpr with_allocator_type< Alloc > with_allocator(iterator f, iterator l, iterator cf, iterator cl, Alloc const &alloc)
switch_t< json_details::get_bits_for< options::PolicyCommentTypes, std::size_t >(PolicyFlags), NoCommentSkippingPolicy, CppCommentSkippingPolicy, HashCommentSkippingPolicy > CommentPolicy
constexpr with_allocator_type< Alloc > with_allocator(Alloc const &alloc) const
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20