Add new marktree data structure for storing marks

This is inspired by Atom's "marker index" data structure to efficiently
adjust marks to text insertions deletions, but uses a wide B-tree
(derived from kbtree) to keep the nesting level down.
This commit is contained in:
Björn Linse
2019-11-15 18:21:45 +01:00
parent 3d1531aee5
commit 55677ddc46
4 changed files with 1456 additions and 0 deletions

View File

@@ -53,6 +53,8 @@ MAP_DECLS(String, handle_T)
#define map_del(T, U) map_##T##_##U##_del
#define map_clear(T, U) map_##T##_##U##_clear
#define map_size(map) ((map)->table->size)
#define pmap_new(T) map_new(T, ptr_t)
#define pmap_free(T) map_free(T, ptr_t)
#define pmap_get(T) map_get(T, ptr_t)

1188
src/nvim/marktree.c Normal file

File diff suppressed because it is too large Load Diff

76
src/nvim/marktree.h Normal file
View File

@@ -0,0 +1,76 @@
#ifndef NVIM_MARKTREE_H
#define NVIM_MARKTREE_H
#include <stdint.h>
#include "nvim/map.h"
#include "nvim/garray.h"
#define MT_MAX_DEPTH 20
#define MT_BRANCH_FACTOR 10
typedef struct {
int32_t row;
int32_t col;
} mtpos_t;
typedef struct {
int32_t row;
int32_t col;
uint64_t id;
bool right_gravity;
} mtmark_t;
typedef struct mtnode_s mtnode_t;
typedef struct {
int oldcol;
int i;
} iterstate_t;
typedef struct {
mtpos_t pos;
int lvl;
mtnode_t *node;
int i;
iterstate_t s[MT_MAX_DEPTH];
} MarkTreeIter;
// Internal storage
//
// NB: actual marks have id > 0, so we can use (row,col,0) pseudo-key for
// "space before (row,col)"
typedef struct {
mtpos_t pos;
uint64_t id;
} mtkey_t;
struct mtnode_s {
int32_t n;
int32_t level;
// TODO(bfredl): we could consider having a only-sometimes-valid
// index into parent for faster "chached" lookup.
mtnode_t *parent;
mtkey_t key[2 * MT_BRANCH_FACTOR - 1];
mtnode_t *ptr[];
};
// TODO(bfredl): the iterator is pretty much everpresent, make it part of the
// tree struct itself?
typedef struct {
mtnode_t *root;
size_t n_keys, n_nodes;
uint64_t next_id;
// TODO(bfredl): the pointer to node could be part of the larger
// Map(uint64_t, ExtmarkItem) essentially;
PMap(uint64_t) *id2node;
} MarkTree;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "marktree.h.generated.h"
#endif
#define MARKTREE_PAIRED_FLAG (((uint64_t)1) << 1)
#define MARKTREE_END_FLAG (((uint64_t)1) << 0)
#endif // NVIM_MARKTREE_H