DAW JSON Link
to_daw_json_string.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 
13 #include "daw_json_assert.h"
15 #include "daw_json_value.h"
16 
17 #include <daw/daw_algorithm.h>
18 #include <daw/daw_arith_traits.h>
19 #include <daw/daw_cpp_feature_check.h>
20 #include <daw/daw_cxmath.h>
21 #include <daw/daw_likely.h>
22 #include <daw/daw_move.h>
23 #include <daw/daw_traits.h>
24 #include <daw/daw_visit.h>
25 #include <utf8/unchecked.h>
26 
27 #include <array>
28 #include <ciso646>
29 #include <optional>
30 #include <sstream>
31 #include <string>
32 
33 #ifndef DAW_JSON_CUSTOM_D2S
34 #include <third_party/dragonbox/dragonbox.h>
35 #elif DAW_HAS_INCLUDE( "custom_d2s.h" )
36 #include "custom_d2s.h"
37 #else
38 #error Request for local d2s, but no custom_d2s.h supplied with char * d2s( Real const & value, char * ); declaration/definition in namespace daw::json
39 #endif
40 #include <type_traits>
41 #include <variant>
42 
43 namespace daw::json {
44  inline namespace DAW_JSON_VER {
45  template<typename Real, typename OutputIterator>
46  constexpr OutputIterator real2string( Real const &value,
47  OutputIterator out_it ) {
48  // TODO: Customization point, add to readme
49 #ifndef DAW_JSON_CUSTOM_D2S
50  if constexpr( std::is_same<Real, float>::value ) {
51  return jkj::dragonbox::to_chars_n( value, out_it );
52  } else {
53  return jkj::dragonbox::to_chars_n( static_cast<double>( value ),
54  out_it );
55  }
56 #else
57  if constexpr( std::is_same<Real, float>::value ) {
58  return d2s( value, out_it );
59  } else {
60  return d2s( static_cast<double>( value ), out_it );
61  }
62 #endif
63  }
64 
65  namespace json_details::to_strings {
66  using std::to_string;
67  // Need to use ADL to_string in unevaluated contexts. Limiting to it's
68  // own namespace
69  template<typename T>
70  [[nodiscard, maybe_unused]] constexpr auto
71  to_string( std::optional<T> const &v ) -> decltype( to_string( *v ) ) {
72  if( not has_value( v ) ) {
73  return { "null" };
74  }
75  return to_string( *v );
76  }
77 
78  namespace to_string_test {
79  template<typename T>
80  [[maybe_unused]] auto to_string_test( T &&v )
81  -> decltype( to_string( DAW_FWD2( T, v ) ) );
82 
83  template<typename T>
85  decltype( to_string_test( std::declval<T>( ) ) );
86  } // namespace to_string_test
87 
88  template<typename T>
89  using has_to_string =
90  daw::is_detected<to_string_test::to_string_result, T>;
91 
92  template<typename T>
93  inline constexpr bool has_to_string_v = has_to_string<T>::value;
94 
95  } // namespace json_details::to_strings
96  namespace json_details {
97  template<typename T>
98  using from_string_test = decltype( from_string(
99  std::declval<daw::tag_t<T>>( ), std::declval<std::string_view>( ) ) );
100 
101  template<typename T>
102  inline constexpr bool has_from_string_v =
103  daw::is_detected_v<from_string_test, T>;
104 
105  template<typename T, typename U>
106  using has_lshift_test = decltype( operator<<(
107  std::declval<T &>( ), std::declval<U const &>( ) ) );
108 
109  template<typename T, typename U>
110  using has_rshift_test = decltype( operator>>(
111  std::declval<T &>( ), std::declval<U const &>( ) ) );
112 
113  template<typename T>
114  inline constexpr bool has_ostream_op_v =
115  daw::is_detected_v<has_lshift_test, std::stringstream, T>;
116 
117  template<typename T>
118  inline constexpr bool has_istream_op_v =
119  daw::is_detected_v<has_rshift_test, std::stringstream, T>;
120 
121  } // namespace json_details
122 
123  /***
124  * This is the default ToJsonConverter for json_custom. By default is will
125  * return the stringified version of the value if, to_string( T ) exists.
126  * Otherwise it will fallback to an std::ostream converter for T if it
127  * exists.
128  * @tparam T type of value to convert to a string
129  */
130  template<typename T>
132  template<typename U>
133  [[nodiscard]] static inline auto use_stream( U const &v ) {
134  std::stringstream ss{ };
135  ss << v;
136  return DAW_MOVE( ss ).str( );
137  }
138 
139  template<typename U>
140  [[nodiscard]] inline constexpr auto operator( )( U const &value ) const {
141  if constexpr( json_details::is_string_view_like_v<U> ) {
142  return std::string_view( std::data( value ), std::size( value ) );
143  } else if constexpr( json_details::to_strings::has_to_string_v<U> ) {
145  return to_string( value );
146  } else if constexpr( json_details::has_ostream_op_v<U> ) {
147  return use_stream( value );
148  } else if constexpr( std::is_convertible_v<U, std::string_view> ) {
149  return static_cast<std::string_view>( value );
150  } else if constexpr( std::is_convertible_v<U, std::string> ) {
151  return static_cast<std::string>( value );
152  } else if constexpr( daw::is_arithmetic_v<U> ) {
153  return to_string( value );
154  } else if constexpr( std::is_enum_v<U> ) {
155  return to_string( static_cast<std::underlying_type_t<U>>( value ) );
156  } else if constexpr( json_details::can_deref_v<U> ) {
157  static_assert( json_details::has_op_bool_v<U>,
158  "default_to_converter cannot work with type" );
159  using deref_t = daw::remove_cvref_t<decltype( *value )>;
160  if constexpr( json_details::is_string_view_like_v<deref_t> ) {
161  if( value ) {
162  auto const &v = *value;
163  return std::string_view( std::data( v ), std::size( v ) );
164  }
165  return std::string_view( "null", 4 );
166  } else if constexpr( json_details::to_strings::has_to_string_v<
167  deref_t> ) {
168  if( value ) {
170  return to_string( *value );
171  } else {
172  using result_t =
173  daw::remove_cvref_t<decltype( to_string( *value ) )>;
174  return result_t{ "null" };
175  }
176  } else if constexpr( std::is_convertible_v<deref_t,
177  std::string_view> ) {
178  if( value ) {
179  return static_cast<std::string_view>( value );
180  }
181  return std::string_view{ "null" };
182  } else if constexpr( std::is_convertible_v<deref_t, std::string> ) {
183  if( value ) {
184  return static_cast<std::string>( value );
185  }
186  return std::string( "null" );
187  } else {
188  if( value ) {
189  return use_stream( *value );
190  } else {
191  return std::string( "null" );
192  }
193  }
194  }
195  }
196  };
197 
198  namespace from_json_conv_details {
199  template<typename T>
200  [[nodiscard]] inline auto use_stream( std::string_view sv ) {
201  std::stringstream ss{ };
202  ss << sv;
203  T result;
204  ss >> result;
205  return result;
206  }
207  } // namespace from_json_conv_details
208 
209  template<typename T>
211  [[nodiscard]] inline constexpr decltype( auto )
212  operator( )( std::string_view sv ) const {
213  if constexpr( std::disjunction<
214  std::is_same<T, std::string_view>,
215  std::is_same<T, std::optional<std::string_view>>>::
216  value ) {
217  return sv;
218  } else if constexpr( json_details::has_from_string_v<T> ) {
219  return from_string( daw::tag<T>, sv );
220  } else if constexpr( std::is_convertible_v<std::string_view, T> ) {
221  return static_cast<T>( sv );
222  } else if constexpr( std::is_convertible_v<std::string, T> ) {
223  return static_cast<T>( static_cast<std::string>( sv ) );
224  } else {
225  static_assert( json_details::has_istream_op_v<T>,
226  "Unsupported type in default to converter. Must "
227  "supply a custom one" );
228  static_assert( std::is_default_constructible_v<T>,
229  "Unsupported type in default to converter. Must "
230  "supply a custom one" );
231  return from_json_conv_details::use_stream<T>( sv );
232  }
233  }
234  };
235 
236  namespace json_details {
237  template<typename JsonMember, typename OutputIterator,
238  typename parse_to_t>
239  [[nodiscard]] inline OutputIterator constexpr to_daw_json_string(
240  ParseTag<JsonParseTypes::Null>, OutputIterator it,
241  parse_to_t const &value );
242 
243  template<typename JsonMember, typename OutputIterator,
244  typename parse_to_t>
245  [[nodiscard]] constexpr OutputIterator
247  parse_to_t const &value );
248 
249  template<typename JsonMember, typename OutputIterator,
250  typename parse_to_t>
251  [[nodiscard]] constexpr OutputIterator
253  OutputIterator it, parse_to_t const &value );
254 
255  template<typename JsonMember, typename OutputIterator,
256  typename parse_to_t>
257  [[nodiscard]] constexpr OutputIterator
259  OutputIterator it, parse_to_t const &value );
260 
261  template<typename JsonMember, typename OutputIterator,
262  typename parse_to_t>
263  [[nodiscard]] constexpr OutputIterator
265  parse_to_t const &value );
266 
267  template<typename JsonMember, typename OutputIterator,
268  typename parse_to_t>
269  [[nodiscard]] constexpr OutputIterator
271  parse_to_t const &value );
272 
273  template<typename JsonMember, typename OutputIterator,
274  typename parse_to_t>
275  [[nodiscard]] constexpr OutputIterator
277  parse_to_t const &value );
278 
279  template<typename JsonMember, typename OutputIterator,
280  typename parse_to_t>
281  [[nodiscard]] constexpr OutputIterator
283  parse_to_t const &value );
284 
285  template<typename JsonMember, typename OutputIterator,
286  typename parse_to_t>
287  [[nodiscard]] inline OutputIterator
289  parse_to_t const &value );
290 
291  template<typename JsonMember, typename OutputIterator,
292  typename parse_to_t>
293  [[nodiscard]] constexpr OutputIterator
295  parse_to_t const &value );
296 
297  template<typename JsonMember, typename OutputIterator,
298  typename parse_to_t>
299  [[nodiscard]] constexpr OutputIterator
301  parse_to_t const &value );
302 
303  template<typename JsonMember, typename OutputIterator,
304  typename parse_to_t>
305  [[nodiscard]] constexpr OutputIterator
307  OutputIterator it, parse_to_t const &value );
308 
309  template<typename JsonMember, typename OutputIterator,
310  typename parse_to_t>
311  [[nodiscard]] constexpr OutputIterator
313  OutputIterator it, parse_to_t const &value );
314 
315  template<typename JsonMember, typename OutputIterator,
316  typename parse_to_t>
317  [[nodiscard]] constexpr OutputIterator
319  parse_to_t const &value );
320 
321  template<typename JsonMember, typename OutputIterator,
322  typename parse_to_t>
323  [[nodiscard]] constexpr OutputIterator
325  parse_to_t const &value );
326 
327  //************************************************
328  template<typename Char>
329  constexpr char to_nibble_char( Char c ) {
330  auto const u = static_cast<unsigned>( static_cast<unsigned char>( c ) );
331  daw_json_assert( u < 16, ErrorReason::InvalidUTFEscape );
332  if( u < 10 ) {
333  return static_cast<char>( u + static_cast<unsigned char>( '0' ) );
334  } else {
335  return static_cast<char>( ( u - 10U ) +
336  static_cast<unsigned char>( 'A' ) );
337  }
338  }
339 
340  template<typename OutputIterator>
341  constexpr OutputIterator output_hex( std::uint16_t c,
342  OutputIterator it ) {
343  char const nibbles[] = { '\\',
344  'u',
345  to_nibble_char( ( c >> 12U ) & 0xFU ),
346  to_nibble_char( ( c >> 8U ) & 0xFU ),
347  to_nibble_char( ( c >> 4U ) & 0xFU ),
348  to_nibble_char( c & 0xFU ) };
349 
350  *it++ = nibbles[0];
351  *it++ = nibbles[1];
352  *it++ = nibbles[2];
353  *it++ = nibbles[3];
354  *it++ = nibbles[4];
355  *it++ = nibbles[5];
356  return it;
357  }
358 
359  template<typename OutputIterator>
360  constexpr void utf32_to_utf8( std::uint32_t cp, OutputIterator &it ) {
361  if( cp <= 0x7FU ) {
362  *it++ = static_cast<char>( cp );
363  return;
364  }
365  if( cp <= 0x7FFU ) {
366  *it++ = static_cast<char>( ( cp >> 6U ) | 0b11000000U );
367  *it++ = static_cast<char>( ( cp & 0b00111111U ) | 0b10000000U );
368  return;
369  }
370  if( cp <= 0xFFFFU ) {
371  *it++ = static_cast<char>( ( cp >> 12U ) | 0b11100000U );
372  *it++ =
373  static_cast<char>( ( ( cp >> 6U ) & 0b00111111U ) | 0b10000000U );
374  *it++ = static_cast<char>( ( cp & 0b00111111U ) | 0b10000000U );
375  return;
376  }
377  if( cp <= 0x10FFFFU ) {
378  *it++ = static_cast<char>( ( cp >> 18U ) | 0b11110000U );
379  *it++ =
380  static_cast<char>( ( ( cp >> 12U ) & 0b00111111U ) | 0b10000000U );
381  *it++ =
382  static_cast<char>( ( ( cp >> 6U ) & 0b00111111U ) | 0b10000000U );
383  *it++ = static_cast<char>( ( cp & 0b00111111U ) | 0b10000000U );
384  return;
385  }
386  daw_json_error( ErrorReason::InvalidUTFCodepoint );
387  }
388  } // namespace json_details
389 
390  namespace utils {
391  template<bool do_escape = false,
393  typename OutputIterator, typename Container,
394  std::enable_if_t<
395  traits::is_container_like_v<daw::remove_cvref_t<Container>>,
396  std::nullptr_t> = nullptr>
397  [[nodiscard]] constexpr OutputIterator
398  copy_to_iterator( OutputIterator it, Container const &container ) {
399  if constexpr( do_escape ) {
400  using iter = daw::remove_cvref_t<decltype( std::begin( container ) )>;
401  using it_t = utf8::unchecked::iterator<iter>;
402  auto first = it_t( std::begin( container ) );
403  auto const last = it_t( std::end( container ) );
404  while( first != last ) {
405  auto const cp = *first++;
406  switch( cp ) {
407  case '"':
408  *it++ = '\\';
409  *it++ = '"';
410  break;
411  case '\\':
412  *it++ = '\\';
413  *it++ = '\\';
414  break;
415  case '\b':
416  *it++ = '\\';
417  *it++ = 'b';
418  break;
419  case '\f':
420  *it++ = '\\';
421  *it++ = 'f';
422  break;
423  case '\n':
424  *it++ = '\\';
425  *it++ = 'n';
426  break;
427  case '\r':
428  *it++ = '\\';
429  *it++ = 'r';
430  break;
431  case '\t':
432  *it++ = '\\';
433  *it++ = 't';
434  break;
435  default:
436  if( cp < 0x20U ) {
437  it = json_details::output_hex( static_cast<std::uint16_t>( cp ),
438  it );
439  break;
440  }
441  if constexpr( EightBitMode == EightBitModes::DisallowHigh ) {
442  if( cp >= 0x7FU and cp <= 0xFFFFU ) {
444  static_cast<std::uint16_t>( cp ), it );
445  break;
446  }
447  if( cp > 0xFFFFU ) {
449  static_cast<std::uint16_t>( 0xD7C0U + ( cp >> 10U ) ), it );
451  static_cast<std::uint16_t>( 0xDC00U + ( cp & 0x3FFU ) ),
452  it );
453  break;
454  }
455  }
457  break;
458  }
459  }
460  } else {
461  for( auto c : container ) {
462  if constexpr( EightBitMode == EightBitModes::DisallowHigh ) {
463  daw_json_assert( ( static_cast<unsigned char>( c ) >= 0x20U and
464  static_cast<unsigned char>( c ) <= 0x7FU ),
465  ErrorReason::InvalidStringHighASCII );
466  }
467  *it++ = c;
468  }
469  }
470  return it;
471  }
472 
473  template<bool do_escape = false,
475  typename OutputIterator>
476  [[nodiscard]] constexpr OutputIterator
477  copy_to_iterator( OutputIterator it, char const *ptr ) {
478  if( ptr == nullptr ) {
479  return it;
480  }
481  if constexpr( do_escape ) {
482 
483  auto chr_it = utf8::unchecked::iterator<char const *>( ptr );
484  while( *chr_it.base( ) != '\0' ) {
485  auto const cp = *chr_it++;
486  switch( cp ) {
487  case '"':
488  *it++ = '\\';
489  *it++ = '"';
490  break;
491  case '\\':
492  *it++ = '\\';
493  *it++ = '\\';
494  break;
495  case '\b':
496  *it++ = '\\';
497  *it++ = 'b';
498  break;
499  case '\f':
500  *it++ = '\\';
501  *it++ = 'f';
502  break;
503  case '\n':
504  *it++ = '\\';
505  *it++ = 'n';
506  break;
507  case '\r':
508  *it++ = '\\';
509  *it++ = 'r';
510  break;
511  case '\t':
512  *it++ = '\\';
513  *it++ = 't';
514  break;
515  default:
516  if( cp < 0x20U ) {
517  it = json_details::output_hex( static_cast<std::uint16_t>( cp ),
518  it );
519  break;
520  }
521  if constexpr( EightBitMode == EightBitModes::DisallowHigh ) {
522  if( cp >= 0x7FU and cp <= 0xFFFFU ) {
524  static_cast<std::uint16_t>( cp ), it );
525  break;
526  }
527  if( cp > 0xFFFFU ) {
529  static_cast<std::uint16_t>( 0xD7C0U + ( cp >> 10U ) ), it );
530  it = output_hex(
531  static_cast<std::uint16_t>( 0xDC00U + ( cp & 0x3FFU ) ),
532  it );
533  break;
534  }
535  }
537  break;
538  }
539  }
540  } else {
541  while( *ptr != '\0' ) {
542  if constexpr( EightBitMode == EightBitModes::DisallowHigh ) {
543  daw_json_assert( ( static_cast<unsigned>( *ptr ) >= 0x20U and
544  static_cast<unsigned>( *ptr ) <= 0x7FU ),
545  ErrorReason::InvalidStringHighASCII );
546  }
547  *it++ = *ptr++;
548  }
549  }
550  return it;
551  }
552 
553  template<bool do_escape = false,
555  typename OutputIterator, typename ParseState>
556  [[nodiscard]] constexpr OutputIterator
557  copy_to_iterator( OutputIterator it,
558  basic_json_value<ParseState> const &jv ) {
559  if( jv.is_null( ) ) {
560  return copy_to_iterator<do_escape, EightBitMode>( it, "null" );
561  } else {
562  return copy_to_iterator<do_escape, EightBitMode>(
563  it, jv.get_string_view( ) );
564  }
565  }
566  } // namespace utils
567 
568  namespace json_details {
569  template<typename JsonMember, typename OutputIterator,
570  typename parse_to_t>
571  [[nodiscard]] constexpr OutputIterator
573  parse_to_t const &value ) {
574 
575  if constexpr( JsonMember::literal_as_string ==
577  *it++ = '"';
578  }
579  if( value ) {
580  it = utils::copy_to_iterator( it, "true" );
581  } else {
582  it = utils::copy_to_iterator( it, "false" );
583  }
584  if constexpr( JsonMember::literal_as_string ==
586  *it++ = '"';
587  }
588  return it;
589  }
590 
591  template<std::size_t idx, typename JsonMembers, typename OutputIterator,
592  typename parse_to_t>
593  constexpr void to_variant_string( OutputIterator &it,
594  parse_to_t const &value ) {
595  if constexpr( idx < std::variant_size<parse_to_t>::value ) {
596  if( value.index( ) != idx ) {
597  to_variant_string<idx + 1, JsonMembers>( it, value );
598  return;
599  }
600  using element_t = typename JsonMembers::json_elements;
601  using JsonMember =
602  typename pack_element<idx, typename element_t::element_map_t>::type;
603  it = to_daw_json_string<JsonMember>(
605  daw::get_nt<idx>( value ) );
606  }
607  }
608 
609  template<typename JsonMember, typename OutputIterator,
610  typename parse_to_t>
611  [[nodiscard]] inline constexpr OutputIterator
613  parse_to_t const &value ) {
614 
615  assert( value.index( ) >= 0 );
616  to_variant_string<0, JsonMember>( it, value );
617  return it;
618  }
619 
620  template<typename JsonMember, typename OutputIterator,
621  typename parse_to_t>
622  [[nodiscard]] inline constexpr OutputIterator
624  OutputIterator it, parse_to_t const &value ) {
625 
626  to_variant_string<0, JsonMember>( it, value );
627  return it;
628  }
629 
630  template<typename T>
631  [[maybe_unused]] constexpr auto deref_detect( T &&value )
632  -> decltype( *value );
633 
634  [[maybe_unused]] inline constexpr void deref_detect( ... ) {}
635 
636  template<typename T>
637  using deref_t =
638  daw::remove_cvref_t<decltype( deref_detect( std::declval<T>( ) ) )>;
639 
640  template<typename Optional>
641  inline constexpr bool is_valid_optional_v =
642  daw::is_detected<deref_t, Optional>::value;
643 
644  template<typename JsonMember, typename OutputIterator, typename Optional>
645  [[nodiscard]] inline constexpr OutputIterator
647  Optional const &value ) {
648  static_assert( is_valid_optional_v<Optional> );
649 
650  if( not json_details::has_value( value ) ) {
651  return utils::copy_to_iterator( it, "null" );
652  }
654  if constexpr( json_details::has_op_star_v<Optional> ) {
655  return to_daw_json_string<JsonMember>( tag_type{ }, it, *value );
656  } else {
657  return to_daw_json_string<JsonMember>( tag_type{ }, it, value );
658  }
659  }
660 
661  template<typename JsonMember, typename OutputIterator,
662  typename parse_to_t>
663  [[nodiscard]] inline OutputIterator
665  parse_to_t const &value ) {
666 
667  static_assert(
668  std::is_convertible<parse_to_t,
669  typename JsonMember::parse_to_t>::value,
670  "value must be convertible to specified type in class contract" );
671 
672  if constexpr( std::is_floating_point<
673  typename JsonMember::parse_to_t>::value ) {
674  if( daw::cxmath::is_nan( value ) ) {
675  if constexpr( JsonMember::literal_as_string ==
677  daw_json_error( ErrorReason::NumberIsNaN );
678  } else {
679  *it++ = '"';
680  it = utils::copy_to_iterator( it, "NaN" );
681  *it++ = '"';
682  return it;
683  }
684  } else if( daw::cxmath::is_inf( value ) ) {
685  if constexpr( JsonMember::literal_as_string ==
687  daw_json_error( ErrorReason::NumberIsInf );
688  } else {
689  *it++ = '"';
690  it = utils::copy_to_iterator( it, "Infinity" );
691  *it++ = '"';
692  return it;
693  }
694  }
695  }
696 
697  if constexpr( JsonMember::literal_as_string ==
699  *it++ = '"';
700  }
701  if constexpr( daw::is_floating_point_v<parse_to_t> ) {
702  static_assert( sizeof( parse_to_t ) <= sizeof( double ) );
703  if constexpr( std::is_same<OutputIterator, char *>::value ) {
704  it = real2string( value, it );
705  } else {
706  char buff[50]{ };
707  buff[49] = 0;
708  char *ptr = buff;
709  ptr = real2string( value, ptr );
710  std::copy( buff, ptr, it );
711  }
712  } else {
713  using std::to_string;
714  using to_strings::to_string;
715  it = utils::copy_to_iterator( it, to_string( value ) );
716  }
717  if constexpr( JsonMember::literal_as_string ==
719  *it++ = '"';
720  }
721  return it;
722  }
723 
724  template<typename T>
725  using base_int_type_impl = std::underlying_type<T>;
726 
727  template<typename T>
729  typename std::conditional_t<std::is_enum_v<T>, base_int_type_impl<T>,
730  daw::traits::identity<T>>::type;
731 
732  inline constexpr auto digits100 = [] {
733  std::array<char[2], 100> result{ };
734  for( size_t n = 0; n < 100; ++n ) {
735  result[n][0] =
736  static_cast<char>( ( n % 10 ) + static_cast<unsigned char>( '0' ) );
737  result[n][1] =
738  static_cast<char>( ( n / 10 ) + static_cast<unsigned char>( '0' ) );
739  }
740  return result;
741  }( );
742 
743  template<typename JsonMember, typename OutputIterator,
744  typename parse_to_t>
745  [[nodiscard]] constexpr OutputIterator
747  parse_to_t const &value ) {
748 
749  static_assert(
750  std::is_convertible<parse_to_t,
751  typename JsonMember::parse_to_t>::value,
752  "value must be convertible to specified type in class contract" );
753 
754  using std::to_string;
755  using to_strings::to_string;
756  using under_type = base_int_type_t<parse_to_t>;
757 
758  if constexpr( JsonMember::literal_as_string ==
760  *it++ = '"';
761  }
762  if constexpr( std::disjunction<std::is_enum<parse_to_t>,
763  daw::is_integral<parse_to_t>>::value ) {
764  auto v = static_cast<under_type>( value );
765 
766  char buff[daw::numeric_limits<under_type>::digits10 + 1]{ };
767  char *ptr = buff;
768  if( v < 0 ) {
769  *it++ = '-';
770  // Do 1 round here just in case we are
771  // daw::numeric_limits<intmax_t>::min( ) and cannot negate
772  // This is a subtraction because v < 0 % 10 is negative
773  *ptr++ = static_cast<char>( '0' - static_cast<char>( v % 10 ) );
774  v /= -10;
775  if( v == 0 ) {
776  *it++ = buff[0];
777  if constexpr( JsonMember::literal_as_string ==
779  *it++ = '"';
780  }
781  return it;
782  }
783  }
784  if( v == 0 ) {
785  *ptr++ = '0';
786  }
787  while( v >= 10 ) {
788  auto const tmp = static_cast<std::size_t>( v % 100 );
789  v /= 100;
790  ptr[0] = digits100[tmp][0];
791  ptr[1] = digits100[tmp][1];
792  ptr += 2;
793  }
794  if( v > 0 ) {
795  *ptr++ = static_cast<char>( '0' + static_cast<char>( v ) );
796  }
797  --ptr;
798  *it++ = *ptr;
799  while( ptr != buff ) {
800  --ptr;
801  *it++ = *ptr;
802  }
803  } else {
804  // Fallback to ADL
805  it = utils::copy_to_iterator( it, to_string( value ) );
806  }
807  if constexpr( JsonMember::literal_as_string ==
809  *it++ = '"';
810  }
811  return it;
812  }
813 
814  template<typename JsonMember, typename OutputIterator,
815  typename parse_to_t>
816  [[nodiscard]] constexpr OutputIterator
818  parse_to_t const &value ) {
819 
820  static_assert(
821  std::is_convertible<parse_to_t,
822  typename JsonMember::parse_to_t>::value,
823  "value must be convertible to specified type in class contract" );
824 
825  using std::to_string;
826  using to_strings::to_string;
827  using under_type = base_int_type_t<parse_to_t>;
828 
829  if constexpr( JsonMember::literal_as_string ==
831  *it++ = '"';
832  }
833  if constexpr( std::disjunction<std::is_enum<parse_to_t>,
834  daw::is_integral<parse_to_t>>::value ) {
835  auto v = static_cast<under_type>( value );
836 
837  if( DAW_UNLIKELY( v == 0 ) ) {
838  *it++ = '0';
839  } else {
840  daw_json_assert( v > 0, ErrorReason::NumberOutOfRange );
841  char buff[daw::numeric_limits<under_type>::digits10 + 1]{ };
842  char *ptr = buff;
843  while( v >= 10 ) {
844  auto const tmp = static_cast<std::size_t>( v % 100 );
845  v /= 100;
846  ptr[0] = digits100[tmp][0];
847  ptr[1] = digits100[tmp][1];
848  ptr += 2;
849  }
850  if( v > 0 ) {
851  *ptr++ = static_cast<char>( '0' + static_cast<char>( v ) );
852  }
853  --ptr;
854  *it++ = *ptr;
855  while( ptr != buff ) {
856  --ptr;
857  *it++ = *ptr;
858  }
859  }
860  } else {
861  // Fallback to ADL
862  it = utils::copy_to_iterator( it, to_string( value ) );
863  }
864  if constexpr( JsonMember::literal_as_string ==
866  *it++ = '"';
867  }
868  return it;
869  }
870  } // namespace json_details
871 
872  namespace utils {
873  namespace utils_details {
874  template<typename Integer>
875  struct number {
876  using parse_to_t = Integer;
879  };
880  } // namespace utils_details
881 
882  template<typename Integer, typename OutputIterator>
883  inline constexpr OutputIterator
884  integer_to_string( OutputIterator it, Integer const &value ) {
885  static_assert( daw::is_integral_v<Integer> );
886 
887  if constexpr( daw::is_unsigned_v<Integer> ) {
891  } else {
895  }
896  }
897  } // namespace utils
898 
899  namespace json_details {
900  template<typename JsonMember, typename OutputIterator,
901  typename parse_to_t>
902  [[nodiscard]] inline constexpr OutputIterator
904  OutputIterator it, parse_to_t const &value ) {
905 
906  static_assert(
907  std::is_convertible<parse_to_t,
908  typename JsonMember::parse_to_t>::value,
909  "Value must be convertible to specialized type in "
910  "json_data_contract" );
911 
912  constexpr EightBitModes eight_bit_mode = JsonMember::eight_bit_mode;
913  *it++ = '"';
914  if( std::size( value ) > 0U ) {
915  it = utils::copy_to_iterator<false, eight_bit_mode>( it, value );
916  }
917  *it++ = '"';
918  return it;
919  }
920 
921  template<typename JsonMember, typename OutputIterator,
922  typename parse_to_t>
923  [[nodiscard]] inline constexpr OutputIterator
925  OutputIterator it, parse_to_t const &value ) {
926 
927  /* TODO is something like this necessary
928  static_assert(
929  std::is_convertible<parse_to_t, typename
930  JsonMember::parse_to_t>::value, "value must be convertible to
931  specified type in class contract" );
932  */
933 
934  constexpr EightBitModes eight_bit_mode = JsonMember::eight_bit_mode;
935  *it++ = '"';
936  it = utils::copy_to_iterator<true, eight_bit_mode>( it, value );
937  *it++ = '"';
938  return it;
939  }
940 
941  template<typename T>
942  [[nodiscard]] inline constexpr bool is_null( std::optional<T> const &v ) {
943  return not static_cast<bool>( v );
944  }
945 
946  template<typename T>
947  [[nodiscard]] inline constexpr bool is_null( T const & ) {
948  return false;
949  }
950 
951  template<typename JsonMember, typename OutputIterator,
952  typename parse_to_t>
953  [[nodiscard]] constexpr OutputIterator
955  parse_to_t const &value ) {
956 
957  static_assert(
958  std::is_convertible<parse_to_t,
959  typename JsonMember::parse_to_t>::value,
960  "value must be convertible to specified type in class contract" );
961 
962  using json_details::is_null;
963  // TODO: document customization point
964  if( is_null( value ) ) {
965  return utils::copy_to_iterator( it, "null" );
966  }
967  *it++ = '"';
968  datetime::ymdhms const civil = datetime::time_point_to_civil( value );
969  it = utils::integer_to_string( it, civil.year );
970  *it++ = '-';
971  if( civil.month < 10 ) {
972  *it++ = '0';
973  }
974  it = utils::integer_to_string( it, civil.month );
975  *it++ = '-';
976  if( civil.day < 10 ) {
977  *it++ = '0';
978  }
979  it = utils::integer_to_string( it, civil.day );
980  *it++ = 'T';
981  if( civil.hour < 10 ) {
982  *it++ = '0';
983  }
984  it = utils::integer_to_string( it, civil.hour );
985  *it++ = ':';
986  if( civil.minute < 10 ) {
987  *it++ = '0';
988  }
989  it = utils::integer_to_string( it, civil.minute );
990  *it++ = ':';
991  if( civil.second < 10 ) {
992  *it++ = '0';
993  }
994  it = utils::integer_to_string( it, civil.second );
995  if( civil.millisecond > 0 ) {
996  *it++ = '.';
998  }
999  *it++ = 'Z';
1000  *it++ = '"';
1001  return it;
1002  }
1003 
1004  template<typename JsonMember, typename OutputIterator,
1005  typename parse_to_t>
1006  [[nodiscard]] inline constexpr OutputIterator
1008  parse_to_t const &value ) {
1009 
1010  return utils::copy_to_iterator( it, value );
1011  }
1012 
1013  template<typename JsonMember, typename OutputIterator,
1014  typename parse_to_t>
1015  [[nodiscard]] inline constexpr OutputIterator
1017  parse_to_t const &value ) {
1018 
1019  static_assert(
1020  std::is_convertible<parse_to_t,
1021  typename JsonMember::parse_to_t>::value,
1022  "value must be convertible to specified type in class contract" );
1023 
1024  if constexpr( has_json_to_json_data_v<parse_to_t> ) {
1027  } else if constexpr( is_json_map_alias_v<parse_to_t> ) {
1029  value );
1030  } else {
1031  static_assert( is_submember_tagged_variant_v<parse_to_t>,
1032  "Could not find appropriate mapping or to_json_data "
1033  "member of json_data_contract" );
1035  }
1036  }
1037 
1038  template<typename JsonMember, typename OutputIterator,
1039  typename parse_to_t>
1040  [[nodiscard]] inline constexpr OutputIterator
1042  parse_to_t const &value ) {
1043 
1044  static_assert(
1045  std::is_convertible<parse_to_t,
1046  typename JsonMember::parse_to_t>::value,
1047  "value must be convertible to specified type in class contract" );
1048 
1049  if constexpr( JsonMember::custom_json_type !=
1051  *it++ = '"';
1052  if constexpr( std::is_invocable_r<
1053  OutputIterator, typename JsonMember::to_converter_t,
1054  OutputIterator, parse_to_t>::value ) {
1055 
1056  it = typename JsonMember::to_converter_t{ }( it, value );
1057  } else {
1059  it, typename JsonMember::to_converter_t{ }( value ) );
1060  }
1061  *it++ = '"';
1062  return it;
1063  } else {
1064  return utils::copy_to_iterator(
1065  it, typename JsonMember::to_converter_t{ }( value ) );
1066  }
1067  }
1068 
1069  template<typename JsonMember, typename OutputIterator,
1070  typename parse_to_t, std::size_t... Is>
1071  OutputIterator to_daw_json_string_tuple( OutputIterator it,
1072  parse_to_t const &value,
1073  std::index_sequence<Is...> ) {
1074 
1075  auto const to_daw_json_string_help = [&]( auto Idx, bool &is_first ) {
1076  constexpr std::size_t index = decltype( Idx )::value;
1077  using pack_element = tuple_elements_pack<parse_to_t>;
1078  using T =
1080 
1081  if( is_first ) {
1082  is_first = false;
1083  } else {
1084  *it++ = ',';
1085  }
1086  it =
1087  to_daw_json_string<T>( ParseTag<T::expected_type>{ }, it,
1088  pack_element::template get<index>( value ) );
1089  };
1090 
1091  bool is_first = true;
1092  daw::Empty const expander[]{
1093  ( to_daw_json_string_help( std::integral_constant<std::size_t, Is>{ },
1094  is_first ),
1095  daw::Empty{ } )...,
1096  daw::Empty{} };
1097  (void)expander;
1098 
1099  return it;
1100  }
1101 
1102  template<typename JsonMember, typename OutputIterator,
1103  typename parse_to_t>
1104  [[nodiscard]] constexpr OutputIterator
1106  parse_to_t const &value ) {
1107 
1108  using tuple_t = typename JsonMember::parse_to_t;
1109  using element_pack = tuple_elements_pack<tuple_t>;
1110 
1111  static_assert( is_tuple_v<tuple_t>, "Expected tuple like type" );
1112  static_assert(
1113  std::is_convertible<parse_to_t, tuple_t>::value,
1114  "value must be convertible to specified type in class contract" );
1115 
1116  *it++ = '[';
1117  it = to_daw_json_string_tuple<JsonMember>(
1118  it, value, std::make_index_sequence<element_pack::size>{ } );
1119  *it++ = ']';
1120  return it;
1121  }
1122 
1123  template<typename JsonMember, typename OutputIterator,
1124  typename parse_to_t>
1125  [[nodiscard]] constexpr OutputIterator
1127  parse_to_t const &value ) {
1128 
1129  using array_t = typename JsonMember::parse_to_t;
1130  if constexpr( is_container_v<array_t> ) {
1131  static_assert(
1132  std::is_convertible<parse_to_t, array_t>::value,
1133  "value must be convertible to specified type in class contract" );
1134  } else {
1135  static_assert(
1137  "This is a special case for pointer like(T*, unique_ptr<T>, "
1138  "shared_ptr<T>) arrays. In the to_json_data it is required to "
1139  "encode the size of the data with the pointer. Will take any "
1140  "Container like type, but std::span like types work too" );
1141  static_assert(
1142  is_container_v<parse_to_t>,
1143  "This is a special case for pointer like(T*, unique_ptr<T>, "
1144  "shared_ptr<T>) arrays. In the to_json_data it is required to "
1145  "encode the size of the data with the pointer. Will take any "
1146  "Container like type, but std::span like types work too" );
1147  }
1148 
1149  *it++ = '[';
1150  if( not std::empty( value ) ) {
1151  auto count = std::size( value ) - 1U;
1152  for( auto const &v : value ) {
1153  it = to_daw_json_string<typename JsonMember::json_element_t>(
1155  if( count-- > 0 ) {
1156  *it++ = ',';
1157  }
1158  }
1159  }
1160  *it++ = ']';
1161  return it;
1162  }
1163 
1164  template<typename JsonMember, typename OutputIterator,
1165  typename parse_to_t>
1166  [[nodiscard]] constexpr OutputIterator
1168  OutputIterator it, parse_to_t const &value ) {
1169  return to_daw_json_string<JsonMember>(
1170  ParseTag<JsonParseTypes::Array>{ }, it, value );
1171  }
1172 
1173  template<typename Key, typename Value>
1174  [[maybe_unused]] inline constexpr Key const &
1175  json_get_key( std::pair<Key, Value> const &kv ) {
1176  return kv.first;
1177  }
1178 
1179  template<typename Key, typename Value>
1180  [[maybe_unused]] inline constexpr Value const &
1181  json_get_value( std::pair<Key, Value> const &kv ) {
1182  return kv.second;
1183  }
1184 
1185  template<typename JsonMember, typename OutputIterator,
1186  typename parse_to_t>
1187  [[nodiscard]] constexpr OutputIterator
1189  OutputIterator it, parse_to_t const &value ) {
1190 
1191  static_assert(
1192  std::is_convertible<parse_to_t,
1193  typename JsonMember::parse_to_t>::value,
1194  "value must be convertible to specified type in class contract" );
1195  using key_t = typename JsonMember::json_key_t;
1196  using value_t = typename JsonMember::json_value_t;
1197  *it++ = '[';
1198  if( not std::empty( value ) ) {
1199  auto count = std::size( value ) - 1U;
1200  for( auto const &v : value ) {
1201  *it++ = '{';
1202  // Append Key Name
1203  *it++ = '"';
1204  it = utils::copy_to_iterator( it, key_t::name );
1205  *it++ = '"';
1206  *it++ = ':';
1207  // Append Key Value
1208  it = to_daw_json_string<key_t>( ParseTag<key_t::expected_type>{ },
1209  it, json_get_key( v ) );
1210 
1211  *it++ = ',';
1212  // Append Value Name
1213  *it++ = '"';
1214  it = utils::copy_to_iterator( it, value_t::name );
1215  *it++ = '"';
1216  *it++ = ':';
1217  // Append Value Value
1218  it = to_daw_json_string<value_t>(
1220 
1221  *it++ = '}';
1222  if( count-- > 0 ) {
1223  *it++ = ',';
1224  }
1225  }
1226  }
1227  *it++ = ']';
1228  return it;
1229  }
1230 
1231  template<typename JsonMember, typename OutputIterator,
1232  typename parse_to_t>
1233  [[nodiscard]] constexpr OutputIterator
1235  parse_to_t const &value ) {
1236 
1237  *it++ = '{';
1238  if( not std::empty( value ) ) {
1239  auto count = std::size( value ) - 1U;
1240  for( auto const &v : value ) {
1241  it = to_daw_json_string<typename JsonMember::json_key_t>(
1243  json_get_key( v ) );
1244  *it++ = ':';
1245  it = to_daw_json_string<typename JsonMember::json_element_t>(
1247  json_get_value( v ) );
1248  if( count-- > 0 ) {
1249  *it++ = ',';
1250  }
1251  }
1252  }
1253  *it++ = '}';
1254  return it;
1255  }
1256 
1257  template<typename JsonMember, typename OutputIterator, typename T>
1258  [[nodiscard]] inline constexpr OutputIterator
1259  member_to_string( template_param<JsonMember>, OutputIterator it,
1260  T const &value ) {
1261  return to_daw_json_string<JsonMember>(
1262  ParseTag<JsonMember::expected_type>{ }, DAW_MOVE( it ), value );
1263  }
1264 
1265  template<std::size_t, typename JsonMember, typename /*NamePack*/,
1266  typename OutputIterator, typename TpArgs, typename Value,
1267  typename VisitedMembers,
1268  std::enable_if_t<not has_dependent_member_v<JsonMember>,
1269  std::nullptr_t> = nullptr>
1270  inline constexpr void
1271  dependent_member_to_json_str( bool &, OutputIterator const &,
1272  TpArgs const &, Value const &,
1273  VisitedMembers const & ) {
1274 
1275  // This is empty so that the call is able to be put into a pack
1276  }
1277 
1278  template<typename>
1280 
1281  template<typename Needle, typename... Haystack>
1282  constexpr std::size_t find_names_in_pack( daw::fwd_pack<Haystack...> ) {
1283  constexpr auto const names = std::array{ Haystack::name... };
1284  for( size_t n = 0; n < sizeof...( Haystack ); ++n ) {
1285  if( Needle::name == names[n] ) {
1286  return n;
1287  }
1288  }
1290  }
1291 
1292  template<std::size_t pos, typename JsonMember, typename NamePack,
1293  typename OutputIterator, typename TpArgs, typename Value,
1294  typename VisitedMembers,
1295  std::enable_if_t<has_dependent_member_v<JsonMember>,
1296  std::nullptr_t> = nullptr>
1297  constexpr void
1298  dependent_member_to_json_str( bool &is_first, OutputIterator it,
1299  TpArgs const &args, Value const &v,
1300  VisitedMembers &visited_members ) {
1301  using dependent_member = dependent_member_t<JsonMember>;
1302  static_assert( is_a_json_type<JsonMember>::value,
1303  "Unsupported data type" );
1304  if constexpr( JsonMember::nullable == JsonNullable::Nullable ) {
1305  // We have no requirement to output this member when it's null
1306  if( not get<pos>( args ) ) {
1307  return;
1308  }
1309  }
1310  constexpr auto dependent_member_name =
1311  daw::string_view( std::data( dependent_member::name ),
1312  std::size( dependent_member::name ) );
1313  if( daw::algorithm::contains( std::data( visited_members ),
1314  daw::data_end( visited_members ),
1315  dependent_member_name ) ) {
1316  // Already outputted this member
1317  return;
1318  }
1319  visited_members.push_back( dependent_member_name );
1320  if( not is_first ) {
1321  *it++ = ',';
1322  }
1323  is_first = false;
1324  *it++ = '"';
1325  it = utils::copy_to_iterator<false, EightBitModes::AllowFull>(
1326  it, dependent_member_name );
1327  it =
1328  utils::copy_to_iterator<false, EightBitModes::AllowFull>( it, "\":" );
1329  if constexpr( has_switcher_v<JsonMember> ) {
1330  it = member_to_string( template_arg<dependent_member>, it,
1331  typename JsonMember::switcher{ }( v ) );
1332  } else {
1333  constexpr std::size_t dependent_member_pos =
1334  find_names_in_pack<dependent_member>( NamePack{ } );
1335  it = member_to_string( template_arg<dependent_member>, it,
1336  get<dependent_member_pos>( args ) );
1337  }
1338  }
1339 
1340  template<std::size_t pos, typename JsonMember, typename OutputIterator,
1341  typename Tuple, typename Value, typename Visited>
1342  inline constexpr void to_json_str( bool &is_first, OutputIterator &it,
1343  Tuple const &tp, Value const &,
1344  Visited &visited_members ) {
1345  constexpr auto json_member_name = daw::string_view(
1346  std::data( JsonMember::name ), std::size( JsonMember::name ) );
1347  if( daw::algorithm::contains( std::data( visited_members ),
1348  daw::data_end( visited_members ),
1349  json_member_name ) ) {
1350  return;
1351  }
1352  visited_members.push_back( json_member_name );
1354  "Unsupported data type" );
1356  JsonMember::nullable == JsonNullable::Nullable ) {
1357  if( not json_details::has_value( get<pos>( tp ) ) ) {
1358  return;
1359  }
1360  }
1361  if( not is_first ) {
1362  *it++ = ',';
1363  }
1364  is_first = false;
1365  *it++ = '"';
1366  it = utils::copy_to_iterator<false, EightBitModes::AllowFull>(
1367  it, JsonMember::name );
1368 
1369  it =
1370  utils::copy_to_iterator<false, EightBitModes::AllowFull>( it, "\":" );
1371  it = member_to_string( template_arg<JsonMember>, DAW_MOVE( it ),
1372  get<pos>( tp ) );
1373  }
1374 
1375  template<size_t TupleIdx, typename JsonMember, typename OutputIterator,
1376  template<class...> class Tuple, typename... Args>
1377  constexpr void to_json_ordered_str( std::size_t &array_idx,
1378  OutputIterator &it,
1379  Tuple<Args...> const &tp ) {
1380 
1381  using json_member_type = ordered_member_subtype_t<JsonMember>;
1383  "Unsupported data type" );
1384  // json_tagged_variant like members cannot work as we have no member
1385  // names to work with
1386  static_assert(
1388  "JSON tagged variant types are not supported when inside an array "
1389  "as an ordered structure" );
1390 
1391  if constexpr( is_an_ordered_member_v<JsonMember> ) {
1392  for( ; array_idx < JsonMember::member_index; ++array_idx ) {
1393  if( array_idx > 0 ) {
1394  *it++ = ',';
1395  }
1396  *it++ = 'n';
1397  *it++ = 'u';
1398  *it++ = 'l';
1399  *it++ = 'l';
1400  }
1401  }
1402  if( array_idx > 0 ) {
1403  *it++ = ',';
1404  }
1405  it = member_to_string( template_arg<json_member_type>, it,
1406  get<TupleIdx>( tp ) );
1407  ++array_idx;
1408  }
1409  } // namespace json_details
1410  } // namespace DAW_JSON_VER
1411 } // namespace daw::json
Definition: daw_json_value.h:316
constexpr std::string_view get_string_view() const
Definition: daw_json_value.h:444
constexpr bool is_null() const
Definition: daw_json_value.h:485
#define daw_json_assert(Bool,...)
Definition: daw_json_assert.h:178
ParseState & tmp
Definition: daw_json_iterator.h:37
Iterator & it
Definition: daw_json_traits.h:231
constexpr ymdhms time_point_to_civil(std::chrono::time_point< Clock, Duration > const &tp)
Definition: daw_json_parse_iso8601_utils.h:274
auto use_stream(std::string_view sv)
Definition: to_daw_json_string.h:200
auto to_string_test(T &&v) -> decltype(to_string(DAW_FWD2(T, v)))
decltype(to_string_test(std::declval< T >())) to_string_result
Definition: to_daw_json_string.h:85
constexpr bool has_to_string_v
Definition: to_daw_json_string.h:93
daw::is_detected< to_string_test::to_string_result, T > has_to_string
Definition: to_daw_json_string.h:90
constexpr auto to_string(std::optional< T > const &v) -> decltype(to_string(*v))
Definition: to_daw_json_string.h:71
constexpr void to_variant_string(OutputIterator &it, parse_to_t const &value)
Definition: to_daw_json_string.h:593
std::bool_constant< JsonType::expected_type==JsonParseTypes::Null > is_json_nullable
Definition: daw_json_parse_common.h:289
constexpr auto digits100
Definition: to_daw_json_string.h:732
daw::remove_cvref_t< decltype(deref_detect(std::declval< T >()))> deref_t
Definition: to_daw_json_string.h:638
OutputIterator to_daw_json_string_tuple(OutputIterator it, parse_to_t const &value, std::index_sequence< Is... >)
Definition: to_daw_json_string.h:1071
constexpr bool has_istream_op_v
Definition: to_daw_json_string.h:118
decltype(from_string(std::declval< daw::tag_t< T > >(), std::declval< std::string_view >())) from_string_test
Definition: to_daw_json_string.h:99
typename json_type_deducer< T, has_json_data_contract_trait_v< T >, json_details::is_a_json_type_v< T >, has_json_link_quick_map_v< T >, is_container_v< T > >::type json_deduced_type
Definition: daw_json_parse_common.h:931
constexpr Value const & json_get_value(std::pair< Key, Value > const &kv)
Definition: to_daw_json_string.h:1181
constexpr OutputIterator member_to_string(template_param< JsonMember >, OutputIterator it, T const &value)
Definition: to_daw_json_string.h:1259
daw::is_detected< is_a_json_tagged_variant_test, T > is_a_json_tagged_variant
Definition: daw_json_traits.h:449
decltype(operator>>(std::declval< T & >(), std::declval< U const & >())) has_rshift_test
Definition: to_daw_json_string.h:111
decltype(operator<<(std::declval< T & >(), std::declval< U const & >())) has_lshift_test
Definition: to_daw_json_string.h:107
constexpr bool has_from_string_v
Definition: to_daw_json_string.h:102
constexpr void to_json_ordered_str(std::size_t &array_idx, OutputIterator &it, Tuple< Args... > const &tp)
Definition: to_daw_json_string.h:1377
std::bool_constant< daw::is_detected_v< json_type_t, T > > is_a_json_type
Definition: daw_json_traits.h:426
typename daw::detected_or_t< T, ordered_member_subtype_test, T > ordered_member_subtype_t
Definition: daw_json_parse_common.h:54
constexpr auto has_value(T const &v) -> std::enable_if_t< is_readable_v< T >, bool >
Definition: daw_json_traits.h:60
constexpr char to_nibble_char(Char c)
Definition: to_daw_json_string.h:329
std::underlying_type< T > base_int_type_impl
Definition: to_daw_json_string.h:725
constexpr bool is_valid_optional_v
Definition: to_daw_json_string.h:641
typename JsonMember::dependent_member dependent_member_t
Definition: daw_json_parse_common.h:961
constexpr void utf32_to_utf8(std::uint32_t cp, OutputIterator &it)
Definition: to_daw_json_string.h:360
typename std::conditional_t< std::is_enum_v< T >, base_int_type_impl< T >, daw::traits::identity< T > >::type base_int_type_t
Definition: to_daw_json_string.h:730
constexpr void dependent_member_to_json_str(bool &, OutputIterator const &, TpArgs const &, Value const &, VisitedMembers const &)
Definition: to_daw_json_string.h:1271
constexpr OutputIterator to_daw_json_string(ParseTag< JsonParseTypes::Null >, OutputIterator it, parse_to_t const &value)
constexpr OutputIterator output_hex(std::uint16_t c, OutputIterator it)
Definition: to_daw_json_string.h:341
constexpr Key const & json_get_key(std::pair< Key, Value > const &kv)
Definition: to_daw_json_string.h:1175
constexpr bool is_null(std::optional< T > const &v)
Definition: to_daw_json_string.h:942
constexpr bool has_ostream_op_v
Definition: to_daw_json_string.h:114
constexpr void to_json_str(bool &is_first, OutputIterator &it, Tuple const &tp, Value const &, Visited &visited_members)
Definition: to_daw_json_string.h:1342
constexpr std::size_t find_names_in_pack(daw::fwd_pack< Haystack... >)
Definition: to_daw_json_string.h:1282
constexpr auto deref_detect(T &&value) -> decltype(*value)
constexpr OutputIterator integer_to_string(OutputIterator it, Integer const &value)
Definition: to_daw_json_string.h:884
constexpr OutputIterator copy_to_iterator(OutputIterator it, Container const &container)
Definition: to_daw_json_string.h:398
EightBitModes
Definition: daw_json_type_options.h:104
constexpr std::string_view to_string(JsonBaseParseTypes pt)
Definition: daw_json_enums.h:50
LiteralAsStringOpt
Definition: daw_json_type_options.h:38
typename json_data_contract< T >::type json_data_contract_trait_t
Definition: daw_json_traits.h:133
std::integral_constant< JsonParseTypes, v > ParseTag
Definition: daw_json_enums.h:106
DAW_ATTRIB_NOINLINE void daw_json_error(ErrorReason reason)
Definition: daw_json_assert.h:39
constexpr OutputIterator real2string(Real const &value, OutputIterator out_it)
Definition: to_daw_json_string.h:46
Definition: daw_from_json.h:22
Definition: daw_json_parse_iso8601_utils.h:263
std::int_least32_t year
Definition: daw_json_parse_iso8601_utils.h:264
std::uint_least32_t second
Definition: daw_json_parse_iso8601_utils.h:269
std::uint_least32_t month
Definition: daw_json_parse_iso8601_utils.h:265
std::uint_least32_t hour
Definition: daw_json_parse_iso8601_utils.h:267
std::uint_least32_t day
Definition: daw_json_parse_iso8601_utils.h:266
std::uint_least32_t minute
Definition: daw_json_parse_iso8601_utils.h:268
std::uint_least32_t millisecond
Definition: daw_json_parse_iso8601_utils.h:270
Definition: to_daw_json_string.h:210
Definition: to_daw_json_string.h:131
static auto use_stream(U const &v)
Definition: to_daw_json_string.h:133
Definition: daw_json_traits.h:632
Definition: daw_json_traits.h:125
Definition: daw_json_value_state.h:56
Allow tuple like types to be used in json_tuple.
Definition: daw_json_traits.h:638
Definition: to_daw_json_string.h:875
static constexpr LiteralAsStringOpt literal_as_string
Definition: to_daw_json_string.h:877
Integer parse_to_t
Definition: to_daw_json_string.h:876
#define DAW_JSON_VER
Definition: version.h:11