Loading...
Searching...
No Matches
bitfield
// vi:set ft=cpp: -*- Mode: C++ -*-
/*
* (c) 2012 Alexander Warg <warg@os.inf.tu-dresden.de>,
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
#include "type_list"
namespace cxx {
template<typename T, unsigned LSB, unsigned MSB>
class Bitfield
{
private:
typedef remove_reference_t<T> Base_type;
static_assert(MSB >= LSB, "boundary mismatch in bit-field definition");
static_assert(MSB < sizeof(Base_type) * 8, "MSB outside of bit-field type");
static_assert(LSB < sizeof(Base_type) * 8, "LSB outside of bit-field type");
template<unsigned BITS> struct Best_type
{
template< typename TY > struct Cmp { enum { value = (BITS <= sizeof(TY)*8) }; };
typedef cxx::type_list<
unsigned char,
unsigned short,
unsigned int,
unsigned long,
unsigned long long
> Unsigned_types;
typedef cxx::find_type_t<Unsigned_types, Cmp> Type;
};
public:
enum
{
Bits = MSB + 1 - LSB,
Lsb = LSB,
Msb = MSB,
};
enum Masks : Base_type
{
Low_mask = static_cast<Base_type>(~0ULL) >> (sizeof(Base_type)*8 - Bits),
Mask = Low_mask << Lsb,
};
typedef typename Best_type<Bits>::Type Bits_type;
typedef typename Best_type<Bits + Lsb>::Type Shift_type;
private:
static_assert(sizeof(Bits_type)*8 >= Bits, "error finding the type to store the bits");
static_assert(sizeof(Shift_type)*8 >= Bits + Lsb, "error finding the type to keep the shifted bits");
static_assert(sizeof(Bits_type) <= sizeof(Base_type), "size mismatch for Bits_type");
static_assert(sizeof(Shift_type) <= sizeof(Base_type), "size mismatch for Shift_type");
static_assert(sizeof(Bits_type) <= sizeof(Shift_type), "size mismatch for Shift_type and Bits_type");
public:
static constexpr Bits_type get(Shift_type val)
{ return (val >> Lsb) & Low_mask; }
static constexpr Base_type get_unshifted(Shift_type val)
{ return val & Mask; }
static constexpr Base_type set_dirty(Base_type dest, Shift_type val)
{
//assert (!(val & ~Low_mask));
return (dest & ~Mask) | (val << Lsb);
}
static constexpr Base_type set_unshifted_dirty(Base_type dest, Shift_type val)
{
//assert (!(val & ~Mask));
return (dest & ~Mask) | val;
}
static Base_type set(Base_type dest, Bits_type val)
{ return set_dirty(dest, val & Low_mask); }
static Base_type set_unshifted(Base_type dest, Shift_type val)
{ return set_unshifted_dirty(dest, val & Mask); }
static constexpr Base_type val_dirty(Shift_type val) { return val << Lsb; }
static constexpr Base_type val(Bits_type val) { return val_dirty(val & Low_mask); }
static constexpr Base_type val_unshifted(Shift_type val) { return val & Mask; }
template< typename TT >
class Value_base
{
private:
TT v;
public:
constexpr Value_base(TT t) : v(t) {}
constexpr Bits_type get() const { return Bitfield::get(v); }
constexpr Base_type get_unshifted() const { return Bitfield::get_unshifted(v); }
void set(Bits_type val) { v = Bitfield::set(v, val); }
void set_dirty(Bits_type val) { v = Bitfield::set_dirty(v, val); }
void set_unshifted(Shift_type val) { v = Bitfield::set_unshifted(v, val); }
void set_unshifted_dirty(Shift_type val) { v = Bitfield::set_unshifted_dirty(v, val); }
};
template< typename TT >
class Value : public Value_base<TT>
{
public:
constexpr Value(TT t) : Value_base<TT>(t) {}
constexpr operator Bits_type () const { return this->get(); }
constexpr Value &operator = (Bits_type val) { this->set(val); return *this; }
constexpr Value &operator = (Value const &val)
{ this->set(val.get()); return *this; }
Value(Value const &) = default;
};
template< typename TT >
class Value_unshifted : public Value_base<TT>
{
public:
constexpr Value_unshifted(TT t) : Value_base<TT>(t) {}
constexpr operator Shift_type () const { return this->get_unshifted(); }
constexpr Value_unshifted &operator = (Shift_type val) { this->set_unshifted(val); return *this; }
constexpr Value_unshifted &operator = (Value_unshifted const &val)
{ this->set_unshifted(val.get_unshifted()); return *this; }
Value_unshifted(Value_unshifted const &) = default;
};
typedef Value<Base_type &> Ref;
typedef Value<Base_type volatile &> Ref_volatile;
typedef Value<Base_type const> Val;
typedef Value_unshifted<Base_type &> Ref_unshifted;
typedef Value_unshifted<Base_type volatile &> Ref_unshifted_volatile;
typedef Value_unshifted<Base_type const> Val_unshifted;
};
#define CXX_BITFIELD_MEMBER(LSB, MSB, name, data_member) \
\
\
typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
\
constexpr typename name ## _bfm_t::Val name() const { return data_member; } \
typename name ## _bfm_t::Val name() const volatile { return data_member; } \
\
constexpr typename name ## _bfm_t::Ref name() { return data_member; } \
typename name ## _bfm_t::Ref_volatile name() volatile { return data_member; } \
#define CXX_BITFIELD_MEMBER_RO(LSB, MSB, name, data_member) \
\
\
typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
\
constexpr typename name ## _bfm_t::Val name() const { return data_member; } \
typename name ## _bfm_t::Val name() const volatile { return data_member; } \
#define CXX_BITFIELD_MEMBER_UNSHIFTED(LSB, MSB, name, data_member) \
\
\
typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
\
constexpr typename name ## _bfm_t::Val_unshifted name() const { return data_member; } \
typename name ## _bfm_t::Val_unshifted name() const volatile { return data_member; } \
\
constexpr typename name ## _bfm_t::Ref_unshifted name() { return data_member; } \
typename name ## _bfm_t::Ref_unshifted_volatile name() volatile { return data_member; } \
#define CXX_BITFIELD_MEMBER_UNSHIFTED_RO(LSB, MSB, name, data_member) \
\
\
typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
\
constexpr typename name ## _bfm_t::Val_unshifted name() const { return data_member; } \
typename name ## _bfm_t::Val_unshifted name() const volatile { return data_member; } \
}
cxx::Bitfield
Definition for a member (part) of a bit field.
Definition bitfield:25
cxx::Bitfield::get
static constexpr Bits_type get(Shift_type val)
Get the bits out of val.
Definition bitfield:99
cxx::Bitfield< decltype(raw), 0, 0 >::Msb
@ Msb
Definition bitfield:56
cxx::Bitfield< decltype(raw), 0, 0 >::Bits
@ Bits
Definition bitfield:54
cxx::Bitfield< decltype(raw), 0, 0 >::Lsb
@ Lsb
Definition bitfield:55
cxx::Bitfield< decltype(raw), 0, 0 >::Ref_unshifted_volatile
Value_unshifted< Base_type volatile & > Ref_unshifted_volatile
Definition bitfield:262
cxx::Bitfield::val_unshifted
static constexpr Base_type val_unshifted(Shift_type val)
Get the shifted bits for val.
Definition bitfield:206
cxx::Bitfield< decltype(raw), 0, 0 >::Ref_volatile
Value< Base_type volatile & > Ref_volatile
Definition bitfield:255
cxx::Bitfield::Masks
Masks
Masks for bitswise operation on internal parts of a bitfield.
Definition bitfield:61
cxx::Bitfield< decltype(raw), 0, 0 >::Low_mask
@ Low_mask
Definition bitfield:63
cxx::Bitfield< decltype(raw), 0, 0 >::Mask
@ Mask
Definition bitfield:65
cxx::Bitfield::set
static Base_type set(Base_type dest, Bits_type val)
Set the bits corresponding to val.
Definition bitfield:161
cxx::Bitfield< decltype(raw), 0, 0 >::Shift_type
Best_type< Bits+Lsb >::Type Shift_type
Definition bitfield:82
cxx::Bitfield< decltype(raw), 0, 0 >::Val
Value< Base_type const > Val
Definition bitfield:257
cxx::Bitfield::val_dirty
static constexpr Base_type val_dirty(Shift_type val)
Get the shifted bits for val.
Definition bitfield:187
cxx::Bitfield::set_unshifted_dirty
static constexpr Base_type set_unshifted_dirty(Base_type dest, Shift_type val)
Set the bits corresponding to val.
Definition bitfield:147
cxx::Bitfield< decltype(raw), 0, 0 >::val
static constexpr Base_type val(Bits_type val)
Definition bitfield:196
cxx::Bitfield< decltype(raw), 0, 0 >::Bits_type
Best_type< Bits >::Type Bits_type
Definition bitfield:74
cxx::Bitfield::set_unshifted
static Base_type set_unshifted(Base_type dest, Shift_type val)
Set the bits corresponding to val.
Definition bitfield:173
cxx::Bitfield< decltype(raw), 0, 0 >::Ref_unshifted
Value_unshifted< Base_type & > Ref_unshifted
Definition bitfield:260
cxx::Bitfield::get_unshifted
static constexpr Base_type get_unshifted(Shift_type val)
Get the bits in place out of val.
Definition bitfield:112
cxx::Bitfield::set_dirty
static constexpr Base_type set_dirty(Base_type dest, Shift_type val)
Set the bits corresponding to val.
Definition bitfield:127
cxx::Bitfield< decltype(raw), 0, 0 >::Val_unshifted
Value_unshifted< Base_type const > Val_unshifted
Definition bitfield:264
cxx::Bitfield< decltype(raw), 0, 0 >::Ref
Value< Base_type & > Ref
Definition bitfield:253
cxx
Our C++ library.
Definition arith:11