diff options
| author | WormHeamer | 2025-12-29 03:47:03 -0500 |
|---|---|---|
| committer | WormHeamer | 2025-12-29 03:47:03 -0500 |
| commit | ae29fc07f0eae5fba0cfc6e028afb6025c0065bc (patch) | |
| tree | f3d64d83c699434d73769f9f19ff8ececd8effe3 /txt.c | |
| parent | 4c5442ccd9428c4bb4e73939d3eff50911b574c0 (diff) | |
try and prevent 0-length splits occurring
Diffstat (limited to 'txt.c')
| -rw-r--r-- | txt.c | 86 |
1 files changed, 51 insertions, 35 deletions
@@ -94,48 +94,65 @@ static int txt_are_pieces_adjacent(Txt *t, u32 a, u32 b) { return pa->buf == pb->buf && pa->ofs + pa->n == pb->ofs; } -static TxtLoc txt_join_or_kill(TxtLoc l) { - Txt *b = l.t; - while (l.t->ptbl.v[l.p].n == 0 && b->ptbl.n > 1) { - txt_remove_piece(b, l.p); - if (l.p >= b->ptbl.n) { - l.p = b->ptbl.n - 1; - l.i = b->ptbl.v[l.p].n; - } +static int txt_trim_empty(TxtLoc *lp) { + TxtLoc l = *lp; + int deleted = 0; + while (l.p > 0 && l.t->ptbl.v[l.p-1].n == 0) { + txt_remove_piece(l.t, l.p - 1); + l.p--; + deleted = 1; } - while (l.p + 1 < b->ptbl.n && l.t->ptbl.v[l.p + 1].n == 0) { - txt_remove_piece(b, l.p + 1); - if (l.p >= b->ptbl.n) { - l.p = b->ptbl.n - 1; - l.i = b->ptbl.v[l.p].n; - } + while (l.p + 1 < l.t->ptbl.n && l.t->ptbl.v[l.p+1].n == 0) { + txt_remove_piece(l.t, l.p + 1); + deleted = 1; } - if (l.p + 1 < b->ptbl.n && txt_are_pieces_adjacent(b, l.p, l.p + 1)) { - b->ptbl.v[l.p].n += b->ptbl.v[l.p+1].n; - txt_remove_piece(b, l.p + 1); - if (l.p >= b->ptbl.n) { - l.p = b->ptbl.n - 1; - l.i = b->ptbl.v[l.p].n; + while (l.t->ptbl.n > 1 && l.t->ptbl.v[l.p].n == 0) { + txt_remove_piece(l.t, l.p); + if (l.p >= l.t->ptbl.n) { + l.p = l.t->ptbl.n - 1; + l.i = l.t->ptbl.v[l.p].n; } + deleted = 1; } - if (l.p > 0 && txt_are_pieces_adjacent(b, l.p - 1, l.p)) { - l.i = b->ptbl.v[l.p - 1].n; - b->ptbl.v[l.p - 1].n += b->ptbl.v[l.p].n; - txt_remove_piece(b, l.p); - l.p--; - ASSERT(l.p < b->ptbl.n); - } - return l; + *lp = l; + return deleted; } static inline TxtLoc resolve_loc(TxtLoc l) { - if (l.p + 1 < l.t->ptbl.n && l.i == l.t->ptbl.v[l.p].n) { + while (l.p + 1 < l.t->ptbl.n && l.i == l.t->ptbl.v[l.p].n) { l.p++; l.i = 0; } + ASSERT(txt_valid_loc(l)); return l; } +static TxtLoc txt_post_edit(TxtLoc l) { + l = resolve_loc(l); + ASSERT(txt_valid_loc(l)); +loop: + if (txt_trim_empty(&l)) { + ASSERT(txt_valid_loc(l)); + goto loop; + } + if (l.p > 0 && txt_are_pieces_adjacent(l.t, l.p - 1, l.p)) { + l.i = l.t->ptbl.v[l.p - 1].n; + l.t->ptbl.v[l.p - 1].n += l.t->ptbl.v[l.p].n; + txt_remove_piece(l.t, l.p); + l.p--; + ASSERT(txt_valid_loc(l)); + goto loop; + } + if (l.p + 1 < l.t->ptbl.n && txt_are_pieces_adjacent(l.t, l.p, l.p + 1)) { + l.t->ptbl.v[l.p].n += l.t->ptbl.v[l.p + 1].n; + txt_remove_piece(l.t, l.p + 1); + ASSERT(txt_valid_loc(l)); + goto loop; + } + ASSERT(txt_valid_loc(l)); + return resolve_loc(l); +} + TxtLoc txt_insert(TxtLoc l, const char *s, u32 n) { l = txt_add_piece(l.t, l); TxtPiece *p = &l.t->ptbl.v[l.p]; @@ -148,9 +165,7 @@ TxtLoc txt_insert(TxtLoc l, const char *s, u32 n) { p->n += n; l.t->len += n; l.i = p->n; - l = txt_join_or_kill(l); - l.i = l.t->ptbl.v[l.p].n; - return resolve_loc(l); + return txt_post_edit(l); } TxtLoc txt_insert_c(TxtLoc l, u32 ch) { @@ -166,7 +181,7 @@ TxtLoc txt_delete(TxtLoc l, u32 n) { l.p = pi; l.i = l.t->ptbl.v[l.p].n; for (;;) { - ASSERT(l.i == l.t->ptbl.v[l.p].n); + if (l.i != l.t->ptbl.v[l.p].n) break; if (l.i >= n) { l.i -= n; l.t->ptbl.v[l.p].n -= n; @@ -179,9 +194,9 @@ TxtLoc txt_delete(TxtLoc l, u32 n) { l.p = l.p - 1; l.i = l.t->ptbl.v[l.p].n; } - l = txt_join_or_kill(l); + while (txt_trim_empty(&l)); } - return resolve_loc(txt_join_or_kill(l)); + return txt_post_edit(l); } u32 txt_range_len(TxtLoc lo, TxtLoc hi) { @@ -270,6 +285,7 @@ void txt_write_range(int fd, TxtLoc lo, TxtLoc hi) { lo.p++; lo.i = 0; } + ASSERT(lo.p == hi.p); if (hi.i > lo.i) { TxtPiece *p = &lo.t->ptbl.v[lo.p]; write(fd, lo.t->buf[p->buf].s + p->ofs + lo.i, hi.i - lo.i); |
