Reputation: 6638
I have a byte array arr
of size 1024 and 4 variables into which I want to copy the beginning of array arr
.
Later I want to read more data from the array. What would be the best and most dynamic way to achieve this? At the moment I am just copying bytes statically. Maybe a pointer that is set to the current reading position automatically?
Thanks!
unsigned char arr[1024];
unsigned char field1 = 0;
unsigned int field2 =0;
unsigned int field3 = 0;
unsigned char field4 = 0;
memcpy(&field1, arr, sizeof(field1));
memcpy(&field2, arr[1], sizeof(field2));
memcpy(&field3, arr[5], sizeof(field3));
memcpy(&field4, arr[9], sizeof(field4));
Upvotes: 0
Views: 1232
Reputation: 13551
My take:
unsigned int copy_data( void* from, unsigned int size, void* to )
{
memcpy( from, to, size);
return size;
}
unsigned int offset = 0;
unsigned char arr[1024];
unsigned char field1 = 0;
unsigned int field2 =0;
unsigned int field3 = 0;
unsigned char field4 = 0;
offset += copy_data( arr + offset, &field1, sizeof(field1) );
offset += copy_data( arr + offset, &field2, sizeof(field2) );
offset += copy_data( arr + offset, &field3, sizeof(field3) );
offset += copy_data( arr + offset, &field4, sizeof(field4) );
Then offset is ready to be used for the next read from your buffer.
You can MACROize if you feel (but that's becoming ugly):
#define COPY_TO_FIELD( arr, off, field_number ) \
(offset) += copy_data( (arr) + (offset), &field##field_number, sizeof(field##field_number))
COPY_TO_FIELD( arr, offset, 1);
COPY_TO_FIELD( arr, offset, 2);
COPY_TO_FIELD( arr, offset, 3);
COPY_TO_FIELD( arr, offset, 4);
Upvotes: 0
Reputation: 70402
How about a variadic template function to help out.
size_t copy_array_r (const void *, size_t, size_t accum) {
return accum;
}
template <typename T, typename... Params>
size_t copy_array_r (const void *arr, size_t sz, size_t accum,
T &arg, Params... parameters) {
if (sz < sizeof(T)) {
return copy_array_r(0, 0, accum + sizeof(T), parameters...);
}
const char *arrp = static_cast<const char *>(arr);
std::copy(arrp, arrp + sizeof(T), &arg);
return copy_array_r(arrp + sizeof(T), sz - sizeof(T), accum + sizeof(T),
parameters...);
}
template <typename... Params>
size_t copy_array (const void *arr, size_t sz, Params... parameters) {
size_t bytes_copied = copy_array_r(arr, sz, 0, parameters...);
if (bytes_copied > sz) {
throw std::invalid_argument("insufficient size");
}
return bytes_copied;
}
Then use it like this:
bytes_copied = copy_array(arr, sizeof(arr), field1, field2, field3, field4);
Upvotes: 0
Reputation: 40830
Group up your variables in a structure:
typedef struct {
unsigned char f1;
unsigned int f2, f3;
unsigned char f4;
} __attribute__((packed)) mystruct_t;
unsigned char buffer[1024];
/* Track your position in the buffer: */
unsigned char *pos = buffer;
/* Map your variables on the buffer: */
mystruct_t *first_tuple = (mystruct_t *) pos;
/* Advance your position in the buffer: */
pos += sizeof *first_tuple;
Upvotes: -1
Reputation: 34911
Create a struct:
struct s{
unsigned char field1;
unsigned int field2;
unsigned int field3;
unsigned char field4;
}__attribute__((packed));
And then:
struct s* ptr;
ptr = arr;
That will interpret data from array as this structure. Then just increment pointer if you want to read next records. Please note that I'm using custom GCC extension, look for extension for your compiler if you're not using GCC.
Upvotes: 0
Reputation: 129364
You mean something like:
char *curr = arr;
memcpy(&field1, curr, sizeof(field1));
curr += sizeof(field1);
memcpy(&field2, curr, sizeof(field2));
curr += sizeof(field2);
...
Of course, you could go a step further and make a table:
struct Table
{
void *field;
size_t size;
} table =
{
{ &field1, sizeof(field1) },
{ &filed2, sizeof(field2) },
...
};
curr = arr;
for(int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
{
memcpy(table[i].field, curr, table[i].size);
curr += table[i].size;
}
Upvotes: 2