diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2014-10-25 14:58:05 +0200 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2014-10-25 15:32:49 +0200 |
| commit | af1859662a3551f6b0da4c7c56df3854748d66e8 (patch) | |
| tree | c50a1d008bf3ce266fab47f0cf6824d78c0c6aed /text.c | |
| parent | d19c7962600cde319ede932f162e24bf8391d65c (diff) | |
| download | vis-af1859662a3551f6b0da4c7c56df3854748d66e8.tar.gz vis-af1859662a3551f6b0da4c7c56df3854748d66e8.tar.xz | |
Support partial saves
Diffstat (limited to 'text.c')
| -rw-r--r-- | text.c | 35 |
1 files changed, 24 insertions, 11 deletions
@@ -594,17 +594,23 @@ size_t text_redo(Text *txt) { return pos; } +bool text_save(Text *txt, const char *filename) { + Filerange r = (Filerange){ .start = 0, .end = text_size(txt) }; + return text_range_save(txt, &r, filename); +} + /* save current content to given filename. the data is first saved to `filename~` * and then atomically moved to its final (possibly alredy existing) destination * using rename(2). */ -bool text_save(Text *txt, const char *filename) { +bool text_range_save(Text *txt, Filerange *range, const char *filename) { int fd = -1; - size_t len = strlen(filename) + 10; - char *tmpname = malloc(len); + size_t bufsize = strlen(filename) + 10; + size_t size = range->end - range->start; + char *tmpname = malloc(bufsize); if (!tmpname) return false; - snprintf(tmpname, len, "%s~", filename); + snprintf(tmpname, bufsize, "%s~", filename); // TODO preserve user/group struct stat meta; if (stat(filename, &meta) == -1) { @@ -616,21 +622,28 @@ bool text_save(Text *txt, const char *filename) { /* O_RDWR is needed because otherwise we can't map with MAP_SHARED */ if ((fd = open(tmpname, O_CREAT|O_RDWR|O_TRUNC, meta.st_mode)) == -1) goto err; - if (ftruncate(fd, txt->size) == -1) + if (ftruncate(fd, size) == -1) goto err; - if (txt->size > 0) { - void *buf = mmap(NULL, txt->size, PROT_WRITE, MAP_SHARED, fd, 0); + if (size > 0) { + void *buf = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0); if (buf == MAP_FAILED) goto err; char *cur = buf; - text_iterate(txt, it, 0) { - size_t len = it.end - it.start; - memcpy(cur, it.start, len); + size_t rem = size; + + for (Iterator it = text_iterator_get(txt, range->start); + rem > 0 && text_iterator_valid(&it); + text_iterator_next(&it)) { + size_t len = it.end - it.text; + if (len > rem) + len = rem; + memcpy(cur, it.text, len); cur += len; + rem -= len; } - if (munmap(buf, txt->size) == -1) + if (munmap(buf, size) == -1) goto err; } if (close(fd) == -1) |
