shithub: pokecrystal

ref: 313deab55253ee49ef3872491f6805a03b5ea36b
dir: /tools/common.h/

View raw version
#ifndef GUARD_COMMON_H
#define GUARD_COMMON_H

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <inttypes.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>

int getopt_long_index;
#define getopt_long(c, v, s, l) getopt_long(c, v, s, l, &getopt_long_index)

void *malloc_verbose(size_t size) {
	void *m = malloc(size);
	if (!m) {
		fprintf(stderr, "Could not allocate %zu bytes: %s\n", size, strerror(errno));
		exit(1);
	}
	return m;
}

FILE *fopen_verbose(const char *filename, char rw) {
	char mode[3] = {rw, 'b', '\0'};
	FILE *f = fopen(filename, mode);
	if (!f) {
		fprintf(stderr, "Could not open file \"%s\": %s\n", filename, strerror(errno));
		exit(1);
	}
	return f;
}

void fread_verbose(uint8_t *data, size_t size, const char *filename, FILE *f) {
	if (fread(data, 1, size, f) != size) {
		fprintf(stderr, "Could not read from file \"%s\": %s\n", filename, strerror(errno));
		fclose(f);
		exit(1);
	}
}

void fwrite_verbose(const uint8_t *data, size_t size, const char *filename, FILE *f) {
	if (fwrite(data, 1, size, f) != size) {
		fprintf(stderr, "Could not write to file \"%s\": %s\n", filename, strerror(errno));
		fclose(f);
		exit(1);
	}
}

long file_size(const char *filename, FILE *f) {
	long size = 0;
	if (!fseek(f, 0, SEEK_END)) {
		size = ftell(f);
		if (size != -1) {
			rewind(f);
		}
	}
	if (errno) {
		fprintf(stderr, "Could not measure file \"%s\": %s\n", filename, strerror(errno));
		exit(1);
	}
	return size;
}

uint8_t *read_u8(const char *filename, long *size) {
	FILE *f = fopen_verbose(filename, 'r');
	*size = file_size(filename, f);
	uint8_t *data = malloc_verbose(*size);
	fread_verbose(data, *size, filename, f);
	fclose(f);
	return data;
}

void write_u8(const char *filename, uint8_t *data, size_t size) {
	FILE *f = fopen_verbose(filename, 'w');
	fwrite_verbose(data, size, filename, f);
	fclose(f);
}

uint32_t read_png_width_verbose(const char *filename) {
	FILE *f = fopen_verbose(filename, 'r');
	uint8_t header[16] = {0};
	fread_verbose(header, sizeof(header), filename, f);
	static uint8_t expected_header[16] = {
		0x89, 'P', 'N', 'G', '\r', '\n', 0x1A, '\n', // signature
		0, 0, 0, 13,                                 // IHDR chunk length
		'I', 'H', 'D', 'R',                          // IHDR chunk type
	};
	if (memcmp(header, expected_header, sizeof(header))) {
		fprintf(stderr, "Not a valid PNG file: \"%s\"\n", filename);
		fclose(f);
		exit(1);
	}
	uint8_t bytes[4] = {0};
	fread_verbose(bytes, sizeof(bytes), filename, f);
	fclose(f);
	return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
}

#endif // GUARD_COMMON_H