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