Advertisement
Swiftkill

ByAccess2

Aug 25th, 2021
1,268
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.09 KB | None | 0 0
  1. template <typename _T, unsigned _pos, unsigned _size>
  2. class ByteAcess
  3. {
  4.     STATIC_ASSERT(_size + _pos <= sizeof(_T)*8,
  5.                                     "ByteAcess field is too big");
  6.     // базовый тип без знака
  7.     typedef typename stdlib::make_unsigned<_T>::type _uT;
  8.     // maxBits::value макс.число бит
  9.     typedef typename stdlib::integral_constant<_uT, sizeof(_uT)*8> maxBits;
  10.  
  11.     // SFINAE флаг если описание поля валидно (не выходит за границу)
  12.     template<class U, class Type = void>
  13.     struct if_valid : stdlib::enable_if_c <(sizeof(_T)*8 >= _pos + _size) && ( sizeof(_T)*8 != _size )
  14.                                             && (sizeof(U) >= sizeof(_T)), Type> {};
  15.     // SFINAE флаг если поле описывает все слово целиком (вопадает размер и начало)
  16.     template<class U, class Type = void>
  17.     struct if_simple : stdlib::enable_if_c <(sizeof(_T)*8 == _size) && (_pos == 0)
  18.                                             && (sizeof(U) >= sizeof(_T)), Type> {};
  19.     // маска из _size установленных бит
  20.     // (data_type(1) << _size) - 1; В C++11 ведет к UB если _size == maxBits::value;
  21.     typedef typename stdlib::integral_constant< _uT,
  22.         (_size >= maxBits::value) ? ~_uT(0) : ((_uT(1) << _size)-1) > mask;
  23. public:
  24.     typedef _T data_type;
  25.  
  26.     // маска поля
  27.     typedef typename stdlib::integral_constant<_uT,
  28.          _uT(mask::value << _pos) > mask_self;
  29.  
  30.     /// размер поля в битах
  31.     typedef typename stdlib::integral_constant<_uT, _size> bit_size;
  32. private:
  33.     /// @brief Данные, с частью которых работает класс
  34.     data_type data;
  35. public:
  36.     /// @brief Установка требуемых битов заданным числом
  37.     /// @param value Данные для записи
  38.     template <class V>
  39.     typename if_valid<V>::type  set(V value)
  40.     {
  41.  
  42.         data_type val = value & mask::value;
  43.         val = val << _pos;
  44.                                     // Инвертирование маски для обнуления
  45.         data &= ~(mask::value << _pos); // Обнуление имеющихся данных в заданном месте
  46.         data |= val;
  47.     }
  48.  
  49.     template <class V>
  50.     typename if_simple<V>::type  set( V value ) { data = value; }
  51.  
  52.     /// @brief Описание оператора = через set
  53.     /// @param value Данные для записи
  54.     ByteAcess& operator=(data_type value)
  55.     {
  56.         set(value);
  57.         return *this;
  58.     }
  59.  
  60.     /// @brief Получение числа заданного в template типа из заданных бит
  61.     /// @return Чисто заданного типа, сформированное из заданных бит
  62.     template <class V>
  63.     typename if_valid<V, data_type>::type  get() const
  64.     {
  65.         // число бит на которое надо сдвинуть
  66.         //const static data_type move = sizeof (data_type) * 8 - _size;
  67.         typedef typename stdlib::integral_constant<data_type, maxBits::value - _size> move;
  68.         data_type result = data << (move::value - _pos); // Сдвиг влево для воспроизведения знака
  69.         result >>= move::value; // Разбито на два действия - в противном случае не происходит
  70.                          //обрезания из - за использования регистра большего размера
  71.         return result;
  72.     }
  73.  
  74.     template <class V>
  75.     typename if_simple<V, data_type>::type  get() const { return data; }
  76.  
  77.     /// @brief Обертка, чтобы получать данные, не вызывая get(),
  78.     /// используется переопределения оператора TYPE()
  79.     /// @return Чисто заданного типа, сформированное из заданных бит
  80.     operator data_type() const
  81.     {
  82.         return get<data_type>();
  83.     }
  84.  
  85.     bool is_zero() const
  86.     {
  87.         return ! (data & mask_self::value);
  88.     }
  89.  
  90.     bool not_zero() const
  91.     {
  92.         return (data & mask_self::value) != 0;
  93.     }
  94. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement