diff options
| author | nasr <nsrddyn@gmail.com> | 2026-03-16 19:20:23 +0000 |
|---|---|---|
| committer | nasr <nsrddyn@gmail.com> | 2026-03-16 19:20:23 +0000 |
| commit | 180ccc84aac07c7bee2b09a6e07f7406908409b9 (patch) | |
| tree | efa39665e41c3132626f2c08b2f3ae0d18adc17a /source/b_tree_impl.h | |
| parent | 2e258673171c2e4663a8b5d58e2ad174bb0ecd96 (diff) | |
feature(main): lots of stuff see description
1. increased compile time warnings to help with some optimizations.
2. impelmeented csv lexing helper functions that do stuff on tokenlists
like appending and concatenating lists with each other
3. realiszed that btree design in faulty so disabled it and will
refactor it in the next approach
Diffstat (limited to 'source/b_tree_impl.h')
| -rw-r--r-- | source/b_tree_impl.h | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/source/b_tree_impl.h b/source/b_tree_impl.h new file mode 100644 index 0000000..8eb0723 --- /dev/null +++ b/source/b_tree_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 | ||
| 8 | global_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 | ||
| 14 | typedef struct key key; | ||
| 15 | struct key | ||
| 16 | { | ||
| 17 | string8 header; | ||
| 18 | s32 row; | ||
| 19 | }; | ||
| 20 | |||
| 21 | typedef struct b_tree_node b_tree_node; | ||
| 22 | struct 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 | |||
| 49 | typedef struct b_tree b_tree; | ||
| 50 | struct 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 | |||
| 63 | internal b_tree_node * | ||
| 64 | btree_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 | ||
| 72 | internal s32 | ||
| 73 | btree_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 | |||
| 88 | internal void | ||
| 89 | b_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 | ||
| 98 | internal void * | ||
| 99 | b_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) | ||
| 123 | internal void | ||
| 124 | b_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 | |||
| 157 | internal void | ||
| 158 | b_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 */ | ||
