aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--file_loader.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/file_loader.c b/file_loader.c
index 0ce4b4c..82f594b 100644
--- a/file_loader.c
+++ b/file_loader.c
@@ -7,6 +7,8 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
#include <unistd.h>
#include "file_loader.h"
@@ -22,19 +24,33 @@ file_t *load_file(const char *filename)
file_t *f = calloc(sizeof(file_t), 1);
f->filename = strdup(filename);
// TODO: use mmap when possible
+ struct stat sb;
+ if (fstat(fd, &sb) == -1)
+ goto skip_mmap;
+
+ f->contents = mmap(NULL, (size_t)sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (f->contents == MAP_FAILED)
+ goto skip_mmap;
+
+ f->mmapped = 1;
+ f->length = (size_t)sb.st_size;
+ goto finished_loading;
+
+ skip_mmap:
f->mmapped = 0;
size_t capacity = 1000;
f->length = 0;
- f->contents = calloc(sizeof(char), capacity+1);
+ f->contents = calloc(sizeof(char), capacity);
ssize_t just_read;
while ((just_read=read(fd, &f->contents[f->length], capacity - f->length)) > 0) {
f->length += (size_t)just_read;
if (f->length >= capacity)
f->contents = realloc(f->contents, sizeof(char)*(capacity *= 2) + 1);
}
- f->contents[f->length] = '\0';
- f->end = &f->contents[f->length];
close(fd);
+
+ finished_loading:
+ f->end = &f->contents[f->length];
// Calculate line numbers:
size_t linecap = 10;
@@ -64,7 +80,11 @@ void destroy_file(file_t **f)
(*f)->lines = NULL;
}
if ((*f)->contents) {
- free((*f)->contents);
+ if ((*f)->mmapped) {
+ munmap((*f)->contents, (*f)->length);
+ } else {
+ free((*f)->contents);
+ }
(*f)->contents = NULL;
}
free(*f);