aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/marktree_defs.h
blob: d43130db6f0261a7b471983b8486121ea7f47c1f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#pragma once

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "nvim/decoration_defs.h"
#include "nvim/map_defs.h"

enum {
  MT_MAX_DEPTH     = 20,
  MT_BRANCH_FACTOR = 10,
  // note max branch is actually 2*MT_BRANCH_FACTOR
  // and strictly this is ceil(log2(2*MT_BRANCH_FACTOR + 1))
  // as we need a pseudo-index for "right before this node"
  MT_LOG2_BRANCH   = 5,
};

typedef struct {
  int32_t row;
  int32_t col;
} MTPos;
#define MTPos(r, c) ((MTPos){ .row = (r), .col = (c) })

// Currently there are four counts, which makes for a uint32_t[4] per node
// which makes for nice autovectorization into a single XMM or NEON register
typedef enum {
  kMTMetaInline,
  kMTMetaLines,
  kMTMetaSignHL,
  kMTMetaSignText,
  kMTMetaCount,  // sentinel, must be last
} MetaIndex;

#define kMTFilterSelect ((uint32_t)-1)

// a filter should be set to kMTFilterSelect for the selected kinds, zero otherwise
typedef const uint32_t *MetaFilter;

typedef struct mtnode_s MTNode;

typedef struct {
  MTPos pos;
  int lvl;
  MTNode *x;
  int i;
  struct {
    int oldcol;
    int i;
  } s[MT_MAX_DEPTH];

  size_t intersect_idx;
  MTPos intersect_pos;
  MTPos intersect_pos_x;
} MarkTreeIter;

#define marktree_itr_valid(itr) ((itr)->x != NULL)
// access raw key: flags in MT_FLAG_EXTERNAL_MASK and decor_data are safe to modify.
#define mt_itr_rawkey(itr) ((itr)->x->key[(itr)->i])

// Internal storage
//
// NB: actual marks have flags > 0, so we can use (row,col,0) pseudo-key for
// "space before (row,col)"
typedef struct {
  MTPos pos;
  uint32_t ns;
  uint32_t id;
  uint16_t flags;
  DecorInlineData decor_data;  // "ext" tag in flags
} MTKey;

typedef struct {
  MTKey start;
  MTPos end_pos;
  bool end_right_gravity;
} MTPair;

typedef kvec_withinit_t(uint64_t, 4) Intersection;

// part of mtnode_s which is only allocated for inner nodes:
// pointer to children as well as their meta counts
struct mtnode_inner_s {
  MTNode *i_ptr[2 * MT_BRANCH_FACTOR];
  uint32_t i_meta[2 * MT_BRANCH_FACTOR][kMTMetaCount];
};

struct mtnode_s {
  int32_t n;
  int16_t level;
  int16_t p_idx;  // index in parent
  Intersection intersect;
  MTNode *parent;
  MTKey key[2 * MT_BRANCH_FACTOR - 1];
  struct mtnode_inner_s s[];
};

typedef struct {
  MTNode *root;
  uint32_t meta_root[kMTMetaCount];
  size_t n_keys, n_nodes;
  PMap(uint64_t) id2node[1];
} MarkTree;