I recently programmed some byte swapping functions. As a special I did a function which can convert an entire int array. I please you to look at the following aspects:
- portability
- performance
- usability
- efficiency
#include <stdint.h>
uint16_t _bswap16(uint16_t a)
{
a = ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8);
return a;
}
uint32_t _bswap32(uint32_t a)
{
a = ((a & 0x000000FF) << 24) |
((a & 0x0000FF00) << 8) |
((a & 0x00FF0000) >> 8) |
((a & 0xFF000000) >> 24);
return a;
}
uint64_t _bswap64(uint64_t a)
{
a = ((a & 0x00000000000000FFULL) << 56) |
((a & 0x000000000000FF00ULL) << 40) |
((a & 0x0000000000FF0000ULL) << 24) |
((a & 0x00000000FF000000ULL) << 8) |
((a & 0x000000FF00000000ULL) >> 8) |
((a & 0x0000FF0000000000ULL) >> 24) |
((a & 0x00FF000000000000ULL) >> 40) |
((a & 0xFF00000000000000ULL) >> 56);
return a;
}
Byte Swapping functions for arrays:
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
void *_bswap_a(void *restrict const array, size_t const elem_size, size_t const ndimensions, size_t const *restrict const dimensions, bool const copy, void (*bswapfcn)(void *))
{
/* Validate arguments */
if (array == NULL || elem_size <= 1 || ndimensions == 0 || dimensions == NULL || bswapfcn == NULL) {
return NULL;
}
{
size_t array_size = elem_size;
size_t i = 0;
unsigned char *a = array;
// I know, this is only needed for copy=true....
unsigned char *elemval = malloc(elem_size);
if (!elemval) return NULL;
/* Caluclate array size */
for (i = 0; i < ndimensions; ++i) {
array_size *= dimensions[i];
}
/* Copy the array ? */
if (copy) {
a = malloc(array_size);
if (!a) {
free(elemval);
return NULL;
}
}
/* Go through each element */
for (i = 0; i < array_size; i += elem_size) {
/* Pointer to element */
void *element = (((unsigned char *)array) + i);
if (copy) {
memcpy(elemval, element, elem_size);
bswapfcn(elemval);
memcpy(a + i, elemval, elem_size);
} else {
// Swap the bytes
bswapfcn(element);
}
}
free(elemval);
return a;
}
}
void _bswap16f(void *el)
{
uint16_t *ptr = el;
uint16_t val = *ptr;
*ptr = _bswap16(val);
}
uint16_t *_bswap16a(uint16_t *restrict a, size_t const ndimensions, size_t *restrict const dimensions, bool const copy)
{
return _bswap_a(a, sizeof(uint16_t), ndimensions, dimensions, copy, _bswap16f);
}
void _bswap32f(void *el)
{
uint32_t *ptr = el;
uint32_t val = *ptr;
*ptr = _bswap32(val);
}
uint32_t *_bswap32a(uint32_t *restrict const a, size_t const ndimensions, size_t *restrict const dimensions, bool const copy)
{
return _bswap_a(a, sizeof(uint32_t), ndimensions, dimensions, copy, _bswap32f);
}
void _bswap64f(void *el)
{
uint64_t *ptr = el;
uint64_t val = *ptr;
*ptr = _bswap64(val);
}
uint32_t *_bswap64a(uint64_t *restrict const a, size_t const ndimensions, size_t *restrict const dimensions, bool const copy)
{
return _bswap_a(a, sizeof(uint64_t), ndimensions, dimensions, copy, _bswap64f);
}
Usage:
int main(int argc, const char **argv)
{
/* Swap 32bit Integer */
uint32_t _swappedInteger = _bswap32(32);
/* Swap 32bit Integer array (2 dimensional) and copy the array */
uint32_t _2darray[2][4] = {{8, 7, 6, 5}, {4, 3, 2, 1}};
size_t dimensions[2] = {2, 4};
uint32_t (*_swappedArray)[4] = (void *)_bswap32a((void *)_2darray, 2, dimensions, true);
fprintf(stderr, "%-12u:%4u \n", _swappedInteger, _bswap32(_swappedInteger));
fprintf(stderr, "%-12u:%4u \n", _swappedArray[1][2], _bswap32(_swappedArray[1][2]));
/* _swappedArray is a copy of _2darray so we need to free it */
free(_swappedArray);
}