13 #include <daw/cpp_17.h>
14 #include <daw/daw_attributes.h>
15 #include <daw/daw_traits.h>
25 namespace json_details {
28 inline constexpr
unsigned json_option_bits_width = 0;
31 inline constexpr
auto default_json_option_value = [] {
32 struct unknown_policy {};
33 return unknown_policy{ };
36 template<
typename Policy,
typename Options>
37 struct option_bits_start_impl;
39 template<
typename Policy,
typename... Options>
40 struct option_bits_start_impl<Policy, pack_list<Options...>> {
41 static constexpr
auto idx =
42 daw::traits::pack_index_of_v<Policy, Options...>;
43 static_assert( idx >= 0,
"Policy is not registered" );
44 using tp_policies = pack_list<Options...>;
46 template<std::
size_t Pos,
int End>
47 static constexpr
unsigned do_step( ) {
48 if constexpr( Pos >=
static_cast<std::size_t
>( End ) ) {
51 return json_option_bits_width<pack_element_t<Pos, tp_policies>>;
54 template<std::size_t... Is>
55 DAW_ATTRIB_INLINE
static constexpr
unsigned
56 calc( std::index_sequence<Is...> ) {
57 return ( do_step<Is, idx>( ) + ... );
61 template<
typename... Options>
62 struct option_list_impl {
63 using type = pack_list<Options...>;
66 ( json_option_bits_width<Options> + ... + 0 ) <=
68 "The size of json_options_t is not large enough "
69 "to safely hold all the bits of state. Use a larger size." );
72 template<
typename Option>
73 inline constexpr
bool is_option_flag = json_option_bits_width<Option> > 0;
75 template<
typename... Options>
76 inline constexpr
bool are_option_flags =
77 ( is_option_flag<Options> and ... );
79 template<
typename Option,
typename Options>
80 inline constexpr
unsigned basic_option_bits_start =
81 option_bits_start_impl<Option, Options>::template calc<>(
82 std::make_index_sequence<pack_size_v<Options>>{ } );
84 template<
typename... JsonOptions>
85 struct JsonOptionList;
87 template<
typename... OptionList,
typename Option>
89 set_bits_for( JsonOptionList<OptionList...>, Option e );
91 template<
typename... JsonOptions>
92 struct JsonOptionList {
93 using OptionList =
typename option_list_impl<JsonOptions...>::type;
95 template<
typename Option>
96 static inline constexpr
unsigned option_bits_start =
97 basic_option_bits_start<Option, OptionList>;
99 template<
typename... ,
typename Option>
101 static_assert( is_option_flag<Option>,
102 "Only registered policy types are allowed" );
104 new_bits <<= option_bits_start<Option>;
109 ( set_bits_for<JsonOptions>(
110 default_json_option_value<JsonOptions> ) |
119 template<
typename... Options>
121 static_assert( json_details::are_option_flags<Options...>,
122 "Only registered option types are allowed" );
123 auto result = default_option_flag;
124 if constexpr(
sizeof...( Options ) > 0 ) {
125 result |= ( set_bits_for( options ) | ... );
131 template<
typename... OptionList,
typename Option>
132 constexpr
void set_bits_in( JsonOptionList<OptionList...>,
134 static_assert( is_option_flag<Option>,
135 "Only registered policy types are allowed" );
136 auto new_bits =
static_cast<unsigned>( e );
137 constexpr
unsigned mask = (1U << json_option_bits_width<Option>)-1U;
140 JsonOptionList<OptionList...>::template option_bits_start<Option>;
145 template<
typename... OptionList,
typename Option,
typename... Options>
149 static_assert( are_option_flags<Options...>,
150 "Only registered policy types are allowed" );
152 auto new_bits =
static_cast<unsigned>( pol );
153 constexpr
unsigned mask = ( (1U << json_option_bits_width<Option>)-1U );
156 JsonOptionList<OptionList...>::template option_bits_start<Option>;
157 value &= ~( mask << JsonOptionList<
158 OptionList...>::template option_bits_start<Option> );
160 if constexpr(
sizeof...( Options ) > 0 ) {
161 return set_bits( JsonOptionList<OptionList...>{ }, value, pols... );
167 template<
typename... OptionList,
typename Option>
169 set_bits_for( JsonOptionList<OptionList...>, Option e ) {
170 return JsonOptionList<OptionList...>::set_bits_for( e );
173 template<
typename Option,
typename Result = Option,
174 typename... OptionList>
175 constexpr Result get_bits_for( JsonOptionList<OptionList...>,
177 static_assert( std::is_enum_v<Option>,
178 "Only enum options are allowed" );
179 static_assert( std::is_same_v<
unsigned, std::underlying_type_t<Option>>,
180 "Looks like option was no specified correctly. "
181 "Underlying type should be unsigned" );
182 static_assert( is_option_flag<Option>,
183 "Only registered option types are allowed" );
184 constexpr
unsigned mask =
185 ( 1U << (JsonOptionList<OptionList...>::template option_bits_start<
187 json_option_bits_width<Option>)) -
191 JsonOptionList<OptionList...>::template option_bits_start<Option>;
192 return static_cast<Result
>( Option{ value } );
195 template<
typename... OptionList,
typename... Options>
196 constexpr
json_options_t json_option( JsonOptionList<OptionList...>,
197 Options... options ) {
198 return JsonOptionList<OptionList...>::options( options... );
202 struct default_option_flag_t;
204 template<
template<
class...>
class OptionList,
typename... Options>
205 struct default_option_flag_t<OptionList<Options...>> {
207 ( OptionList<Options...>::template set_bits_for<Options>(
208 default_json_option_value<Options> ) |
215 template<
typename OptionList>
217 default_option_flag_t<OptionList>::value;
std::uint32_t json_options_t
Customization point traits.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.