Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
bit_utils.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <cstdint>
5
6#include "gaia/core/span.h"
7
8namespace gaia {
9 namespace core {
12 template <uint32_t BlockBits>
13 struct bit_view {
15 static constexpr uint32_t MaxValue = (1 << BlockBits) - 1;
16
18 std::span<uint8_t> m_data;
19
23 void set(uint32_t bitPosition, uint8_t value) noexcept {
24 GAIA_ASSERT(bitPosition < (m_data.size() * 8));
25 GAIA_ASSERT(value <= MaxValue);
26
27 const uint32_t idxByte = bitPosition / 8;
28 const uint32_t idxBit = bitPosition % 8;
29
30 const uint32_t mask = ~(MaxValue << idxBit);
31 m_data[idxByte] = (uint8_t)(((uint32_t)m_data[idxByte] & mask) | ((uint32_t)value << idxBit));
32
33 const bool overlaps = idxBit + BlockBits > 8;
34 if (overlaps) {
35 // Value spans over two bytes
36 const uint32_t shift2 = 8U - idxBit;
37 const uint32_t mask2 = ~(MaxValue >> shift2);
38 m_data[idxByte + 1] = (uint8_t)(((uint32_t)m_data[idxByte + 1] & mask2) | ((uint32_t)value >> shift2));
39 }
40 }
41
45 uint8_t get(uint32_t bitPosition) const noexcept {
46 GAIA_ASSERT(bitPosition < (m_data.size() * 8));
47
48 const uint32_t idxByte = bitPosition / 8;
49 const uint32_t idxBit = bitPosition % 8;
50
51 const uint8_t byte1 = (m_data[idxByte] >> idxBit) & MaxValue;
52
53 const bool overlaps = idxBit + BlockBits > 8;
54 if (overlaps) {
55 // Value spans over two bytes
56 const uint32_t shift2 = uint8_t(8U - idxBit);
57 const uint32_t mask2 = MaxValue >> shift2;
58 const uint8_t byte2 = uint8_t(((uint32_t)m_data[idxByte + 1] & mask2) << shift2);
59 return byte1 | byte2;
60 }
61
62 return byte1;
63 }
64 };
65
72 template <typename T>
73 inline auto swap_bits(T& mask, uint32_t left, uint32_t right) {
74 // Swap the bits in the read-write mask
75 const uint32_t b0 = (mask >> left) & 1U;
76 const uint32_t b1 = (mask >> right) & 1U;
77 // XOR the two bits
78 const uint32_t bxor = b0 ^ b1;
79 // Put the XOR bits back to their original positions
80 const uint32_t m = (bxor << left) | (bxor << right);
81 // XOR mask with the original one effectively swapping the bits
82 mask = mask ^ (uint8_t)m;
83 }
84 } // namespace core
85} // namespace gaia
Provides packed access to fixed-width unsigned values stored in a byte span.
Definition bit_utils.h:13
uint8_t get(uint32_t bitPosition) const noexcept
Reads a packed value from the specified bit position.
Definition bit_utils.h:45
std::span< uint8_t > m_data
Bytes containing the packed values.
Definition bit_utils.h:18
void set(uint32_t bitPosition, uint8_t value) noexcept
Stores a packed value at the specified bit position.
Definition bit_utils.h:23
static constexpr uint32_t MaxValue
Largest value representable by one packed block.
Definition bit_utils.h:15