15 #include <daw/daw_algorithm.h>
16 #include <daw/daw_arith_traits.h>
17 #include <daw/daw_bounded_vector.h>
18 #include <daw/daw_traits.h>
19 #include <utf8/unchecked.h>
25 #ifndef DAW_JSON_CUSTOM_D2S
26 #include <third_party/dragonbox/dragonbox.h>
27 #elif __has_include( "custom_d2s.h" )
28 #include "custom_d2s.h"
30 #error Request for local d2s, but no custom_d2s.h supplied with char * d2s( Real const & value, char * ); declaration/definition in namespace daw::json
33 #include <type_traits>
37 template<
typename Real,
typename OutputIterator>
39 OutputIterator out_it ) {
40 #ifndef DAW_JSON_CUSTOM_D2S
41 if constexpr( std::is_same_v<Real, float> ) {
42 return jkj::dragonbox::to_chars_n( value, out_it );
44 return jkj::dragonbox::to_chars_n(
static_cast<double>( value ), out_it );
47 if constexpr( std::is_same_v<Real, float> ) {
48 return daw::json::d2s( value, out_it );
50 return daw::json::d2s(
static_cast<double>( value ), out_it );
56 namespace daw::json::json_details::to_strings {
59 namespace to_string_test {
61 [[maybe_unused]]
auto to_string_test( T &&v )
62 -> decltype(
to_string( std::forward<T>( v ) ) );
65 using to_string_result = decltype( to_string_test( std::declval<T>( ) ) );
69 using has_to_string = daw::is_detected<to_string_test::to_string_result, T>;
72 inline constexpr
bool has_to_string_v = has_to_string<T>::value;
75 [[nodiscard, maybe_unused]]
auto to_string( std::optional<T>
const &v )
89 std::enable_if_t<json_details::to_strings::has_to_string_v<U>,
90 std::nullptr_t> =
nullptr>
91 [[nodiscard]]
inline constexpr decltype(
auto )
92 operator( )( U &&value )
const {
94 return to_string( std::forward<U>( value ) );
98 std::enable_if_t<not json_details::to_strings::has_to_string_v<U>,
99 std::nullptr_t> =
nullptr>
100 [[nodiscard]]
inline std::string operator( )( U &&value )
const {
101 std::stringstream ss;
102 ss << std::forward<U>( value );
108 namespace daw::json::json_details {
109 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
110 [[nodiscard]]
inline OutputIterator constexpr
to_string(
111 ParseTag<JsonParseTypes::Null>, OutputIterator it,
112 parse_to_t
const &container );
114 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
115 [[nodiscard]] constexpr OutputIterator
116 to_string( ParseTag<JsonParseTypes::Array>, OutputIterator it,
117 parse_to_t
const &value );
119 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
120 [[nodiscard]] constexpr OutputIterator
121 to_string( ParseTag<JsonParseTypes::KeyValueArray>, OutputIterator it,
122 parse_to_t
const &value );
124 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
125 [[nodiscard]] constexpr OutputIterator
126 to_string( ParseTag<JsonParseTypes::KeyValue>, OutputIterator it,
127 parse_to_t
const &value );
129 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
130 [[nodiscard]] constexpr OutputIterator
131 to_string( ParseTag<JsonParseTypes::Custom>, OutputIterator it,
132 parse_to_t
const &value );
134 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
135 [[nodiscard]] constexpr OutputIterator
136 to_string( ParseTag<JsonParseTypes::Variant>, OutputIterator it,
137 parse_to_t
const &value );
139 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
140 [[nodiscard]] constexpr OutputIterator
141 to_string( ParseTag<JsonParseTypes::Class>, OutputIterator it,
142 parse_to_t
const &value );
144 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
145 [[nodiscard]] OutputIterator
to_string( ParseTag<JsonParseTypes::Real>,
147 parse_to_t
const &value );
149 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
150 [[nodiscard]] constexpr OutputIterator
151 to_string( ParseTag<JsonParseTypes::Signed>, OutputIterator it,
152 parse_to_t
const &value );
154 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
155 [[nodiscard]] constexpr OutputIterator
156 to_string( ParseTag<JsonParseTypes::Unsigned>, OutputIterator it,
157 parse_to_t
const &value );
159 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
160 [[nodiscard]] constexpr OutputIterator
161 to_string( ParseTag<JsonParseTypes::StringRaw>, OutputIterator it,
162 parse_to_t
const &value );
164 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
165 [[nodiscard]] constexpr OutputIterator
166 to_string( ParseTag<JsonParseTypes::StringEscaped>, OutputIterator it,
167 parse_to_t
const &value );
169 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
170 [[nodiscard]] constexpr OutputIterator
171 to_string( ParseTag<JsonParseTypes::Date>, OutputIterator it,
172 parse_to_t
const &value );
174 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
175 [[nodiscard]] constexpr OutputIterator
176 to_string( ParseTag<JsonParseTypes::Bool>, OutputIterator it,
177 parse_to_t
const &value );
180 template<
typename Char>
181 constexpr
char to_nibble_char( Char c ) {
184 return static_cast<char>( c +
'0' );
186 return static_cast<char>( ( c - 10U ) +
'A' );
190 template<
typename OutputIterator>
191 constexpr OutputIterator output_hex( std::uint16_t c, OutputIterator it ) {
192 char const nibbles[] = {
'\\',
194 to_nibble_char( ( c >> 12U ) & 0xFU ),
195 to_nibble_char( ( c >> 8U ) & 0xFU ),
196 to_nibble_char( ( c >> 4U ) & 0xFU ),
197 to_nibble_char( c & 0xFU ) };
208 template<
typename OutputIterator>
209 constexpr
void utf32_to_utf8( std::uint32_t cp, OutputIterator &it ) {
211 *it++ =
static_cast<char>( cp );
215 *it++ =
static_cast<char>( ( cp >> 6U ) | 0b11000000U );
216 *it++ =
static_cast<char>( ( cp & 0b00111111U ) | 0b10000000U );
219 if( cp <= 0xFFFFU ) {
220 *it++ =
static_cast<char>( ( cp >> 12U ) | 0b11100000U );
221 *it++ =
static_cast<char>( ( ( cp >> 6U ) & 0b00111111U ) | 0b10000000U );
222 *it++ =
static_cast<char>( ( cp & 0b00111111U ) | 0b10000000U );
225 if( cp <= 0x10FFFFU ) {
226 *it++ =
static_cast<char>( ( cp >> 18U ) | 0b11110000U );
228 static_cast<char>( ( ( cp >> 12U ) & 0b00111111U ) | 0b10000000U );
229 *it++ =
static_cast<char>( ( ( cp >> 6U ) & 0b00111111U ) | 0b10000000U );
230 *it++ =
static_cast<char>( ( cp & 0b00111111U ) | 0b10000000U );
238 template<
bool do_escape =
false,
240 typename OutputIterator,
typename Container,
241 daw::enable_when_t<daw::traits::is_container_like_v<
242 daw::remove_cvref_t<Container>>> =
nullptr>
243 [[nodiscard]] constexpr OutputIterator
245 if constexpr( do_escape ) {
246 using iter = daw::remove_cvref_t<decltype( std::begin( container ) )>;
247 using it_t = utf8::unchecked::iterator<iter>;
248 auto first = it_t( std::begin( container ) );
249 auto const last = it_t( std::end( container ) );
250 while( first != last ) {
251 auto const cp = *first++;
284 json_details::output_hex(
static_cast<std::uint16_t
>( cp ), it );
287 if constexpr( EightBitMode == EightBitModes::DisallowHigh ) {
288 if( cp >= 0x7FU and cp <= 0xFFFFU ) {
289 it = json_details::output_hex(
static_cast<std::uint16_t
>( cp ),
294 it = json_details::output_hex(
295 static_cast<std::uint16_t
>( 0xD7C0U + ( cp >> 10U ) ), it );
296 it = json_details::output_hex(
297 static_cast<std::uint16_t
>( 0xDC00U + ( cp & 0x3FFU ) ), it );
301 json_details::utf32_to_utf8( cp, it );
306 for(
auto c : container ) {
307 if constexpr( EightBitMode == EightBitModes::DisallowHigh ) {
309 static_cast<unsigned char>( c ) <= 0x7FU ),
310 ErrorReason::InvalidStringHighASCII );
318 template<
bool do_escape =
false,
320 typename OutputIterator>
323 if( ptr ==
nullptr ) {
326 if constexpr( do_escape ) {
328 auto chr_it = utf8::unchecked::iterator<char const *>( ptr );
329 while( *chr_it.base( ) !=
'\0' ) {
330 auto const cp = *chr_it++;
363 json_details::output_hex(
static_cast<std::uint16_t
>( cp ), it );
366 if constexpr( EightBitMode == EightBitModes::DisallowHigh ) {
367 if( cp >= 0x7FU and cp <= 0xFFFFU ) {
368 it = json_details::output_hex(
static_cast<std::uint16_t
>( cp ),
373 it = json_details::output_hex(
374 static_cast<std::uint16_t
>( 0xD7C0U + ( cp >> 10U ) ), it );
376 static_cast<std::uint16_t
>( 0xDC00U + ( cp & 0x3FFU ) ), it );
380 json_details::utf32_to_utf8( cp, it );
385 while( *ptr !=
'\0' ) {
386 if constexpr( EightBitMode == EightBitModes::DisallowHigh ) {
388 static_cast<unsigned>( *ptr ) <= 0x7FU ),
389 ErrorReason::InvalidStringHighASCII );
397 template<
bool do_escape =
false,
399 typename OutputIterator,
typename Range>
400 [[nodiscard]] constexpr OutputIterator
403 return copy_to_iterator<do_escape, EightBitMode>( it,
"null" );
405 return copy_to_iterator<do_escape, EightBitMode>( it,
411 namespace daw::json::json_details {
412 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
413 [[nodiscard]] constexpr OutputIterator
414 to_string( ParseTag<JsonParseTypes::Bool>, OutputIterator it,
415 parse_to_t
const &value ) {
417 if constexpr( JsonMember::literal_as_string ==
426 if constexpr( JsonMember::literal_as_string ==
433 template<std::size_t idx,
typename JsonMembers,
typename OutputIterator,
435 constexpr
void to_variant_string( OutputIterator &it,
436 parse_to_t
const &value ) {
437 if constexpr( idx < std::variant_size_v<parse_to_t> ) {
438 if( value.index( ) != idx ) {
439 to_variant_string<idx + 1, JsonMembers>( it, value );
442 using element_t =
typename JsonMembers::json_elements;
444 typename std::tuple_element<idx,
445 typename element_t::element_map_t>::type;
446 it = to_string<JsonMember>( ParseTag<JsonMember::base_expected_type>{ },
447 it, std::get<idx>( value ) );
451 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
452 [[nodiscard]]
inline constexpr OutputIterator
453 to_string( ParseTag<JsonParseTypes::Variant>, OutputIterator it,
454 parse_to_t
const &value ) {
456 to_variant_string<0, JsonMember>( it, value );
460 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
461 [[nodiscard]]
inline constexpr OutputIterator
462 to_string( ParseTag<JsonParseTypes::VariantTagged>, OutputIterator it,
463 parse_to_t
const &value ) {
465 to_variant_string<0, JsonMember>( it, value );
470 [[maybe_unused]] constexpr
auto deref_detect( T &&value )
471 -> decltype( *value );
473 [[maybe_unused]]
inline constexpr
void deref_detect( ... ) {}
477 daw::remove_cvref_t<decltype( deref_detect( std::declval<T>( ) ) )>;
479 template<
typename Optional>
480 inline constexpr
bool is_valid_optional_v =
481 daw::is_detected_v<deref_t, Optional>;
483 template<
typename JsonMember,
typename OutputIterator,
typename Optional>
484 [[nodiscard]]
inline constexpr OutputIterator
485 to_string( ParseTag<JsonParseTypes::Null>, OutputIterator it,
486 Optional
const &value ) {
487 static_assert( is_valid_optional_v<Optional> );
489 using tag_type = ParseTag<JsonMember::base_expected_type>;
490 return to_string<JsonMember>( tag_type{ }, it, *value );
493 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
494 [[nodiscard]]
inline OutputIterator
to_string( ParseTag<JsonParseTypes::Real>,
496 parse_to_t
const &value ) {
499 std::is_convertible_v<parse_to_t, typename JsonMember::parse_to_t>,
500 "value must be convertible to specified type in class contract" );
502 if constexpr( std::is_floating_point_v<typename JsonMember::parse_to_t> ) {
503 if( std::isnan( value ) ) {
504 if constexpr( JsonMember::literal_as_string ==
505 LiteralAsStringOpt::Never ) {
513 }
else if( std::isinf( value ) ) {
514 if constexpr( JsonMember::literal_as_string ==
515 LiteralAsStringOpt::Never ) {
526 if constexpr( JsonMember::literal_as_string ==
530 if constexpr( daw::is_floating_point_v<parse_to_t> ) {
531 static_assert(
sizeof( parse_to_t ) <=
sizeof(
double ) );
532 if constexpr( std::is_same_v<OutputIterator, char *> ) {
539 std::copy( buff, ptr, it );
542 using std::to_string;
543 using to_strings::to_string;
546 if constexpr( JsonMember::literal_as_string ==
553 template<
typename T,
bool>
554 struct base_int_type_impl {
559 struct base_int_type_impl<T, true> {
560 using type = std::underlying_type_t<T>;
564 using base_int_type_t =
565 typename base_int_type_impl<T, std::is_enum_v<T>>::type;
567 inline constexpr
auto digits100 = [] {
568 std::array<char[2], 100> result{ };
569 for(
size_t n = 0; n < 100; ++n ) {
570 result[n][0] =
static_cast<char>( n % 10 ) +
'0';
571 result[n][1] =
static_cast<char>( n / 10 ) +
'0';
576 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
577 [[nodiscard]] constexpr OutputIterator
578 to_string( ParseTag<JsonParseTypes::Signed>, OutputIterator it,
579 parse_to_t
const &value ) {
582 std::is_convertible_v<parse_to_t, typename JsonMember::parse_to_t>,
583 "value must be convertible to specified type in class contract" );
585 using std::to_string;
586 using to_strings::to_string;
587 using under_type = base_int_type_t<parse_to_t>;
589 if constexpr( JsonMember::literal_as_string ==
593 if constexpr( std::is_enum_v<parse_to_t> or
594 daw::is_integral_v<parse_to_t> ) {
595 auto v =
static_cast<under_type
>( value );
597 char buff[daw::numeric_limits<under_type>::digits10 + 1]{ };
603 *ptr++ =
'0' -
static_cast<char>( v % 10 );
607 if constexpr( JsonMember::literal_as_string ==
618 auto const tmp =
static_cast<std::size_t
>( v % 100 );
620 ptr[0] = digits100[tmp][0];
621 ptr[1] = digits100[tmp][1];
625 *ptr++ =
'0' +
static_cast<char>( v );
629 while( ptr != buff ) {
637 if constexpr( JsonMember::literal_as_string ==
644 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
645 [[nodiscard]] constexpr OutputIterator
646 to_string( ParseTag<JsonParseTypes::Unsigned>, OutputIterator it,
647 parse_to_t
const &value ) {
650 std::is_convertible_v<parse_to_t, typename JsonMember::parse_to_t>,
651 "value must be convertible to specified type in class contract" );
653 using std::to_string;
654 using to_strings::to_string;
655 using under_type = base_int_type_t<parse_to_t>;
657 if constexpr( JsonMember::literal_as_string ==
661 if constexpr( std::is_enum_v<parse_to_t> or
662 daw::is_integral_v<parse_to_t> ) {
663 auto v =
static_cast<under_type
>( value );
665 char buff[daw::numeric_limits<under_type>::digits10 + 1]{ };
671 auto const tmp =
static_cast<std::size_t
>( v % 100 );
673 ptr[0] = digits100[tmp][0];
674 ptr[1] = digits100[tmp][1];
678 *ptr++ =
'0' +
static_cast<char>( v );
682 while( ptr != buff ) {
690 if constexpr( JsonMember::literal_as_string ==
700 namespace utils_details {
701 template<
typename Integer>
703 using parse_to_t = Integer;
705 LiteralAsStringOpt::Never;
709 template<
typename Integer,
typename OutputIterator>
711 Integer
const &value ) {
712 static_assert( daw::is_integral_v<Integer> );
714 if constexpr( daw::is_unsigned_v<Integer> ) {
715 return json_details::to_string<utils_details::number<Integer>>(
718 return json_details::to_string<utils_details::number<Integer>>(
724 namespace daw::json::json_details {
725 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
726 [[nodiscard]]
inline constexpr OutputIterator
727 to_string( ParseTag<JsonParseTypes::StringRaw>, OutputIterator it,
728 parse_to_t
const &value ) {
731 std::is_convertible_v<parse_to_t, typename JsonMember::parse_to_t>,
732 "value must be convertible to specified type in class contract" );
734 constexpr
EightBitModes eight_bit_mode = JsonMember::eight_bit_mode;
736 if( value.size( ) > 0U ) {
737 it = utils::copy_to_iterator<false, eight_bit_mode>( it, value );
743 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
744 [[nodiscard]]
inline constexpr OutputIterator
745 to_string( ParseTag<JsonParseTypes::StringEscaped>, OutputIterator it,
746 parse_to_t
const &value ) {
754 constexpr
EightBitModes eight_bit_mode = JsonMember::eight_bit_mode;
756 it = utils::copy_to_iterator<true, eight_bit_mode>( it, value );
762 [[nodiscard]]
inline constexpr
bool is_null( std::optional<T>
const &v ) {
763 return not
static_cast<bool>( v );
767 [[nodiscard]]
inline constexpr
bool is_null( T
const & ) {
771 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
772 [[nodiscard]] constexpr OutputIterator
773 to_string( ParseTag<JsonParseTypes::Date>, OutputIterator it,
774 parse_to_t
const &value ) {
777 std::is_convertible_v<parse_to_t, typename JsonMember::parse_to_t>,
778 "value must be convertible to specified type in class contract" );
780 using daw::json::json_details::is_null;
781 if( is_null( value ) ) {
788 if( civil.month < 10 ) {
793 if( civil.day < 10 ) {
798 if( civil.hour < 10 ) {
803 if( civil.minute < 10 ) {
808 if( civil.second < 10 ) {
812 if( civil.millisecond > 0 ) {
822 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
823 [[nodiscard]]
inline constexpr OutputIterator
824 to_string( ParseTag<JsonParseTypes::Unknown>, OutputIterator it,
825 parse_to_t
const &value ) {
830 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
831 [[nodiscard]]
inline constexpr OutputIterator
832 to_string( ParseTag<JsonParseTypes::Class>, OutputIterator it,
833 parse_to_t
const &value ) {
836 std::is_convertible_v<parse_to_t, typename JsonMember::parse_to_t>,
837 "value must be convertible to specified type in class contract" );
839 if constexpr( has_json_to_json_data_v<parse_to_t> ) {
840 return json_data_contract_trait_t<parse_to_t>::serialize(
844 static_assert( is_submember_tagged_variant_v<parse_to_t> );
845 return json_data_contract_trait_t<parse_to_t>::serialize( it, value );
849 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
850 [[nodiscard]]
inline constexpr OutputIterator
851 to_string( ParseTag<JsonParseTypes::Custom>, OutputIterator it,
852 parse_to_t
const &value ) {
855 std::is_convertible_v<parse_to_t, typename JsonMember::parse_to_t>,
856 "value must be convertible to specified type in class contract" );
858 if constexpr( JsonMember::custom_json_type != CustomJsonTypes::Literal ) {
860 if constexpr( std::is_invocable_r_v<OutputIterator,
861 typename JsonMember::to_converter_t,
862 OutputIterator, parse_to_t> ) {
864 it =
typename JsonMember::to_converter_t{ }( it, value );
867 it,
typename JsonMember::to_converter_t{ }( value ) );
873 it,
typename JsonMember::to_converter_t{ }( value ) );
877 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
878 [[nodiscard]] constexpr OutputIterator
879 to_string( ParseTag<JsonParseTypes::Array>, OutputIterator it,
880 parse_to_t
const &container ) {
883 std::is_convertible_v<parse_to_t, typename JsonMember::parse_to_t>,
884 "value must be convertible to specified type in class contract" );
887 if( not std::empty( container ) ) {
888 auto count = std::size( container ) - 1U;
889 for(
auto const &v : container ) {
890 it = to_string<typename JsonMember::json_element_t>(
891 ParseTag<JsonMember::json_element_t::expected_type>{ }, it, v );
901 template<
typename Key,
typename Value>
902 [[maybe_unused]]
inline constexpr Key
const &
903 json_get_key( std::pair<Key, Value>
const &kv ) {
907 template<
typename Key,
typename Value>
908 [[maybe_unused]]
inline constexpr Value
const &
909 json_get_value( std::pair<Key, Value>
const &kv ) {
913 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
914 [[nodiscard]] constexpr OutputIterator
915 to_string( ParseTag<JsonParseTypes::KeyValueArray>, OutputIterator it,
916 parse_to_t
const &container ) {
919 std::is_convertible_v<parse_to_t, typename JsonMember::parse_to_t>,
920 "value must be convertible to specified type in class contract" );
921 using key_t =
typename JsonMember::json_key_t;
922 using value_t =
typename JsonMember::json_value_t;
924 if( not std::empty( container ) ) {
925 auto count = std::size( container ) - 1U;
926 for(
auto const &v : container ) {
934 it = to_string<key_t>( ParseTag<key_t::expected_type>{ }, it,
944 it = to_string<value_t>( ParseTag<value_t::expected_type>{ }, it,
945 json_get_value( v ) );
957 template<
typename JsonMember,
typename OutputIterator,
typename parse_to_t>
958 [[nodiscard]] constexpr OutputIterator
959 to_string( ParseTag<JsonParseTypes::KeyValue>, OutputIterator it,
960 parse_to_t
const &container ) {
963 std::is_convertible_v<parse_to_t, typename JsonMember::parse_to_t>,
964 "value must be convertible to specified type in class contract" );
967 if( not std::empty( container ) ) {
968 auto count = std::size( container ) - 1U;
969 for(
auto const &v : container ) {
970 it = to_string<typename JsonMember::json_key_t>(
971 ParseTag<JsonMember::json_key_t::expected_type>{ }, it,
974 it = to_string<typename JsonMember::json_element_t>(
975 ParseTag<JsonMember::json_element_t::expected_type>{ }, it,
976 json_get_value( v ) );
986 template<
typename JsonMember,
typename OutputIterator,
typename T>
987 [[nodiscard]]
inline constexpr OutputIterator
988 member_to_string( OutputIterator it, T
const &value ) {
989 return to_string<JsonMember>( ParseTag<JsonMember::expected_type>{ },
990 daw::move( it ), value );
993 template<
typename JsonMember>
994 using tag_member_t =
typename JsonMember::tag_member;
996 template<
typename JsonMember>
997 inline constexpr
bool has_tag_member_v =
998 daw::is_detected_v<tag_member_t, JsonMember>;
999 template<std::size_t,
typename JsonMember,
typename OutputIterator,
1000 typename Value,
typename VisitedMembers,
1001 std::enable_if_t<not has_tag_member_v<JsonMember>, std::nullptr_t> =
1003 inline constexpr
void tags_to_json_str(
bool &, OutputIterator
const &,
1005 VisitedMembers
const & ) {}
1007 std::size_t pos,
typename JsonMember,
typename OutputIterator,
1008 typename Value,
typename VisitedMembers,
1009 std::enable_if_t<has_tag_member_v<JsonMember>, std::nullptr_t> =
nullptr>
1010 constexpr
void tags_to_json_str(
bool &is_first, OutputIterator it,
1012 VisitedMembers &visited_members ) {
1013 using tag_member = tag_member_t<JsonMember>;
1014 constexpr
auto tag_member_name =
1015 daw::string_view( tag_member::name.data( ), tag_member::name.size( ) );
1016 if( daw::algorithm::contains( visited_members.begin( ),
1017 visited_members.end( ), tag_member_name ) ) {
1020 visited_members.push_back( tag_member_name );
1021 if( not is_first ) {
1026 it = utils::copy_to_iterator<false, EightBitModes::AllowFull>(
1027 it, tag_member_name );
1028 it = utils::copy_to_iterator<false, EightBitModes::AllowFull>( it,
"\":" );
1029 it = member_to_string<tag_member>( daw::move( it ),
1030 typename JsonMember::switcher{ }( v ) );
1033 template<std::size_t pos,
typename JsonMember,
typename OutputIterator,
1034 typename... Args,
typename Value,
typename Visited>
1035 inline constexpr
void to_json_str(
bool &is_first, OutputIterator &it,
1036 std::tuple<Args...>
const &tp,
1037 Value
const &, Visited &visited_members ) {
1038 constexpr
auto json_member_name =
1039 daw::string_view( JsonMember::name.data( ), JsonMember::name.size( ) );
1040 if( daw::algorithm::contains( visited_members.begin( ),
1041 visited_members.end( ), json_member_name ) ) {
1044 visited_members.push_back( json_member_name );
1045 static_assert( is_a_json_type_v<JsonMember>,
"Unsupported data type" );
1046 if constexpr( is_json_nullable_v<JsonMember> ) {
1047 if( not std::get<pos>( tp ) ) {
1051 if( not is_first ) {
1056 it = utils::copy_to_iterator<false, EightBitModes::AllowFull>(
1057 it, JsonMember::name );
1058 it = utils::copy_to_iterator<false, EightBitModes::AllowFull>( it,
"\":" );
1059 it = member_to_string<JsonMember>( daw::move( it ), std::get<pos>( tp ) );
1062 template<
size_t TupleIdx,
typename JsonMember,
typename OutputIterator,
1064 constexpr
void to_json_ordered_str( std::size_t &array_idx,
1066 std::tuple<Args...>
const &tp ) {
1068 using json_member_type = ordered_member_subtype_t<JsonMember>;
1069 static_assert( is_a_json_type_v<json_member_type>,
1070 "Unsupported data type" );
1074 not is_a_json_tagged_variant_v<json_member_type>,
1075 "JSON tagged variant types are not supported when inside an array "
1076 "as an ordered structure" );
1078 if constexpr( is_an_ordered_member_v<JsonMember> ) {
1079 for( ; array_idx < JsonMember::member_index; ++array_idx ) {
1080 if( array_idx > 0 ) {
1089 if( array_idx > 0 ) {
1092 it = member_to_string<json_member_type>( it, std::get<TupleIdx>( tp ) );