emlabcpp
modern opinionated embedded C++ library
register_map.h
Go to the documentation of this file.
1 
24 #pragma once
25 
26 #include "../algorithm.h"
27 #include "./base.h"
28 #include "./traits.h"
29 
30 namespace emlabcpp::protocol
31 {
32 
35 template < auto Key, convertible D >
37 {
38  using def_type = D;
39  using key_type = decltype( Key );
40  static constexpr key_type key = Key;
42  using value_type = typename traits::value_type;
43  static constexpr std::size_t size = traits::max_size;
44 
46 
47  friend constexpr auto operator<=>( register_pair const&, register_pair const& ) = default;
48 };
49 
50 template < typename UnaryCallable, typename Registers >
52  invocable_returning< UnaryCallable, void, std::tuple_element_t< 0, Registers > >;
53 
61 template < std::endian Endianess, typename... Regs >
63 {
64  static_assert( are_same_v< typename Regs::key_type... > );
65 
66 public:
67  static constexpr std::endian endianess = Endianess;
68  using registers_tuple = std::tuple< Regs... >;
70  static constexpr auto max_key = std::max( { Regs::key... } );
71 
72  static constexpr std::size_t registers_count = sizeof...( Regs );
73  using register_index = bounded< std::size_t, 0, registers_count - 1 >;
74 
75  static constexpr std::size_t max_value_size = std::max( { Regs::traits::max_size... } );
77 
78 private:
79  registers_tuple registers_;
80 
81  static constexpr std::size_t get_reg_index( key_type k )
82  {
83  return find_if_index< std::tuple_size_v< registers_tuple > >(
84  [&k]< std::size_t i >() {
85  return std::tuple_element_t< i, registers_tuple >::key == k;
86  } );
87  }
88 
89 public:
90  template < key_type Key >
91  static constexpr std::size_t key_index = get_reg_index( Key );
92 
93  template < key_type Key >
94  static constexpr bool contains_key =
95  key_index< Key > != std::tuple_size_v< registers_tuple >;
96 
97  template < key_type Key >
98  using reg_type = std::tuple_element_t< key_index< Key >, registers_tuple >;
99 
100  template < key_type Key >
102 
103  template < key_type Key >
104  using traits = typename reg_type< Key >::traits;
105 
106  template < key_type Key >
108 
109  static constexpr std::array< key_type, registers_count > keys = { Regs::key... };
110 
111  register_map() = default;
112 
113  explicit register_map( typename Regs::value_type&... args )
114  : registers_( Regs{ args }... )
115  {
116  }
117 
118  constexpr explicit register_map( Regs const&... regs )
119  : registers_( regs... )
120  {
121  }
122 
123  [[nodiscard]] static constexpr bool contains( key_type key )
124  {
125  return get_reg_index( key ) != std::tuple_size_v< registers_tuple >;
126  }
127 
128  template < key_type Key >
129  [[nodiscard]] reg_value_type< Key > get_val() const
130  {
131  static_assert( contains_key< Key > );
132  reg_type< Key > const& reg = std::get< key_index< Key > >( registers_ );
133  return reg.value;
134  }
135 
136  template < key_type Key >
137  constexpr void set_val( reg_value_type< Key > val )
138  {
139  static_assert( contains_key< Key > );
140  reg_type< Key >& reg = std::get< key_index< Key > >( registers_ );
141  reg.value = val;
142  }
143 
144  static constexpr std::size_t register_size( register_index i )
145  {
146  return select_index( i, []< std::size_t j >() {
147  return std::tuple_element_t< j, registers_tuple >::size;
148  } );
149  }
150 
151  static constexpr key_type register_key( register_index i )
152  {
153  return select_index( i, []< std::size_t j >() {
154  return std::tuple_element_t< j, registers_tuple >::key;
155  } );
156  }
157 
158  template < typename UnaryCallable >
159  constexpr void setup_register( key_type key, UnaryCallable&& f )
160  {
162  key,
163  [this,
164  f = std::forward< UnaryCallable >( f )]< typename reg_type >( reg_type& reg ) {
165  reg.value = f.template operator()< reg_type >();
166  } );
167  }
168 
169  template < typename UnaryCallable >
170  constexpr auto with_register( key_type key, UnaryCallable&& f ) const
171  {
172  return with_register_impl( *this, key, std::forward< UnaryCallable >( f ) );
173  }
174 
175  template < typename UnaryCallable >
176  constexpr auto with_register( key_type key, UnaryCallable&& f )
177  {
178  return with_register_impl( *this, key, std::forward< UnaryCallable >( f ) );
179  }
180 
181  friend constexpr auto operator<=>( register_map const&, register_map const& ) = default;
182 
183  static constexpr void with_reg_type( key_type key, auto&& f )
184  {
185  until_index< registers_count >( [&key, &f]< std::size_t j >() {
186  using reg_type = std::tuple_element_t< j, registers_tuple >;
187  if ( reg_type::key != key )
188  return false;
189  f.template operator()< reg_type >();
190  return true;
191  } );
192  }
193 
194 private:
195  template < typename Class, typename UnaryCallable >
196  requires( !register_map_void_returning< UnaryCallable, registers_tuple > )
197  constexpr auto with_register_impl( Class& obj, key_type key, UnaryCallable&& f ) const
198  {
199  using ret_type = decltype( f( std::get< 0 >( registers_ ) ) );
200  ret_type res;
201  with_register_impl( obj, key, [&res, &f]( auto const& reg ) {
202  res = f( reg );
203  } );
204  return res;
205  }
206 
207  template < typename Class, typename UnaryCallable >
208  requires( register_map_void_returning< UnaryCallable, registers_tuple > )
209  static constexpr void with_register_impl( Class& obj, key_type key, UnaryCallable&& f )
210  {
211  until_index< registers_count >( [&obj, &key, &f]< std::size_t j >() {
212  using reg_type = std::tuple_element_t< j, registers_tuple >;
213  if ( reg_type::key != key )
214  return false;
215  f( std::get< j >( obj.registers_ ) );
216  return true;
217  } );
218  }
219 };
220 
221 template < typename Map, typename UnaryCallable >
222 void for_each_register( Map const& m, UnaryCallable&& f )
223 {
224  for_each_index< Map::registers_count >(
225  [&m, f = std::forward< UnaryCallable >( f )]< std::size_t i >() {
226  static constexpr auto key = Map::register_key( bounded_constant< i > );
227  f.template operator()< key >( m.template get_val< key >() );
228  } );
229 }
230 
231 #ifdef EMLABCPP_USE_OSTREAM
232 template < std::endian Endianess, typename... Regs >
233 std::ostream& operator<<( std::ostream& os, register_map< Endianess, Regs... > const& m )
234 {
235  for_each_register( m, [&os]< auto key, typename T >( T const& val ) {
236  os << key << "\t" << val << "\n";
237  } );
238 
239  return os;
240 }
241 #endif
242 
243 } // namespace emlabcpp::protocol
The bounded class represents a wrapper over type T constrained between MinVal and MaxVal as compile-t...
Definition: bounded.h:44
Protocol library has custom type that represents message, however this is just simple overaly over st...
Definition: message.h:40
Register map is abstraction to work with registers of external devices.
Definition: register_map.h:63
constexpr auto with_register(key_type key, UnaryCallable &&f) const
Definition: register_map.h:170
std::tuple< Regs... > registers_tuple
Definition: register_map.h:68
constexpr friend auto operator<=>(register_map const &, register_map const &)=default
static constexpr std::endian endianess
Definition: register_map.h:67
static constexpr std::size_t key_index
Definition: register_map.h:91
static constexpr std::size_t max_value_size
Definition: register_map.h:75
typename reg_type< Key >::value_type reg_value_type
Definition: register_map.h:101
static constexpr std::array< key_type, registers_count > keys
Definition: register_map.h:109
static constexpr std::size_t register_size(register_index i)
Definition: register_map.h:144
constexpr void setup_register(key_type key, UnaryCallable &&f)
Definition: register_map.h:159
reg_value_type< Key > get_val() const
Definition: register_map.h:129
static constexpr bool contains(key_type key)
Definition: register_map.h:123
static constexpr std::size_t registers_count
Definition: register_map.h:72
std::tuple_element_t< key_index< Key >, registers_tuple > reg_type
Definition: register_map.h:98
static constexpr key_type register_key(register_index i)
Definition: register_map.h:151
static constexpr auto max_key
Definition: register_map.h:70
typename reg_type< Key >::def_type reg_def_type
Definition: register_map.h:107
constexpr void set_val(reg_value_type< Key > val)
Definition: register_map.h:137
static constexpr void with_reg_type(key_type key, auto &&f)
Definition: register_map.h:183
register_map(typename Regs::value_type &... args)
Definition: register_map.h:113
typename reg_type< Key >::traits traits
Definition: register_map.h:104
typename std::tuple_element_t< 0, registers_tuple >::key_type key_type
Definition: register_map.h:69
static constexpr bool contains_key
Definition: register_map.h:94
constexpr register_map(Regs const &... regs)
Definition: register_map.h:118
constexpr auto with_register(key_type key, UnaryCallable &&f)
Definition: register_map.h:176
MIT License.
Definition: multiplexer.h:33
Endianess
Definition: serializer.h:70
static constexpr std::size_t max_size
Definition: serializer.h:73
void for_each_register(Map const &m, UnaryCallable &&f)
Definition: register_map.h:222
concept register_map_void_returning
Definition: register_map.h:51
Each definition of item provided to protocol library should have specialization of 'proto_traits' str...
Definition: traits.h:44
key_type_buffer key_type
Definition: base.h:47
std::variant< int64_t, float, bool, string_buffer > value_type
Definition: base.h:51
select_index(i, [&res, &f]< std::size_t i >() { res=f.template operator()< i >();})
Args const & args
Definition: min_max.h:83
T res
Definition: algorithm.h:505
constexpr Derived max(vec_point_base< Derived, N > const &a, vec_point_base< Derived, N > const &b)
Definition: vec_point_base.h:229
UnaryCallable
Definition: types.h:54
std::ostream & operator<<(std::ostream &os, string_buffer< N > const &sb)
Definition: string_buffer.h:112
UnaryCallable && f
Definition: algorithm.h:161
Structure that represents definition of one register in the map.
Definition: register_map.h:37
D def_type
Definition: register_map.h:38
decltype(Key) key_type
Definition: register_map.h:39
value_type value
Definition: register_map.h:45
static constexpr key_type key
Definition: register_map.h:40
typename traits::value_type value_type
Definition: register_map.h:42
static constexpr std::size_t size
Definition: register_map.h:43
constexpr friend auto operator<=>(register_pair const &, register_pair const &)=default