28#define SEQ_LOG(FMT, ...) DBG("SEQ", FMT __VA_OPT__(, ) __VA_ARGS__)
30#define SEQ_LOG(FMT, ...)
35static inline uint16_t
seq_depth_index(
const uint8_t depth,
const uint64_t index) {
43 for (
size_t i = 0; i <
SEQ_BR; i++) {
70 if (
n->children[index] ==
nullptr) {
73 return n->children[index];
81 seq.maybe_error =
nullptr;
88 if (seq->
len >= SIZE_MAX) {
90 failed_seq.maybe_error =
100 new_seq.maybe_error =
nullptr;
109 size_t sz_without_tail = seq->
len - (size_t)seq->
tail_len;
116 if (seq->
root ==
nullptr) {
119 seq_t new_seq = *seq;
120 new_seq.maybe_error =
nullptr;
141 seq_t new_seq = *seq;
142 new_seq.
root = new_root;
146 new_seq.
len = seq->
len + 1;
153 for (uint8_t d = seq->
depth; d > 1; --d) {
160 uint16_t leaf_parent_idx =
seq_depth_index(1, (uint64_t)sz_without_tail);
164 seq_t new_seq = *seq;
167 new_seq.
len = seq->
len + 1;
177 char *err_msg = (
char *)
ALLOC(ctx,
size_t);
179 SNPRINTF(err_msg,
sizeof(
size_t) + 1,
"%zu",
n);
182 result.
data =
nullptr;
186 size_t tail_start = seq->
len - (size_t)seq->
tail_len;
187 if (
n >= tail_start) {
189 size_t off =
n - tail_start;
196 for (int16_t d = seq->
depth; d >= 0; d--) {
198 SEQ_LOG(
"Looking up in trie: D: %d, I: %hu", d, index);
201 SEQ_LOG(
"We're at depth zero");
209 result.
data =
nullptr;
214 PANIC(
"It should never happen");
216 result.
data =
nullptr;
217 result.maybe_error =
ERR(ctx,
ABSURD,
"");
#define ALLOCN(ctx, T, N)
@ CORRUPTED_SEQ
When the memory layout of a seq is incorrect.
#define ERR(ctx, err, msg)
seq_t seq_push(const srn_context_t *ctx, const seq_t *seq, seq_elem_t x)
static seq_node_t * seq_new_node(const srn_context_t *ctx)
static seq_node_t * seq_new_path(const srn_context_t *ctx, uint8_t depth, seq_node_t *leaf)
Walk from the root to a possible leaf node and create all the inner and leaf nodes if necessary.
seq_t seq_empty(const srn_context_t *ctx)
static seq_node_t * seq_next_child(const srn_context_t *ctx, seq_node_t *n, uint16_t index)
Get or create the next node of the tree.
static uint16_t seq_depth_index(const uint8_t depth, const uint64_t index)
Find the array index of the given index, considering the given depth.
seq_lookup_result_t seq_get(const srn_context_t *ctx, const seq_t *seq, size_t n)
Negative index is not supported.
static seq_elem_t * seq_create_page(const srn_context_t *ctx)
Create a PAGE (just slots for the data)
This is an implementation of bit - partitioned, persistent, immutable sequence For more information,...
#define SEQ_BR
branching factor (power of two)
#define SEQ_SHIFT
log2(SEQ_BR)
void * seq_elem_t
We use generic pointers to refer to internal nodes, leaf nodes and even elements.
We have two type of node that both are implemented using the same data structure.
seq_elem_t * children
We allocate children to be a buffer of SEQ_BR number of pointers.
size_t len
logical length.
seq_node_t * root
NULL means “all data is in tail”
seq_elem_t * tail
small tail array for fast push/pop.
uint8_t depth
tree depth in levels (0 == leaf level)
uint16_t tail_len
0..SEQ_BR
#define PANIC_IF_NULL(ptr)
#define SNPRINTF(buf, s, f,...)