pstore2
bit_field.hpp
Go to the documentation of this file.
1 //===- include/pstore/support/bit_field.hpp ---------------*- mode: C++ -*-===//
2 //* _ _ _ __ _ _ _ *
3 //* | |__ (_) |_ / _(_) ___| | __| | *
4 //* | '_ \| | __| | |_| |/ _ \ |/ _` | *
5 //* | |_) | | |_ | _| | __/ | (_| | *
6 //* |_.__/|_|\__| |_| |_|\___|_|\__,_| *
7 //* *
8 //===----------------------------------------------------------------------===//
9 //
10 // Part of the pstore project, under the Apache License v2.0 with LLVM Exceptions.
11 // See https://github.com/SNSystems/pstore/blob/master/LICENSE.txt for license
12 // information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //===----------------------------------------------------------------------===//
52 
53 #ifndef PSTORE_SUPPORT_BIT_FIELD_HPP
54 #define PSTORE_SUPPORT_BIT_FIELD_HPP
55 
56 #include <cstddef>
57 #include <cstdint>
58 #include <limits>
59 #include <type_traits>
60 
62 
63 namespace pstore {
64 
65  namespace details {
66 
67  template <typename ValueType, unsigned Bits>
68  struct max_value {
69  static constexpr ValueType value = static_cast<ValueType> ((ValueType{1} << Bits) - 1);
70  };
71 
72  template <typename ValueType>
73  struct max_value<ValueType, 8U> {
74  static constexpr ValueType value = std::numeric_limits<std::uint8_t>::max ();
75  };
76 
77  template <typename ValueType>
78  struct max_value<ValueType, 16U> {
79  static constexpr ValueType value = std::numeric_limits<std::uint16_t>::max ();
80  };
81 
82  template <typename ValueType>
83  struct max_value<ValueType, 32U> {
84  static constexpr ValueType value = std::numeric_limits<std::uint32_t>::max ();
85  };
86 
87  template <typename ValueType>
88  struct max_value<ValueType, 64U> {
89  static constexpr ValueType value = std::numeric_limits<std::uint64_t>::max ();
90  };
91 
92  template <typename ValueType, unsigned Bits>
93  constexpr ValueType max_value<ValueType, Bits>::value;
94  template <typename ValueType>
95  constexpr ValueType max_value<ValueType, 8U>::value;
96  template <typename ValueType>
97  constexpr ValueType max_value<ValueType, 16U>::value;
98  template <typename ValueType>
99  constexpr ValueType max_value<ValueType, 32U>::value;
100  template <typename ValueType>
101  constexpr ValueType max_value<ValueType, 64U>::value;
102 
103 
104  template <typename ValueType, unsigned Index, unsigned Bits,
105  typename = typename std::enable_if<std::is_unsigned<ValueType>::value &&
106  Index + Bits <= sizeof (ValueType) * 8>::type>
107  class bit_field_base {
108  public:
109  static constexpr auto first_bit = Index;
110  static constexpr auto last_bit = Index + Bits;
112  using value_type = ValueType;
113 
115  static constexpr value_type min () noexcept { return 0; }
117  static constexpr value_type max () noexcept { return mask_; }
118 
120  constexpr value_type value () const noexcept {
121  return (this->value_ >> Index) & this->mask_;
122  }
123 
124  template <typename T,
125  typename = typename std::enable_if<std::is_unsigned<T>::value &&
126  sizeof (T) <= sizeof (value_type)>::type>
127  void assign (T v) noexcept {
128  value_ = static_cast<value_type> (value_ & ~(mask_ << Index)) |
129  static_cast<value_type> ((v & mask_) << Index);
130  }
131 
132  private:
133  static constexpr auto mask_ = max_value<ValueType, Bits>::value;
134  value_type value_;
135  };
136 
137  } // end namespace details
138 
139 
140  template <typename ValueType, unsigned Index, unsigned Bits>
141  class bit_field : private details::bit_field_base<ValueType, Index, Bits> {
142  using inherited = details::bit_field_base<ValueType, Index, Bits>;
143 
144  public:
145  using inherited::first_bit;
146  using inherited::last_bit;
147  using inherited::max;
148  using inherited::min;
150  using typename inherited::value_type;
152  using assign_type = ValueType;
153 
155  using inherited::value;
157  constexpr operator value_type () const noexcept { return this->value (); }
158 
160  template <typename T>
161  bit_field & operator= (T v) noexcept {
162  this->assign (v);
163  return *this;
164  }
165 
166 
167  template <typename T>
168  bit_field & operator+= (T other) noexcept {
169  this->assign (static_cast<value_type> (this->value () + other));
170  return *this;
171  }
172  template <typename T>
173  bit_field & operator-= (T other) noexcept {
174  this->assign (static_cast<value_type> (this->value () - other));
175  return *this;
176  }
177 
178  bit_field & operator++ () noexcept { return operator+=(value_type{1}); }
179  bit_field operator++ (int) noexcept {
180  bit_field const prev = *this;
181  ++*this;
182  return prev;
183  }
184 
185  bit_field & operator-- () noexcept { return operator-=(value_type{1}); }
186  bit_field operator-- (int) noexcept {
187  bit_field const prev = *this;
188  --*this;
189  return prev;
190  }
191  };
192 
193  template <typename ValueType, unsigned Index>
194  class bit_field<ValueType, Index, 1> : private details::bit_field_base<ValueType, Index, 1> {
195  using inherited = details::bit_field_base<ValueType, Index, 1>;
196 
197  public:
198  using inherited::first_bit;
199  using inherited::last_bit;
200  using inherited::max;
201  using inherited::min;
203  using typename inherited::value_type;
205  using assign_type = bool;
206 
208  bit_field & operator= (bool const v) noexcept {
209  this->assign (static_cast<value_type> (v));
210  return *this;
211  }
212 
213  constexpr bool value () const noexcept { return static_cast<bool> (inherited::value ()); }
214  constexpr operator bool () const noexcept { return value (); }
215  };
216 
217 } // end namespace pstore
218 
219 #endif // PSTORE_SUPPORT_BIT_FIELD_HPP
bool assign_type
The canonical type that can be assigned to a bit-field instance.
Definition: bit_field.hpp:205
Definition: bit_field.hpp:68
std::uint16_t assign_type
The canonical type that can be assigned to a bit-field instance.
Definition: bit_field.hpp:152
Definition: bit_field.hpp:141
Definition: print.cpp:18
Yields either &#39;T&#39; or &#39;T const&#39; depending on the value is IsConst.
Definition: chunked_sequence.hpp:234
Definition: nonpod2.cpp:40
An implementation of the standard assert() macro with the exception that it will, on failure...