]> git.mdlowis.com Git - projs/tide.git/commitdiff
switched from mmap saving and loading to read/write
authorMichael D. Lowis <mike@mdlowis.com>
Tue, 27 Mar 2018 00:39:19 +0000 (20:39 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Tue, 27 Mar 2018 00:39:19 +0000 (20:39 -0400)
inc/edit.h
lib/buf.c
lib/utils.c

index 37c2854fc67c78376f4dbf5c5d515f447ec9389b..38eb6ed2e9f68d1a689e7cbe95acf050ea82a704 100644 (file)
@@ -6,6 +6,7 @@ typedef struct {
     size_t len;   /* length of the buffer */
 } FMap;
 
+size_t pagealign(size_t sz);
 FMap mmap_readonly(char* path);
 FMap mmap_readwrite(char* path, size_t sz);
 void mmap_close(FMap file);
index 367943e63b870ee2d4b82a9e1b14197e3e8b5d77..b536139e9d78ef62c5af069ce091561427831db8 100644 (file)
--- a/lib/buf.c
+++ b/lib/buf.c
@@ -4,6 +4,8 @@
 #include <edit.h>
 #include <ctype.h>
 #include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
 
 size_t buf_setln(Buf* buf, size_t line);
 size_t buf_getcol(Buf* buf, size_t pos);
@@ -49,11 +51,23 @@ size_t buf_load(Buf* buf, char* path) {
     char* addr = strrchr(buf->path, ':');
     if (addr) *addr = '\0', addr++;
 
-    /* load the file and determine the character set */
-    FMap file = mmap_readonly(buf->path);
-    buf_resize(buf, next_size(file.len));
-    for (size_t i = 0; i < file.len;)
-        buf_insert(buf, false, buf_end(buf), file.buf[i++]);
+    /* load the contents from the file */
+    int fd, nread;
+    struct stat sb = {0};
+    if (((fd = open(path, O_RDONLY, 0)) >= 0) && (fstat(fd, &sb) >= 0) && (sb.st_size > 0)) {
+        /* allocate the buffer in advance */
+        free(buf->bufstart);
+        buf->bufsize  = pagealign(sb.st_size);
+        buf->bufstart = malloc(buf->bufsize);
+        buf->bufend   = buf->bufstart + buf->bufsize;
+        buf->gapstart = buf->bufstart;
+        buf->gapend   = buf->bufend;
+        /* Read the file into the buffer */
+        while (sb.st_size && (nread = read(fd, buf->gapstart, sb.st_size)) > 0)
+            buf->gapstart += nread, sb.st_size -= nread;
+        if (nread < 0) buf->errfn("Failed to read file");
+    }
+    if (fd > 0) close(fd);
 
     /* jump to address if we got one */
     if (addr)
@@ -75,25 +89,28 @@ void buf_reload(Buf* buf) {
 
 void buf_save(Buf* buf) {
     if (0 == buf_end(buf)) return;
-
     /* text files should  always end in a new line. If we detected a
        binary file or at least a non-utf8 file, skip this part. */
     if (!buf_iseol(buf, buf_end(buf)-1))
         buf_insert(buf, false, buf_end(buf), '\n');
 
-    size_t wrlen = 0;
-    if (buf->path) {
-        FMap file = mmap_readwrite(buf->path, buf_end(buf) * UTF_MAX);
-        if (file.buf) {
-            for (size_t i = 0, end = buf_end(buf); i < end; i++)
-                file.buf[wrlen++] = buf_get(buf, i);
-            mmap_close(file);
-            truncate(buf->path, wrlen);
+    char* wptr;
+    long fd, nwrite, towrite;
+    if (buf->path && (fd = open(buf->path, O_WRONLY|O_CREAT, 0644)) >= 0) {
+        /* write the chunk before the gap */
+        wptr = buf->bufstart, towrite = (buf->gapstart - buf->bufstart);
+        while (towrite && ((nwrite = write(fd, wptr, towrite)) > 0))
+            wptr += nwrite, towrite -= nwrite;
+        /* write the chunk after the gap */
+        wptr = buf->gapend, towrite = (buf->bufend - buf->gapend);
+        while (towrite && ((nwrite = write(fd, wptr, towrite)) > 0))
+            wptr += nwrite, towrite -= nwrite;
+        close(fd);
+        /* report success or failure */
+        if (nwrite >= 0)
             buf->modified = false;
-            buf->modtime  = modtime(buf->path);
-        } else {
-            buf->errfn("Failed to open file for writing");
-        }
+        else
+            buf->errfn("Failed to write file");
     } else {
         buf->errfn("Need a filename: SaveAs ");
     }
index 30e7f3ef701f38675fc3ec573cc5a8aede7eb124..f5eb902752bb24f4c7141cbf4154dc3990fba5d7 100644 (file)
 #include <time.h>
 #include <sys/time.h>
 
-static size_t pagealign(size_t sz) {
-    size_t pgsize  = sysconf(_SC_PAGE_SIZE);
-    size_t alignmask = pgsize - 1;
+size_t pagealign(size_t sz) {
+    size_t pgsize = sysconf(_SC_PAGE_SIZE), alignmask = pgsize - 1;
     if (sz & alignmask)
         sz += pgsize - (sz & alignmask);
     return sz;
 }
 
-FMap mmap_readonly(char* path) {
-    FMap file = { .buf = NULL, .len = 0 };
-    int fd;
-    struct stat sb;
-    if (((fd = open(path, O_RDONLY, 0)) < 0) ||
-        (fstat(fd, &sb) < 0) ||
-        (sb.st_size == 0)) {
-        return file;
-    }
-    file.buf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
-    file.len = sb.st_size;
-    if (file.buf == MAP_FAILED)
-        die("memory mapping of file failed");
-    close(fd);
-    return file;
-}
-
-FMap mmap_readwrite(char* path, size_t sz) {
-    FMap file = { .buf = NULL, .len = 0 };
-    int fd = open(path, O_CREAT|O_RDWR, 0644);
-    if (fd >= 0) {
-        ftruncate(fd, sz);
-        void* buf = mmap(NULL, pagealign(sz), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
-        if (buf != MAP_FAILED) {
-            file.buf = buf;
-            file.len = sz;
-        }
-        close(fd);
-    }
-    return file;
-}
-
-void mmap_close(FMap file) {
-    if (file.buf)
-        munmap(file.buf, file.len);
-}
-
 uint64_t getmillis(void) {
     struct timespec time;
     clock_gettime(CLOCK_MONOTONIC, &time);
@@ -82,19 +44,6 @@ char* stringdup(const char* s) {
     return ns;
 }
 
-char* fdgets(int fd) {
-    char buf[256];
-    size_t len = 0, nread = 0;
-    char* str = NULL;
-    while ((nread = read(fd, buf, 256)) > 0) {
-        str = realloc(str, len + nread + 1);
-        memcpy(str+len, buf, nread);
-        len += nread;
-    }
-    if (str) str[len] = '\0';
-    return str;
-}
-
 uint64_t modtime(char* path) {
     struct stat status;
     if (stat(path, &status) < 0)