mirror of
https://gitlab.com/80486DX2-66/gists
synced 2024-11-12 22:45:54 +05:30
C: add fwrite_le.*
This commit is contained in:
parent
30dee62706
commit
8b243b9bea
91
c-programming/fwrite_le.c
Normal file
91
c-programming/fwrite_le.c
Normal file
@ -0,0 +1,91 @@
|
||||
#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
|
||||
}
|
25
c-programming/fwrite_le.h
Normal file
25
c-programming/fwrite_le.h
Normal file
@ -0,0 +1,25 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _FWRITE_LE_H
|
||||
#define _FWRITE_LE_H
|
||||
|
||||
#define FWRITE_LE_NO_MODIFICATION 0
|
||||
|
||||
#define DETECTED_LITTLE_ENDIAN 0
|
||||
#define DETECTED_BIG_ENDIAN 1
|
||||
#define UNSUPPORTED_ENDIANNESS -1
|
||||
|
||||
int detect_endianness(void);
|
||||
size_t fwrite_le(void* ptr, size_t size, size_t count, FILE* stream);
|
||||
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);
|
||||
|
||||
#endif /* _FWRITE_LE_H */
|
Loading…
Reference in New Issue
Block a user