Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- template <typename _T, unsigned _pos, unsigned _size>
- class ByteAcess
- {
- STATIC_ASSERT(_size + _pos <= sizeof(_T)*8,
- "ByteAcess field is too big");
- // базовый тип без знака
- typedef typename stdlib::make_unsigned<_T>::type _uT;
- // maxBits::value макс.число бит
- typedef typename stdlib::integral_constant<_uT, sizeof(_uT)*8> maxBits;
- // SFINAE флаг если описание поля валидно (не выходит за границу)
- template<class U, class Type = void>
- struct if_valid : stdlib::enable_if_c <(sizeof(_T)*8 >= _pos + _size) && ( sizeof(_T)*8 != _size )
- && (sizeof(U) >= sizeof(_T)), Type> {};
- // SFINAE флаг если поле описывает все слово целиком (вопадает размер и начало)
- template<class U, class Type = void>
- struct if_simple : stdlib::enable_if_c <(sizeof(_T)*8 == _size) && (_pos == 0)
- && (sizeof(U) >= sizeof(_T)), Type> {};
- // маска из _size установленных бит
- // (data_type(1) << _size) - 1; В C++11 ведет к UB если _size == maxBits::value;
- typedef typename stdlib::integral_constant< _uT,
- (_size >= maxBits::value) ? ~_uT(0) : ((_uT(1) << _size)-1) > mask;
- public:
- typedef _T data_type;
- // маска поля
- typedef typename stdlib::integral_constant<_uT,
- _uT(mask::value << _pos) > mask_self;
- /// размер поля в битах
- typedef typename stdlib::integral_constant<_uT, _size> bit_size;
- private:
- /// @brief Данные, с частью которых работает класс
- data_type data;
- public:
- /// @brief Установка требуемых битов заданным числом
- /// @param value Данные для записи
- template <class V>
- typename if_valid<V>::type set(V value)
- {
- data_type val = value & mask::value;
- val = val << _pos;
- // Инвертирование маски для обнуления
- data &= ~(mask::value << _pos); // Обнуление имеющихся данных в заданном месте
- data |= val;
- }
- template <class V>
- typename if_simple<V>::type set( V value ) { data = value; }
- /// @brief Описание оператора = через set
- /// @param value Данные для записи
- ByteAcess& operator=(data_type value)
- {
- set(value);
- return *this;
- }
- /// @brief Получение числа заданного в template типа из заданных бит
- /// @return Чисто заданного типа, сформированное из заданных бит
- template <class V>
- typename if_valid<V, data_type>::type get() const
- {
- // число бит на которое надо сдвинуть
- //const static data_type move = sizeof (data_type) * 8 - _size;
- typedef typename stdlib::integral_constant<data_type, maxBits::value - _size> move;
- data_type result = data << (move::value - _pos); // Сдвиг влево для воспроизведения знака
- result >>= move::value; // Разбито на два действия - в противном случае не происходит
- //обрезания из - за использования регистра большего размера
- return result;
- }
- template <class V>
- typename if_simple<V, data_type>::type get() const { return data; }
- /// @brief Обертка, чтобы получать данные, не вызывая get(),
- /// используется переопределения оператора TYPE()
- /// @return Чисто заданного типа, сформированное из заданных бит
- operator data_type() const
- {
- return get<data_type>();
- }
- bool is_zero() const
- {
- return ! (data & mask_self::value);
- }
- bool not_zero() const
- {
- return (data & mask_self::value) != 0;
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement