jaffarCommon
Loading...
Searching...
No Matches
bitwise.hpp
Go to the documentation of this file.
1#pragma once
2
8#include "exceptions.hpp"
9#include <stddef.h>
10#include <stdint.h>
11
12namespace jaffarCommon
13{
14
15namespace bitwise
16{
17
21inline constexpr uint8_t bitMaskTable[8] = {0b00000001, 0b00000010, 0b00000100, 0b00001000, 0b00010000, 0b00100000, 0b01000000, 0b10000000};
22
26inline constexpr uint8_t bitNotMaskTable[8] = {0b11111110, 0b11111101, 0b11111011, 0b11110111, 0b11101111, 0b11011111, 0b10111111, 0b01111111};
27
40__JAFFAR_COMMON_INLINE__ void bitcopy(void* dstBufferPtr, const size_t dstBufferSize, const size_t dstBufferOffset, const void* srcBufferPtr, const size_t srcBufferSize,
41 const size_t srcBufferOffset, const size_t count, const size_t elementBitSize)
42{
43 if (elementBitSize == 0) JAFFAR_THROW_LOGIC("Element bit size must be a positive number greater than zero");
44
45 const auto dstBufferSizeBits = dstBufferSize * 8;
46 const auto srcBufferSizeBits = srcBufferSize * 8;
47
48 // Offsets are expressed in elements, so the actual bit position is offset * elementBitSize.
49 // The overflow guards must be computed in bits to correctly catch out-of-bounds accesses.
50 const size_t totalBitCount = count * elementBitSize;
51 const size_t dstOffsetBits = dstBufferOffset * elementBitSize;
52 const size_t srcOffsetBits = srcBufferOffset * elementBitSize;
53
54 if (dstOffsetBits + totalBitCount > dstBufferSizeBits)
55 JAFFAR_THROW_LOGIC("The operation will overflow destination buffer (%lu + %lu > %lu)", dstOffsetBits, totalBitCount, dstBufferSizeBits);
56 if (srcOffsetBits + totalBitCount > srcBufferSizeBits)
57 JAFFAR_THROW_LOGIC("The operation will overflow source buffer (%lu + %lu > %lu)", srcOffsetBits, totalBitCount, srcBufferSizeBits);
58
59 uint8_t* dstBuffer = (uint8_t*)dstBufferPtr;
60 const uint8_t* srcBuffer = (const uint8_t*)srcBufferPtr;
61 size_t dstPosByte = dstOffsetBits / 8;
62 uint8_t dstPosBit = dstOffsetBits % 8;
63 size_t srcPosByte = srcOffsetBits / 8;
64 uint8_t srcPosBit = srcOffsetBits % 8;
65
66 for (size_t i = 0; i < totalBitCount; i++)
67 {
68 // Clear bit in question
69 dstBuffer[dstPosByte] = dstBuffer[dstPosByte] & bitNotMaskTable[dstPosBit];
70
71 // If the corresponding bit is set in source, set it up in dst
72 if ((srcBuffer[srcPosByte] & bitMaskTable[srcPosBit]) > 0) dstBuffer[dstPosByte] = dstBuffer[dstPosByte] | bitMaskTable[dstPosBit];
73
74 // Advance bit positions
75 dstPosBit++;
76 srcPosBit++;
77
78 // If crossed a byte barrier, go over the next byte
79 if (dstPosBit == 8)
80 {
81 dstPosBit = 0;
82 dstPosByte++;
83 }
84 if (srcPosBit == 8)
85 {
86 srcPosBit = 0;
87 srcPosByte++;
88 }
89 }
90}
91
99__JAFFAR_COMMON_INLINE__ size_t getEncodingBitsForElementCount(const size_t elementCount)
100{
101 // Corner cases
102 if (elementCount == 0) return 0;
103 if (elementCount == 1) return 1;
104
105 // Calculating bit storage for the possible inputs index
106 size_t bitEncodingSize = 0;
107 size_t encodingCapacity = 1;
108 while (encodingCapacity < elementCount) { encodingCapacity <<= 1, bitEncodingSize++; };
109 return bitEncodingSize;
110}
111
118__JAFFAR_COMMON_INLINE__ size_t getByteStorageForBitCount(const size_t bitCount)
119{
120 // Calculating bit storage for the possible inputs index
121 size_t byteStorageSize = bitCount / 8;
122 if (bitCount % 8 > 0) byteStorageSize++;
123 return byteStorageSize;
124}
125
133__JAFFAR_COMMON_INLINE__ void setBitValue(void* dst, const size_t idx, const bool value)
134{
135 size_t dstPosByte = idx / 8;
136 uint8_t dstPosBit = idx % 8;
137 auto dstPtr = (uint8_t*)dst;
138
139 if (value == false) dstPtr[dstPosByte] = dstPtr[dstPosByte] & bitNotMaskTable[dstPosBit];
140 if (value == true) dstPtr[dstPosByte] = dstPtr[dstPosByte] | bitMaskTable[dstPosBit];
141}
142
150__JAFFAR_COMMON_INLINE__ bool getBitValue(const void* src, const size_t idx)
151{
152 size_t srcPosByte = idx / 8;
153 uint8_t srcPosBit = idx % 8;
154 auto srcPtr = (const uint8_t*)src;
155
156 return (srcPtr[srcPosByte] & bitMaskTable[srcPosBit]) > 0;
157}
158
166__JAFFAR_COMMON_INLINE__ bool getBitFlag(const uint8_t value, const uint8_t idx)
167{
168 if (idx > 7) JAFFAR_THROW_LOGIC("Provided bit index higher than 7 for a an 8-bit value");
169
170 if (((idx == 7) && (value & 0b10000000)) || ((idx == 6) && (value & 0b01000000)) || ((idx == 5) && (value & 0b00100000)) || ((idx == 4) && (value & 0b00010000)) ||
171 ((idx == 3) && (value & 0b00001000)) || ((idx == 2) && (value & 0b00000100)) || ((idx == 1) && (value & 0b00000010)) || ((idx == 0) && (value & 0b00000001)))
172 return true;
173 return false;
174}
175
176} // namespace bitwise
177
178} // namespace jaffarCommon
constexpr uint8_t bitMaskTable[8]
Definition bitwise.hpp:21
__JAFFAR_COMMON_INLINE__ bool getBitFlag(const uint8_t value, const uint8_t idx)
Definition bitwise.hpp:166
__JAFFAR_COMMON_INLINE__ void setBitValue(void *dst, const size_t idx, const bool value)
Definition bitwise.hpp:133
__JAFFAR_COMMON_INLINE__ void bitcopy(void *dstBufferPtr, const size_t dstBufferSize, const size_t dstBufferOffset, const void *srcBufferPtr, const size_t srcBufferSize, const size_t srcBufferOffset, const size_t count, const size_t elementBitSize)
Definition bitwise.hpp:40
__JAFFAR_COMMON_INLINE__ bool getBitValue(const void *src, const size_t idx)
Definition bitwise.hpp:150
__JAFFAR_COMMON_INLINE__ size_t getEncodingBitsForElementCount(const size_t elementCount)
Definition bitwise.hpp:99
constexpr uint8_t bitNotMaskTable[8]
Definition bitwise.hpp:26
__JAFFAR_COMMON_INLINE__ size_t getByteStorageForBitCount(const size_t bitCount)
Definition bitwise.hpp:118
Contains common functions for exception throwing.
#define JAFFAR_THROW_LOGIC(...)
Definition exceptions.hpp:27