tzippy
tzippy

Reputation: 6638

Copying 1KB Byte array to single variables using memcpy. Looking for smarter way

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

Answers (5)

Gui13
Gui13

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

jxh
jxh

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

Michael F
Michael F

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

Wookie88
Wookie88

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

Mats Petersson
Mats Petersson

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

Related Questions