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++) {
73 for (
size_t i = 0; i <
SEQ_BR; i++) {
94 copy->
children[idx] = (child ==
nullptr)
106 seq.maybe_error =
nullptr;
117 if (seq->
len >= SIZE_MAX) {
119 failed_seq.maybe_error =
123 failed_seq.
depth = 0;
124 failed_seq.
root =
nullptr;
125 failed_seq.
tail =
nullptr;
133 seq_t new_seq = *seq;
134 new_seq.maybe_error =
nullptr;
137 for (uint16_t i = 0; i < seq->
tail_len; i++) {
148 size_t sz_without_tail = seq->
len - (size_t)seq->
tail_len;
157 if (seq->
root ==
nullptr) {
160 seq_t new_seq = *seq;
161 new_seq.maybe_error =
nullptr;
182 seq_t new_seq = *seq;
183 new_seq.maybe_error =
nullptr;
184 new_seq.
root = new_root;
188 new_seq.
len = seq->
len + 1;
194 seq_t new_seq = *seq;
195 new_seq.maybe_error =
nullptr;
199 new_seq.
len = seq->
len + 1;
214 int msg_len = snprintf(
nullptr, 0,
"%zu",
n);
215 PANIC_IF(msg_len < 0,
"index formatting failed");
216 char *err_msg =
srn_allocate(ctx, (
size_t)msg_len + 1,
alignof(
char));
217 (void)snprintf(err_msg, (
size_t)msg_len + 1,
"%zu",
n);
220 result.
data =
nullptr;
224 size_t tail_start = seq->
len - (size_t)seq->
tail_len;
225 if (
n >= tail_start) {
227 size_t off =
n - tail_start;
234 for (int16_t d = seq->
depth; d >= 0; d--) {
236 SEQ_LOG(
"Looking up in trie: D: %d, I: %hu", d, index);
239 SEQ_LOG(
"We're at depth zero");
249 result.
data =
nullptr;
254 PANIC(
"It should never happen");
256 result.
data =
nullptr;
257 result.maybe_error =
ERR(ctx,
ABSURD,
"");
void * srn_allocate(const srn_context_t *ctx, size_t size, size_t alignment)
#define ALLOCN(ctx, T, N)
#define ERR(ctx, err, msg)
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)
Create an empty seq pinned to ctx.
static seq_node_t * seq_clone_node(const srn_context_t *ctx, const seq_node_t *n)
Clone n into a fresh node with its own children page.
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 seq_t *seq, size_t n)
Negative index is not supported.
static seq_node_t * seq_push_leaf(const srn_context_t *ctx, const seq_node_t *node, uint8_t depth, uint64_t index, seq_node_t *leaf)
Insert leaf below node at the position of logical index index, cloning every node along the path.
static seq_elem_t * seq_create_page(const srn_context_t *ctx)
Create a PAGE (just slots for the data).
seq_t seq_push(const seq_t *seq, seq_elem_t x)
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”
const srn_context_t * seq_ctx
The context that owns every allocation the seq retains.
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 PANIC_IF(cond, msg)