/* * fwrite_le.c * * Author: Intel A80486DX2-66 * License: Creative Commons Zero 1.0 Universal */ #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; } void reorder_le_be( #if FWRITE_LE_NO_MODIFICATION uint8_t* dest, uint8_t* src, #else uint8_t* bytes, #endif size_t count, size_t step) { for (size_t i = 0; i < count; i += step) { const size_t div_size = step / 2; for (size_t j = 0; j < div_size; j++) { const size_t old_pos = i + j, new_pos = i + step - j - 1; #if FWRITE_LE_NO_MODIFICATION dest[old_pos] = src[new_pos]; dest[new_pos] = src[old_pos]; #else uint8_t temp = bytes[old_pos]; bytes[old_pos] = bytes[new_pos]; bytes[new_pos] = temp; #endif } } } 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); #endif reorder_le_be( #if FWRITE_LE_NO_MODIFICATION bytes, #endif (uint8_t*) ptr, bytes_count, size); #if FWRITE_LE_NO_MODIFICATION size_t res = #else return #endif fwrite( #if FWRITE_LE_NO_MODIFICATION bytes, #else (uint8_t*) ptr, #endif size, count, stream); #if FWRITE_LE_NO_MODIFICATION free(bytes); return res; #endif }