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