I am trying to get to read individual bits of a byte array. I am basically iterating through the byte array and want to tell whether each individual bit is 0 or 1.
My problem is, I am unable to differentiate between a 0 and 1 bit. The code is always reading each bit as a 1.
This is my code:
const unsigned char bitmap[] = {
0x00,0xFF,0xFF,0x00,0x00,0x00,
0x00,0x00,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF
};
void drawBitmap(Framebuffer *fb) {
uint8_t x = 1;
for (int i = 0; i < sizeof(bitmap); ++i) {
for (int p = 0; p < 8; ++p) {
if ((bitmap[i] >> p) & 1) { // If bit
fb->drawPixel(x, 1); // **RIGHT HERE** --> I AM ALWAYS GETTING THIS AS TRUE
}
x++;
}
}
}
Note that there are some bytes that should be all zeroes (0x00). I am assuming by default these are bytes (8 bits), right? Any ideas why am I unable to differentiate between a 1 and a 0?
Note: Here's the whole code... I am trying to use this library: https://github.com/tibounise/SSD1306-AVR with an atmega328P... This just doesn't make any sensse. Whenever I use "fb->drawPixel(x, 1);" on it's own it works fine, but on that particular function I always get a "1" (a pixel).
#define F_CPU 14745600
#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include <util/delay.h>
//#include "SSD1306.h"
#include "Framebuffer.h"
const unsigned char bitmap[] = {
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF
};
void drawBitmap(Framebuffer *fb) {
uint8_t x = 1;
int z = 0;
for (int i = 0; i < sizeof(bitmap); ++i) {
for (int p = 0; p < 8; ++p) {
if ((bitmap[i] >> p) & 1) { // If bit
fb->drawPixel(x,1);
}
x++;
}
}
}
int main(void) {
//const uint8_t *bitmap;
//bitmap = &bitmap1;
Framebuffer fb;
Framebuffer *FB;
//Pointer to the class
FB = &fb;
//fb.drawPixel(5, 5);
drawBitmap(FB);
fb.show();
//delay_ms(1000);
return 0;
}
Any ideas?
Thanks in advance.
Your code seems okay. However your sample data is in bytes, not bits.
If you are working with a 1-bit bitmap, there are 8-bits per pixel. Each bit is 0 or 1 (black or white). Each set of 8-bits is compacted in to byte:
0xFF contains 8-bits: "11111111"
0x00 contains 8-bits: "00000000"
An actual bitmap may have the following sequence:
"1011 0001"
Try the same code with a more realistic data:
const unsigned char bitmap[] =
{
1 | 0 | 4 | 8 | 0 | 0 | 0 | 128,//1011 0001 <- first 8-bits
0xFF, //<- second set of 8-bits
0x00, //...
};
int main(void)
{
for(int i = 0; i < sizeof(bitmap); ++i)
{
printf("%3d ", bitmap[i]);
for(int p = 0; p < 8; ++p)
printf(((bitmap[i] >> p) & 1) ? "1" : "0");
printf("\n");
}
return 0;
}
Result:
141 10110001
255 11111111
0 00000000
Related
I am learning C++ and I wonder if it is possible to decompose a structure object into a sequence of bits?
// The task is this! I have a structure
struct test {
// It contains an array
private:
int arr [8];
public:
void init () {
for (int i = 0; i <8; i ++) {
arr [i] = 5;
}
}
};
int main () {
// at some point this array is initialized
test h;
h.init ();
// without referring to the arr field and its elements, we must convert the structure to this format
// we know that int is stored there, and these are 32 bits -> 00000000 00000000 00000000 00000101. 00000000 00000000 00000000 00000101. - and there are 8 such pieces by number
// elements in the array
return -1;
}
Well, we know the size of the array too. We need to convert the structure object to a sequence of bits:
00000000000000000000000000000101000000000000000000000000000001010000000000000000000000000000010100000000000000000000000000000101000000000000000000000000000001010000000000000000000000000000010100000000000000000000000000000000010100000000000000000000000000000101
The standard answer for converting number into bit strings is to you std::bitset. I will use a more low level approach. And use a bit mask and & operation to mask out single bits and then assign the corresdponding characters to the resulting string.
Masking woks with the bit and operator and on the locical AND operation
Bit Mask AND
0 0 0
0 1 0
1 0 0
1 1 1
You see, 0 and 1 is 0. And 1 and 1 is 1.
That allows us to access a bit in a byte.
Byte: 10101010
Mask: 00001111
--------------
00001010
And this mecahnism we will use.
But, I cannot imagine that this is homework, because of the dirty reintepret_cast that would be needed, by accessing the struct from outside.
Anyway. Let me present this solution to you.
I find it utmost ugly.
#include <iostream>
#include <bitset>
// The task is this! I have a structure
struct test {
// It contains an array
private:
int arr[8];
public:
void init() {
for (int i = 0; i < 8; i++) {
arr[i] = 5;
}
}
};
// Convert an int to a string with the bit representaion of the int
std::string intToBits(int value) {
// Here we will store the result
std::string result{};
// We want to mask the bit from MSB to LSB
unsigned int mask = 1<<31;
// Now we will work on 4 bytes with 8bits each
for (unsigned int byteNumber = 0; byteNumber < 4; ++byteNumber) {
for (unsigned int bitNumber = 0; bitNumber < 8; ++bitNumber) {
// Mask out bit and store the resulting 1 or 0 in the string
result += (value & mask) ? '1' : '0';
// Next mask
mask >>= 1;
}
// Add a space between bytes
result += ' ';
}
// At the end, we do want to have a point
result.back() = '.';
return result;
}
int main() {
// At some point this array is initialized
test h;
h.init();
// Now do dirty, ugly, and none compliant type cast
int* test = reinterpret_cast<int*>(&h);
// Convert all bytes and show result
for (unsigned int k = 0; k < 8; ++k)
std::cout << intToBits(test[k]) << ' ';
return 0;
}
Giving a uint8_t buffer of x length, I am trying to come up with a function or a macro that can remove nth bit (or n to n+i), then left-shift the remaining bits.
example #1:
for input 0b76543210 0b76543210 ... then output should be 0b76543217 0b654321 ...
example #2: if the input is:
uint8_t input[8] = {
0b00110011,
0b00110011,
...
};
the output without the first bit, should be
uint8_t output[8] = {
0b00110010,
0b01100100,
...
};
I have tried the following to remove the first bit, but it did not work for the second group of bits.
/* A macro to extract (a-b) range of bits without shifting */
#define BIT_RANGE(N,x,y) ((N) & ((0xff >> (7 - (y) + (x))) << ((x))))
void removeBit0(uint8_t *n) {
for (int i=0; i < 7; i++) {
n[i] = (BIT_RANGE(n[i], i + 1, 7)) << (i + 1) |
(BIT_RANGE(n[i + 1], 1, i + 1)) << (7 - i); /* This does not extract the next element bits */
}
n[7] = 0;
}
Update #1
In my case, the input will be uint64_t number, then I will use memmov to shift it one place to the left.
Update #2
The solution can be in C/C++, assembly(x86-64) or inline assembly.
This is really 2 subproblems: remove bits from each byte and pack the results. This is the flow of the code below. I wouldn't use a macro for this. Too much going on. Just inline the function if you're worried about performance at that level.
#include <stdio.h>
#include <stdint.h>
// Remove bits n to n+k-1 from x.
unsigned scrunch_1(unsigned x, int n, int k) {
unsigned hi_bits = ~0u << n;
return (x & ~hi_bits) | ((x >> k) & hi_bits);
}
// Remove bits n to n+k-1 from each byte in the buffer,
// then pack left. Return number of packed bytes.
size_t scrunch(uint8_t *buf, size_t size, int n, int k) {
size_t i_src = 0, i_dst = 0;
unsigned src_bits = 0; // Scrunched source bit buffer.
int n_src_bits = 0; // Initially it's empty.
for (;;) {
// Get scrunched bits until the buffer has at least 8.
while (n_src_bits < 8) {
if (i_src >= size) { // Done when source bytes exhausted.
// If there are left-over bits, add one more byte to output.
if (n_src_bits > 0) buf[i_dst++] = src_bits << (8 - n_src_bits);
return i_dst;
}
// Pack 'em in.
src_bits = (src_bits << (8 - k)) | scrunch_1(buf[i_src++], n, k);
n_src_bits += 8 - k;
}
// Write the highest 8 bits of the buffer to the destination byte.
n_src_bits -= 8;
buf[i_dst++] = src_bits >> n_src_bits;
}
}
int main(void) {
uint8_t x[] = { 0xaa, 0xaa, 0xaa, 0xaa };
size_t n = scrunch(x, 4, 2, 3);
for (size_t i = 0; i < n; i++) {
printf("%x ", x[i]);
}
printf("\n");
return 0;
}
This writes b5 ad 60, which by my reckoning is correct. A few other test cases work as well.
Oops I coded it the first time shifting the wrong way, but include that here in case it's useful to someone.
#include <stdio.h>
#include <stdint.h>
// Remove bits n to n+k-1 from x.
unsigned scrunch_1(unsigned x, int n, int k) {
unsigned hi_bits = 0xffu << n;
return (x & ~hi_bits) | ((x >> k) & hi_bits);
}
// Remove bits n to n+k-1 from each byte in the buffer,
// then pack right. Return number of packed bytes.
size_t scrunch(uint8_t *buf, size_t size, int n, int k) {
size_t i_src = 0, i_dst = 0;
unsigned src_bits = 0; // Scrunched source bit buffer.
int n_src_bits = 0; // Initially it's empty.
for (;;) {
// Get scrunched bits until the buffer has at least 8.
while (n_src_bits < 8) {
if (i_src >= size) { // Done when source bytes exhausted.
// If there are left-over bits, add one more byte to output.
if (n_src_bits > 0) buf[i_dst++] = src_bits;
return i_dst;
}
// Pack 'em in.
src_bits |= scrunch_1(buf[i_src++], n, k) << n_src_bits;
n_src_bits += 8 - k;
}
// Write the lower 8 bits of the buffer to the destination byte.
buf[i_dst++] = src_bits;
src_bits >>= 8;
n_src_bits -= 8;
}
}
int main(void) {
uint8_t x[] = { 0xaa, 0xaa, 0xaa, 0xaa };
size_t n = scrunch(x, 4, 2, 3);
for (size_t i = 0; i < n; i++) {
printf("%x ", x[i]);
}
printf("\n");
return 0;
}
This writes d6 5a b. A few other test cases work as well.
Something similar to this should work:
template<typename S> void removeBit(S* buffer, size_t length, size_t index)
{
const size_t BITS_PER_UNIT = sizeof(S)*8;
// first we find which data unit contains the desired bit
const size_t unit = index / BITS_PER_UNIT;
// and which index has the bit inside the specified unit, starting counting from most significant bit
const size_t relativeIndex = (BITS_PER_UNIT - 1) - index % BITS_PER_UNIT;
// then we unset that bit
buffer[unit] &= ~(1 << relativeIndex);
// now we have to shift what's on the right by 1 position
// we create a mask such that if 0b00100000 is the bit removed we use 0b00011111 as mask to shift the rest
const S partialShiftMask = (1 << relativeIndex) - 1;
// now we keep all bits left to the removed one and we shift left all the others
buffer[unit] = (buffer[unit] & ~partialShiftMask) | ((buffer[unit] & partialShiftMask) << 1);
for (int i = unit+1; i < length; ++i)
{
//we set rightmost bit of previous unit according to last bit of current unit
buffer[i-1] |= buffer[i] >> (BITS_PER_UNIT-1);
// then we shift current unit by one
buffer[i] <<= 1;
}
}
I just tested it on some basic cases so maybe something is not exactly correct but this should move you onto the right track.
I'm trying to make a function that would return N number of bits of a given memory chunk, and optionally skipping M bits.
Example:
unsigned char *data = malloc(3);
data[0] = 'A'; data[1] = 'B'; data[2] = 'C';
read(data, 8, 4);
would skip 12 bits and then read 8 bits from the data chunk "ABC".
"Skipping" bits means it would actually bitshift the entire array, carrying bits from the right to the left.
In this example ABC is
01000001 01000010 01000011
and the function would need to return
0001 0100
This question is a follow up of my previous question
Minimal compilable code
#include <ios>
#include <cmath>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
using namespace std;
typedef unsigned char byte;
typedef struct bit_data {
byte *data;
size_t length;
} bit_data;
/*
Asume skip_n_bits will be 0 >= skip_n_bits <= 8
*/
bit_data *read(size_t n_bits, size_t skip_n_bits) {
bit_data *bits = (bit_data *) malloc(sizeof(struct bit_data));
size_t bytes_to_read = ceil(n_bits / 8.0);
size_t bytes_to_read_with_skip = ceil(n_bits / 8.0) + ceil(skip_n_bits / 8.0);
bits->data = (byte *) calloc(1, bytes_to_read);
bits->length = n_bits;
/* Hardcoded for the sake of this example*/
byte *tmp = (byte *) malloc(3);
tmp[0] = 'A'; tmp[1] = 'B'; tmp[2] = 'C';
/*not working*/
if(skip_n_bits > 0){
unsigned char *tmp2 = (unsigned char *) calloc(1, bytes_to_read_with_skip);
size_t i;
for(i = bytes_to_read_with_skip - 1; i > 0; i--) {
tmp2[i] = tmp[i] << skip_n_bits;
tmp2[i - 1] = (tmp[i - 1] << skip_n_bits) | (tmp[i] >> (8 - skip_n_bits));
}
memcpy(bits->data, tmp2, bytes_to_read);
free(tmp2);
}else{
memcpy(bits->data, tmp, bytes_to_read);
}
free(tmp);
return bits;
}
int main(void) {
//Reading "ABC"
//01000001 01000010 01000011
bit_data *res = read(8, 4);
cout << bitset<8>(*res->data);
cout << " -> Should be '00010100'";
return 0;
}
The current code returns 00000000 instead of 00010100.
I feel like the error is something small, but I'm missing it. Where is the problem?
Your code is tagged as C++, and indeed you're already using C++ constructs like bitset, however it's very C-like. The first thing to do I think would be to use more C++.
Turns out bitset is pretty flexible already. My approach would be to create one to store all the bits in our input data, and then grab a subset of that based on the number you wish to skip, and return the subset:
template<size_t N, size_t M, typename T = unsigned char>
std::bitset<N> read(size_t skip_n_bits, const std::array<T, M>& data)
{
const size_t numBits = sizeof(T) * 8;
std::bitset<N> toReturn; // initially all zeros
// if we want to skip all bits, return all zeros
if (M*numBits <= skip_n_bits)
return toReturn;
// create a bitset to store all the bits represented in our data array
std::bitset<M*numBits> tmp;
// set bits in tmp based on data
// convert T into bit representations
size_t pos = M*numBits-1;
for (const T& element : data)
{
for (size_t i=0; i < numBits; ++i)
{
tmp.set(pos-i, (1 << (numBits - i-1)) & element);
}
pos -= numBits;
}
// grab just the bits we need
size_t startBit = tmp.size()-skip_n_bits-1;
for (size_t i = 0; i < N; ++i)
{
toReturn[N-i-1] = tmp[startBit];
tmp <<= 1;
}
return toReturn;
}
Full working demo
And now we can call it like so:
// return 8-bit bitset, skip 12 bits
std::array<unsigned char, 3> data{{'A', 'B', 'C'}};
auto&& returned = read<8>(12, data);
std::cout << returned << std::endl;
Prints
00100100
which is precisely our input 01000001 01000010 01000011 skipping the first twelve bits (from the left towards the right), and only grabbing the next 8 available.
I'd argue this is a bit easier to read than what you've got, esp. from a C++ programmer's point of view.
Trying to hide data within a PPM Image using C++:
void PPMObject::hideData(string phrase)
{
phrase += '\0';
size_t size = phrase.size() * 8;
bitset<8> binary_phrase (phrase.c_str()[0]);
//We need 8 channels for each letter
for (size_t index = 0; index < size; index += 3)
{
//convert red channel to bits
bitset<8> r (this->m_Ptr[index]);
if (r.at(7) != binary_phrase.at(index))
{
r.flip(7);
}
this->m_Ptr[index] = (char) r.to_ulong();
//convert blue channel to bits and find LSB
bitset<8> g (this->m_Ptr[index+1]);
if (g.at(7) != binary_phrase.at(index+1))
{
g.flip(7);
}
this->m_Ptr[index+1] = (char) g.to_ulong();
//convert green channel to bits and find LSB
bitset<8> b (this->m_Ptr[index+2]);
if (b.at(7) != binary_phrase.at(index+2))
{
b.flip(7);
}
this->m_Ptr[index+2] = (char) b.to_ulong();
}
//this->m_Ptr[index+1] = (r.to_ulong() & 0xFF);
}
Then extracting the data by reversing the above process:
string PPMObject::recoverData()
{
size_t size = this->width * this->height * 3;
string message("");
//We need 8 channels for each letter
for (size_t index = 0; index < size; index += 3)
{
//retreive our hidden data from the LSB in red channel
bitset<8> r (this->m_Ptr[index]);
message += r.to_string()[7];
//retreive our hidden data from the LSB in green channel
bitset<8> g (this->m_Ptr[index+1]);
message += g.to_string()[7];
//retreive our hidden data from the LSB in blue channel
bitset<8> b (this->m_Ptr[index+2]);
message += b.to_string()[7];
}
return message;
}
The above hide data function converts each channel (RGB) to binary. It then attempts to find the least significant bit and flips it if it does not match the nth bit of the phrase (starting at zero). It then assigns that new converted binary string back into the pointer as a casted char.
Is using the bitset library a "best practice" technique? I am all ears to a more straightforward, efficient technique. Perhaps, using bitwise maniuplations?
There are no logic errors or problems whatsoever with reading and writing the PPM Image. The pixel data is assigned to a char pointer: this->m_Ptr (above).
Here's some more compact code that does bit manipulation. It doesn't bounds check m_Ptr, but neither does your code.
#include <iostream>
#include <string>
using namespace std;
struct PPMObject
{
void hideData(const string &phrase);
string recoverData(size_t size);
char m_Ptr[256];
};
void PPMObject::hideData(const string &phrase)
{
size_t size = phrase.size();
for (size_t p_index = 0, i_index = 0; p_index < size; ++p_index)
for (int i = 0, bits = phrase[p_index]; i < 8; ++i, bits >>= 1, ++i_index)
{
m_Ptr[i_index] &= 0xFE; // set lsb to 0
m_Ptr[i_index] |= (bits & 0x1); // set lsb to lsb of bits
}
}
string PPMObject::recoverData(size_t size)
{
string ret(size, ' ');
for (size_t p_index = 0, i_index = 0; p_index < size; ++p_index)
{
int i, bits;
for (i = 0, bits = 0; i < 8; ++i, ++i_index)
bits |= ((m_Ptr[i_index] & 0x1) << i);
ret[p_index] = (char) bits;
}
return ret;
}
int main()
{
PPMObject p;
p.hideData("Hello World!");
cout << p.recoverData(12) << endl;
return 0;
}
Note that this code encodes from lsb to msb of each byte of the phrase.
I'm working on a program that manipulates brain data. It recieves a value represents the current magnitude of 8 commonly-recognized types of EEG (brain-waves). This data value is output as a series of eight 3-byte unsigned integers in little-endian format.
Here is a piece of my code:
if (extendedCodeLevel == 0 && code == ASIC_EEG_POWER_CODE)
{
fprintf(arq4, "EXCODE level: %d CODE: 0x%02X vLength: %d\n", extendedCodeLevel, code, valueLength );
fprintf(arq4, "Data value(s):" );
for( i=0; i<valueLength; i++ ) fprintf(arq4, " %d", value[0] & 0xFF );
}
The value value[0] is my output. It is the series of bytes that represents the brain waves. The current output file contains is the following data:
EXCODE level: 0x00 CODE: 0x83 vLength: 24
Data value(s): 16 2 17 5 3 2 22 1 2 1 0 0 0 4 0 0 3 0 0 5 1 0 4 8
What I need is to divide the sequence of bytes above into 3-byte chunks, to identify the EEG. The wave delta is represented by the first 3-byte sequence, theta is represented by the next bytes, and so on. How can I do it?
Assuming that you know that your input will always be exactly eight three-bit integers, all you need is a simple loop that reads three bytes from the input and writes them out as a four-byte value. The easiest way to do this is to treat the input as an array of bytes and then pull bytes off of this array in groups of three.
// Convert an array of eight 3-byte integers into an array
// of eight 4-byte integers.
void convert_3to4(const void* input, void* output)
{
uint32_t tmp;
uint32_t* pOut = output;
uint8_t* pIn = input;
int i;
for (i=0; i<24; i+=3)
{
tmp = pIn[i];
tmp += (pIn[i+1] << 8);
tmp += (pIn[i+2] << 16);
pOut[((i+2) / 3)] = tmp;
}
}
Like this? The last bytes are not be printed if are not aligned by 3. Do you need them?
for( i=0; i<valueLength; i+=3 ) fprintf(arq4, "%d %d %d - ", value[i] & 0xFF,
value[i+1] & 0xFF,
value[i+2] & 0xFF );
Converting eight 3-byte little endian character-steams into eight 4-byte integers is fairly trivial:
for( int i = 0; i < 24; ++i )
{
output[ i & 0x07 ] |= input[ i ] << ( i & 0x18 );
}
I think that (untested) code will do it. Assuming input is a 24-entry char array, and output is an eight-entry int array.
You might try s.th. like this:
union _32BitValue
{
uint8_t bytes[4];
uint32_t uval;
}
size_t extractUint32From3ByteSegemented(const std::vector<uint8_t>& rawData, size_t index, uint32_t& result)
{
// May be do some checks, if the vector size fits extracting the data from it,
// throwing exception or return 0 etc. ...
_32BitValue tmp;
tmp.bytes[0] = 0;
tmp.bytes[1] = rawData[index + 2];
tmp.bytes[2] = rawData[index + 1];
tmp.bytes[3] = rawData[index];
result = ntohl(tmp.uval);
return index + 3;
}
The code used to parse the values from the raw data array:
size_t index = 0;
std::vector<uint8_t> rawData = readRawData(); // Provide such method to read the raw data into the vector
std::vector<uint32_t> myDataValues;
while(index < rawData.size())
{
uint32_t extractedValue;
index = extractUint32From3ByteSegemented(rawData,index,extractedValue);
// Depending on what error detection you choose do check for index returned
// != 0, or catch exception ...
myDataValues.push_back(extractedValue);
}
// Continue with calculations on the extracted values ...
Using the left shift operator and addition as shown in other answers will do the trick as well. But IMHO this sample shows clearly what's going on. It fills the unions byte array with a value in big-endian (network) order and uses ntohl() to retrieve the result in the host machine's used format (big- or little-endian) portably.
What I need is, instead of displaying the whole sequence of 24 bytes, I need to get the 3-byte sequences separately.
You can easily copy the 1d byte array to the desired 2d shape.
Example:
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
int main() {
/* make up data */
uint8_t bytes[] =
{ 16, 2, 17,
5, 3, 2,
22, 1, 2,
1, 0, 0,
0, 4, 0,
0, 3, 0,
0, 5, 1,
0, 4, 8 };
int32_t n_bytes = sizeof(bytes);
int32_t chunksize = 3;
int32_t n_chunks = n_bytes/chunksize + (n_bytes%chunksize ? 1 : 0);
/* chunkify */
uint8_t chunks[n_chunks][chunksize];
memset(chunks, 0, sizeof(uint8_t[n_chunks][chunksize]));
memcpy(chunks, bytes, n_bytes);
/* print result */
size_t i, j;
for (i = 0; i < n_chunks; i++)
{
for (j = 0; j < chunksize; j++)
printf("%02hhd ", chunks[i][j]);
printf("\n");
}
return 0;
}
The output is:
16 02 17
05 03 02
22 01 02
01 00 00
00 04 00
00 03 00
00 05 01
00 04 08
I used some of the examples here to come up with a solution, so I thought I'd share it. It could be a basis for an interface so that objects can transmit copies of themselves over a network with the hton and ntoh functions, which is actually what I am trying to do.
#include <iostream>
#include <string>
#include <exception>
#include <arpa/inet.h>
using namespace std;
void DispLength(string name, size_t var){
cout << "The size of " << name << " is : " << var << endl;
}
typedef int8_t byte;
class Bytes {
public:
Bytes(void* data_ptr, size_t size)
: size_(size)
{ this->bytes_ = (byte*)data_ptr; }
~Bytes(){ bytes_ = NULL; } // Caller is responsible for data deletion.
const byte& operator[] (int idx){
if((size_t)idx <= size_ && idx >= 0)
return bytes_[idx];
else
throw exception();
}
int32_t ret32(int idx) //-- Return a 32 bit value starting at index idx
{
int32_t* ret_ptr = (int32_t*)&((*this)[idx]);
int32_t ret = *ret_ptr;
return ret;
}
int64_t ret64(int idx) //-- Return a 64 bit value starting at index idx
{
int64_t* ret_ptr = (int64_t*)&((*this)[idx]);
int64_t ret = *ret_ptr;
return ret;
}
template <typename T>
T retVal(int idx) //-- Return a value of type T starting at index idx
{
T* T_ptr = (T*)&((*this)[idx]);
T T_ret = *T_ptr;
return T_ret;
}
protected:
Bytes() : bytes_(NULL), size_(0) {}
private:
byte* bytes_; //-- pointer used to scan for bytes
size_t size_;
};
int main(int argc, char** argv){
long double LDouble = 1.0;
Bytes bytes(&LDouble, sizeof(LDouble));
DispLength(string("LDouble"), sizeof(LDouble));
DispLength(string("bytes"), sizeof(bytes));
cout << "As a long double LDouble is " << LDouble << endl;
for( int i = 0; i < 16; i++){
cout << "Byte " << i << " : " << bytes[i] << endl;
}
cout << "Through the eyes of bytes : " <<
(long double) bytes.retVal<long double>(0) << endl;
return 0;
}
you can use bit manipulation operators
I would use, not following actual code, just show example
(for I =0 until 7){
temp val = Value && 111 //AND operation with 111
Value = Value >> 3; //to shift right
}
Some self documenting, maintainable code might look something like this (untested).
typedef union
{
struct {
uint8_t padding;
uint8_t value[3];
} raw;
int32_t data;
} Measurement;
void convert(uint8_t* rawValues, int32_t* convertedValues, int convertedSize)
{
Measurement sample;
int i;
memset(&sample, '\0', sizeof(sample));
for(i=0; i<convertedSize; ++i)
{
memcpy(&sample.raw.value[0], &rawValues[i*sizeof(sample.raw.value)], sizeof(sample.raw.value));
convertedValues[i]=sample.data;
}
}