diff options
Diffstat (limited to 'tools/common.h')
-rw-r--r-- | tools/common.h | 130 |
1 files changed, 111 insertions, 19 deletions
diff --git a/tools/common.h b/tools/common.h index 4da0b2ef..a8b69445 100644 --- a/tools/common.h +++ b/tools/common.h @@ -1,40 +1,132 @@ #ifndef GUARD_COMMON_H #define GUARD_COMMON_H -int __getopt_long_i__; -#define getopt_long(c, v, s, l) getopt_long(c, v, s, l, &__getopt_long_i__) +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <inttypes.h> +#include <string.h> +#include <errno.h> +#include <getopt.h> -FILE *fopen_verbose(char *filename, char *mode) { +#ifndef PROGRAM_NAME +#error Define PROGRAM_NAME before including common.h! +#endif +#ifndef USAGE_OPTS +#error Define USAGE_OPTS before including common.h! +#endif + +#define error_exit(...) exit((fprintf(stderr, PROGRAM_NAME ": " __VA_ARGS__), 1)) + +void usage_exit(int status) { + fprintf(stderr, "Usage: " PROGRAM_NAME " " USAGE_OPTS "\n"); + exit(status); +} + +int getopt_long_index; +#define getopt_long(argc, argv, optstring, longopts) getopt_long(argc, argv, optstring, longopts, &getopt_long_index) + +void *xmalloc(size_t size) { + errno = 0; + void *m = malloc(size); + if (!m) { + error_exit("Could not allocate %zu bytes: %s\n", size, strerror(errno)); + } + return m; +} + +void *xcalloc(size_t size) { + errno = 0; + void *m = calloc(size, 1); + if (!m) { + error_exit("Could not allocate %zu bytes: %s\n", size, strerror(errno)); + } + return m; +} + +void *xrealloc(void *m, size_t size) { + errno = 0; + m = realloc(m, size); + if (!m) { + error_exit("Could not allocate %zu bytes: %s\n", size, strerror(errno)); + } + return m; +} + +FILE *xfopen(const char *filename, char rw) { + char mode[3] = {rw, 'b', '\0'}; + errno = 0; FILE *f = fopen(filename, mode); if (!f) { - fprintf(stderr, "Could not open file: \"%s\"\n", filename); + error_exit("Could not open file \"%s\": %s\n", filename, strerror(errno)); } return f; } -uint8_t *read_u8(char *filename, int *size) { - FILE *f = fopen_verbose(filename, "rb"); - if (!f) { - exit(1); +void xfread(uint8_t *data, size_t size, const char *filename, FILE *f) { + errno = 0; + if (fread(data, 1, size, f) != size) { + fclose(f); + error_exit("Could not read from file \"%s\": %s\n", filename, strerror(errno)); + } +} + +void xfwrite(const uint8_t *data, size_t size, const char *filename, FILE *f) { + errno = 0; + if (fwrite(data, 1, size, f) != size) { + fclose(f); + error_exit("Could not write to file \"%s\": %s\n", filename, strerror(errno)); + } +} + +long xfsize(const char *filename, FILE *f) { + long size = -1; + errno = 0; + if (!fseek(f, 0, SEEK_END)) { + size = ftell(f); + if (size != -1) { + rewind(f); + } } - fseek(f, 0, SEEK_END); - *size = ftell(f); - rewind(f); - uint8_t *data = malloc(*size); - if (*size != (int)fread(data, 1, *size, f)) { - fprintf(stderr, "Could not read file: \"%s\"\n", filename); - exit(1); + if (size == -1) { + error_exit("Could not measure file \"%s\": %s\n", filename, strerror(errno)); } + return size; +} + +uint8_t *read_u8(const char *filename, long *size) { + FILE *f = xfopen(filename, 'r'); + *size = xfsize(filename, f); + uint8_t *data = xmalloc(*size); + xfread(data, *size, filename, f); fclose(f); return data; } -void write_u8(char *filename, uint8_t *data, int size) { - FILE *f = fopen_verbose(filename, "wb"); - if (f) { - fwrite(data, 1, size, f); +void write_u8(const char *filename, uint8_t *data, size_t size) { + FILE *f = xfopen(filename, 'w'); + xfwrite(data, size, filename, f); + fclose(f); +} + +uint32_t read_png_width(const char *filename) { + FILE *f = xfopen(filename, 'r'); + uint8_t header[16] = {0}; + xfread(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))) { fclose(f); + error_exit("Not a valid PNG file: \"%s\"\n", filename); } + uint8_t bytes[4] = {0}; + xfread(bytes, sizeof(bytes), filename, f); + fclose(f); + return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; } #endif // GUARD_COMMON_H |