16#if defined( DAW_JSON_HAS_REFLECTION )
17#include <daw/daw_concepts.h>
20#include <daw/daw_move.h>
21#include <daw/traits/daw_traits_remove_cvref.h>
28 namespace json_writer_details {
29 template<
typename JsonClass,
typename Value>
30 using json_write_value_class_t =
31 json_details::json_serialize_deduced_type<JsonClass, Value>;
33 enum class json_writer_states : std::uint8_t {
49 template<
typename WritableType,
typename StackType,
auto... PolicyFlags>
52 decltype( json_details::make_output_iterator<PolicyFlags...>(
53 std::declval<WritableType>( ) ) );
56 json_writer_details::json_writer_states m_current_state =
57 json_writer_details::json_writer_states::json_writer_nothing;
58 bool m_is_first =
true;
59 bool m_is_key_written =
false;
63 push_state( json_writer_details::json_writer_states new_state ) {
64 m_stack.push_back( m_current_state );
65 m_current_state = new_state;
70 m_current_state = m_stack.back( );
76 if( not m_is_first ) {
81 m_writer.next_member( );
85 if( m_current_state ==
86 json_writer_details::json_writer_states::json_writer_nothing ) {
90 if( m_current_state ==
91 json_writer_details::json_writer_states::json_writer_object ) {
93 m_is_key_written =
false;
96 if( m_current_state !=
97 json_writer_details::json_writer_states::json_writer_nothing ) {
102 template<
typename JsonClass = use_default,
typename T>
104 if constexpr( json_details::is_char_pointer_v<T> ) {
107 if( value ==
nullptr ) {
109 m_writer.write(
"null" );
112 do_write_value<JsonClass>( daw::string_view( value ) );
114 }
else if constexpr( json_details::is_char_array_v<T> ) {
117 do_write_value<JsonClass>(
118 daw::string_view( value, std::extent_v<T> - 1U ) );
121 json_details::json_serialize_deduced_type<JsonClass, T>;
123 if constexpr( std::is_pointer_v<std::remove_reference_t<T>> ) {
125 m_writer.write(
"null" );
128 json_details::member_to_string<json_class_t>( m_writer, value );
132 json_details::member_to_string<json_class_t>( m_writer, value );
141 : m_writer( json_details::make_output_iterator<PolicyFlags...>(
142 DAW_FWD( writer ) ) ) {}
149 if( m_is_key_written ) {
150 write_value(
nullptr );
152 while( m_current_state !=
153 json_writer_details::json_writer_states::json_writer_nothing ) {
154 switch( m_current_state ) {
155 case json_writer_details::json_writer_states::json_writer_object:
158 case json_writer_details::json_writer_states::json_writer_array:
161 case json_writer_details::json_writer_states::json_writer_nothing:
171 json_writer_details::json_writer_states::json_writer_nothing;
173 m_is_key_written =
false;
177 noexcept( m_writer.put( ' ' ) ) ) {
184 json_writer_details::json_writer_states::json_writer_object );
186 m_writer.add_indent( );
193 json_writer_details::json_writer_states::json_writer_object,
194 ErrorReason::OutputError );
195 if( m_is_key_written ) {
196 write_value(
nullptr );
198 m_writer.del_indent( );
199 if( not m_is_first ) {
200 if constexpr( iterator_t::output_trailing_comma ==
201 options::OutputTrailingComma::Yes ) {
204 m_writer.next_member( );
214 json_writer_details::json_writer_states::json_writer_array );
216 m_writer.add_indent( );
223 json_writer_details::json_writer_states::json_writer_array,
224 ErrorReason::OutputError );
225 m_writer.del_indent( );
226 if( not m_is_first ) {
227 if constexpr( iterator_t::output_trailing_comma ==
228 options::OutputTrailingComma::Yes ) {
231 m_writer.next_member( );
242 template<
typename JsonClass = use_default,
typename T>
246 json_writer_details::json_writer_states::json_writer_object or
248 ErrorReason::OutputError );
251 json_writer_details::json_writer_states::json_writer_nothing or
253 ErrorReason::OutputError );
255 do_write_value<JsonClass>( value );
258 template<
typename T,
typename T2,
typename... Ts>
260 Ts
const &...values ) {
263 json_writer_details::json_writer_states::json_writer_object or
265 ErrorReason::OutputError );
268 json_writer_details::json_writer_states::json_writer_nothing or
270 ErrorReason::OutputError );
272 write_array_values( value, value2, values... );
276 template<
typename JsonClass = use_default,
typename T>
277 constexpr void write_value( std::initializer_list<T>
const &values ) {
280 json_writer_details::json_writer_states::json_writer_object or
282 ErrorReason::OutputError );
285 json_writer_details::json_writer_states::json_writer_nothing or
287 ErrorReason::OutputError );
289 write_array_values<JsonClass>( values );
293 template<JSONNAMETYPE Name>
295 if( m_is_key_written ) {
296 write_value(
nullptr );
300 json_writer_details::json_writer_states::json_writer_object,
301 ErrorReason::OutputError );
303 write_item_prefix( );
305 '"', json_details::encode_json_name_v<Name>,
"\":", m_writer.space );
306 m_is_key_written =
true;
309 constexpr void add_key( daw::string_view name ) {
310 if( m_is_key_written ) {
311 write_value(
nullptr );
315 json_writer_details::json_writer_states::json_writer_object,
316 ErrorReason::OutputError );
318 write_item_prefix( );
319 if constexpr( iterator_t::allow_escaped_names ) {
321 m_writer = json_details::encode_name( m_writer, name );
322 m_writer.write(
"\":", m_writer.space );
324 m_writer.write(
'"', name,
"\":", m_writer.space );
326 m_is_key_written =
true;
334 template<
typename JsonClass = use_default,
typename T>
336 std::initializer_list<T>
const &values ) {
339 write_array_values<JsonClass>( values );
343 template<
typename JsonClass = use_default,
typename T>
346 write_value<JsonClass>( value );
349 template<
typename T,
typename T2,
typename... Ts>
351 T2
const &value2, Ts
const &...values ) {
354 write_array_values( value, value2, values... );
358 template<JSONNAMETYPE Name>
360 add_static_key<Name>( );
364 template<JSONNAMETYPE Name,
typename JsonClass = use_default,
typename T>
367 add_static_key<Name>( );
369 write_array_values<JsonClass>( values );
373 template<JSONNAMETYPE Name,
typename JsonClass = use_default,
typename T>
375 add_static_key<Name>( );
376 write_value<JsonClass>( value );
379 template<
JSONNAMETYPE Name,
typename T,
typename T2,
typename... Ts>
381 Ts
const &...values ) {
382 add_static_key<Name>( );
384 write_array_values( value, value2, values... );
390 typename JsonClass = use_default,
391 typename Range DAW_ENABLEIF( daw::traits::is_container_like_v<Range> )>
393 constexpr
void write_array_values( Range const &values ) {
396 json_writer_details::json_writer_states::json_writer_array,
397 ErrorReason::OutputError );
398 for(
auto const &value : values ) {
399 do_write_value<JsonClass>( value );
403 template<
typename JsonClass = use_default,
typename T>
408 json_writer_details::json_writer_states::json_writer_array,
409 ErrorReason::OutputError );
410 for(
auto const &value : values ) {
411 write_value<JsonClass>( value );
415 template<
typename T,
typename... Ts>
419 json_writer_details::json_writer_states::json_writer_array,
420 ErrorReason::OutputError );
421 write_value( value );
422 (void)( ( write_value( values ),
true ) and ... );
432 json_writer_details::json_writer_states::json_writer_nothing or
434 ErrorReason::OutputError );
436 m_writer.write(
"null" );
440 template<
typename JsonClass = use_default,
typename T>
443 json_writer_details::json_write_value_class_t<JsonClass, T>;
445 JsonMember::underlying_json_type;
447 json_base_type == JsonBaseParseTypes::Number or
448 json_base_type == JsonBaseParseTypes::Bool,
449 "The underlying mapping must be a number or boolean type" );
450 if constexpr( json_base_type == JsonBaseParseTypes::Bool ) {
451 write_value<JsonClass>(
static_cast<bool>( value ) ? 1 : 0 );
454 write_value<JsonClass>( value );
462 json_details::json_serialize_deduced_type<use_default, T>;
463 auto tmp = std::string{ };
465 json_details::make_output_iterator<PolicyFlags...>( tmp );
466 tmp_iterator.indentation_level = m_writer.indentation_level;
467 (void)json_details::member_to_string<json_class_t>( tmp_iterator,
469 do_write_value<json_string_no_name<>>( tmp );
473 template<
typename JsonClass = use_default,
typename T>
475 if constexpr( json_details::is_char_pointer_v<T> or
476 json_details::is_char_array_v<T> ) {
477 write_value<JsonClass>( value );
479 write_string_impl<JsonClass>( value );
484 template<
typename JsonClass,
typename T>
487 json_writer_details::json_write_value_class_t<JsonClass, T>;
489 JsonMember::underlying_json_type;
490 if constexpr( json_base_type == JsonBaseParseTypes::String ) {
491 write_value<JsonClass>( value );
492 }
else if constexpr( json_base_type == JsonBaseParseTypes::Bool or
493 json_base_type == JsonBaseParseTypes::Number ) {
497 json_details::member_to_string<JsonMember>( m_writer, value );
501 write_string_class( value );
505#if defined( DAW_JSON_HAS_REFLECTION )
507 constexpr void write_enum_string( daw::EnumType
auto e ) {
508 write_string( refl_details::enum_to_string( e ) );
513 template<json_options_t NumberOptions = number_opts_def>
514 constexpr void write_enum_string_or_number( daw::EnumType
auto e ) {
516 refl_details::enum_string_or_number<
decltype( e ), NumberOptions>>(
522 template<
auto... PolicyFlags,
typename WriterType>
523 constexpr auto json_writer( WriterType &&writer DAW_LIFETIME_BOUND ) {
525 std::vector<json_writer_details::json_writer_states>,
526 PolicyFlags...>( writer );
constexpr void write_boolean(bool b)
constexpr void do_write_value(T const &value)
constexpr void write_null()
DAW_CPP20_CX_DTOR ~json_writer_t() noexcept(noexcept(m_writer.put(' ')))
constexpr void prepare_value()
constexpr void write_number(T const &value)
constexpr void write_array_values(std::initializer_list< T > const &values)
json_writer_t(json_writer_t &&other)=delete
constexpr void write_key_value(daw::string_view name, std::nullptr_t)
constexpr void close_object()
constexpr void open_array()
DAW_CPP20_CX_ALLOC void write_string_class(T const &value)
constexpr void write_string_impl(T const &value)
constexpr void write_string(T const &value)
constexpr void write_static_key_value(std::initializer_list< T > const &values)
json_writer_t & operator=(json_writer_t &&)=delete
constexpr void write_value(T const &value)
json_writer_t & operator=(json_writer_t const &)=delete
constexpr void finalize()
constexpr void write_value(T const &value, T2 const &value2, Ts const &...values)
constexpr void open_object()
constexpr void write_item_prefix()
constexpr void push_state(json_writer_details::json_writer_states new_state)
constexpr void write_static_key_value(T const &value)
constexpr void write_key_value(daw::string_view name, std::initializer_list< T > const &values)
constexpr void write_value(std::initializer_list< T > const &values)
constexpr void add_static_key()
constexpr void write_static_key_value(T const &value, T2 const &value2, Ts const &...values)
json_writer_t(json_writer_t const &)=delete
constexpr void write_value(std::nullptr_t)
constexpr void write_array_values(T const &value, Ts const &...values)
decltype(json_details::make_output_iterator< PolicyFlags... >(std::declval< WritableType >())) iterator_t
constexpr void pop_state()
constexpr void close_array()
constexpr void write_static_key_value(std::nullptr_t)
constexpr void write_key_value(daw::string_view name, T const &value, T2 const &value2, Ts const &...values)
constexpr json_writer_t(W &&writer DAW_LIFETIME_BOUND)
constexpr void write_key_value(daw::string_view name, T const &value)
constexpr void add_key(daw::string_view name)
#define daw_json_ensure(Bool,...)
Ensure that Bool is true. If false pass rest of args to daw_json_error.
DAW_REQUIRES(daw::json::json_details::is_container_opted_into_json_iostreams_v< Container >) std
An opt in ostream interface for containers of types that have JSON mappings.
JsonBaseParseTypes
The fundamental JSON types.
constexpr auto json_writer(WriterType &&writer DAW_LIFETIME_BOUND)
string_writer grows its string with resize_and_overwrite, leaving the new bytes uninitialized,...
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.