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