aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2014-08-23 09:07:24 +0200
committerMarc André Tanner <mat@brain-dump.org>2014-08-23 09:07:24 +0200
commit28e94c3fe4a6ff51b769a3a179f0926b1de6e89b (patch)
treef9c4f3ef8c26bd927fb0a7e2c6be9514d3cc1d6b
parenta700f0c1f7e9ea30543955c56bffec8ad3a23286 (diff)
downloadvis-28e94c3fe4a6ff51b769a3a179f0926b1de6e89b.tar.gz
vis-28e94c3fe4a6ff51b769a3a179f0926b1de6e89b.tar.xz
text: redesing mark implementation
Previously a mark was a byte offset from the start of the file which required updates whenever a text modification happened before it. Now it is simply a pointer into the underlying (mostly) append only buffer which remains valid throughout the whole life cycle.
-rw-r--r--text.c36
1 files changed, 16 insertions, 20 deletions
diff --git a/text.c b/text.c
index 02e96fd..a401c62 100644
--- a/text.c
+++ b/text.c
@@ -109,7 +109,7 @@ struct Text {
struct stat info; /* stat as proped on load time */
int fd; /* the file descriptor of the original mmap-ed data */
LineCache lines; /* mapping between absolute pos in bytes and logical line breaks */
- size_t marks[26]; /* a mark is a byte offset from the start of the document */
+ const char *marks[26]; /* a mark is a pointer into an underlying buffer */
};
/* buffer management */
@@ -493,10 +493,6 @@ bool text_insert_raw(Text *ed, size_t pos, const char *data, size_t len) {
return false;
if (pos < ed->lines.pos)
lineno_cache_invalidate(&ed->lines);
- for (Mark mark = 0; mark < LENGTH(ed->marks); mark++) {
- if (ed->marks[mark] > pos)
- ed->marks[mark] += len;
- }
Location loc = piece_get_intern(ed, pos);
Piece *p = loc.piece;
@@ -697,17 +693,6 @@ bool text_delete(Text *ed, size_t pos, size_t len) {
return false;
if (pos < ed->lines.pos)
lineno_cache_invalidate(&ed->lines);
- for (Mark mark = 0; mark < LENGTH(ed->marks); mark++) {
- if (ed->marks[mark] > pos) {
- if (ed->marks[mark] > pos + len) {
- /* whole delete range before mark position */
- ed->marks[mark] -= len;
- } else {
- /* mark lies within delete range */
- text_mark_clear(ed, mark);
- }
- }
- }
Location loc = piece_get_intern(ed, pos);
Piece *p = loc.piece;
@@ -1014,21 +999,32 @@ size_t text_lineno_by_pos(Text *ed, size_t pos) {
}
void text_mark_set(Text *ed, Mark mark, size_t pos) {
- if (mark < 0 || mark >= LENGTH(ed->marks) || pos >= ed->size)
+ if (mark < 0 || mark >= LENGTH(ed->marks))
+ return;
+ Location loc = piece_get_extern(ed, pos);
+ if (!loc.piece)
return;
- ed->marks[mark] = pos;
+ ed->marks[mark] = loc.piece->data + loc.off;
}
size_t text_mark_get(Text *ed, Mark mark) {
if (mark < 0 || mark >= LENGTH(ed->marks))
return -1;
- return ed->marks[mark];
+ const char *pos = ed->marks[mark];
+ size_t cur = 0;
+ for (Piece *p = ed->begin.next; p->next; p = p->next) {
+ if (p->data <= pos && pos < p->data + p->len)
+ return cur + (pos - p->data);
+ cur += p->len;
+ }
+
+ return -1;
}
void text_mark_clear(Text *ed, Mark mark) {
if (mark < 0 || mark >= LENGTH(ed->marks))
return;
- ed->marks[mark] = -1;
+ ed->marks[mark] = NULL;
}
void text_mark_clear_all(Text *ed) {