Вставка байта в больший тип по индексу - PullRequest
0 голосов
/ 16 мая 2019

Вот мой шаблон класса и один из его конструкторов, который будет создавать тип T с размером N в байтах от типа P с размером M в байтах.Конструктор также принимает индекс u8.

Индекс работает на основе диапазона:

// pseudo code
lower bound is >= 0 in all cases
upper bound depends on sizeof(T) & sizeof(P) therefore
if (M > N) then
    idx <= (M / N) - 1
else 
    idx <= 0;

Вот шаблон класса и его конструктор:

// Actual class implementation without the include files and 
// of the using's and other constructors.

using u8 = std::uint8_t;
// etc. u16, u32 & u64...

template<typename T> 
    struct Register {
    T data;
    T value;
    std::bitset<sizeof(T) * CHAR_BIT> bits;

    template<typename P>
    Register(const P val, const u8 idx) :
        data{ static_cast<T>((val >> std::size(bits) * idx) &
              std::numeric_limits<std::make_unsigned_t<T>>::max()) },
        value{ data },
        bits{ data }
    {
        // Reg8  From: 16 idx=[0,1], 32 idx=[0,3], 64 idx=[0,7]
        // Reg16 From: 32 idx=[0,1], 64 idx=[0,3]
        // Reg32 From: 64 idx=[0,1]

        constexpr u16 sizeT = sizeof(T);
        constexpr u16 sizeP = sizeof(P);
        assert((idx >= 0) &&  ((sizeP > sizeT) ? (idx <= ((sizeP / sizeT) - 1)) : (idx <= 0)));
    }
};

// I for got to add these:
using Reg8  = Register<u8>;
using Reg16 = Register<u16>
using Reg32 = Register<u32>
using Reg64 = Register<u64>

Вот базовое визуальное представление этого конструктора в действии. Я буду использовать u8 и u16 для простоты

// pseudo code: 
// low byte always farthest to right 
// high byte always farthest to left
u16 val{ 0x69BC };

Reg8 r8a{val, 0); // get byte from index 1 or low byte
r8.value = 188
r8.value in hex = 0xBC;
r8.bits  = 1011110;

Reg8 r8b{val, 1); // get byte from index 1 or high byte
r8.value = 105;
r8.value in hex = 0x69;
r8.bits = 01101001

И это работает для любого из четырех размеров типа unsigned int с u8 = 1 байт, u16= 2 байта, u32 = 4 байта и u64 = 8 байтов.


На этот раз, если (M

Я собираюсь либо скорректировать этот конструктор, либо создать перегрузку.Здесь мне нужно знать, как выяснить, как сделать обратное тому, что описано выше.

Я буду использовать то же значение u16, что и выше: Но на этот раз мы собираемся построить Reg64 из него синдекс.Диапазон этого индекса будет [0,3] Что-нибудь после 3, и конструктор будет утверждать.

u16 val{ 0x69BC };
Reg64 r64a( val, 0 );
Reg64 r64b( val, 1 );
Reg64 r64c( val, 2 );
Reg64 r64d( val, 3 );   
// Reg64 r64x(val, x > 3); Assertion Failure

Здесь я хочу вставить байтовый шаблон значения типа u16 в соответствующее положение слова с индексом0 начиная справаЧтобы упростить это, я не собираюсь использовать двоичную последовательность, поэтому я просто буду использовать шестнадцатеричное обозначение того, что должен делать конструктор в каждом из четырех случаев.

// u16 val{ 0x69BC }; // visual reference
r64a.value in hex: = in bin: 0x0000 0000 0000 69BC
r64b.value in hex: = in bin: 0x0000 0000 69BC 0000
r64c.value in hex: = in bin  0x0000 69BC 0000 0000
r64d.value in hex: = in bin: 0x69BC 0000 0000 0000

r64a.bits = bin rep of above ... and so one for 46b,c&d.

Поэтому, когда я оглядываюсь назад наконструктор из извлечения для элемента данных

data{ static_cast<T>((val >> std::size(bits) * idx) &
      std::numeric_limits<std::make_unsigned_t<T>>::max()) },

и условия утверждения:

assert( (idx >= 0) &&  
        ((sizeP > sizeT) ? 
            (idx <= ((sizeP / sizeT) - 1)) : 
            (idx <= 0))
      );

Оба они должны быть обращены или скорректированы.

Вот мой набор связанных вопросов и проблем:

  • Смогу ли я использовать один и тот же конструктор для выполнения обеих ролей?Или я должен написать перегруженную версию этого конструктора?
  • Что касается формулы утверждения, я могу понять это достаточно легко, так что никаких проблем нет.Для вставки байтов в заданном месте индекса;это то, что я пытаюсь понять.Любая помощь здесь будет очень полезна с операциями сдвига и логической логикой.
  • Наконец, в отношении конструктора;как указано выше, сначала инициализируются данные, а затем из этого строится bitset.Должен ли я сначала инициализировать bitset, а затем соответственно установить для него значения и данные, или же лучше подойдет шаблон вспомогательной функции?
...