69 lines
1.6 KiB
C
69 lines
1.6 KiB
C
|
#include "fwrite_le.h"
|
||
|
|
||
|
int detect_endianness(void) {
|
||
|
volatile uint32_t i = 0x01234567;
|
||
|
uint8_t* bytes = (uint8_t*)(&i);
|
||
|
if (bytes[0] == 0x01 &&
|
||
|
bytes[1] == 0x23 &&
|
||
|
bytes[2] == 0x45 &&
|
||
|
bytes[3] == 0x67)
|
||
|
return DETECTED_BIG_ENDIAN;
|
||
|
else if (
|
||
|
bytes[0] == 0x67 &&
|
||
|
bytes[1] == 0x45 &&
|
||
|
bytes[2] == 0x23 &&
|
||
|
bytes[3] == 0x01)
|
||
|
return DETECTED_LITTLE_ENDIAN;
|
||
|
return UNSUPPORTED_ENDIANNESS;
|
||
|
}
|
||
|
|
||
|
size_t fwrite_le(void* ptr, size_t size, size_t count, FILE* stream) {
|
||
|
/*
|
||
|
* warning: this function modifies `void* ptr` by default!
|
||
|
* (if FWRITE_LE_NO_MODIFICATION in the header is 0)
|
||
|
*/
|
||
|
if (ptr == NULL)
|
||
|
return 0;
|
||
|
|
||
|
int endianness = detect_endianness();
|
||
|
if (endianness == UNSUPPORTED_ENDIANNESS) {
|
||
|
fprintf(stderr, "Unsupported endianness\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
} else if (endianness == DETECTED_LITTLE_ENDIAN)
|
||
|
return fwrite(ptr, size, count, stream);
|
||
|
|
||
|
// case: big-endian
|
||
|
size_t bytes_count = size * count;
|
||
|
#if FWRITE_LE_NO_MODIFICATION
|
||
|
uint8_t* bytes = calloc(bytes_count, sizeof(uint8_t));
|
||
|
if (bytes == NULL) {
|
||
|
perror("calloc");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
memcpy(bytes, ptr, bytes_count);
|
||
|
#else
|
||
|
uint8_t* bytes = (uint8_t*) ptr;
|
||
|
#endif
|
||
|
|
||
|
for (size_t i = 0; i < bytes_count; i += size) {
|
||
|
const size_t div_size = size >> 1; // divide by 2
|
||
|
for (size_t j = 0; j < div_size; j++) {
|
||
|
const size_t old_pos = i + j, new_pos = i + size - j - 1;
|
||
|
uint8_t temp = bytes[old_pos];
|
||
|
bytes[old_pos] = bytes[new_pos];
|
||
|
bytes[new_pos] = temp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if FWRITE_LE_NO_MODIFICATION
|
||
|
size_t res =
|
||
|
#else
|
||
|
return
|
||
|
#endif
|
||
|
fwrite(bytes, size, count, stream);
|
||
|
#if FWRITE_LE_NO_MODIFICATION
|
||
|
free(bytes);
|
||
|
return res;
|
||
|
#endif
|
||
|
}
|