18 #include <daw/daw_arith_traits.h>
19 #include <daw/daw_parser_helper_sv.h>
20 #include <daw/daw_string_view.h>
21 #include <daw/daw_traits.h>
27 #if defined( __cpp_constexpr_dynamic_alloc )
28 #define CPP20CONSTEXPR constexpr
29 #define HAS_CPP20CONSTEXPR
31 #define CPP20CONSTEXPR
40 template<
typename... Members>
42 std::tuple<
typename Members::parse_to_t...>
members;
44 template<
typename... Ts>
46 :
members{ std::forward<Ts>( values )... } {}
50 namespace daw::json::json_details {
52 using json_type_t =
typename T::i_am_a_json_type;
55 inline constexpr
bool is_a_json_type_v = daw::is_detected_v<json_type_t, T>;
58 using ordered_member_t =
typename T::i_am_an_ordered_member;
61 inline constexpr
bool is_an_ordered_member_v =
62 daw::is_detected_v<ordered_member_t, T>;
65 using is_a_json_tagged_variant_test =
typename T::i_am_a_json_tagged_variant;
68 inline constexpr
bool is_a_json_tagged_variant_v =
69 daw::is_detected_v<is_a_json_tagged_variant_test, T>;
71 template<
typename T,
bool = false>
72 struct ordered_member_subtype {
77 struct ordered_member_subtype<T, true> {
78 using type =
typename T::json_member;
82 using ordered_member_subtype_t =
83 typename ordered_member_subtype<T, is_an_ordered_member_v<T>>::type;
86 using json_data_contract_trait_t =
89 template<
typename T,
bool,
bool>
90 struct json_data_constract_constructor_impl {
91 using type = default_constructor<T>;
95 using has_json_data_constract_constructor_test =
96 typename json_data_contract_trait_t<T>::constructor;
99 struct json_data_constract_constructor_impl<T, true, true> {
100 using type =
typename json_data_contract_trait_t<T>::constructor;
104 using json_data_contract_constructor_t =
105 typename json_data_constract_constructor_impl<
106 T, daw::is_detected_v<json_data_contract_trait_t, T>,
107 daw::is_detected_v<has_json_data_constract_constructor_test, T>>::type;
110 using json_class_constructor_t =
111 std::conditional_t<daw::is_detected_v<json_data_contract_constructor_t, T>,
112 json_data_contract_constructor_t<T>,
113 default_constructor<T>>;
116 inline constexpr
auto json_class_constructor = json_class_constructor_t<T>{ };
118 template<
typename Value,
typename Constructor,
typename Range,
120 DAW_ATTRIBUTE_FLATTEN
static inline constexpr
auto
121 construct_value( Constructor &&ctor, Range &rng, Args &&...args ) {
122 if constexpr( Range::has_allocator ) {
123 using alloc_t =
typename Range::template allocator_type_as<Value>;
124 auto alloc = rng.template get_allocator_for<Value>( );
125 if constexpr( std::is_invocable_v<Constructor, Args..., alloc_t> ) {
126 return ctor( std::forward<Args>( args )..., std::move( alloc ) );
127 }
else if constexpr( daw::traits::is_callable_v<Constructor,
128 std::allocator_arg_t,
129 alloc_t, Args...> ) {
130 return ctor( std::allocator_arg, std::move( alloc ),
131 std::forward<Args>( args )... );
133 static_assert( std::is_invocable_v<Constructor, Args...> );
134 return ctor( std::forward<Args>( args )... );
137 static_assert( std::is_invocable_v<Constructor, Args...> );
138 if constexpr( std::is_invocable_v<Constructor, Args...> ) {
139 return ctor( std::forward<Args>( args )... );
144 template<
typename Allocator>
145 using has_allocate_test =
146 decltype( std::declval<Allocator>( ).allocate(
size_t{ 1 } ) );
148 template<
typename Allocator>
149 using has_deallocate_test = decltype( std::declval<Allocator>( ).deallocate(
150 static_cast<void *
>(
nullptr ),
size_t{ 1 } ) );
152 template<
typename Allocator>
153 inline constexpr
bool is_allocator_v =
154 daw::is_detected_v<has_allocate_test, Allocator>
155 and daw::is_detected_v<has_deallocate_test, Allocator>;
158 struct has_json_data_contract_trait
159 : std::bool_constant<
160 not std::is_same_v<daw::json::missing_json_data_contract_for<T>,
161 json_data_contract_trait_t<T>>> {};
164 inline constexpr
bool has_json_data_contract_trait_v =
165 has_json_data_contract_trait<T>::value;
167 template<
typename Container,
typename Value>
168 using detect_push_back = decltype( std::declval<Container &>( ).push_back(
169 std::declval<Value>( ) ) );
171 template<
typename Container,
typename Value>
172 using detect_insert_end = decltype( std::declval<Container &>( ).insert(
173 std::end( std::declval<Container &>( ) ), std::declval<Value>( ) ) );
175 template<
typename Container,
typename Value>
176 inline constexpr
bool has_push_back_v =
177 daw::is_detected_v<detect_push_back, Container, Value>;
179 template<
typename Container,
typename Value>
180 inline constexpr
bool has_insert_end_v =
181 daw::is_detected_v<detect_insert_end, Container, Value>;
183 template<
typename JsonMember>
184 using json_result =
typename JsonMember::parse_to_t;
186 template<
typename JsonMember>
187 using json_base_type =
typename JsonMember::base_type;
189 template<std::size_t I,
typename... JsonMembers>
190 using json_result_n =
191 json_result<daw::traits::nth_element<I, JsonMembers...>>;
193 template<
typename Container>
194 struct basic_appender {
195 using value_type =
typename Container::value_type;
196 using reference = value_type;
197 using pointer = value_type
const *;
198 using difference_type = std::ptrdiff_t;
199 using iterator_category = std::output_iterator_tag;
200 Container *m_container;
202 explicit inline constexpr basic_appender( Container &container )
203 : m_container( &container ) {}
205 template<
typename Value>
206 inline constexpr
void operator( )( Value &&value )
const {
207 if constexpr( has_push_back_v<Container, daw::remove_cvref_t<Value>> ) {
208 m_container->push_back( std::forward<Value>( value ) );
209 }
else if constexpr( has_insert_end_v<Container,
210 daw::remove_cvref_t<Value>> ) {
211 m_container->insert( std::end( *m_container ),
212 std::forward<Value>( value ) );
215 has_push_back_v<Container, daw::remove_cvref_t<Value>> or
216 has_insert_end_v<Container, daw::remove_cvref_t<Value>>,
217 "basic_appender requires a Container that either has push_back or "
218 "insert with the end iterator as first argument" );
222 template<
typename Value,
224 not std::is_same_v<basic_appender, daw::remove_cvref_t<Value>>,
225 std::nullptr_t> =
nullptr>
226 inline constexpr basic_appender &operator=( Value &&v ) {
227 operator( )( std::forward<Value>( v ) );
231 inline constexpr basic_appender &operator++( ) {
235 inline constexpr basic_appender operator++(
int )
const {
239 inline constexpr basic_appender &operator*( ) {
245 using json_parser_to_json_data_t =
247 std::declval<T &>( ) ) );
250 static inline constexpr
bool has_json_to_json_data_v =
251 daw::is_detected_v<json_parser_to_json_data_t, T>;
254 using is_submember_tagged_variant_t =
255 typename json_data_contract<T>::type::i_am_a_submember_tagged_variant;
258 static inline constexpr
bool is_submember_tagged_variant_v =
259 daw::is_detected_v<is_submember_tagged_variant_t, T>;
263 #if defined( __cpp_nontype_template_parameter_class ) and \
264 not defined( DAW_JSON_NO_CPP_NAMES )
271 template<std::
size_t N>
273 static_assert( N > 0 );
274 char const m_data[N]{ };
277 template<std::size_t... Is>
278 constexpr json_name(
char const ( &ptr )[N], std::index_sequence<Is...> )
279 : m_data{ ptr[Is]... } {}
282 constexpr json_name(
char const ( &ptr )[N] )
283 : json_name( ptr, std::make_index_sequence<N>{ } ) {}
285 constexpr
operator daw::string_view( )
const {
286 return { m_data, N - 1 };
290 [[nodiscard]] constexpr
char const *begin( )
const {
295 [[nodiscard]] constexpr
char const *end( )
const {
296 return m_data +
static_cast<ptrdiff_t
>( size( ) );
299 [[nodiscard]]
static constexpr std::size_t size( ) {
303 template<std::
size_t M>
304 constexpr
bool operator==( json_name<M>
const &rhs )
const {
308 for( std::size_t n = 0; n < N; ++n ) {
309 if( m_data[n] != rhs.m_data[n] ) {
316 constexpr
bool operator==( daw::string_view rhs )
const {
317 return daw::string_view( m_data, N - 1 ) == rhs;
320 constexpr
bool operator==( std::string_view rhs )
const {
321 return std::string_view( m_data, N - 1 ) == rhs;
324 constexpr
operator std::string_view( )
const {
325 return std::string_view( m_data, N - 1 );
328 template<
typename... Chars>
329 json_name( Chars... ) -> json_name<
sizeof...( Chars )>;
331 template<std::
size_t N>
332 json_name(
char const ( & )[N] ) -> json_name<N>;
334 #define JSONNAMETYPE daw::json::json_name
338 namespace json_details {
339 inline constexpr
JSONNAMETYPE default_key_name{
"key" };
340 inline constexpr
JSONNAMETYPE default_value_name{
"value" };
343 template<
typename JsonMember>
346 #define JSONNAMETYPE char const *
349 namespace json_details {
351 inline constexpr
char const default_key_name[] =
"key";
352 inline constexpr
char const default_value_name[] =
"value";
356 template<
typename JsonMember>
391 case JsonBaseParseTypes::Number:
393 case JsonBaseParseTypes::Bool:
395 case JsonBaseParseTypes::String:
397 case JsonBaseParseTypes::Class:
399 case JsonBaseParseTypes::Array:
401 case JsonBaseParseTypes::Null:
423 template<JsonParseTypes ParseType, JsonNullable Nullable>
425 Nullable == JsonNullable::Never ? ParseType : JsonParseTypes::Null;
427 namespace json_details {
429 inline constexpr std::size_t parse_space_needed_v = 1U;
432 inline constexpr std::size_t parse_space_needed_v<simd_exec_tag> = 16U;
434 template<
typename JsonType>
435 static inline constexpr
bool is_json_nullable_v =
436 JsonType::expected_type == JsonParseTypes::Null;
439 [[maybe_unused]]
auto dereffed_type_impl( daw::tag_t<T> )
440 -> decltype( *( std::declval<T &>( ) ) );
443 using dereffed_type =
444 daw::remove_cvref_t<decltype( dereffed_type_impl( daw::tag<T> ) )>;
446 template<
typename T, JsonNullable Nullable>
447 using unwrap_type = std::conditional_t<
448 std::conjunction_v<std::bool_constant<Nullable == JsonNullable::Nullable>,
449 daw::is_detected<dereffed_type, T>>,
450 daw::detected_t<dereffed_type, T>, T>;
453 using can_deref = daw::is_detected<dereffed_type, T>;
456 using cant_deref = daw::not_trait<can_deref<T>>;
459 inline constexpr
bool can_deref_v = can_deref<T>::value;
463 static_assert( daw::is_arithmetic_v<T>,
"Unexpected non-number" );
464 if constexpr( daw::is_floating_point_v<T> ) {
465 return JsonParseTypes::Real;
466 }
else if constexpr( daw::is_signed_v<T> ) {
467 return JsonParseTypes::Signed;
468 }
else if constexpr( daw::is_unsigned_v<T> ) {
469 return JsonParseTypes::Unsigned;
474 constexpr
auto number_parse_type_test( )
477 return number_parse_type_impl_v<std::underlying_type_t<T>>;
480 constexpr
auto number_parse_type_test( )
483 return number_parse_type_impl_v<T>;
487 number_parse_type_v = number_parse_type_test<T>( );
494 template<JsonParseTypes v>
495 using ParseTag = std::integral_constant<JsonParseTypes, v>;
519 namespace daw::json::json_details {
524 template<
typename Range>
525 [[nodiscard]] DAW_ATTRIBUTE_FLATTEN
static inline constexpr Range
526 skip_string_nq( Range &rng ) {
528 result.counter = string_quote::string_quote_parser::parse_nq( rng );
532 result.last = rng.first;
533 rng.remove_prefix( );
540 template<
typename Range>
541 [[nodiscard]] DAW_ATTRIBUTE_FLATTEN
static inline constexpr Range
542 skip_string( Range &rng ) {
546 if( *std::prev( rng.first ) !=
'"' ) {
547 daw_json_assert( rng.front( ) ==
'"', ErrorReason::InvalidString, rng );
548 rng.remove_prefix( );
551 return skip_string_nq( rng );
554 template<
typename Range>
555 [[nodiscard]]
static constexpr Range skip_true( Range &rng ) {
557 if constexpr( Range::is_unchecked_input ) {
558 rng.remove_prefix( 4 );
560 rng.remove_prefix( );
563 rng.remove_prefix( 3 );
565 result.last = rng.first;
568 ErrorReason::InvalidEndOfValue, rng );
572 template<
typename Range>
573 [[nodiscard]]
static constexpr Range skip_false( Range &rng ) {
575 if constexpr( Range::is_unchecked_input ) {
576 rng.remove_prefix( 5 );
578 rng.remove_prefix( );
581 rng.remove_prefix( 4 );
583 result.last = rng.first;
586 ErrorReason::InvalidEndOfValue, rng );
590 template<
typename Range>
591 [[nodiscard]]
static constexpr Range skip_null( Range &rng ) {
592 if constexpr( Range::is_unchecked_input ) {
593 rng.remove_prefix( 4 );
595 rng.remove_prefix( );
598 rng.remove_prefix( 3 );
604 ErrorReason::UnexpectedEndOfData, rng );
606 result.first =
nullptr;
607 result.last =
nullptr;
611 template<
bool is_unchecked_input>
612 DAW_ATTRIBUTE_FLATTEN [[nodiscard]]
static inline constexpr
char const *
613 skip_digits(
char const *first,
char const *
const last ) {
617 unsigned dig = parse_digit( *first );
620 if constexpr( not is_unchecked_input ) {
625 dig = parse_digit( *first );
633 template<
typename Range>
634 [[nodiscard]]
static constexpr Range skip_number( Range &rng ) {
636 char const *first = rng.first;
637 char const *
const last = rng.last;
639 if( *first ==
'-' ) {
642 first = skip_digits<Range::is_unchecked_input>( first, last );
643 char const *decimal =
nullptr;
644 if( ( Range::is_unchecked_input or first < last ) and ( *first ==
'.' ) ) {
647 first = skip_digits<Range::is_unchecked_input>( first, last );
649 char const *exp =
nullptr;
650 unsigned dig = parse_digit( *first );
651 if( ( Range::is_unchecked_input or ( first < last ) ) &
652 ( ( dig == parsed_constants::e_char ) |
653 ( dig == parsed_constants::E_char ) ) ) {
662 dig = parse_digit( *first );
663 if( ( dig == parsed_constants::plus_char ) |
664 ( dig == parsed_constants::minus_char ) ) {
667 first = skip_digits<Range::is_unchecked_input>( first, last );
672 result.class_first = decimal;
673 result.class_last = exp;
683 template<
typename Range>
684 [[nodiscard]]
static inline constexpr Range skip_value( Range &rng ) {
690 switch( rng.front( ) ) {
692 return skip_string( rng );
694 return rng.skip_array( );
696 return rng.skip_class( );
698 return skip_true( rng );
700 return skip_false( rng );
702 return skip_null( rng );
714 return skip_number( rng );
716 if constexpr( Range::is_unchecked_input ) {
727 template<
typename JsonMember,
typename Range>
728 [[nodiscard]] DAW_ATTRIBUTE_FLATTEN
inline constexpr Range
729 skip_known_value( Range &rng ) {
732 if constexpr( JsonMember::expected_type == JsonParseTypes::Date or
733 JsonMember::expected_type == JsonParseTypes::StringRaw or
734 JsonMember::expected_type == JsonParseTypes::StringEscaped or
735 JsonMember::expected_type == JsonParseTypes::Custom ) {
739 rng.remove_prefix( );
740 return json_details::skip_string_nq( rng );
741 }
else if constexpr( JsonMember::expected_type == JsonParseTypes::Real or
742 JsonMember::expected_type == JsonParseTypes::Signed or
743 JsonMember::expected_type ==
744 JsonParseTypes::Unsigned or
745 JsonMember::expected_type == JsonParseTypes::Bool or
746 JsonMember::expected_type == JsonParseTypes::Null ) {
748 return json_details::skip_number( rng );
749 }
else if constexpr( JsonMember::expected_type == JsonParseTypes::Array ) {
751 ErrorReason::InvalidArrayStart, rng );
752 return rng.skip_array( );
753 }
else if constexpr( JsonMember::expected_type == JsonParseTypes::Class ) {
755 ErrorReason::InvalidClassStart, rng );
756 return rng.skip_class( );
759 static_assert( JsonMember::expected_type == JsonParseTypes::Class,
760 "Unknown JsonParseTypes value. This is a programmer "
761 "error and the preceding did not check for it" );