#include #include #include #include #include #include "read_file.h" #define CHECK_OOM(ptr) \ if (ptr == NULL) { \ fprintf(stderr, "geheugen is op\n"); \ /* I think I should free the original memory here, but whatever */ \ return NULL; \ } struct filebuf *stream_to_filebuf(FILE *restrict stream) { size_t sz = 0; size_t cap = 4096; char *buf = malloc(cap); CHECK_OOM(buf); while (!feof(stream)) { if (cap-sz == 0) { cap *= 2; buf = realloc(buf, cap); CHECK_OOM(buf); } const size_t amount = cap-sz; const size_t n = fread(buf+sz, 1, amount, stream); sz += n; if (n != amount && !feof(stream)) { fprintf(stderr, "fout tijdens lezen van standaard invoer.\n"); free(buf); return NULL; } } buf = realloc(buf, sz); struct filebuf *res = calloc(1, sizeof(struct filebuf)); res->buf = buf; res->sz = sz; res->mapping_type = MT_OWNED; return res; } static void *fd_to_mmap(const int fd, struct stat sb) { void *addr = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { return NULL; } close(fd); return addr; } struct filebuf *file_to_filebuf(char *fname) { const int fd = open(fname, O_RDONLY); struct stat sb; if (fstat(fd, &sb) == -1) { goto stream; } void *addr; if ((addr = fd_to_mmap(fd, sb)) != NULL) { struct filebuf *res = calloc(1, sizeof(struct filebuf)); res->buf = addr; res->sz = sb.st_size; res->mapping_type = MT_MMAP; return res; } stream: { FILE *stream = fdopen(fd, "rb"); struct filebuf *res = stream_to_filebuf(stream); fclose(stream); return res; } } void free_filebuf(struct filebuf *fb) { switch (fb->mapping_type) { case MT_MMAP: munmap(fb->buf, fb->sz); break; case MT_OWNED: free(fb->buf); break; } free(fb); }