28 namespace json_details {
31 inline constexpr unsigned json_option_bits_width = 0;
34 inline constexpr auto default_json_option_value =
35 [] DAW_CPP23_STATIC_CALL_OP {
36 struct unknown_policy {};
37 return unknown_policy{ };
40 template<
typename Policy,
typename Options>
41 struct option_bits_start_impl;
43 template<
typename Policy,
typename... Options>
44 struct option_bits_start_impl<Policy, pack_list<Options...>> {
45 static constexpr auto idx =
46 daw::traits::pack_index_of_v<Policy, Options...>;
47 static_assert( idx >= 0,
"Policy is not registered" );
48 using tp_policies = pack_list<Options...>;
50 template<std::
size_t Pos,
int End>
51 static DAW_CONSTEVAL
unsigned do_step( ) {
52 if constexpr( Pos >=
static_cast<std::size_t
>( End ) ) {
55 return json_option_bits_width<pack_element_t<Pos, tp_policies>>;
58 template<std::size_t... Is>
59 DAW_ATTRIB_INLINE
static DAW_CONSTEVAL
unsigned
60 calc( std::index_sequence<Is...> ) {
61 return ( do_step<Is, idx>( ) + ... );
65 template<
typename... Options>
66 struct option_list_impl {
67 using type = pack_list<Options...>;
70 ( json_option_bits_width<Options> + ... + 0 ) <=
71 daw::bit_count_v<json_options_t>,
72 "The size of json_options_t is not large enough "
73 "to safely hold all the bits of state. Use a larger size." );
76 template<
typename Option>
77 DAW_CPP20_CONCEPT is_option_flag = json_option_bits_width<Option> > 0;
79 template<
typename... Options>
80 DAW_CPP20_CONCEPT are_option_flags = ( is_option_flag<Options> and ... );
82 template<
typename Option,
typename Options>
83 inline constexpr unsigned basic_option_bits_start =
84 option_bits_start_impl<Option, Options>::template calc<>(
85 std::make_index_sequence<pack_size_v<Options>>{ } );
87 template<
typename... JsonOptions>
88 struct JsonOptionList;
90 template<
typename... OptionList,
typename Option>
92 set_bits_for( JsonOptionList<OptionList...>, Option e );
94 template<
typename... JsonOptions>
95 struct JsonOptionList {
96 using OptionList =
typename option_list_impl<JsonOptions...>::type;
98 template<
typename Option>
99 static constexpr unsigned option_bits_start =
100 basic_option_bits_start<Option, OptionList>;
102 template<
typename... ,
typename Option>
104 static_assert( is_option_flag<Option>,
105 "Only registered policy types are allowed" );
107 new_bits <<= option_bits_start<Option>;
112 ( set_bits_for<JsonOptions>(
113 default_json_option_value<JsonOptions> ) |
122 template<
typename... Options>
124 static_assert( json_details::are_option_flags<Options...>,
125 "Only registered option types are allowed" );
126 auto result = default_option_flag;
127 if constexpr(
sizeof...( Options ) > 0 ) {
128 result |= ( set_bits_for( options ) | ... );
134 template<
typename... OptionList,
typename Option>
135 constexpr void set_bits_in( JsonOptionList<OptionList...>,
137 static_assert( is_option_flag<Option>,
138 "Only registered policy types are allowed" );
139 auto new_bits =
static_cast<unsigned>( e );
140 using mask = daw::constant<(1U << json_option_bits_width<Option>)-1U>;
141 new_bits &= mask::value;
143 JsonOptionList<OptionList...>::template option_bits_start<Option>;
144 value &= ~mask::value;
148 template<
typename... OptionList,
typename Option,
typename... Options>
152 static_assert( are_option_flags<Options...>,
153 "Only registered policy types are allowed" );
155 auto new_bits =
static_cast<unsigned>( pol );
157 daw::constant<( (1U << json_option_bits_width<Option>)-1U )>;
158 new_bits &= mask::value;
160 JsonOptionList<OptionList...>::template option_bits_start<Option>;
161 value &= ~( mask::value << JsonOptionList<
162 OptionList...>::template option_bits_start<Option> );
164 if constexpr(
sizeof...( Options ) > 0 ) {
165 return set_bits( JsonOptionList<OptionList...>{ }, value, pols... );
171 template<
typename... OptionList,
typename Option>
173 set_bits_for( JsonOptionList<OptionList...>, Option e ) {
174 return JsonOptionList<OptionList...>::set_bits_for( e );
177 template<
typename Option,
typename Result = Option,
178 typename... OptionList>
179 constexpr Result get_bits_for( JsonOptionList<OptionList...>,
181 static_assert( std::is_enum_v<Option>,
182 "Only enum options are allowed" );
183 static_assert( std::is_same_v<unsigned, std::underlying_type_t<Option>>,
184 "Looks like option was no specified correctly. "
185 "Underlying type should be unsigned" );
186 static_assert( is_option_flag<Option>,
187 "Only registered option types are allowed" );
189 daw::constant<( 1U << (JsonOptionList<OptionList...>::
190 template option_bits_start<Option> +
191 json_option_bits_width<Option>)) -
193 value &= mask::value;
195 JsonOptionList<OptionList...>::template option_bits_start<Option>;
196 return static_cast<Result
>( Option{ value } );
199 template<
typename... OptionList,
typename... Options>
200 constexpr json_options_t json_option( JsonOptionList<OptionList...>,
201 Options... options ) {
202 return JsonOptionList<OptionList...>::options( options... );
206 struct default_option_flag_t;
208 template<
template<
class...>
class OptionList,
typename... Options>
209 struct default_option_flag_t<OptionList<Options...>> {
211 ( OptionList<Options...>::template set_bits_for<Options>(
212 default_json_option_value<Options> ) |
219 template<
typename OptionList>
221 default_option_flag_t<OptionList>::value;