summaryrefslogtreecommitdiff
path: root/source/btree_impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'source/btree_impl.h')
-rw-r--r--source/btree_impl.h165
1 files changed, 165 insertions, 0 deletions
diff --git a/source/btree_impl.h b/source/btree_impl.h
new file mode 100644
index 0000000..8eb0723
--- /dev/null
+++ b/source/btree_impl.h
@@ -0,0 +1,165 @@
1/* single header b-tree implementation by Abdellah El Morabit */
2#ifndef B_TREE_H
3#define B_TREE_H
4
5// maximum height of the tree the lower the lower the lower amount
6// of disk reads which translates into faster?
7#if 0
8global_variable read_only s16 B_TREE_ORDER = 4;
9#endif
10#define B_TREE_ORDER 4
11
12//- NOTE(nasr): defining a key to improve sorting
13// i think saying that a key is a combination of the column + row is a good way of appraoching this
14typedef struct key key;
15struct key
16{
17 string8 header;
18 s32 row;
19};
20
21typedef struct b_tree_node b_tree_node;
22struct b_tree_node
23{
24 // store the key values of the sub nodes? if they are leaves?
25 key keys[B_TREE_ORDER - 1];
26 // TODO(nasr): replace with something more generic?
27 // NOTE(nasr): cons of void * -> no type safety
28 // is there a way to still have some sort of that?
29 // size not variable
30 void *payload_per_key[B_TREE_ORDER - 1];
31 b_tree_node *parent;
32 // handle to store children faster than linked list
33 // because now we can iterate over the nodes instead of having cache misses
34 // when jumping through linked nodes
35 b_tree_node *children[B_TREE_ORDER];
36 // this shouldn't change things but could be a performance improvement on a bigger scale??
37 s32 *max_children;
38 // NOTE(nasr): reference count ::: check how many leaves are using this node
39 // also not needed for now because we don't free individual node because of arena allocator
40 // s32 *refc;
41 s32 key_count;
42 b32 leaf;
43
44
45 // NOTE(nasr): do we hold the reference to the arena? or do we pass is it as a reference?
46 // this could solve memory location issues?
47};
48
49typedef struct b_tree b_tree;
50struct b_tree
51{
52 // NOTE(nasr): make sure this always stays in memory
53 // so that initial fetch never requires a disk read
54 b_tree_node *root;
55};
56
57#ifdef B_TREE_IMPLEMENTATION
58///////////////////////////////////////////////////////////////////////////////
59//- b_tree.c
60
61// TODO(nasr): 1. splitting the tree when getting too big? (horizontally) 2. joining trees?
62
63internal b_tree_node *
64btree_node_alloc(mem_arena *arena)
65{
66 b_tree_node *node = PushStructZero(arena, b_tree_node);
67 node->leaf = 1;
68 return node;
69}
70
71// NOTE(nasr): @return the index of the found element
72internal s32
73btree_node_find_pos(string8 value, b_tree_node *node)
74{
75 unused(value);
76 unused(node);
77
78#if 0
79 s32 i = 0;
80 for (; i < node->key_count && string8_cmp(node->keys[i], value) < 0; ++i);
81 return i;
82#endif
83
84 return 0;
85
86}
87
88internal void
89b_tree_create(mem_arena *arena, b_tree *tree)
90{
91 tree->root = btree_node_alloc(arena);
92 tree->root->leaf = 1;
93 tree->root->key_count = 0;
94}
95
96
97// NOTE(nasr): nodes that get passed as parameters should've already been loaded into memory
98internal void *
99b_tree_search(b_tree_node *node, string8 key)
100{
101 unused(node);
102 unused(key);
103
104#if 0
105 s32 i = btree_node_find_pos(key, node);
106
107 if (i < node->key_count && string8_cmp(node->keys[i], key) == 0)
108 {
109 return node->payload_per_key[i];
110 }
111 if (node->leaf)
112 {
113 return NULL;
114 }
115 return b_tree_search(node->children[i], key);
116#endif
117
118 return NULL;
119}
120
121
122// TODO(nasr): split node when key_count == B_TREE_ORDER - 1 (node is full)
123internal void
124b_tree_insert(b_tree *tree, string8 key, void *payload)
125{
126 unused(tree);
127 unused(key);
128 unused(payload);
129#if 0
130 b_tree_node *current_node = tree->root;
131
132 if (current_node->leaf)
133 {
134 // find the insertion position and shift keys right to make room
135 s32 i = btree_node_find_pos(key, current_node);
136 for (s32 j = current_node->key_count; j > i; --j)
137 {
138 current_node->keys[j] = current_node->keys[j - 1];
139 current_node->payload_per_key[j] = current_node->payload_per_key[j - 1];
140 }
141 current_node->keys[i] = key;
142 current_node->payload_per_key[i] = payload;
143
144 if(current_node->key_count < (B_TREE_ORDER - 1))
145 {
146 current_node->key_count += 1;
147 }
148 else {
149 // TODO(nasr): creating a new branch / tree?
150 // make a seperate function for this
151 }
152 }
153 // TODO(nasr): internal node case walk down then split on the way back up
154#endif
155}
156
157internal void
158b_tree_write(b_tree *bt)
159{
160 // TODO(nasr): write the b_tree to disk
161 unused(bt);
162}
163
164#endif /* B_TREE_IMPLEMENTATION */
165#endif /* B_TREE_H */