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