aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/marktree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/marktree.c')
-rw-r--r--src/nvim/marktree.c343
1 files changed, 183 insertions, 160 deletions
diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c
index 38014ab375..03340a99d6 100644
--- a/src/nvim/marktree.c
+++ b/src/nvim/marktree.c
@@ -54,17 +54,11 @@
#include "nvim/marktree.h"
#define T MT_BRANCH_FACTOR
-#define ILEN (sizeof(mtnode_t)+(2 * T) * sizeof(void *))
+#define ILEN (sizeof(mtnode_t) + (2 * T) * sizeof(void *))
-#define RIGHT_GRAVITY (((uint64_t)1) << 63)
-#define ANTIGRAVITY(id) ((id)&(RIGHT_GRAVITY-1))
-#define IS_RIGHT(id) ((id)&RIGHT_GRAVITY)
-
-#define PAIRED MARKTREE_PAIRED_FLAG
-#define END_FLAG MARKTREE_END_FLAG
#define ID_INCR (((uint64_t)1) << 2)
-#define rawkey(itr) (itr->node->key[itr->i])
+#define rawkey(itr) ((itr)->node->key[(itr)->i])
static bool pos_leq(mtpos_t a, mtpos_t b)
{
@@ -119,7 +113,7 @@ static int key_cmp(mtkey_t a, mtkey_t b)
}
// NB: keeping the events at the same pos sorted by id is actually not
// necessary only make sure that START is before END etc.
- return mt_generic_cmp(a.id, b.id);
+ return mt_generic_cmp(a.flags, b.flags);
}
static inline int marktree_getp_aux(const mtnode_t *x, mtkey_t k, int *r)
@@ -148,7 +142,7 @@ static inline int marktree_getp_aux(const mtnode_t *x, mtkey_t k, int *r)
static inline void refkey(MarkTree *b, mtnode_t *x, int i)
{
- pmap_put(uint64_t)(b->id2node, ANTIGRAVITY(x->key[i].id), x);
+ pmap_put(uint64_t)(b->id2node, mt_lookup_key(x->key[i]), x);
}
// put functions
@@ -164,7 +158,7 @@ static inline void split_node(MarkTree *b, mtnode_t *x, const int i)
z->level = y->level;
z->n = T - 1;
memcpy(z->key, &y->key[T], sizeof(mtkey_t) * (T - 1));
- for (int j = 0; j < T-1; j++) {
+ for (int j = 0; j < T - 1; j++) {
refkey(b, z, j);
}
if (y->level) {
@@ -185,11 +179,11 @@ static inline void split_node(MarkTree *b, mtnode_t *x, const int i)
refkey(b, x, i);
x->n++;
- for (int j = 0; j < T-1; j++) {
+ for (int j = 0; j < T - 1; j++) {
relative(x->key[i].pos, &z->key[j].pos);
}
if (i > 0) {
- unrelative(x->key[i-1].pos, &x->key[i].pos);
+ unrelative(x->key[i - 1].pos, &x->key[i].pos);
}
}
@@ -204,7 +198,7 @@ static inline void marktree_putp_aux(MarkTree *b, mtnode_t *x, mtkey_t k)
(size_t)(x->n - i - 1) * sizeof(mtkey_t));
}
x->key[i + 1] = k;
- refkey(b, x, i+1);
+ refkey(b, x, i + 1);
x->n++;
} else {
i = marktree_getp_aux(x, k, 0) + 1;
@@ -215,44 +209,34 @@ static inline void marktree_putp_aux(MarkTree *b, mtnode_t *x, mtkey_t k)
}
}
if (i > 0) {
- relative(x->key[i-1].pos, &k.pos);
+ relative(x->key[i - 1].pos, &k.pos);
}
marktree_putp_aux(b, x->ptr[i], k);
}
}
-uint64_t marktree_put(MarkTree *b, int row, int col, bool right_gravity, uint8_t decor_level)
+void marktree_put(MarkTree *b, mtkey_t key, int end_row, int end_col, bool end_right)
{
- uint64_t id = (b->next_id+=ID_INCR);
- assert(decor_level < DECOR_LEVELS);
- id = id | ((uint64_t)decor_level << DECOR_OFFSET);
- uint64_t keyid = id;
- if (right_gravity) {
- // order all right gravity keys after the left ones, for effortless
- // insertion (but not deletion!)
- keyid |= RIGHT_GRAVITY;
- }
- marktree_put_key(b, row, col, keyid);
- return id;
-}
+ assert(!(key.flags & ~MT_FLAG_EXTERNAL_MASK));
+ if (end_row >= 0) {
+ key.flags |= MT_FLAG_PAIRED;
+ }
-uint64_t marktree_put_pair(MarkTree *b, int start_row, int start_col, bool start_right, int end_row,
- int end_col, bool end_right, uint8_t decor_level)
-{
- uint64_t id = (b->next_id+=ID_INCR)|PAIRED;
- assert(decor_level < DECOR_LEVELS);
- id = id | ((uint64_t)decor_level << DECOR_OFFSET);
- uint64_t start_id = id|(start_right?RIGHT_GRAVITY:0);
- uint64_t end_id = id|END_FLAG|(end_right?RIGHT_GRAVITY:0);
- marktree_put_key(b, start_row, start_col, start_id);
- marktree_put_key(b, end_row, end_col, end_id);
- return id;
+ marktree_put_key(b, key);
+
+ if (end_row >= 0) {
+ mtkey_t end_key = key;
+ end_key.flags = (uint16_t)((uint16_t)(key.flags & ~MT_FLAG_RIGHT_GRAVITY)
+ |(uint16_t)MT_FLAG_END
+ |(uint16_t)(end_right ? MT_FLAG_RIGHT_GRAVITY : 0));
+ end_key.pos = (mtpos_t){ end_row, end_col };
+ marktree_put_key(b, end_key);
+ }
}
-void marktree_put_key(MarkTree *b, int row, int col, uint64_t id)
+void marktree_put_key(MarkTree *b, mtkey_t k)
{
- mtkey_t k = { .pos = { .row = row, .col = col }, .id = id };
-
+ k.flags |= MT_FLAG_REAL; // let's be real.
if (!b->root) {
b->root = (mtnode_t *)xcalloc(1, ILEN);
b->n_nodes++;
@@ -263,7 +247,7 @@ void marktree_put_key(MarkTree *b, int row, int col, uint64_t id)
if (r->n == 2 * T - 1) {
b->n_nodes++;
s = (mtnode_t *)xcalloc(1, ILEN);
- b->root = s; s->level = r->level+1; s->n = 0;
+ b->root = s; s->level = r->level + 1; s->n = 0;
s->ptr[0] = r;
r->parent = s;
split_node(b, s, 0);
@@ -302,7 +286,7 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
mtnode_t *cur = itr->node;
int curi = itr->i;
- uint64_t id = cur->key[curi].id;
+ uint64_t id = mt_lookup_key(cur->key[curi]);
// fprintf(stderr, "\nDELET %lu\n", id);
if (itr->node->level) {
@@ -320,9 +304,9 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
mtnode_t *x = itr->node;
assert(x->level == 0);
mtkey_t intkey = x->key[itr->i];
- if (x->n > itr->i+1) {
- memmove(&x->key[itr->i], &x->key[itr->i+1],
- sizeof(mtkey_t) * (size_t)(x->n - itr->i-1));
+ if (x->n > itr->i + 1) {
+ memmove(&x->key[itr->i], &x->key[itr->i + 1],
+ sizeof(mtkey_t) * (size_t)(x->n - itr->i - 1));
}
x->n--;
@@ -331,7 +315,7 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
// abort();
// }
if (adjustment == -1) {
- int ilvl = itr->lvl-1;
+ int ilvl = itr->lvl - 1;
const mtnode_t *lnode = x;
do {
const mtnode_t *const p = lnode->parent;
@@ -341,7 +325,7 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
const int i = itr->s[ilvl].i;
assert(p->ptr[i] == lnode);
if (i > 0) {
- unrelative(p->key[i-1].pos, &intkey.pos);
+ unrelative(p->key[i - 1].pos, &intkey.pos);
}
lnode = p;
ilvl--;
@@ -351,7 +335,7 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
cur->key[curi] = intkey;
refkey(b, cur, curi);
relative(intkey.pos, &deleted.pos);
- mtnode_t *y = cur->ptr[curi+1];
+ mtnode_t *y = cur->ptr[curi + 1];
if (deleted.pos.row || deleted.pos.col) {
while (y) {
for (int k = 0; k < y->n; k++) {
@@ -364,37 +348,37 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
}
b->n_keys--;
- pmap_del(uint64_t)(b->id2node, ANTIGRAVITY(id));
+ pmap_del(uint64_t)(b->id2node, id);
// 5.
bool itr_dirty = false;
- int rlvl = itr->lvl-1;
+ int rlvl = itr->lvl - 1;
int *lasti = &itr->i;
while (x != b->root) {
assert(rlvl >= 0);
mtnode_t *p = x->parent;
- if (x->n >= T-1) {
+ if (x->n >= T - 1) {
// we are done, if this node is fine the rest of the tree will be
break;
}
int pi = itr->s[rlvl].i;
assert(p->ptr[pi] == x);
- if (pi > 0 && p->ptr[pi-1]->n > T-1) {
+ if (pi > 0 && p->ptr[pi - 1]->n > T - 1) {
*lasti += 1;
itr_dirty = true;
// steal one key from the left neighbour
- pivot_right(b, p, pi-1);
+ pivot_right(b, p, pi - 1);
break;
- } else if (pi < p->n && p->ptr[pi+1]->n > T-1) {
+ } else if (pi < p->n && p->ptr[pi + 1]->n > T - 1) {
// steal one key from right neighbour
pivot_left(b, p, pi);
break;
} else if (pi > 0) {
// fprintf(stderr, "LEFT ");
- assert(p->ptr[pi-1]->n == T-1);
+ assert(p->ptr[pi - 1]->n == T - 1);
// merge with left neighbour
*lasti += T;
- x = merge_node(b, p, pi-1);
+ x = merge_node(b, p, pi - 1);
if (lasti == &itr->i) {
// TRICKY: we merged the node the iterator was on
itr->node = x;
@@ -403,7 +387,7 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
itr_dirty = true;
} else {
// fprintf(stderr, "RIGHT ");
- assert(pi < p->n && p->ptr[pi+1]->n == T-1);
+ assert(pi < p->n && p->ptr[pi + 1]->n == T - 1);
merge_node(b, p, pi);
// no iter adjustment needed
}
@@ -415,7 +399,7 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
// 6.
if (b->root->n == 0) {
if (itr->lvl > 0) {
- memmove(itr->s, itr->s+1, (size_t)(itr->lvl-1) * sizeof(*itr->s));
+ memmove(itr->s, itr->s + 1, (size_t)(itr->lvl - 1) * sizeof(*itr->s));
itr->lvl--;
}
if (b->root->level) {
@@ -457,26 +441,26 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
static mtnode_t *merge_node(MarkTree *b, mtnode_t *p, int i)
{
- mtnode_t *x = p->ptr[i], *y = p->ptr[i+1];
+ mtnode_t *x = p->ptr[i], *y = p->ptr[i + 1];
x->key[x->n] = p->key[i];
refkey(b, x, x->n);
if (i > 0) {
- relative(p->key[i-1].pos, &x->key[x->n].pos);
+ relative(p->key[i - 1].pos, &x->key[x->n].pos);
}
- memmove(&x->key[x->n+1], y->key, (size_t)y->n * sizeof(mtkey_t));
+ memmove(&x->key[x->n + 1], y->key, (size_t)y->n * sizeof(mtkey_t));
for (int k = 0; k < y->n; k++) {
- refkey(b, x, x->n+1+k);
- unrelative(x->key[x->n].pos, &x->key[x->n+1+k].pos);
+ refkey(b, x, x->n + 1 + k);
+ unrelative(x->key[x->n].pos, &x->key[x->n + 1 + k].pos);
}
if (x->level) {
- memmove(&x->ptr[x->n+1], y->ptr, ((size_t)y->n + 1) * sizeof(mtnode_t *));
- for (int k = 0; k < y->n+1; k++) {
- x->ptr[x->n+k+1]->parent = x;
+ memmove(&x->ptr[x->n + 1], y->ptr, ((size_t)y->n + 1) * sizeof(mtnode_t *));
+ for (int k = 0; k < y->n + 1; k++) {
+ x->ptr[x->n + k + 1]->parent = x;
}
}
- x->n += y->n+1;
+ x->n += y->n + 1;
memmove(&p->key[i], &p->key[i + 1], (size_t)(p->n - i - 1) * sizeof(mtkey_t));
memmove(&p->ptr[i + 1], &p->ptr[i + 2],
(size_t)(p->n - i - 1) * sizeof(mtkey_t *));
@@ -490,7 +474,7 @@ static mtnode_t *merge_node(MarkTree *b, mtnode_t *p, int i)
// the two nodes instead of stealing just one key
static void pivot_right(MarkTree *b, mtnode_t *p, int i)
{
- mtnode_t *x = p->ptr[i], *y = p->ptr[i+1];
+ mtnode_t *x = p->ptr[i], *y = p->ptr[i + 1];
memmove(&y->key[1], y->key, (size_t)y->n * sizeof(mtkey_t));
if (y->level) {
memmove(&y->ptr[1], y->ptr, ((size_t)y->n + 1) * sizeof(mtnode_t *));
@@ -506,7 +490,7 @@ static void pivot_right(MarkTree *b, mtnode_t *p, int i)
x->n--;
y->n++;
if (i > 0) {
- unrelative(p->key[i-1].pos, &p->key[i].pos);
+ unrelative(p->key[i - 1].pos, &p->key[i].pos);
}
relative(p->key[i].pos, &y->key[0].pos);
for (int k = 1; k < y->n; k++) {
@@ -516,7 +500,7 @@ static void pivot_right(MarkTree *b, mtnode_t *p, int i)
static void pivot_left(MarkTree *b, mtnode_t *p, int i)
{
- mtnode_t *x = p->ptr[i], *y = p->ptr[i+1];
+ mtnode_t *x = p->ptr[i], *y = p->ptr[i + 1];
// reverse from how we "always" do it. but pivot_left
// is just the inverse of pivot_right, so reverse it literally.
@@ -525,7 +509,7 @@ static void pivot_left(MarkTree *b, mtnode_t *p, int i)
}
unrelative(p->key[i].pos, &y->key[0].pos);
if (i > 0) {
- relative(p->key[i-1].pos, &p->key[i].pos);
+ relative(p->key[i - 1].pos, &p->key[i].pos);
}
x->key[x->n] = p->key[i];
@@ -533,10 +517,10 @@ static void pivot_left(MarkTree *b, mtnode_t *p, int i)
p->key[i] = y->key[0];
refkey(b, p, i);
if (x->level) {
- x->ptr[x->n+1] = y->ptr[0];
- x->ptr[x->n+1]->parent = x;
+ x->ptr[x->n + 1] = y->ptr[0];
+ x->ptr[x->n + 1]->parent = x;
}
- memmove(y->key, &y->key[1], (size_t)(y->n-1) * sizeof(mtkey_t));
+ memmove(y->key, &y->key[1], (size_t)(y->n - 1) * sizeof(mtkey_t));
if (y->level) {
memmove(y->ptr, &y->ptr[1], (size_t)y->n * sizeof(mtnode_t *));
}
@@ -562,7 +546,7 @@ void marktree_clear(MarkTree *b)
void marktree_free_node(mtnode_t *x)
{
if (x->level) {
- for (int i = 0; i < x->n+1; i++) {
+ for (int i = 0; i < x->n + 1; i++) {
marktree_free_node(x->ptr[i]);
}
}
@@ -570,30 +554,35 @@ void marktree_free_node(mtnode_t *x)
}
/// NB: caller must check not pair!
-uint64_t marktree_revise(MarkTree *b, MarkTreeIter *itr, uint8_t decor_level)
+void marktree_revise(MarkTree *b, MarkTreeIter *itr, uint8_t decor_level, mtkey_t key)
{
- uint64_t old_id = rawkey(itr).id;
- pmap_del(uint64_t)(b->id2node, ANTIGRAVITY(old_id));
- uint64_t new_id = (b->next_id += ID_INCR) + ((uint64_t)decor_level << DECOR_OFFSET);
- rawkey(itr).id = new_id + (RIGHT_GRAVITY&old_id);
- refkey(b, itr->node, itr->i);
- return new_id;
+ // TODO(bfredl): clean up this mess and re-instantiate &= and |= forms
+ // once we upgrade to a non-broken version of gcc in functionaltest-lua CI
+ rawkey(itr).flags = (uint16_t)(rawkey(itr).flags & (uint16_t) ~MT_FLAG_DECOR_MASK);
+ rawkey(itr).flags = (uint16_t)(rawkey(itr).flags
+ | (uint16_t)(decor_level << MT_FLAG_DECOR_OFFSET)
+ | (uint16_t)(key.flags & MT_FLAG_DECOR_MASK));
+ rawkey(itr).decor_full = key.decor_full;
+ rawkey(itr).hl_id = key.hl_id;
+ rawkey(itr).priority = key.priority;
}
void marktree_move(MarkTree *b, MarkTreeIter *itr, int row, int col)
{
- uint64_t old_id = rawkey(itr).id;
+ mtkey_t key = rawkey(itr);
// TODO(bfredl): optimize when moving a mark within a leaf without moving it
// across neighbours!
marktree_del_itr(b, itr, false);
- marktree_put_key(b, row, col, old_id);
+ key.pos = (mtpos_t){ row, col };
+
+ marktree_put_key(b, key);
itr->node = NULL; // itr might become invalid by put
}
// itr functions
// TODO(bfredl): static inline?
-bool marktree_itr_get(MarkTree *b, int row, int col, MarkTreeIter *itr)
+bool marktree_itr_get(MarkTree *b, int32_t row, int col, MarkTreeIter *itr)
{
return marktree_itr_get_ext(b, (mtpos_t){ row, col },
itr, false, false, NULL);
@@ -602,14 +591,15 @@ bool marktree_itr_get(MarkTree *b, int row, int col, MarkTreeIter *itr)
bool marktree_itr_get_ext(MarkTree *b, mtpos_t p, MarkTreeIter *itr, bool last, bool gravity,
mtpos_t *oldbase)
{
- mtkey_t k = { .pos = p, .id = gravity ? RIGHT_GRAVITY : 0 };
- if (last && !gravity) {
- k.id = UINT64_MAX;
- }
if (b->n_keys == 0) {
itr->node = NULL;
return false;
}
+
+ mtkey_t k = { .pos = p, .flags = gravity ? MT_FLAG_RIGHT_GRAVITY : 0 };
+ if (last && !gravity) {
+ k.flags = MT_FLAG_LAST;
+ }
itr->pos = (mtpos_t){ 0, 0 };
itr->node = b->root;
itr->lvl = 0;
@@ -617,7 +607,7 @@ bool marktree_itr_get_ext(MarkTree *b, mtpos_t p, MarkTreeIter *itr, bool last,
oldbase[itr->lvl] = itr->pos;
}
while (true) {
- itr->i = marktree_getp_aux(itr->node, k, 0)+1;
+ itr->i = marktree_getp_aux(itr->node, k, 0) + 1;
if (itr->node->level == 0) {
break;
@@ -627,8 +617,8 @@ bool marktree_itr_get_ext(MarkTree *b, mtpos_t p, MarkTreeIter *itr, bool last,
itr->s[itr->lvl].oldcol = itr->pos.col;
if (itr->i > 0) {
- compose(&itr->pos, itr->node->key[itr->i-1].pos);
- relative(itr->node->key[itr->i-1].pos, &k.pos);
+ compose(&itr->pos, itr->node->key[itr->i - 1].pos);
+ relative(itr->node->key[itr->i - 1].pos, &k.pos);
}
itr->node = itr->node->ptr[itr->i];
itr->lvl++;
@@ -685,7 +675,7 @@ int marktree_itr_last(MarkTree *b, MarkTreeIter *itr)
itr->s[itr->lvl].oldcol = itr->pos.col;
assert(itr->i > 0);
- compose(&itr->pos, itr->node->key[itr->i-1].pos);
+ compose(&itr->pos, itr->node->key[itr->i - 1].pos);
itr->node = itr->node->ptr[itr->i];
itr->lvl++;
@@ -721,7 +711,7 @@ static bool marktree_itr_next_skip(MarkTree *b, MarkTreeIter *itr, bool skip, mt
itr->lvl--;
itr->i = itr->s[itr->lvl].i;
if (itr->i > 0) {
- itr->pos.row -= itr->node->key[itr->i-1].pos.row;
+ itr->pos.row -= itr->node->key[itr->i - 1].pos.row;
itr->pos.col = itr->s[itr->lvl].oldcol;
}
}
@@ -732,10 +722,10 @@ static bool marktree_itr_next_skip(MarkTree *b, MarkTreeIter *itr, bool skip, mt
// internal key, there is always a child after
if (itr->i > 0) {
itr->s[itr->lvl].oldcol = itr->pos.col;
- compose(&itr->pos, itr->node->key[itr->i-1].pos);
+ compose(&itr->pos, itr->node->key[itr->i - 1].pos);
}
if (oldbase && itr->i == 0) {
- oldbase[itr->lvl+1] = oldbase[itr->lvl];
+ oldbase[itr->lvl + 1] = oldbase[itr->lvl];
}
itr->s[itr->lvl].i = itr->i;
assert(itr->node->ptr[itr->i]->parent == itr->node);
@@ -766,7 +756,7 @@ bool marktree_itr_prev(MarkTree *b, MarkTreeIter *itr)
return false;
}
itr->lvl--;
- itr->i = itr->s[itr->lvl].i-1;
+ itr->i = itr->s[itr->lvl].i - 1;
if (itr->i >= 0) {
itr->pos.row -= itr->node->key[itr->i].pos.row;
itr->pos.col = itr->s[itr->lvl].oldcol;
@@ -779,7 +769,7 @@ bool marktree_itr_prev(MarkTree *b, MarkTreeIter *itr)
// internal key, there is always a child before
if (itr->i > 0) {
itr->s[itr->lvl].oldcol = itr->pos.col;
- compose(&itr->pos, itr->node->key[itr->i-1].pos);
+ compose(&itr->pos, itr->node->key[itr->i - 1].pos);
}
itr->s[itr->lvl].i = itr->i;
assert(itr->node->ptr[itr->i]->parent == itr->node);
@@ -805,10 +795,9 @@ void marktree_itr_rewind(MarkTree *b, MarkTreeIter *itr)
bool marktree_itr_node_done(MarkTreeIter *itr)
{
- return !itr->node || itr->i == itr->node->n-1;
+ return !itr->node || itr->i == itr->node->n - 1;
}
-
mtpos_t marktree_itr_pos(MarkTreeIter *itr)
{
mtpos_t pos = rawkey(itr).pos;
@@ -816,28 +805,32 @@ mtpos_t marktree_itr_pos(MarkTreeIter *itr)
return pos;
}
-mtmark_t marktree_itr_current(MarkTreeIter *itr)
+mtkey_t marktree_itr_current(MarkTreeIter *itr)
{
if (itr->node) {
- uint64_t keyid = rawkey(itr).id;
- mtpos_t pos = marktree_itr_pos(itr);
- mtmark_t mark = { .row = pos.row,
- .col = pos.col,
- .id = ANTIGRAVITY(keyid),
- .right_gravity = keyid & RIGHT_GRAVITY };
- return mark;
- }
- return (mtmark_t){ -1, -1, 0, false };
+ mtkey_t key = rawkey(itr);
+ key.pos = marktree_itr_pos(itr);
+ return key;
+ }
+ return MT_INVALID_KEY;
}
-static void swap_id(uint64_t *id1, uint64_t *id2)
+static bool itr_eq(MarkTreeIter *itr1, MarkTreeIter *itr2)
{
- uint64_t temp = *id1;
- *id1 = *id2;
- *id2 = temp;
+ return (&rawkey(itr1) == &rawkey(itr2));
}
-bool marktree_splice(MarkTree *b, int start_line, int start_col, int old_extent_line,
+static void itr_swap(MarkTreeIter *itr1, MarkTreeIter *itr2)
+{
+ mtkey_t key1 = rawkey(itr1);
+ mtkey_t key2 = rawkey(itr2);
+ rawkey(itr1) = key2;
+ rawkey(itr1).pos = key1.pos;
+ rawkey(itr2) = key1;
+ rawkey(itr2).pos = key2.pos;
+}
+
+bool marktree_splice(MarkTree *b, int32_t start_line, int start_col, int old_extent_line,
int old_extent_col, int new_extent_line, int new_extent_col)
{
mtpos_t start = { start_line, start_col };
@@ -859,13 +852,13 @@ bool marktree_splice(MarkTree *b, int start_line, int start_col, int old_extent_
return false;
}
mtpos_t delta = { new_extent.row - old_extent.row,
- new_extent.col-old_extent.col };
+ new_extent.col - old_extent.col };
if (may_delete) {
mtpos_t ipos = marktree_itr_pos(itr);
if (!pos_leq(old_extent, ipos)
|| (old_extent.row == ipos.row && old_extent.col == ipos.col
- && !IS_RIGHT(rawkey(itr).id))) {
+ && !mt_right(rawkey(itr)))) {
marktree_itr_get_ext(b, old_extent, enditr, true, true, NULL);
assert(enditr->node);
// "assert" (itr <= enditr)
@@ -895,13 +888,13 @@ continue_same_node:
break;
}
- if (IS_RIGHT(rawkey(itr).id)) {
- while (rawkey(itr).id != rawkey(enditr).id
- && IS_RIGHT(rawkey(enditr).id)) {
+ if (mt_right(rawkey(itr))) {
+ while (!itr_eq(itr, enditr)
+ && mt_right(rawkey(enditr))) {
marktree_itr_prev(b, enditr);
}
- if (!IS_RIGHT(rawkey(enditr).id)) {
- swap_id(&rawkey(itr).id, &rawkey(enditr).id);
+ if (!mt_right(rawkey(enditr))) {
+ itr_swap(itr, enditr);
refkey(b, itr->node, itr->i);
refkey(b, enditr->node, enditr->i);
} else {
@@ -911,20 +904,20 @@ continue_same_node:
}
}
- if (rawkey(itr).id == rawkey(enditr).id) {
+ if (itr_eq(itr, enditr)) {
// actually, will be past_right after this key
past_right = true;
}
moved = true;
if (itr->node->level) {
- oldbase[itr->lvl+1] = rawkey(itr).pos;
- unrelative(oldbase[itr->lvl], &oldbase[itr->lvl+1]);
+ oldbase[itr->lvl + 1] = rawkey(itr).pos;
+ unrelative(oldbase[itr->lvl], &oldbase[itr->lvl + 1]);
rawkey(itr).pos = loc_start;
marktree_itr_next_skip(b, itr, false, oldbase);
} else {
rawkey(itr).pos = loc_start;
- if (itr->i < itr->node->n-1) {
+ if (itr->i < itr->node->n - 1) {
itr->i++;
if (!past_right) {
goto continue_same_node;
@@ -951,12 +944,12 @@ past_continue_same_node:
rawkey(itr).pos = loc_new;
moved = true;
if (itr->node->level) {
- oldbase[itr->lvl+1] = oldpos;
- unrelative(oldbase[itr->lvl], &oldbase[itr->lvl+1]);
+ oldbase[itr->lvl + 1] = oldpos;
+ unrelative(oldbase[itr->lvl], &oldbase[itr->lvl + 1]);
marktree_itr_next_skip(b, itr, false, oldbase);
} else {
- if (itr->i < itr->node->n-1) {
+ if (itr->i < itr->node->n - 1) {
itr->i++;
goto past_continue_same_node;
} else {
@@ -966,7 +959,6 @@ past_continue_same_node:
}
}
-
while (itr->node) {
unrelative(oldbase[itr->lvl], &rawkey(itr).pos);
int realrow = rawkey(itr).pos.row;
@@ -1006,13 +998,13 @@ void marktree_move_region(MarkTree *b, int start_row, colnr_T start_col, int ext
marktree_itr_get_ext(b, start, itr, false, true, NULL);
kvec_t(mtkey_t) saved = KV_INITIAL_VALUE;
while (itr->node) {
- mtpos_t pos = marktree_itr_pos(itr);
- if (!pos_leq(pos, end) || (pos.row == end.row && pos.col == end.col
- && rawkey(itr).id & RIGHT_GRAVITY)) {
+ mtkey_t k = marktree_itr_current(itr);
+ if (!pos_leq(k.pos, end) || (k.pos.row == end.row && k.pos.col == end.col
+ && mt_right(k))) {
break;
}
- relative(start, &pos);
- kv_push(saved, ((mtkey_t){ .pos = pos, .id = rawkey(itr).id }));
+ relative(start, &k.pos);
+ kv_push(saved, k);
marktree_del_itr(b, itr, false);
}
@@ -1024,30 +1016,36 @@ void marktree_move_region(MarkTree *b, int start_row, colnr_T start_col, int ext
for (size_t i = 0; i < kv_size(saved); i++) {
mtkey_t item = kv_A(saved, i);
unrelative(new, &item.pos);
- marktree_put_key(b, item.pos.row, item.pos.col, item.id);
+ marktree_put_key(b, item);
}
kv_destroy(saved);
}
/// @param itr OPTIONAL. set itr to pos.
-mtpos_t marktree_lookup(MarkTree *b, uint64_t id, MarkTreeIter *itr)
+mtkey_t marktree_lookup_ns(MarkTree *b, uint32_t ns, uint32_t id, bool end, MarkTreeIter *itr)
+{
+ return marktree_lookup(b, mt_lookup_id(ns, id, end), itr);
+}
+
+/// @param itr OPTIONAL. set itr to pos.
+mtkey_t marktree_lookup(MarkTree *b, uint64_t id, MarkTreeIter *itr)
{
mtnode_t *n = pmap_get(uint64_t)(b->id2node, id);
if (n == NULL) {
if (itr) {
itr->node = NULL;
}
- return (mtpos_t){ -1, -1 };
+ return MT_INVALID_KEY;
}
int i = 0;
for (i = 0; i < n->n; i++) {
- if (ANTIGRAVITY(n->key[i].id) == id) {
+ if (mt_lookup_key(n->key[i]) == id) {
goto found;
}
}
abort();
found: {}
- mtpos_t pos = n->key[i].pos;
+ mtkey_t key = n->key[i];
if (itr) {
itr->i = i;
itr->node = n;
@@ -1055,7 +1053,7 @@ found: {}
}
while (n->parent != NULL) {
mtnode_t *p = n->parent;
- for (i = 0; i < p->n+1; i++) {
+ for (i = 0; i < p->n + 1; i++) {
if (p->ptr[i] == n) {
goto found_node;
}
@@ -1063,17 +1061,31 @@ found: {}
abort();
found_node:
if (itr) {
- itr->s[b->root->level-p->level].i = i;
+ itr->s[b->root->level - p->level].i = i;
}
if (i > 0) {
- unrelative(p->key[i-1].pos, &pos);
+ unrelative(p->key[i - 1].pos, &key.pos);
}
n = p;
}
if (itr) {
marktree_itr_fix_pos(b, itr);
}
- return pos;
+ return key;
+}
+
+mtpos_t marktree_get_altpos(MarkTree *b, mtkey_t mark, MarkTreeIter *itr)
+{
+ return marktree_get_alt(b, mark, itr).pos;
+}
+
+mtkey_t marktree_get_alt(MarkTree *b, mtkey_t mark, MarkTreeIter *itr)
+{
+ mtkey_t end = MT_INVALID_KEY;
+ if (mt_paired(mark)) {
+ end = marktree_lookup_ns(b, mark.ns, mark.id, !mt_end(mark), itr);
+ }
+ return end;
}
static void marktree_itr_fix_pos(MarkTree *b, MarkTreeIter *itr)
@@ -1084,7 +1096,7 @@ static void marktree_itr_fix_pos(MarkTree *b, MarkTreeIter *itr)
itr->s[lvl].oldcol = itr->pos.col;
int i = itr->s[lvl].i;
if (i > 0) {
- compose(&itr->pos, x->key[i-1].pos);
+ compose(&itr->pos, x->key[i - 1].pos);
}
assert(x->level);
x = x->ptr[i];
@@ -1092,6 +1104,20 @@ static void marktree_itr_fix_pos(MarkTree *b, MarkTreeIter *itr)
assert(x == itr->node);
}
+// for unit test
+void marktree_put_test(MarkTree *b, uint32_t id, int row, int col, bool right_gravity)
+{
+ mtkey_t key = { { row, col }, UINT32_MAX, id, 0,
+ mt_flags(right_gravity, 0), 0, NULL };
+ marktree_put(b, key, -1, -1, false);
+}
+
+// for unit test
+bool mt_right_test(mtkey_t key)
+{
+ return mt_right(key);
+}
+
void marktree_check(MarkTree *b)
{
#ifndef NDEBUG
@@ -1118,7 +1144,7 @@ static size_t check_node(MarkTree *b, mtnode_t *x, mtpos_t *last, bool *last_rig
{
assert(x->n <= 2 * T - 1);
// TODO(bfredl): too strict if checking "in repair" post-delete tree.
- assert(x->n >= (x != b->root ? T-1 : 0));
+ assert(x->n >= (x != b->root ? T - 1 : 0));
size_t n_keys = (size_t)x->n;
for (int i = 0; i < x->n; i++) {
@@ -1128,33 +1154,31 @@ static size_t check_node(MarkTree *b, mtnode_t *x, mtpos_t *last, bool *last_rig
*last = (mtpos_t) { 0, 0 };
}
if (i > 0) {
- unrelative(x->key[i-1].pos, last);
- }
- if (x->level) {
+ unrelative(x->key[i - 1].pos, last);
}
assert(pos_leq(*last, x->key[i].pos));
if (last->row == x->key[i].pos.row && last->col == x->key[i].pos.col) {
- assert(!*last_right || IS_RIGHT(x->key[i].id));
+ assert(!*last_right || mt_right(x->key[i]));
}
- *last_right = IS_RIGHT(x->key[i].id);
+ *last_right = mt_right(x->key[i]);
assert(x->key[i].pos.col >= 0);
- assert(pmap_get(uint64_t)(b->id2node, ANTIGRAVITY(x->key[i].id)) == x);
+ assert(pmap_get(uint64_t)(b->id2node, mt_lookup_key(x->key[i])) == x);
}
if (x->level) {
n_keys += check_node(b, x->ptr[x->n], last, last_right);
- unrelative(x->key[x->n-1].pos, last);
+ unrelative(x->key[x->n - 1].pos, last);
- for (int i = 0; i < x->n+1; i++) {
+ for (int i = 0; i < x->n + 1; i++) {
assert(x->ptr[i]->parent == x);
- assert(x->ptr[i]->level == x->level-1);
+ assert(x->ptr[i]->level == x->level - 1);
// PARANOIA: check no double node ref
for (int j = 0; j < i; j++) {
assert(x->ptr[i] != x->ptr[j]);
}
}
} else {
- *last = x->key[x->n-1].pos;
+ *last = x->key[x->n - 1].pos;
}
return n_keys;
}
@@ -1182,11 +1206,10 @@ void mt_inspect_node(MarkTree *b, garray_T *ga, mtnode_t *n, mtpos_t off)
snprintf((char *)buf, sizeof(buf), "%d/%d", p.row, p.col);
ga_concat(ga, buf);
if (n->level) {
- mt_inspect_node(b, ga, n->ptr[i+1], p);
+ mt_inspect_node(b, ga, n->ptr[i + 1], p);
} else {
ga_concat(ga, ",");
}
}
ga_concat(ga, "]");
}
-