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
23
24#include <daw/cpp_17.h>
25#include <daw/daw_attributes.h>
26#include <daw/daw_consteval.h>
27#include <daw/daw_likely.h>
28#include <daw/daw_not_null.h>
29#include <daw/daw_rw_ref.h>
30#include <daw/daw_traits.h>
31
32#include <cassert>
33#include <cstddef>
34#include <iterator>
35#include <type_traits>
36
37namespace daw::json {
38 inline namespace DAW_JSON_VER {
49 template<json_options_t PolicyFlags = json_details::default_policy_flag,
50 typename Allocator = json_details::NoAllocator>
51 struct BasicParsePolicy : json_details::AllocatorWrapper<Allocator> {
52
53 using i_am_a_parse_policy = void;
54 static constexpr bool is_default_parse_policy =
55 PolicyFlags == json_details::default_policy_flag and
56 std::is_same_v<Allocator, json_details::NoAllocator>;
57
58 static DAW_CONSTEVAL json_options_t policy_flags( ) {
59 return PolicyFlags;
60 }
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, no longer has an effect
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::AllowStringMutation
102 */
103 static constexpr bool allow_string_mutation =
104 json_details::get_bits_for<options::AllowStringMutation>(
105 PolicyFlags ) == options::AllowStringMutation::yes;
106
107 /***
108 * See options::IEEE754Precise
109 */
110 static constexpr bool precise_ieee754 =
111 json_details::get_bits_for<options::IEEE754Precise>( PolicyFlags ) ==
112 options::IEEE754Precise::yes;
113
114 /***
115 * See options::MinifiedDocument
116 */
117 static constexpr bool minified_document =
118 json_details::get_bits_for<options::MinifiedDocument>( PolicyFlags ) ==
119 options::MinifiedDocument::yes;
120
121 /***
122 * See options::ExcludeSpecialEscapes
123 */
124 static constexpr bool exclude_special_escapes =
125 json_details::get_bits_for<options::ExcludeSpecialEscapes>(
126 PolicyFlags ) == options::ExcludeSpecialEscapes::yes;
127
129 static constexpr bool allow_leading_zero_plus = true;
130
131 static constexpr bool use_exact_mappings_by_default =
132 json_details::get_bits_for<options::UseExactMappingsByDefault>(
133 PolicyFlags ) == options::UseExactMappingsByDefault::yes;
134
135 static constexpr bool must_verify_end_of_data_is_valid =
136 json_details::get_bits_for<options::MustVerifyEndOfDataIsValid>(
137 PolicyFlags ) == options::MustVerifyEndOfDataIsValid::yes;
138
139 static constexpr bool expect_long_strings =
140 json_details::get_bits_for<options::ExpectLongNames>( PolicyFlags ) ==
141 options::ExpectLongNames::yes;
142
145 static constexpr std::size_t array_reserve_amount = [] {
146 switch( json_details::get_bits_for<options::ArrayReserve>(
147 PolicyFlags ) ) {
148 case options::ArrayReserve::none:
149 return std::size_t{ 0 };
150 case options::ArrayReserve::elements_128:
151 return std::size_t{ 128 };
152 case options::ArrayReserve::elements_512:
153 return std::size_t{ 512 };
154 case options::ArrayReserve::elements_1024:
155 return std::size_t{ 1024 };
156 }
157 return std::size_t{ 0 };
158 }( );
159
161 switch_t<json_details::get_bits_for<options::PolicyCommentTypes,
162 std::size_t>( PolicyFlags ),
165
166 using iterator = std::conditional_t<allow_string_mutation ,
167 char *, char const *>;
168 iterator first{ };
169 iterator last{ };
170 iterator class_first{ };
171 iterator class_last{ };
172 std::size_t counter = 0;
173
174 template<auto... PolicyOptions>
176 json_details::set_bits( PolicyFlags, PolicyOptions... ), Allocator>;
177
178 explicit BasicParsePolicy( ) = default;
179
180 explicit constexpr BasicParsePolicy( iterator f, iterator l )
181 : first( f )
182 , last( l )
183 , class_first( f )
184 , class_last( l ) {}
185
186 explicit constexpr BasicParsePolicy( iterator f, iterator l,
187 Allocator &alloc )
188 : json_details::AllocatorWrapper<Allocator>( alloc )
189 , first( f )
190 , last( l )
191 , class_first( f )
192 , class_last( l ) {}
193
194 explicit constexpr BasicParsePolicy( iterator f, iterator l, iterator cf,
195 iterator cl )
196 : first( f )
197 , last( l )
198 , class_first( cf )
199 , class_last( cl ) {}
200
201 explicit constexpr BasicParsePolicy( iterator f, iterator l, iterator cf,
202 iterator cl, std::size_t cnter )
203 : first( f )
204 , last( l )
205 , class_first( cf )
206 , class_last( cl )
207 , counter( cnter ) {}
208
209 explicit constexpr BasicParsePolicy( iterator f, iterator l, iterator cf,
210 iterator cl, Allocator const &alloc )
211 : json_details::AllocatorWrapper<Allocator>( alloc )
212 , first( f )
213 , last( l )
214 , class_first( cf )
215 , class_last( cl ) {}
216
217 [[nodiscard]] constexpr BasicParsePolicy
218 copy( iterator f = iterator{ }, iterator l = iterator{ },
219 iterator cf = iterator{ }, iterator cl = iterator{ } ) const {
220 BasicParsePolicy result = *this;
221 if( f ) {
222 result.first = f;
223 }
224 if( l ) {
225 result.last = l;
226 }
227 if( cf ) {
228 result.class_first = cf;
229 }
230 if( cl ) {
231 result.class_last = cl;
232 }
233 return result;
234 }
235
236 DAW_ATTRIB_INLINE constexpr decltype( auto ) get_allocator( ) const {
237 return json_details::AllocatorWrapper<Allocator>::get_allocator( );
238 }
239
240 template<typename Alloc>
242
243 template<typename Alloc>
244 [[nodiscard]] static constexpr with_allocator_type<Alloc>
246 Alloc const &alloc ) {
247 return with_allocator_type<Alloc>{ f, l, cf, cl, alloc };
248 }
249
250 [[nodiscard]] static constexpr BasicParsePolicy
252 json_details::NoAllocator const & ) {
253 return BasicParsePolicy( f, l, cf, cl );
254 }
255
256 template<typename Alloc>
257 [[nodiscard]] constexpr auto
259 if constexpr( std::is_same_v<Alloc, json_details::NoAllocator> ) {
260 return *this;
261 } else {
262 auto result = with_allocator(
263 first, last, class_first, class_last, p.get_allocator( ) );
264 result.counter = p.counter;
265 return result;
266 }
267 }
268
269 template<typename Alloc>
270 [[nodiscard]] constexpr with_allocator_type<Alloc>
271 with_allocator( Alloc const &alloc ) const {
272 auto result =
273 with_allocator( first, last, class_first, class_last, alloc );
274 result.counter = counter;
275 return result;
276 }
277
278 [[nodiscard]] DAW_ATTRIB_INLINE constexpr auto
279 with_allocator( json_details::NoAllocator const & ) const {
280 return *this;
281 }
282
285
286 template<typename Alloc>
287 [[nodiscard]] static constexpr with_allocator_type<Alloc>
288 with_allocator( iterator f, iterator l, Alloc const &alloc ) {
289 return with_allocator_type<Alloc>{ f, l, f, l, alloc };
290 }
291
292 template<typename Alloc>
293 [[nodiscard]] static constexpr BasicParsePolicy
295 json_details::NoAllocator const & ) {
296 return BasicParsePolicy{ f, l, f, l };
297 }
298
299 [[nodiscard]] DAW_ATTRIB_INLINE constexpr iterator data( ) const {
300 return first;
301 }
302
303 [[nodiscard]] DAW_ATTRIB_INLINE constexpr iterator data_end( ) const {
304 return last;
305 }
306
307 [[nodiscard]] DAW_ATTRIB_INLINE constexpr iterator begin( ) const {
308 return first;
309 }
310
311 [[nodiscard]] DAW_ATTRIB_INLINE constexpr iterator end( ) const {
312 return last;
313 }
314
315 [[nodiscard]] DAW_ATTRIB_INLINE constexpr bool empty( ) const {
316 if( not first ) {
317 return true;
318 }
319 if constexpr( is_zero_terminated_string ) {
320 return first >= last or *first == '\0';
321 } else {
322 return first >= last;
323 }
324 }
325
326 [[nodiscard]] DAW_ATTRIB_INLINE constexpr bool has_more( ) const {
327#if not defined( NDEBUG )
328 daw_json_ensure( first != nullptr and last != nullptr,
329 ErrorReason::InvalidNull );
330#endif
331 return first < last;
332 }
333
334 template<std::size_t N>
335 constexpr bool starts_with( char const ( &rhs )[N] ) const {
336 static_assert( N > 0 );
337 if( size( ) < ( N - 1 ) ) {
338 return false;
339 }
340 bool result = true;
341 for( std::size_t n = 0; n < ( N - 1 ); ++n ) {
342 result = result & ( first[n] == rhs[n] );
343 }
344 return result;
345 }
346
347 template<std::size_t N>
348 constexpr bool starts_with_skip( char const ( &rhs )[N] ) {
349 if( not starts_with( rhs ) ) {
350 return false;
351 }
352 first += static_cast<std::ptrdiff_t>( N - 1 );
353 return true;
354 }
355
356 template<char c>
357 DAW_ATTRIB_INLINE constexpr void move_to_next_of_unchecked( ) {
358 auto const position =
359 json_details::memchr_unchecked<c, exec_tag_t, expect_long_strings>(
360 daw::not_null<char const *>{ daw::never_null, first },
361 daw::not_null<char const *>{ daw::never_null, last } );
362 first = json_details::input_pointer( first, position.get( ) );
363 }
364
365 template<char c>
366 DAW_ATTRIB_INLINE constexpr void move_to_next_of_checked( ) {
367 auto const position =
368 json_details::memchr_checked<c, exec_tag_t, expect_long_strings>(
369 daw::not_null<char const *>{ first },
370 daw::not_null<char const *>{ last } );
371 first = json_details::input_pointer( first, position.get( ) );
372 }
373
374 template<char c>
375 DAW_ATTRIB_INLINE constexpr void move_to_next_of( ) {
376 if( is_unchecked_input ) {
377 move_to_next_of_unchecked<c>( );
378 } else {
379 move_to_next_of_checked<c>( );
380 }
381 }
382
383 [[nodiscard]] DAW_ATTRIB_INLINE constexpr char front( ) const {
384 return *first;
385 }
386
387 [[nodiscard]] DAW_ATTRIB_INLINE constexpr char front_checked( ) const {
389 first < last, ErrorReason::UnexpectedEndOfData, *this );
390 return *first;
391 }
392
393 [[nodiscard]] DAW_ATTRIB_INLINE constexpr std::size_t size( ) const {
394 assert( last >= first );
395 return static_cast<std::size_t>( last - first );
396 }
397
398 [[nodiscard]] constexpr bool is_null( ) const {
399 return first == nullptr;
400 }
401
402 DAW_ATTRIB_INLINE constexpr void remove_prefix( ) {
403 ++first;
404 }
405
406 DAW_ATTRIB_INLINE constexpr void remove_prefix( std::size_t n ) {
407 first += static_cast<std::ptrdiff_t>( n );
408 }
409
410 constexpr void set_class_position( ) {
411 class_first = first;
412 class_last = last;
413 }
414
419
420 constexpr void set_class_position( class_pos_t new_pos ) {
421 class_first = new_pos.f;
422 class_last = new_pos.l;
423 }
424
425 [[nodiscard]] constexpr class_pos_t get_class_position( ) const {
426 return { class_first, class_last };
427 }
428
429 constexpr void trim_left_checked( ) {
430 return CommentPolicy::trim_left_checked( *this );
431 }
432
433 constexpr void trim_left_unchecked( ) {
434 return CommentPolicy::trim_left_unchecked( *this );
435 }
436
437 [[nodiscard]] constexpr bool is_literal_end( ) const {
438 return CommentPolicy::is_literal_end( *first );
439 }
440
441 [[nodiscard]] DAW_ATTRIB_INLINE constexpr bool
443 return ( static_cast<unsigned>( static_cast<unsigned char>( *first ) ) -
444 1U ) <= 0x1FU;
445 }
446
447 [[nodiscard]] constexpr bool is_opening_bracket_checked( ) const {
448 return DAW_LIKELY( first < last ) and *first == '[';
449 }
450
451 [[nodiscard]] constexpr bool is_opening_brace_checked( ) const {
452 return DAW_LIKELY( first < last ) and *first == '{';
453 }
454
455 [[nodiscard]] constexpr bool is_closing_brace_checked( ) const {
456 return DAW_LIKELY( first < last ) and *first == '}';
457 }
458
459 [[nodiscard]] constexpr bool is_quotes_checked( ) const {
460 return DAW_LIKELY( first < last ) and *first == '"';
461 }
462
463 DAW_ATTRIB_INLINE constexpr void trim_left( ) {
464 if constexpr( is_unchecked_input ) {
465 trim_left_unchecked( );
466 } else {
467 trim_left_checked( );
468 }
469 }
470
472 trim_left_unchecked( );
473 if( *first == ',' ) {
474 ++first;
475 trim_left_unchecked( );
476 }
477 }
478
479 DAW_ATTRIB_FLATINLINE constexpr void move_next_member_or_end_checked( ) {
480 trim_left_checked( );
481 if constexpr( is_zero_terminated_string ) {
482 if( *first == ',' ) {
483 ++first;
484 trim_left( );
485 }
486 } else {
487 if( DAW_LIKELY( first < last ) and *first == ',' ) {
488 ++first;
489 trim_left( );
490 }
491 }
492 }
493
494 DAW_ATTRIB_INLINE constexpr void move_next_member_or_end( ) {
495 if constexpr( is_unchecked_input ) {
496 move_next_member_or_end_unchecked( );
497 } else {
498 move_next_member_or_end_checked( );
499 }
500 }
501
502 DAW_ATTRIB_INLINE constexpr void move_next_member( ) {
503 if constexpr( is_unchecked_input ) {
504 CommentPolicy::move_next_member_unchecked( *this );
505 } else {
506 // We have no guarantee that all members are available
507 move_next_member_or_end_checked( );
508 }
509 }
510
511 constexpr void move_to_next_class_member( ) {
512 CommentPolicy::template move_to_next_of<'"', '}'>( *this );
513 }
514
515 [[nodiscard]] constexpr bool is_at_next_class_member( ) const {
516 return parse_policy_details::in<'"', '}'>( *first );
517 }
518
519 [[nodiscard]] constexpr bool is_at_next_array_element( ) const {
520 return parse_policy_details::in<',', ']'>( *first );
521 }
522
523 [[nodiscard]] constexpr bool is_at_token_after_value( ) const {
524 return parse_policy_details::in<',', '}', ']'>( *first );
525 }
526
527 template<json_details::SkipBracketedType BracketedType>
528 [[nodiscard]] DAW_ATTRIB_INLINE constexpr BasicParsePolicy
530 return CommentPolicy::template skip_bracketed_item_checked<
531 BracketedType>( *this );
532 }
533
534 template<json_details::SkipBracketedType BracketedType>
535 [[nodiscard]] DAW_ATTRIB_INLINE constexpr BasicParsePolicy
537 return CommentPolicy::template skip_bracketed_item_unchecked<
538 BracketedType>( *this );
539 }
540
541 [[nodiscard]] DAW_ATTRIB_INLINE constexpr BasicParsePolicy skip_class( ) {
542#if defined( DAW_JSON_HAS_STD_SIMD )
543 if constexpr( std::is_same_v<CommentPolicy, NoCommentSkippingPolicy> ) {
544 return json_details::skip_bracketed_item_simd<
545 json_details::SkipBracketedType::Class>( *this );
546 } else
547#elif defined( DAW_JSON_HAS_SIMD )
548 if constexpr( std::is_same_v<CommentPolicy, NoCommentSkippingPolicy> ) {
549 if( not DAW_IS_CONSTANT_EVALUATED_COMPAT( ) ) {
550 return json_details::skip_bracketed_item_simd<
551 json_details::SkipBracketedType::Class>( *this );
552 }
553 }
554#endif
555 if constexpr( is_unchecked_input ) {
556 return skip_bracketed_item_unchecked<
557 json_details::SkipBracketedType::Class>( );
558 } else {
559 return skip_bracketed_item_checked<
560 json_details::SkipBracketedType::Class>( );
561 }
562 }
563
564 [[nodiscard]] DAW_ATTRIB_INLINE constexpr BasicParsePolicy skip_array( ) {
565#if defined( DAW_JSON_HAS_STD_SIMD )
566 if constexpr( std::is_same_v<CommentPolicy, NoCommentSkippingPolicy> ) {
567 return json_details::skip_bracketed_item_simd<
568 json_details::SkipBracketedType::Array>( *this );
569 } else
570#elif defined( DAW_JSON_HAS_SIMD )
571 if constexpr( std::is_same_v<CommentPolicy, NoCommentSkippingPolicy> ) {
572 if( not DAW_IS_CONSTANT_EVALUATED_COMPAT( ) ) {
573 return json_details::skip_bracketed_item_simd<
574 json_details::SkipBracketedType::Array>( *this );
575 }
576 }
577#endif
578 if constexpr( is_unchecked_input ) {
579 return skip_bracketed_item_unchecked<
580 json_details::SkipBracketedType::Array>( );
581 } else {
582 return skip_bracketed_item_checked<
583 json_details::SkipBracketedType::Array>( );
584 }
585 }
586 };
587
589
590 BasicParsePolicy( char const *, char const * ) -> BasicParsePolicy<>;
592
593 template<typename Allocator>
594 BasicParsePolicy( char const *, char const *, Allocator const & )
596 template<typename Allocator>
597 BasicParsePolicy( char *, char *, Allocator const & )
599
600 BasicParsePolicy( char const *, char const *, char const *, char const * )
602 BasicParsePolicy( char *, char *, char *, char * ) -> BasicParsePolicy<>;
603
604 template<typename Allocator>
605 BasicParsePolicy( char const *, char const *, char const *, char const *,
606 Allocator const & )
608 template<typename Allocator>
609 BasicParsePolicy( char *, char *, char *, char *, Allocator const & )
611
613 : BasicParsePolicy<json_details::default_policy_flag,
614 json_details::NoAllocator> {
615
616 using BasicParsePolicy::BasicParsePolicy;
617
618 constexpr DefaultParsePolicy( BasicParsePolicy const &other ) noexcept
619 : BasicParsePolicy( other ) {}
620 constexpr DefaultParsePolicy( BasicParsePolicy &&other ) noexcept
621 : BasicParsePolicy( std::move( other ) ) {}
622 };
623
624 template<json_options_t PolicyFlags = json_details::default_policy_flag,
625 typename Allocator = json_details::NoAllocator>
627 daw::conditional_t<(PolicyFlags == json_details::default_policy_flag and
628 std::is_same_v<Allocator, json_details::NoAllocator>),
631 template<typename ParsePolicy>
633 daw::conditional_t<ParsePolicy::is_default_parse_policy,
634 DefaultParsePolicy, ParsePolicy>;
635
636 namespace options {
637 /***
638 * @brief Specify parse policy flags in to_json calls. See cookbook item
639 * parse_options.md
640 */
641 template<auto... PolicyFlags>
643 static_assert(
644 json_details::are_option_flags<decltype( PolicyFlags )...>,
645 "Only registered policy types are allowed" );
646 static constexpr json_options_t value = parse_options( PolicyFlags... );
647 };
648 template<>
649 struct parse_flags_t<> {
650 static constexpr json_options_t value =
651 json_details::default_policy_flag;
652 };
653
654 namespace details {
655 template<typename... Ts>
656 std::false_type is_policy_flag( Ts... );
657
658 template<auto... PolicyFlags>
660
661 template<auto... PolicyFlags>
662 DAW_CONSTEVAL auto make_parse_flags( ) {
663 if constexpr( decltype( details::is_policy_flag(
664 PolicyFlags... ) )::value ) {
665 static_assert( sizeof...( PolicyFlags ) == 1 );
666 // We know there is only one but need to unpack
667 return ( PolicyFlags, ... );
668 } else {
669 return parse_flags_t<PolicyFlags...>{ };
670 }
671 }
672 } // namespace details
677 template<auto... PolicyFlags>
678 inline constexpr auto parse_flags =
679 details::make_parse_flags<PolicyFlags...>( );
680 } // namespace options
681
682#define DAW_JSON_CONFORMANCE_FLAGS \
683 daw::json::options::AllowEscapedNames::yes, \
684 daw::json::options::MustVerifyEndOfDataIsValid::yes, \
685 daw::json::options::IEEE754Precise::yes, \
686 daw::json::options::ExcludeSpecialEscapes::yes
687
688 inline constexpr auto ConformancePolicy =
689 options::parse_flags<DAW_JSON_CONFORMANCE_FLAGS>;
690
691 } // namespace DAW_JSON_VER
692} // 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
string_writer grows its string with resize_and_overwrite, leaving the new bytes uninitialized,...
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
std::conditional_t< allow_string_mutation, char *, char const * > iterator
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20