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