mirror of
				https://gitlab.com/80486DX2-66/gists
				synced 2025-05-31 08:31:41 +05:30 
			
		
		
		
	C: add fwrite_le.*
This commit is contained in:
		
							
								
								
									
										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 */
 | 
			
		||||
		Reference in New Issue
	
	Block a user