aah134
aah134

Reputation: 860

memcpy for specific byteorder c/c++

1) I have a big buffer 2) I have a lot of variables of almost every types,

I use this buffer to send to multiple destinations, with different byte orders.

when I send to a network byte order, I usually used htons, or htonl and a customized function for specific data types,

so my issue,

every time I am constructing the buffer, I change byte order for each variable then use memcpy.

however, does anyone know a better way, like I was wishing for an efficient memcpy with specific intended byte order

an example,

UINT32 dwordData = 0x01234567;
UINT32 dwordTmp = htonl(dwordData);
memcpy(&buffer[loc], &dwordTmp, sizeof(UNIT32));
loc += sizeof(UNIT32);

this is just an example I just randomly wrote btw

I hope for a function that look like

memcpyToNetwork(&buffer[loc], &dwordTmp, sizeof(UNIT32));

if you know what I mean, naming is just a descriptive, and depending on the data type it does the byte order for the specific data type so I dont have to keep changing orders manually and have a temp variable to copy to, saving copying twice.

Upvotes: 0

Views: 3407

Answers (1)

Bart van Ingen Schenau
Bart van Ingen Schenau

Reputation: 15768

There is no standard solution, but it is fairly easy to write yourself.

Off the top of my head, an outline could look like this:

// Macro to be able to switch easily between encodings. Just for convenience
#define WriteBuffer WriteBufferBE 

// Generic template as interface specification. Not implemented itself
// Takes buffer (of sufficient size) and value, returns number of bytes written
template <typename T>
size_t WriteBufferBE(char* buffer, const T& value);

template <typename T>
size_t WriteBufferLE(char* buffer, const T& value);

// Specializations for specific types
template <>
size_t WriteBufferBE(char* buffer, const UINT32& value)
{
    buffer[0] = (value >> 24) & 0xFF;
    buffer[1] = (value >> 16) & 0xFF;
    buffer[2] = (value >> 8) & 0xFF;
    buffer[3] = (value) & 0xFF;
    return 4;
}

template <>
size_t WriteBufferBE(char* buffer, const UINT16& value)
{
    buffer[0] = (value >> 8) & 0xFF;
    buffer[1] = (value) & 0xFF;
    return 2;
}

template <>
size_t WriteBufferLE(char* buffer, const UINT32& value)
{
    buffer[0] = (value) & 0xFF;
    buffer[1] = (value >> 8) & 0xFF;
    buffer[2] = (value >> 16) & 0xFF;
    buffer[3] = (value >> 24) & 0xFF;
    return 4;
}

template <>
size_t WriteBufferLE(char* buffer, const UINT16& value)
{
    buffer[0] = (value) & 0xFF;
    buffer[1] = (value >> 8) & 0xFF;
    return 2;
}

// Other types left as an exercise. Can use the existing functions!

// Usage:
loc += writeBuffer(&buffer[loc], dwordData);

Upvotes: 3

Related Questions