DAW JSON Link
daw_json_serialize_impl.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 #pragma once
9 
10 #include "version.h"
11 
12 #include "to_daw_json_string.h"
13 
14 #include <daw/daw_empty.h>
15 #include <daw/daw_fwd_pack_apply.h>
16 #include <daw/daw_string_view.h>
17 #include <daw/daw_undefined.h>
18 #include <daw/traits/daw_traits_nth_element.h>
19 
20 #include <cassert>
21 #include <cstddef>
22 #include <daw/stdinc/integer_sequence.h>
23 
24 namespace daw::json {
25  inline namespace DAW_JSON_VER {
26  namespace json_details {
27 
28  template<typename T, std::size_t Capacity>
29  struct basic_array_t {
30  static constexpr std::size_t capacity = Capacity;
31 
32  private:
33  std::size_t position{ };
34  daw::string_view array[capacity]{ };
35 
36  public:
37  basic_array_t( ) = default;
38 
39  DAW_ATTRIB_RET_NONNULL
40  constexpr T const *data( ) const {
41  return array;
42  }
43 
44  DAW_ATTRIB_RET_NONNULL
45  constexpr T *data( ) {
46  return array;
47  }
48 
49  constexpr std::size_t size( ) const {
50  return position;
51  }
52 
53  constexpr void push_back( T const &v ) {
54  assert( position < capacity );
55  array[position] = v;
56  ++position;
57  }
58  };
59 
60  template<typename T>
61  struct basic_array_t<T, 0> {
62  static constexpr std::size_t capacity = 0;
63 
64  basic_array_t( ) = default;
65 
66  DAW_CONSTEVAL T const *data( ) const {
67  return nullptr;
68  }
69 
70  DAW_CONSTEVAL T *data( ) {
71  return nullptr;
72  }
73 
74  DAW_CONSTEVAL std::size_t size( ) const {
75  return 0;
76  }
77  };
78 
79  /***
80  * Serialize items to an output iterator as members of a class
81  * @tparam JsonMembers member items in json_class
82  * @tparam OutputIterator An Output Iterator that allows writing
83  * character data
84  * @tparam Is index_sequence index into JsonMembers
85  * @tparam Tuple tuple type holding class members
86  * @tparam Value mapped class type to serialize
87  * @param it an Output Iterator to write char data to
88  * @param args A tuple of the member values
89  * @param value class to serialize
90  * @return The OutputIterator it at theposition
91  */
92  template<typename... JsonMembers, typename OutputIterator,
93  json_options_t SerializationOptions, std::size_t... Is,
94  typename Tuple, typename Value>
95  [[nodiscard]] DAW_ATTRIB_INLINE static constexpr serialization_policy<
96  OutputIterator, SerializationOptions>
97  serialize_json_class(
99  Tuple const &args, Value const &value, std::index_sequence<Is...> ) {
100 
101  it.put( '{' );
102  it.add_indent( );
103 
104  constexpr auto visit_size =
105  sizeof...( JsonMembers ) +
106  ( static_cast<std::size_t>( has_dependent_member_v<JsonMembers> ) +
107  ... + 0 );
108  auto visited_members = basic_array_t<daw::string_view, visit_size>{ };
109 
110  // Tag Members, if any. Putting them ahead means we can parse this
111  // faster in the future
112 
113  // Using list init to ensure serialization happens in order
114  bool is_first = true;
115 
116  // gcc complains when JsonMembers is empty
117  (void)visited_members;
118  (void)is_first;
119  {
120  using Names = daw::fwd_pack<JsonMembers...>;
121  daw::empty_t const expander[]{
122  ( dependent_member_to_json_str<
123  Is, daw::traits::nth_element<Is, JsonMembers...>, Names>(
124  is_first, it, args, value, visited_members ),
125  daw::empty_t{ } )...,
126  daw::empty_t{} };
127  (void)expander;
128  }
129 
130  // Regular Members
131  {
132  daw::empty_t const expander[]{
133  ( to_json_str<Is, daw::traits::nth_element<Is, JsonMembers...>>(
134  is_first, it, args, value, visited_members ),
135  daw::empty_t{ } )...,
136  daw::empty_t{} };
137  (void)expander;
138  }
139  it.del_indent( );
140  if constexpr( sizeof...( Is ) > 0 ) {
141  if constexpr( it.output_trailing_comma ==
142  options::OutputTrailingComma::Yes ) {
143  it.put( ',' );
144  }
145  it.next_member( );
146  }
147  it.put( '}' );
148  return it;
149  }
150 
151  template<typename... JsonMembers, typename OutputIterator,
152  json_options_t SerializerOptions, typename Tuple, typename Value,
153  std::size_t... Is>
154  [[nodiscard]] DAW_ATTRIB_INLINE static constexpr serialization_policy<
155  OutputIterator, SerializerOptions>
156  serialize_ordered_json_class(
158  Tuple const &args, Value const &value, std::index_sequence<Is...> ) {
159 
160  it.put( '[' );
161  it.add_indent( );
162  it.next_member( );
163  std::size_t array_idx = 0;
164  (void)array_idx; // gcc was complaining on empty pack
165  Unused( value );
166  {
167  daw::empty_t const expander[]{
168  ( to_json_ordered_str<Is,
169  daw::traits::nth_element<Is, JsonMembers...>>(
170  array_idx, sizeof...( Is ), it, args ),
171  daw::empty_t{ } )...,
172  daw::empty_t{} };
173  (void)expander;
174  }
175  it.del_indent( );
176  if constexpr( sizeof...( Is ) != 0 ) {
177  if constexpr( it.output_trailing_comma ==
178  options::OutputTrailingComma::Yes ) {
179  it.put( ',' );
180  }
181  it.next_member( );
182  }
183  it.put( ']' );
184  return it;
185  }
186  } // namespace json_details
187  } // namespace DAW_JSON_VER
188 } // namespace daw::json
Customization point traits.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition: version.h:25