Last active
March 11, 2026 04:22
-
-
Save cpuwolf/9d7e4f0564f88b9ee16faa13186259ac to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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