#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; #if FWRITE_LE_NO_MODIFICATION bytes[old_pos] = ptr[new_pos]; bytes[new_pos] = ptr[old_pos]; #else uint8_t temp = bytes[old_pos]; bytes[old_pos] = bytes[new_pos]; bytes[new_pos] = temp; #endif } } #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 }