diff options
| author | nasr <nsrddyn@gmail.com> | 2026-03-10 22:27:32 +0000 |
|---|---|---|
| committer | nasr <nsrddyn@gmail.com> | 2026-03-10 22:27:32 +0000 |
| commit | bcf4c2ebce03699110d13608999510c43fa959df (patch) | |
| tree | 53be66ebd48fabe5de3a7e82ef3b37391fbb2c3e | |
| parent | 74097b6252ec8c7b368807381f764b8614e9bf9f (diff) | |
refactor(main): b_tree implementation. single header thing
| -rw-r--r-- | source/b_tree.h (renamed from source/btree.h) | 71 | ||||
| -rw-r--r-- | source/base/base_io.h | 3 |
2 files changed, 41 insertions, 33 deletions
diff --git a/source/btree.h b/source/b_tree.h index 42c8e21..43a33a6 100644 --- a/source/btree.h +++ b/source/b_tree.h | |||
| @@ -1,17 +1,22 @@ | |||
| 1 | #ifndef BTREE_H | 1 | /* single header b-tree implementation by Abdellah El Morabit */ |
| 2 | #define BTREE_H | 2 | #ifndef B_TREE_H |
| 3 | #define B_TREE_H | ||
| 3 | 4 | ||
| 4 | // maximum height of the tree the lower the lower the lower amount | 5 | // maximum height of the tree the lower the lower the lower amount |
| 5 | // of disk reads which translates into faster? | 6 | // of disk reads which translates into faster? |
| 6 | #define B_TREE_ORDER 4 | 7 | #define B_TREE_ORDER 4 |
| 7 | 8 | ||
| 8 | typedef struct b_tree_node b_tree_node; | 9 | typedef struct b_tree_node b_tree_node; |
| 9 | struct b_tree_node | 10 | struct b_tree_node |
| 10 | { | 11 | { |
| 11 | 12 | ||
| 12 | // store the values | 13 | // store the values |
| 13 | string8 keys[B_TREE_ORDER - 1]; | 14 | string8 keys[B_TREE_ORDER - 1]; |
| 14 | csv_row *rows[B_TREE_ORDER - 1]; | 15 | |
| 16 | // TODO(nasr): replace with someting more generic? | ||
| 17 | // NOTE(nasr): cons of void * -> no type safety | ||
| 18 | // is there a way to still have some sort of that? | ||
| 19 | void *payload_per_key[B_TREE_ORDER - 1]; | ||
| 15 | 20 | ||
| 16 | b_tree_node *parent; | 21 | b_tree_node *parent; |
| 17 | // handle to store children faster than linked list | 22 | // handle to store children faster than linked list |
| @@ -19,6 +24,9 @@ struct b_tree_node | |||
| 19 | // when jumping through linked nodes | 24 | // when jumping through linked nodes |
| 20 | b_tree_node *children[B_TREE_ORDER]; | 25 | b_tree_node *children[B_TREE_ORDER]; |
| 21 | 26 | ||
| 27 | // this shouldnt change things but could be a performance improvement on a bigger scale?? | ||
| 28 | s32 *max_children; | ||
| 29 | |||
| 22 | // NOTE(nasr): reference count ::: check how many leaves are using this node | 30 | // NOTE(nasr): reference count ::: check how many leaves are using this node |
| 23 | // also not needed for now because we don't free individual node because of arena allocator | 31 | // also not needed for now because we don't free individual node because of arena allocator |
| 24 | // s32 *refc; | 32 | // s32 *refc; |
| @@ -35,39 +43,35 @@ struct b_tree | |||
| 35 | // NOTE(nasr): make sure this always stays in memory | 43 | // NOTE(nasr): make sure this always stays in memory |
| 36 | // so that initial fetch never requires a disk read | 44 | // so that initial fetch never requires a disk read |
| 37 | b_tree_node *root; | 45 | b_tree_node *root; |
| 38 | |||
| 39 | }; | 46 | }; |
| 40 | 47 | ||
| 41 | 48 | ||
| 42 | 49 | #ifdef B_TREE_IMPLEMENTATION | |
| 50 | /////////////////////////////////////////////////////////////////////////////// | ||
| 51 | //- b_tree.c | ||
| 43 | 52 | ||
| 44 | // TODO(nasr): 1. splitting the tree when getting too big? (horizontally) 2. joining trees? | 53 | // TODO(nasr): 1. splitting the tree when getting too big? (horizontally) 2. joining trees? |
| 45 | 54 | ||
| 46 | internal b_tree_node * | 55 | internal b_tree_node * |
| 47 | node_alloc(mem_arena *arena) | 56 | btree_node_alloc(mem_arena *arena) |
| 48 | { | 57 | { |
| 49 | b_tree_node *node = PushStructZero(arena, type); | 58 | b_tree_node *node = PushStructZero(arena, b_tree_node); |
| 50 | node->leaf = 1; | 59 | node->leaf = 1; |
| 51 | return node; | 60 | return node; |
| 52 | } | 61 | } |
| 53 | 62 | ||
| 54 | // NOTE(nasr): @return the index of of the found element | 63 | // NOTE(nasr): @return the index of of the found element |
| 55 | internal s32 | 64 | internal s32 |
| 56 | node_find_pos(mem_arena *arena, string8 value) | 65 | btree_node_find_pos(mem_arena *arena, string8 value, b_tree_node *node) |
| 57 | { | 66 | { |
| 58 | s32 i = 0; | 67 | for (s32 index = 0; index < node->key_count && string8_cmp(node->keys[i], value) < 0; ++index); |
| 59 | while (i < n->key_count && str8_cmp(n->keys[i], k) < 0) | ||
| 60 | { | ||
| 61 | ++i; | ||
| 62 | } | ||
| 63 | |||
| 64 | return i; | 68 | return i; |
| 65 | } | 69 | } |
| 66 | 70 | ||
| 67 | interal void | 71 | internal void |
| 68 | b_tree_create(mem_arena *arena, b_tree *tree) | 72 | b_tree_create(mem_arena *arena, b_tree *tree) |
| 69 | { | 73 | { |
| 70 | tree->root = node_alloc(arena); | 74 | tree->root = btree_node_alloc(arena); |
| 71 | tree->root->leaf = 1; | 75 | tree->root->leaf = 1; |
| 72 | tree->root->key_count = 0; | 76 | tree->root->key_count = 0; |
| 73 | } | 77 | } |
| @@ -76,33 +80,40 @@ b_tree_create(mem_arena *arena, b_tree *tree) | |||
| 76 | internal void | 80 | internal void |
| 77 | b_tree_search(b_tree_node *node, string8 key) | 81 | b_tree_search(b_tree_node *node, string8 key) |
| 78 | { | 82 | { |
| 79 | s32 found_index = node_find_pos(node, key); | 83 | s32 found_index = btree_node_find_pos(node, key); |
| 80 | 84 | s32 i = 0; | |
| 81 | if (found_index < n->key_count && string_compare(n->keys[i], key) == 0) | ||
| 82 | { | ||
| 83 | return n->rows[i]; | ||
| 84 | } | ||
| 85 | if (n->leaf) | ||
| 86 | { | ||
| 87 | return NULL; | ||
| 88 | 85 | ||
| 89 | } | 86 | if (found_index < node->key_count && string_compare(node->keys[index], key) == 0) |
| 87 | { | ||
| 88 | return node->rows[i]; | ||
| 89 | } | ||
| 90 | if (node->leaf) | ||
| 91 | { | ||
| 92 | return NULL; | ||
| 90 | 93 | ||
| 91 | return b_tree_search(n->children[i], key); | 94 | } |
| 92 | 95 | ||
| 96 | return b_tree_search(node->children[i], key); | ||
| 93 | 97 | ||
| 98 | return NULL; | ||
| 94 | } | 99 | } |
| 95 | 100 | ||
| 96 | internal void | 101 | internal void |
| 97 | b_tree_insert() | 102 | b_tree_insert(b_tree_node *current_node) |
| 98 | { | 103 | { |
| 104 | if(current_node->leaf) | ||
| 105 | { | ||
| 106 | |||
| 107 | } | ||
| 99 | 108 | ||
| 100 | } | 109 | } |
| 101 | 110 | ||
| 102 | internal void | 111 | internal void |
| 103 | b_tree_write() | 112 | b_tree_write() |
| 104 | { | 113 | { |
| 114 | |||
| 105 | // TODO(nasr): write the b_tree to disk | 115 | // TODO(nasr): write the b_tree to disk |
| 106 | } | 116 | } |
| 107 | 117 | ||
| 108 | #endif /* BTREE_H */ | 118 | #endif /* B_TREE_IMPLEMENTATION */ |
| 119 | #endif /* B_TREE_H */ | ||
diff --git a/source/base/base_io.h b/source/base/base_io.h index 85fedc7..a90b41e 100644 --- a/source/base/base_io.h +++ b/source/base/base_io.h | |||
| @@ -32,7 +32,4 @@ print(const char *str) | |||
| 32 | 32 | ||
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | #define Os_read(buffer, buffer_count) | ||
| 36 | |||
| 37 | |||
| 38 | #endif /* BASE_IO_H */ | 35 | #endif /* BASE_IO_H */ |
