DAW JSON Link
Loading...
Searching...
No Matches
daw_json_option_bits.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
12
13#include <daw/cpp_17.h>
14#include <daw/daw_attributes.h>
15#include <daw/daw_bit_count.h>
16#include <daw/daw_constant.h>
17#include <daw/daw_consteval.h>
18#include <daw/daw_cpp20_concept.h>
19#include <daw/daw_traits.h>
20
21#include <climits>
22#include <cstddef>
23#include <cstdint>
24#include <utility>
25
26namespace daw::json {
27 inline namespace DAW_JSON_VER {
28 using json_options_t = std::uint32_t;
29 namespace json_details {
30
31 template<typename>
32 inline constexpr unsigned json_option_bits_width = 0;
33
34 template<typename>
35 inline constexpr auto default_json_option_value =
36 [] DAW_CPP23_STATIC_CALL_OP {
37 struct unknown_policy {};
38 return unknown_policy{ };
39 }( );
40
41 template<typename Policy, typename Options>
42 struct option_bits_start_impl;
43
44 template<typename Policy, typename... Options>
45 struct option_bits_start_impl<Policy, pack_list<Options...>> {
46 static constexpr auto idx =
47 daw::traits::pack_index_of_v<Policy, Options...>;
48 static_assert( idx >= 0, "Policy is not registered" );
49 using tp_policies = pack_list<Options...>;
50
51 template<std::size_t Pos, int End>
52 static DAW_CONSTEVAL unsigned do_step( ) {
53 if constexpr( Pos >= static_cast<std::size_t>( End ) ) {
54 return 0U;
55 }
56 return json_option_bits_width<pack_element_t<Pos, tp_policies>>;
57 }
58
59 template<std::size_t... Is>
60 DAW_ATTRIB_INLINE static DAW_CONSTEVAL unsigned
61 calc( std::index_sequence<Is...> ) {
62 return ( do_step<Is, idx>( ) + ... );
63 }
64 };
65
66 template<typename... Options>
67 struct option_list_impl {
68 using type = pack_list<Options...>;
69
70 static_assert(
71 ( json_option_bits_width<Options> + ... + 0 ) <=
72 daw::bit_count_v<json_options_t>,
73 "The size of json_options_t is not large enough "
74 "to safely hold all the bits of state. Use a larger size." );
75 };
76
77 template<typename Option>
78 DAW_CPP20_CONCEPT is_option_flag = json_option_bits_width<Option> > 0;
79
80 template<typename... Options>
81 DAW_CPP20_CONCEPT are_option_flags = ( is_option_flag<Options> and ... );
82
83 template<typename Option, typename Options>
84 inline constexpr unsigned basic_option_bits_start =
85 option_bits_start_impl<Option, Options>::template calc<>(
86 std::make_index_sequence<pack_size_v<Options>>{ } );
87
88 template<typename... JsonOptions>
89 struct JsonOptionList;
90
91 template<typename... OptionList, typename Option>
92 static constexpr json_options_t
93 set_bits_for( JsonOptionList<OptionList...>, Option e );
94
95 template<typename... OptionList, typename Option, typename... Options>
96 constexpr json_options_t set_bits( JsonOptionList<OptionList...>,
97 json_options_t value, Option pol,
98 Options... pols );
99
100 template<typename... JsonOptions>
101 struct JsonOptionList {
102 using OptionList = typename option_list_impl<JsonOptions...>::type;
103
104 template<typename Option>
105 static constexpr unsigned option_bits_start =
106 basic_option_bits_start<Option, OptionList>;
107
108 template<typename... /*OptionList*/, typename Option>
109 static constexpr json_options_t set_bits_for( Option e ) {
110 static_assert( is_option_flag<Option>,
111 "Only registered policy types are allowed" );
112 auto new_bits = static_cast<json_options_t>( e );
113 new_bits <<= option_bits_start<Option>;
114 return new_bits;
115 }
116
117 static constexpr json_options_t default_option_flag =
118 ( set_bits_for<JsonOptions>(
119 default_json_option_value<JsonOptions> ) |
120 ... | 0 );
121 /***
122 * Create the parser options flag for BasicParseOption
123 * @tparam Options Option types that satisfy the `is_option_flag`
124 * trait.
125 * @param policies A list of parser options to change from the defaults.
126 * @return A json_options_t that encodes the options for the parser
127 */
128 template<typename... Options>
129 static constexpr json_options_t options( Options... options ) {
130 static_assert( json_details::are_option_flags<Options...>,
131 "Only registered option types are allowed" );
132 if constexpr( sizeof...( Options ) > 0 ) {
133 return set_bits(
134 JsonOptionList{ }, default_option_flag, options... );
135 } else {
136 return default_option_flag;
137 }
138 }
139 };
140
141 template<typename... OptionList, typename Option>
142 constexpr void set_bits_in( JsonOptionList<OptionList...>,
143 json_options_t &value, Option e ) {
144 static_assert( is_option_flag<Option>,
145 "Only registered policy types are allowed" );
146 auto new_bits = static_cast<unsigned>( e );
147 using mask = daw::constant<(1U << json_option_bits_width<Option>)-1U>;
148 new_bits &= mask::value;
149 new_bits <<=
150 JsonOptionList<OptionList...>::template option_bits_start<Option>;
151 value &= ~mask::value;
152 value |= new_bits;
153 }
154
155 template<typename... OptionList, typename Option, typename... Options>
156 constexpr json_options_t set_bits( JsonOptionList<OptionList...>,
157 json_options_t value, Option pol,
158 Options... pols ) {
159 static_assert( are_option_flags<Options...>,
160 "Only registered policy types are allowed" );
161
162 auto new_bits = static_cast<unsigned>( pol );
163 using mask =
164 daw::constant<( (1U << json_option_bits_width<Option>)-1U )>;
165 new_bits &= mask::value;
166 new_bits <<=
167 JsonOptionList<OptionList...>::template option_bits_start<Option>;
168 value &= ~( mask::value << JsonOptionList<
169 OptionList...>::template option_bits_start<Option> );
170 value |= new_bits;
171 if constexpr( sizeof...( Options ) > 0 ) {
172 return set_bits( JsonOptionList<OptionList...>{ }, value, pols... );
173 } else {
174 return value;
175 }
176 }
177
178 template<typename... OptionList, typename Option>
179 static constexpr json_options_t
180 set_bits_for( JsonOptionList<OptionList...>, Option e ) {
181 return JsonOptionList<OptionList...>::set_bits_for( e );
182 }
183
184 template<typename Option, typename Result = Option,
185 typename... OptionList>
186 constexpr Result get_bits_for( JsonOptionList<OptionList...>,
187 json_options_t value ) {
188 static_assert( std::is_enum_v<Option>,
189 "Only enum options are allowed" );
190 static_assert( std::is_same_v<unsigned, std::underlying_type_t<Option>>,
191 "Looks like option was no specified correctly. "
192 "Underlying type should be unsigned" );
193 static_assert( is_option_flag<Option>,
194 "Only registered option types are allowed" );
195 using mask =
196 daw::constant<( 1U << (JsonOptionList<OptionList...>::
197 template option_bits_start<Option> +
198 json_option_bits_width<Option>)) -
199 1U>;
200 value &= mask::value;
201 value >>=
202 JsonOptionList<OptionList...>::template option_bits_start<Option>;
203 return static_cast<Result>( Option{ value } );
204 }
205
206 template<typename... OptionList, typename... Options>
207 constexpr json_options_t json_option( JsonOptionList<OptionList...>,
208 Options... options ) {
209 return JsonOptionList<OptionList...>::options( options... );
210 }
211
212 template<typename>
213 struct default_option_flag_t;
214
215 template<template<class...> class OptionList, typename... Options>
216 struct default_option_flag_t<OptionList<Options...>> {
217 static constexpr json_options_t value =
218 ( OptionList<Options...>::template set_bits_for<Options>(
219 default_json_option_value<Options> ) |
220 ... );
221 };
222
223 /***
224 * The defaults for all known policies encoded as a json_options_t
225 */
226 template<typename OptionList>
227 static inline constexpr json_options_t default_option_flag =
228 default_option_flag_t<OptionList>::value;
229 } // namespace json_details
230 } // namespace DAW_JSON_VER
231} // 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:20