Skip to content

Instantly share code, notes, and snippets.

@cpuwolf
Last active March 11, 2026 04:22
Show Gist options
  • Select an option

  • Save cpuwolf/9d7e4f0564f88b9ee16faa13186259ac to your computer and use it in GitHub Desktop.

Select an option

Save cpuwolf/9d7e4f0564f88b9ee16faa13186259ac to your computer and use it in GitHub Desktop.
#include <vector>
#include <cstdint>
#include <stdexcept>
#include <algorithm>
#include <iostream>
#include <bitset> // For printing binary in main
#include <iomanip> // For std::hex, std::setw, std::setfill in main
// Assuming a max byte array length of 20 bytes
// Max bit offset: 20 bytes * 8 bits/byte = 160 bits (relative to start of array)
// Max bit length: 31 bits
// Function to get a bit sequence from the byte array
uint32_t get(const std::vector<uint8_t>& byteArray, int startIndex, int bitOffset, int bitLength) {
if (bitLength <= 0 || bitLength > 31) {
throw std::invalid_argument("Bit length must be between 1 and 31.");
}
if (startIndex < 0 || startIndex >= byteArray.size()) {
throw std::out_of_range("Start index is out of bounds for byteArray.");
}
if (bitOffset < 0) {
throw std::invalid_argument("Bit offset cannot be negative.");
}
// Calculate the absolute bit offset from the beginning of the byteArray
int absoluteBitOffset = startIndex * 8 + bitOffset;
int byteArrayTotalBitLength = byteArray.size() * 8;
if (absoluteBitOffset + bitLength > byteArrayTotalBitLength) {
throw std::out_of_range("Absolute bit offset + bit length exceeds byte array boundaries.");
}
uint32_t result = 0;
int currentAbsoluteBit = absoluteBitOffset;
for (int i = 0; i < bitLength; ++i) {
int byteIndex = currentAbsoluteBit / 8;
int bitInByteIndex = currentAbsoluteBit % 8;
if (byteArray[byteIndex] & (1u << (7 - bitInByteIndex))) {
result |= (1u << (bitLength - 1 - i));
}
currentAbsoluteBit++;
}
return result;
}
// Function to set a bit sequence in the byte array
void set(std::vector<uint8_t>& byteArray, int startIndex, int bitOffset, int bitLength, uint32_t value) {
if (bitLength <= 0 || bitLength > 31) {
throw std::invalid_argument("Bit length must be between 1 and 31.");
}
if (startIndex < 0 || startIndex >= byteArray.size()) {
throw std::out_of_range("Start index is out of bounds for byteArray.");
}
if (bitOffset < 0) {
throw std::invalid_argument("Bit offset cannot be negative.");
}
// Calculate the absolute bit offset from the beginning of the byteArray
int absoluteBitOffset = startIndex * 8 + bitOffset;
int byteArrayTotalBitLength = byteArray.size() * 8;
if (absoluteBitOffset + bitLength > byteArrayTotalBitLength) {
throw std::out_of_range("Absolute bit offset + bit length exceeds byte array boundaries.");
}
// Create a mask for the value to ensure we don't write bits beyond bitLength
uint32_t valueMask = (bitLength == 31) ? 0x7FFFFFFF : ((1u << bitLength) - 1);
value &= valueMask;
int currentAbsoluteBit = absoluteBitOffset;
for (int i = 0; i < bitLength; ++i) {
int byteIndex = currentAbsoluteBit / 8;
int bitInByteIndex = currentAbsoluteBit % 8;
// Check the corresponding bit in the value
if (value & (1u << (bitLength - 1 - i))) {
// Set the bit
byteArray[byteIndex] |= (1u << (7 - bitInByteIndex));
}
else {
// Clear the bit
byteArray[byteIndex] &= ~(1u << (7 - bitInByteIndex));
}
currentAbsoluteBit++;
}
}
// Helper function to print the byte array in binary for easier debugging
void printByteArrayBinary(const std::vector<uint8_t>& arr) {
for (uint8_t byte : arr) {
for (int i = 7; i >= 0; --i) {
std::cout << ((byte >> i) & 1);
}
std::cout << " ";
}
std::cout << std::endl;
}
int main() {
// Initialize a byte array (max 20 bytes)
std::vector<uint8_t> myByteArray(20, 0x00); // All zeros initially
std::cout << "Initial byte array (binary): ";
printByteArrayBinary(myByteArray);
// --- Test 1: Setting and Getting a simple value with startIndex ---
std::cout << "\n--- Test 1: Setting and Getting a simple value with startIndex ---" << std::endl;
// Set 0b1011 at byte index 1, bit offset 5 (i.e., absolute bit 1*8 + 5 = 13) with length 4
set(myByteArray, 1, 5, 4, 0b1011);
std::cout << "After setting 0b1011 at startIndex 1, bitOffset 5, bitLength 4: ";
printByteArrayBinary(myByteArray);
uint32_t retrievedValue1 = get(myByteArray, 1, 5, 4);
std::cout << "Retrieved value: " << std::bitset<4>(retrievedValue1) << " (Decimal: " << retrievedValue1 << ")" << std::endl; // Should be 11 (0b1011)
// --- Test 2: Setting a value across byte boundaries using startIndex ---
std::cout << "\n--- Test 2: Setting a value across byte boundaries using startIndex ---" << std::endl;
std::fill(myByteArray.begin(), myByteArray.end(), 0x00);
// Set 0b1101011010 at byte index 0, bit offset 3 (i.e., absolute bit 3) with length 10
set(myByteArray, 0, 3, 10, 0b1101011010);
std::cout << "After setting 0b1101011010 at startIndex 0, bitOffset 3, bitLength 10: ";
printByteArrayBinary(myByteArray);
uint32_t retrievedValue2 = get(myByteArray, 0, 3, 10);
std::cout << "Retrieved value: " << std::bitset<10>(retrievedValue2) << " (Decimal: " << retrievedValue2 << ")" << std::endl; // Should be 858 (0b1101011010)
// --- Test 3: Setting a value starting in a later byte ---
std::cout << "\n--- Test 3: Setting a value starting in a later byte ---" << std::endl;
std::fill(myByteArray.begin(), myByteArray.end(), 0x00);
// Set 0b11110000 at byte index 5, bit offset 0 (i.e., absolute bit 5*8 = 40) with length 8
set(myByteArray, 5, 0, 8, 0b11110000);
std::cout << "After setting 0b11110000 at startIndex 5, bitOffset 0, bitLength 8: ";
printByteArrayBinary(myByteArray);
uint32_t retrievedValue3 = get(myByteArray, 5, 0, 8);
std::cout << "Retrieved value: " << std::bitset<8>(retrievedValue3) << " (Decimal: " << retrievedValue3 << ")" << std::endl; // Should be 240 (0b11110000)
// --- Test 4: Setting a value at the very end of the array using startIndex ---
std::cout << "\n--- Test 4: Setting a value at the very end of the array using startIndex ---" << std::endl;
std::fill(myByteArray.begin(), myByteArray.end(), 0x00);
// Set 0b00001111 at the last byte (index 19), bit offset 0, length 8
set(myByteArray, 19, 0, 8, 0b00001111);
std::cout << "After setting 0b00001111 at startIndex 19, bitOffset 0, bitLength 8: ";
printByteArrayBinary(myByteArray);
uint32_t retrievedValue4 = get(myByteArray, 19, 0, 8);
std::cout << "Retrieved value: " << std::bitset<8>(retrievedValue4) << " (Decimal: " << retrievedValue4 << ")" << std::endl; // Should be 15 (0b00001111)
// --- Test 5: Setting maximum bit length (31 bits) with startIndex ---
std::cout << "\n--- Test 5: Setting maximum bit length (31 bits) with startIndex ---" << std::endl;
std::fill(myByteArray.begin(), myByteArray.end(), 0x00);
uint32_t largeValue = 0x7FFFFFFF; // Max 31-bit value
set(myByteArray, 1, 2, 31, largeValue); // Start at byte 1, bit offset 2
std::cout << "After setting 0x7FFFFFFF (max 31-bit) at startIndex 1, bitOffset 2, bitLength 31: ";
printByteArrayBinary(myByteArray);
uint32_t retrievedValue5 = get(myByteArray, 1, 2, 31);
std::cout << "Retrieved value: " << std::hex << std::setw(8) << std::setfill('0') << retrievedValue5
<< " (Binary: " << std::bitset<31>(retrievedValue5) << ")" << std::endl; // Should be 0x7FFFFFFF
// --- Test 6: Error handling with startIndex ---
std::cout << "\n--- Test 6: Error handling with startIndex ---" << std::endl;
try {
get(myByteArray, 20, 0, 8); // Invalid startIndex (out of bounds)
}
catch (const std::exception& e) {
std::cerr << "Error (expected): " << e.what() << std::endl;
}
try {
set(myByteArray, -1, 0, 8, 0); // Invalid startIndex (negative)
}
catch (const std::exception& e) {
std::cerr << "Error (expected): " << e.what() << std::endl;
}
try {
get(myByteArray, 19, 5, 8); // Out of range with startIndex + bitOffset + bitLength
}
catch (const std::exception& e) {
std::cerr << "Error (expected): " << e.what() << std::endl;
}
try {
set(myByteArray, 18, 7, 10, 0); // Out of range with startIndex + bitOffset + bitLength
}
catch (const std::exception& e) {
std::cerr << "Error (expected): " << e.what() << std::endl;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment