feat(lsm): iterator over items in trie
This commit is contained in:
parent
5564e23ceb
commit
f4d711365d
9 changed files with 229 additions and 8 deletions
|
|
@ -5,14 +5,11 @@
|
|||
#include "lsm/str_internal.h"
|
||||
#include "lsm/trie.h"
|
||||
|
||||
/**
|
||||
* A node inside a trie structure
|
||||
*/
|
||||
typedef struct lsm_trie_node {
|
||||
struct lsm_trie_node {
|
||||
lsm_bt bt;
|
||||
lsm_str skip;
|
||||
void *data;
|
||||
} lsm_trie_node;
|
||||
};
|
||||
|
||||
/**
|
||||
* Allocate and initialize a new trie node
|
||||
|
|
@ -33,4 +30,13 @@ struct lsm_trie {
|
|||
uint64_t size;
|
||||
};
|
||||
|
||||
struct lsm_trie_iterator {
|
||||
lsm_trie_node *next;
|
||||
struct {
|
||||
lsm_bt_iterator *arr;
|
||||
size_t len;
|
||||
size_t cap;
|
||||
} stack;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ void lsm_bt_iter(lsm_bt_iterator *out, const lsm_bt *bt) {
|
|||
}
|
||||
}
|
||||
|
||||
bool lsm_bt_iter_next(const void **out, char *key_out, lsm_bt_iterator *iter) {
|
||||
bool lsm_bt_iter_next(void **out, char *key_out, lsm_bt_iterator *iter) {
|
||||
if (iter->next == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
117
lsm/src/trie/lsm_trie_iter.c
Normal file
117
lsm/src/trie/lsm_trie_iter.c
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
#include "lsm.h"
|
||||
#include "lsm/trie_internal.h"
|
||||
|
||||
/**
|
||||
* Advance the iterator so that `next` now points to a node containing data. If
|
||||
* no more data nodes are found, `next` is set to NULL. The initial value of
|
||||
* `next` is ignored.
|
||||
*/
|
||||
lsm_error lsm_trie_iter_next_data_node(lsm_trie_iterator *iter) {
|
||||
do {
|
||||
// Traverse back up the stack until we reach either the end of the subtree,
|
||||
// or an iterator that hasn't been exhausted yet
|
||||
while ((iter->stack.len > 0) &&
|
||||
!lsm_bt_iter_next((void **)&iter->next, NULL,
|
||||
&iter->stack.arr[iter->stack.len - 1])) {
|
||||
iter->stack.len--;
|
||||
}
|
||||
|
||||
if (iter->stack.len == 0) {
|
||||
iter->next = NULL;
|
||||
|
||||
return lsm_error_ok;
|
||||
}
|
||||
|
||||
// Add node's subtree to the stack
|
||||
if (iter->stack.len == iter->stack.cap) {
|
||||
lsm_bt_iterator *arr = realloc(
|
||||
iter->stack.arr, iter->stack.cap * 2 * sizeof(lsm_bt_iterator));
|
||||
|
||||
if (arr == NULL) {
|
||||
return lsm_error_failed_alloc;
|
||||
}
|
||||
|
||||
iter->stack.arr = arr;
|
||||
iter->stack.cap *= 2;
|
||||
}
|
||||
|
||||
lsm_bt_iter(&iter->stack.arr[iter->stack.len], &iter->next->bt);
|
||||
iter->stack.len++;
|
||||
|
||||
} while (iter->next->data == NULL);
|
||||
|
||||
return lsm_error_ok;
|
||||
}
|
||||
|
||||
lsm_error lsm_trie_iter(lsm_trie_iterator **out, const lsm_trie *trie,
|
||||
const lsm_str *prefix) {
|
||||
uint64_t prefix_len = prefix == NULL ? 0 : lsm_str_len(prefix);
|
||||
|
||||
uint64_t index = 0;
|
||||
lsm_trie_node *node = trie->root;
|
||||
|
||||
// Simplified traversal down the trie to find the root of the subtree
|
||||
// contaiing all nodes with the given prefix
|
||||
while ((index < prefix_len) && (node != NULL)) {
|
||||
char c = lsm_str_char(prefix, index);
|
||||
lsm_error res = lsm_bt_search((void **)&node, &node->bt, c);
|
||||
|
||||
switch (res) {
|
||||
case lsm_error_ok:
|
||||
index += 1 + lsm_str_len(&node->skip);
|
||||
break;
|
||||
case lsm_error_not_found:
|
||||
node = NULL;
|
||||
break;
|
||||
default:
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
lsm_trie_iterator *iter = calloc(1, sizeof(lsm_trie_iterator));
|
||||
|
||||
if (iter == NULL) {
|
||||
return lsm_error_failed_alloc;
|
||||
}
|
||||
|
||||
iter->next = node;
|
||||
|
||||
if (node != NULL) {
|
||||
lsm_bt_iterator *arr = malloc(sizeof(lsm_bt_iterator));
|
||||
|
||||
if (arr == NULL) {
|
||||
free(iter);
|
||||
|
||||
return lsm_error_failed_alloc;
|
||||
}
|
||||
|
||||
iter->stack.arr = arr;
|
||||
iter->stack.cap = 1;
|
||||
iter->stack.len = 1;
|
||||
|
||||
lsm_bt_iter(&iter->stack.arr[0], &node->bt);
|
||||
|
||||
if (node->data == NULL) {
|
||||
LSM_RES(lsm_trie_iter_next_data_node(iter));
|
||||
}
|
||||
}
|
||||
|
||||
*out = iter;
|
||||
|
||||
return lsm_error_ok;
|
||||
}
|
||||
|
||||
lsm_error lsm_trie_iter_next(void **out, lsm_trie_iterator *iter) {
|
||||
if (iter->next == NULL) {
|
||||
return lsm_error_done;
|
||||
}
|
||||
|
||||
*out = iter->next->data;
|
||||
|
||||
return lsm_trie_iter_next_data_node(iter);
|
||||
}
|
||||
|
||||
void lsm_trie_iter_free(lsm_trie_iterator *iter) {
|
||||
free(iter->stack.arr);
|
||||
free(iter);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue