mirror of
https://github.com/facebook/sapling.git
synced 2024-10-07 07:17:55 +03:00
[fastmanifest fix all the other places where the pointer style is inconsistent
Test Plan: run unit tests. Reviewers: #sourcecontrol, lcharignon Reviewed By: lcharignon Subscribers: mitrandir, mjpieters Differential Revision: https://phabricator.fb.com/D3130423 Signature: t1:3130423:1459811638:268cb647facbde3f2cf2d37118bdfe56bce0e637
This commit is contained in:
parent
88cd00b144
commit
deadce5eb8
@ -9,12 +9,12 @@
|
||||
|
||||
#include "bsearch.h"
|
||||
|
||||
size_t bsearch_between(const void* needle,
|
||||
const void* base, const size_t nel, const size_t width,
|
||||
int (*compare) (const void* needle,
|
||||
const void* fromarray,
|
||||
const void* context),
|
||||
const void* context) {
|
||||
size_t bsearch_between(const void *needle,
|
||||
const void *base, const size_t nel, const size_t width,
|
||||
int (*compare)(const void *needle,
|
||||
const void *fromarray,
|
||||
const void *context),
|
||||
const void *context) {
|
||||
ptrdiff_t start = 0;
|
||||
ptrdiff_t end = nel;
|
||||
|
||||
@ -25,7 +25,7 @@ size_t bsearch_between(const void* needle,
|
||||
return nel;
|
||||
}
|
||||
|
||||
const void* ptr = base + (midpoint * width);
|
||||
const void *ptr = base + (midpoint * width);
|
||||
|
||||
int cmp = compare(needle, ptr, context);
|
||||
|
||||
|
@ -24,13 +24,13 @@
|
||||
* >0 if the element should be placed after `right`.
|
||||
*/
|
||||
extern size_t bsearch_between(
|
||||
const void* needle,
|
||||
const void* base, const size_t nel, const size_t width,
|
||||
int (*compare) (const void* needle,
|
||||
const void* fromarray,
|
||||
const void* context),
|
||||
const void* context
|
||||
);
|
||||
const void *needle,
|
||||
const void *base, const size_t nel, const size_t width,
|
||||
int (*compare)(const void *needle,
|
||||
const void *fromarray,
|
||||
const void *context),
|
||||
const void *context
|
||||
);
|
||||
|
||||
/**
|
||||
* A convenient macro to build comparators for `bsearch_between`. Callers
|
||||
|
@ -37,28 +37,28 @@ void test_bsearch() {
|
||||
20,
|
||||
2,
|
||||
15, 18, 21,
|
||||
);
|
||||
);
|
||||
|
||||
BSEARCH_TEST(
|
||||
20,
|
||||
2,
|
||||
15, 18, 20, 21,
|
||||
);
|
||||
);
|
||||
|
||||
BSEARCH_TEST(
|
||||
10,
|
||||
0,
|
||||
15, 18, 20, 21,
|
||||
);
|
||||
);
|
||||
|
||||
BSEARCH_TEST(
|
||||
30,
|
||||
4,
|
||||
15, 18, 20, 21,
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int main(int argc, char *argv[]) {
|
||||
test_bsearch();
|
||||
|
||||
return 0;
|
||||
|
@ -31,7 +31,7 @@ static inline bool expand_to_fit(
|
||||
new_sz = input_sz + *buffer_sz;
|
||||
}
|
||||
|
||||
void* newbuffer = realloc(*buffer, new_sz);
|
||||
void *newbuffer = realloc(*buffer, new_sz);
|
||||
if (newbuffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
@ -10,13 +10,13 @@
|
||||
#include "node.h"
|
||||
#include "tree.h"
|
||||
|
||||
static void update_checksum(node_t* node) {
|
||||
static void update_checksum(node_t *node) {
|
||||
SHA_CTX ctx;
|
||||
SHA1_Init(&ctx);
|
||||
|
||||
// find all the children and make sure their checksums are up-to-date.
|
||||
for (int ix = 0; ix < node->num_children; node ++) {
|
||||
node_t* child = get_child_by_index(node, ix);
|
||||
for (int ix = 0; ix < node->num_children; node++) {
|
||||
node_t *child = get_child_by_index(node, ix);
|
||||
if (child->checksum_valid == false) {
|
||||
update_checksum(child);
|
||||
}
|
||||
@ -31,6 +31,6 @@ static void update_checksum(node_t* node) {
|
||||
node->checksum_valid = true;
|
||||
}
|
||||
|
||||
void update_checksums(tree_t* tree) {
|
||||
void update_checksums(tree_t *tree) {
|
||||
update_checksum(tree->shadow_root);
|
||||
}
|
||||
|
@ -10,6 +10,6 @@
|
||||
|
||||
#include "tree.h"
|
||||
|
||||
void update_checksums(tree_t* tree);
|
||||
void update_checksums(tree_t *tree);
|
||||
|
||||
#endif /* #ifndef __FASTMANIFEST_CHECKSUM_H__ */
|
||||
|
@ -7,6 +7,6 @@
|
||||
|
||||
#include "checksum.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int main(int argc, char *argv[]) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -32,12 +32,12 @@ typedef enum {
|
||||
} node_enlarge_child_capacity_code_t;
|
||||
typedef struct _node_enlarge_child_capacity_result_t {
|
||||
node_enlarge_child_capacity_code_t code;
|
||||
struct _node_t* old_child;
|
||||
struct _node_t* new_child;
|
||||
struct _node_t *old_child;
|
||||
struct _node_t *new_child;
|
||||
} node_enlarge_child_capacity_result_t;
|
||||
|
||||
typedef struct _node_search_children_result_t {
|
||||
struct _node_t* child;
|
||||
struct _node_t *child;
|
||||
uint32_t child_num;
|
||||
} node_search_children_result_t;
|
||||
|
||||
|
@ -12,8 +12,8 @@
|
||||
static size_t calculate_required_size(
|
||||
uint16_t name_sz,
|
||||
uint32_t num_children) {
|
||||
node_t* ptr = 0;
|
||||
void* name_start = &ptr->name;
|
||||
node_t *ptr = 0;
|
||||
void *name_start = &ptr->name;
|
||||
intptr_t address = (intptr_t) name_start;
|
||||
address += name_sz;
|
||||
address += sizeof(ptrdiff_t) - 1;
|
||||
@ -22,8 +22,8 @@ static size_t calculate_required_size(
|
||||
}
|
||||
|
||||
static void initialize_node(
|
||||
node_t* node, size_t block_sz,
|
||||
const char* name, uint16_t name_sz,
|
||||
node_t *node, size_t block_sz,
|
||||
const char *name, uint16_t name_sz,
|
||||
uint32_t num_children) {
|
||||
node->block_sz = block_sz;
|
||||
node->num_children = 0;
|
||||
@ -34,11 +34,11 @@ static void initialize_node(
|
||||
memcpy(&node->name, name, name_sz);
|
||||
}
|
||||
|
||||
node_t* alloc_node(
|
||||
const char* name, uint16_t name_sz,
|
||||
node_t *alloc_node(
|
||||
const char *name, uint16_t name_sz,
|
||||
uint32_t max_children) {
|
||||
size_t size = calculate_required_size(name_sz, max_children);
|
||||
node_t* result = (node_t*) malloc(size);
|
||||
node_t *result = (node_t *) malloc(size);
|
||||
if (result == NULL) {
|
||||
return result;
|
||||
}
|
||||
@ -47,36 +47,36 @@ node_t* alloc_node(
|
||||
return result;
|
||||
}
|
||||
|
||||
void* setup_node(
|
||||
void* ptr, size_t ptr_size_limit,
|
||||
const char* name, uint16_t name_sz,
|
||||
void *setup_node(
|
||||
void *ptr, size_t ptr_size_limit,
|
||||
const char *name, uint16_t name_sz,
|
||||
uint32_t max_children) {
|
||||
size_t size = calculate_required_size(name_sz, max_children);
|
||||
if (size > ptr_size_limit) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node_t* node = (node_t*) ptr;
|
||||
node_t *node = (node_t *) ptr;
|
||||
intptr_t next = (intptr_t) ptr;
|
||||
next += size;
|
||||
|
||||
initialize_node(node, size, name, name_sz, max_children);
|
||||
|
||||
return (void*) next;
|
||||
return (void *) next;
|
||||
}
|
||||
|
||||
node_t* clone_node(const node_t* node) {
|
||||
node_t *clone_node(const node_t *node) {
|
||||
uint32_t old_capacity = max_children(node);
|
||||
uint32_t new_capacity = (((uint64_t) old_capacity) *
|
||||
(100 + STORAGE_INCREMENT_PERCENTAGE)) /
|
||||
100;
|
||||
(100 + STORAGE_INCREMENT_PERCENTAGE)) /
|
||||
100;
|
||||
if (new_capacity - old_capacity < MIN_STORAGE_INCREMENT) {
|
||||
new_capacity = old_capacity + MIN_STORAGE_INCREMENT;
|
||||
} else if (new_capacity - old_capacity > MAX_STORAGE_INCREMENT) {
|
||||
new_capacity = old_capacity + MAX_STORAGE_INCREMENT;
|
||||
}
|
||||
|
||||
node_t* clone = alloc_node(
|
||||
node_t *clone = alloc_node(
|
||||
node->name, node->name_sz,
|
||||
new_capacity);
|
||||
if (clone == NULL) {
|
||||
@ -95,10 +95,10 @@ node_t* clone_node(const node_t* node) {
|
||||
ptrdiff_t delta = ((intptr_t) node) - ((intptr_t) clone);
|
||||
|
||||
// get the child pointer base of each node.
|
||||
const ptrdiff_t* node_base = get_child_ptr_base_const(node);
|
||||
ptrdiff_t* clone_base = get_child_ptr_base(clone);
|
||||
const ptrdiff_t *node_base = get_child_ptr_base_const(node);
|
||||
ptrdiff_t *clone_base = get_child_ptr_base(clone);
|
||||
|
||||
for (int ix = 0; ix < node->num_children; ix ++) {
|
||||
for (int ix = 0; ix < node->num_children; ix++) {
|
||||
clone_base[ix] = node_base[ix] + delta;
|
||||
}
|
||||
|
||||
@ -106,7 +106,7 @@ node_t* clone_node(const node_t* node) {
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
const char *name;
|
||||
uint16_t name_sz;
|
||||
} find_child_struct_t;
|
||||
|
||||
@ -115,9 +115,10 @@ typedef struct {
|
||||
((const find_child_struct_t*) nameobject)->name, \
|
||||
((const find_child_struct_t*) nameobject)->name_sz, \
|
||||
get_child_from_diff((node_t*) context, *((ptrdiff_t*) relptr))))
|
||||
|
||||
static CONTEXTUAL_COMPARATOR_BUILDER(name_node_cmp, NAME_NODE_COMPARE);
|
||||
|
||||
node_add_child_result_t add_child(node_t* node, const node_t* child) {
|
||||
node_add_child_result_t add_child(node_t *node, const node_t *child) {
|
||||
// verify parent node.
|
||||
if (!node->in_use ||
|
||||
!(node->type == TYPE_IMPLICIT || node->type == TYPE_ROOT)) {
|
||||
@ -134,8 +135,8 @@ node_add_child_result_t add_child(node_t* node, const node_t* child) {
|
||||
return ADD_CHILD_ILLEGAL_CHILD;
|
||||
}
|
||||
|
||||
ptrdiff_t* base = get_child_ptr_base(node);
|
||||
find_child_struct_t needle = { child->name, child->name_sz };
|
||||
ptrdiff_t *base = get_child_ptr_base(node);
|
||||
find_child_struct_t needle = {child->name, child->name_sz};
|
||||
size_t offset = bsearch_between(
|
||||
&needle,
|
||||
get_child_ptr_base(node),
|
||||
@ -147,7 +148,7 @@ node_add_child_result_t add_child(node_t* node, const node_t* child) {
|
||||
if (offset < node->num_children) {
|
||||
// displacing something. ensure we don't have a conflict.
|
||||
ptrdiff_t diff = base[offset];
|
||||
node_t* old_child = get_child_from_diff(node, diff);
|
||||
node_t *old_child = get_child_from_diff(node, diff);
|
||||
|
||||
if (name_compare(child->name, child->name_sz, old_child) == 0) {
|
||||
return CONFLICTING_ENTRY_PRESENT;
|
||||
@ -163,7 +164,7 @@ node_add_child_result_t add_child(node_t* node, const node_t* child) {
|
||||
}
|
||||
|
||||
// bump the number of children we have.
|
||||
node->num_children ++;
|
||||
node->num_children++;
|
||||
|
||||
// write the entry
|
||||
set_child_by_index(node, offset, child);
|
||||
@ -171,7 +172,7 @@ node_add_child_result_t add_child(node_t* node, const node_t* child) {
|
||||
return ADD_CHILD_OK;
|
||||
}
|
||||
|
||||
node_remove_child_result_t remove_child(node_t* node, uint32_t child_num) {
|
||||
node_remove_child_result_t remove_child(node_t *node, uint32_t child_num) {
|
||||
// verify parent node.
|
||||
if (!node->in_use ||
|
||||
!(node->type == TYPE_IMPLICIT || node->type == TYPE_ROOT)) {
|
||||
@ -185,20 +186,20 @@ node_remove_child_result_t remove_child(node_t* node, uint32_t child_num) {
|
||||
|
||||
if (child_num < node->num_children - 1) {
|
||||
// we need to compact the existing entries.
|
||||
ptrdiff_t* base = get_child_ptr_base(node);
|
||||
ptrdiff_t *base = get_child_ptr_base(node);
|
||||
|
||||
memmove(&base[child_num], &base[child_num + 1],
|
||||
sizeof(ptrdiff_t) * (node->num_children - 1 - child_num));
|
||||
}
|
||||
|
||||
// decrement the number of children we have.
|
||||
node->num_children --;
|
||||
node->num_children--;
|
||||
|
||||
return REMOVE_CHILD_OK;
|
||||
}
|
||||
|
||||
node_enlarge_child_capacity_result_t enlarge_child_capacity(
|
||||
node_t* node,
|
||||
node_t *node,
|
||||
uint32_t child_num) {
|
||||
node_enlarge_child_capacity_result_t result;
|
||||
|
||||
@ -214,8 +215,8 @@ node_enlarge_child_capacity_result_t enlarge_child_capacity(
|
||||
return result;
|
||||
}
|
||||
|
||||
node_t* old_child = get_child_by_index(node, child_num);
|
||||
node_t* new_child = clone_node(old_child);
|
||||
node_t *old_child = get_child_by_index(node, child_num);
|
||||
node_t *new_child = clone_node(old_child);
|
||||
|
||||
if (new_child == NULL) {
|
||||
result.code = ENLARGE_OOM;
|
||||
@ -233,11 +234,11 @@ node_enlarge_child_capacity_result_t enlarge_child_capacity(
|
||||
}
|
||||
|
||||
node_search_children_result_t search_children(
|
||||
const node_t* node,
|
||||
const char* name,
|
||||
const node_t *node,
|
||||
const char *name,
|
||||
const uint16_t name_sz) {
|
||||
const ptrdiff_t* base = get_child_ptr_base_const(node);
|
||||
find_child_struct_t needle = { name, name_sz };
|
||||
const ptrdiff_t *base = get_child_ptr_base_const(node);
|
||||
find_child_struct_t needle = {name, name_sz};
|
||||
size_t offset = bsearch_between(
|
||||
&needle,
|
||||
get_child_ptr_base_const(node),
|
||||
@ -247,25 +248,25 @@ node_search_children_result_t search_children(
|
||||
node);
|
||||
|
||||
if (offset >= node->num_children) {
|
||||
return (node_search_children_result_t) { NULL, UINT32_MAX };
|
||||
return (node_search_children_result_t) {NULL, UINT32_MAX};
|
||||
}
|
||||
|
||||
// ensure the spot we found is an exact match.
|
||||
ptrdiff_t diff = base[offset];
|
||||
node_t* child = get_child_from_diff(node, diff);
|
||||
node_t *child = get_child_from_diff(node, diff);
|
||||
if (name_compare(name, name_sz, child) == 0) {
|
||||
// huzzah, we found it.
|
||||
return (node_search_children_result_t) { child, offset };
|
||||
return (node_search_children_result_t) {child, offset};
|
||||
}
|
||||
|
||||
return (node_search_children_result_t) { NULL, UINT32_MAX };
|
||||
return (node_search_children_result_t) {NULL, UINT32_MAX};
|
||||
}
|
||||
|
||||
uint32_t get_child_index(
|
||||
const node_t* const parent,
|
||||
const node_t* const child) {
|
||||
const ptrdiff_t* base = get_child_ptr_base_const(parent);
|
||||
for (uint32_t child_num = 0; child_num < parent->num_children; child_num ++) {
|
||||
const node_t *const parent,
|
||||
const node_t *const child) {
|
||||
const ptrdiff_t *base = get_child_ptr_base_const(parent);
|
||||
for (uint32_t child_num = 0; child_num < parent->num_children; child_num++) {
|
||||
if (((intptr_t) parent) + base[child_num] == (intptr_t) child) {
|
||||
return child_num;
|
||||
}
|
||||
|
@ -57,9 +57,9 @@ typedef struct _node_t {
|
||||
* in node.
|
||||
*/
|
||||
static inline int name_compare(
|
||||
const char* name,
|
||||
const char *name,
|
||||
uint16_t name_sz,
|
||||
const node_t* node) {
|
||||
const node_t *node) {
|
||||
uint32_t min_sz = (name_sz < node->name_sz) ? name_sz : node->name_sz;
|
||||
int sz_compare = name_sz - node->name_sz;
|
||||
|
||||
@ -77,7 +77,7 @@ static inline int name_compare(
|
||||
*/
|
||||
static inline ptrdiff_t get_child_ptr_base_offset(
|
||||
uint16_t name_sz) {
|
||||
node_t* node = (node_t*) 0;
|
||||
node_t *node = (node_t *) 0;
|
||||
intptr_t ptr = (intptr_t) &node->name[name_sz];
|
||||
ptr = (ptr + sizeof(intptr_t) - 1) & PTR_ALIGN_MASK;
|
||||
|
||||
@ -89,29 +89,30 @@ static inline ptrdiff_t get_child_ptr_base_offset(
|
||||
* ptrdiff_t, the type returned is an ptrdiff_t. Note that this is *not* the
|
||||
* value of the first child pointer.
|
||||
*/
|
||||
static inline ptrdiff_t* get_child_ptr_base(node_t* node) {
|
||||
static inline ptrdiff_t *get_child_ptr_base(node_t *node) {
|
||||
assert(node->in_use);
|
||||
|
||||
intptr_t address = (intptr_t) node;
|
||||
ptrdiff_t offset = get_child_ptr_base_offset(node->name_sz);
|
||||
return (ptrdiff_t*) (address + offset);
|
||||
return (ptrdiff_t *) (address + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Const version of get_child_ptr_base
|
||||
*/
|
||||
static inline const ptrdiff_t* get_child_ptr_base_const(const node_t* node) {
|
||||
return get_child_ptr_base((node_t*) node);
|
||||
static inline const ptrdiff_t *get_child_ptr_base_const(const node_t *node) {
|
||||
return get_child_ptr_base((node_t *) node);
|
||||
}
|
||||
|
||||
static inline uint32_t max_children(const node_t* node) {
|
||||
static inline uint32_t max_children(const node_t *node) {
|
||||
ptrdiff_t bytes_avail = node->block_sz;
|
||||
bytes_avail -= ((intptr_t) get_child_ptr_base_const(node)) - ((intptr_t) node);
|
||||
bytes_avail -=
|
||||
((intptr_t) get_child_ptr_base_const(node)) - ((intptr_t) node);
|
||||
return bytes_avail / sizeof(intptr_t);
|
||||
}
|
||||
|
||||
static inline node_t* get_child_by_index(
|
||||
const node_t* node,
|
||||
static inline node_t *get_child_by_index(
|
||||
const node_t *node,
|
||||
uint32_t child_num) {
|
||||
assert(node->in_use);
|
||||
assert(node->type == TYPE_IMPLICIT || node->type == TYPE_ROOT);
|
||||
@ -121,18 +122,18 @@ static inline node_t* get_child_by_index(
|
||||
address += sizeof(ptrdiff_t) * child_num;
|
||||
|
||||
intptr_t base = (intptr_t) node;
|
||||
ptrdiff_t offset = *((ptrdiff_t*) address);
|
||||
ptrdiff_t offset = *((ptrdiff_t *) address);
|
||||
base += offset;
|
||||
return (node_t*) base;
|
||||
return (node_t *) base;
|
||||
}
|
||||
|
||||
static inline node_t* get_child_from_diff(const node_t* node, ptrdiff_t diff) {
|
||||
static inline node_t *get_child_from_diff(const node_t *node, ptrdiff_t diff) {
|
||||
assert(node->in_use);
|
||||
assert(node->type == TYPE_IMPLICIT || node->type == TYPE_ROOT);
|
||||
|
||||
intptr_t base = (intptr_t) node;
|
||||
base += diff;
|
||||
return (node_t*) base;
|
||||
return (node_t *) base;
|
||||
}
|
||||
|
||||
static inline void set_child_by_index(
|
||||
@ -144,7 +145,7 @@ static inline void set_child_by_index(
|
||||
assert(child_num < node->num_children);
|
||||
assert(child->in_use);
|
||||
|
||||
ptrdiff_t* base = get_child_ptr_base(node);
|
||||
ptrdiff_t *base = get_child_ptr_base(node);
|
||||
ptrdiff_t delta = ((intptr_t) child) - ((intptr_t) node);
|
||||
base[child_num] = delta;
|
||||
}
|
||||
@ -161,10 +162,10 @@ static inline void set_child_by_index(
|
||||
* number of children. Initialize the node as unused, but copy the name to the
|
||||
* node.
|
||||
*/
|
||||
extern node_t* alloc_node(
|
||||
const char* name, uint16_t name_sz,
|
||||
extern node_t *alloc_node(
|
||||
const char *name, uint16_t name_sz,
|
||||
uint32_t max_children
|
||||
);
|
||||
);
|
||||
|
||||
/**
|
||||
* Given a block of memory, attempt to place a node at the start of the block.
|
||||
@ -174,9 +175,9 @@ extern node_t* alloc_node(
|
||||
* Returns the address following the end of the node if the block is large
|
||||
* enough to accommodate the node, or NULL if the block is too small.
|
||||
*/
|
||||
extern void* setup_node(
|
||||
void* ptr, size_t ptr_size_limit,
|
||||
const char* name, uint16_t name_sz,
|
||||
extern void *setup_node(
|
||||
void *ptr, size_t ptr_size_limit,
|
||||
const char *name, uint16_t name_sz,
|
||||
uint32_t max_children);
|
||||
|
||||
/**
|
||||
@ -184,7 +185,7 @@ extern void* setup_node(
|
||||
* STORAGE_INCREMENT_PERCENTAGE, but by at least MIN_STORAGE_INCREMENT and no
|
||||
* more than MAX_STORAGE_INCREMENT.
|
||||
*/
|
||||
extern node_t* clone_node(const node_t* node);
|
||||
extern node_t *clone_node(const node_t *node);
|
||||
|
||||
/**
|
||||
* Adds a child to the node. A child with the same name must not already exist.
|
||||
@ -193,7 +194,7 @@ extern node_t* clone_node(const node_t* node);
|
||||
* as the total number of leaf nodes in tree_t and marking the checksum bit
|
||||
* dirty recursively up the tree.
|
||||
*/
|
||||
extern node_add_child_result_t add_child(node_t* node, const node_t* child);
|
||||
extern node_add_child_result_t add_child(node_t *node, const node_t *child);
|
||||
|
||||
/**
|
||||
* Remove a child of a node, given a child index.
|
||||
@ -203,7 +204,7 @@ extern node_add_child_result_t add_child(node_t* node, const node_t* child);
|
||||
* dirty recursively up the tree.
|
||||
*/
|
||||
extern node_remove_child_result_t remove_child(
|
||||
node_t* node,
|
||||
node_t *node,
|
||||
uint32_t child_num);
|
||||
|
||||
/**
|
||||
@ -212,7 +213,7 @@ extern node_remove_child_result_t remove_child(
|
||||
* the freshness of the checksums. However, it may affect total allocation.
|
||||
*/
|
||||
extern node_enlarge_child_capacity_result_t enlarge_child_capacity(
|
||||
node_t* node,
|
||||
node_t *node,
|
||||
uint32_t child_num);
|
||||
|
||||
/**
|
||||
@ -222,8 +223,8 @@ extern node_enlarge_child_capacity_result_t enlarge_child_capacity(
|
||||
* If the child was found, return the index and the pointer to the child.
|
||||
*/
|
||||
extern node_search_children_result_t search_children(
|
||||
const node_t* node,
|
||||
const char* name,
|
||||
const node_t *node,
|
||||
const char *name,
|
||||
const uint16_t name_sz);
|
||||
|
||||
/**
|
||||
@ -231,15 +232,15 @@ extern node_search_children_result_t search_children(
|
||||
* index. Otherwise return UINT32_MAX.
|
||||
*/
|
||||
extern uint32_t get_child_index(
|
||||
const node_t* const parent,
|
||||
const node_t* const child);
|
||||
const node_t *const parent,
|
||||
const node_t *const child);
|
||||
|
||||
/**
|
||||
* Convenience function just to find a child.
|
||||
*/
|
||||
static inline node_t* get_child_by_name(
|
||||
const node_t* node,
|
||||
const char* name,
|
||||
static inline node_t *get_child_by_name(
|
||||
const node_t *node,
|
||||
const char *name,
|
||||
uint16_t name_sz) {
|
||||
node_search_children_result_t result = search_children(node, name, name_sz);
|
||||
|
||||
|
@ -16,8 +16,8 @@
|
||||
* Add a child and ensure that it can be found.
|
||||
*/
|
||||
void test_simple_parent_child() {
|
||||
node_t* parent = ALLOC_NODE_STR("parent", 1);
|
||||
node_t* child = ALLOC_NODE_STR("child", 0);
|
||||
node_t *parent = ALLOC_NODE_STR("parent", 1);
|
||||
node_t *child = ALLOC_NODE_STR("child", 0);
|
||||
parent->in_use = true;
|
||||
parent->type = TYPE_IMPLICIT;
|
||||
child->in_use = true;
|
||||
@ -26,7 +26,7 @@ void test_simple_parent_child() {
|
||||
node_add_child_result_t result = add_child(parent, child);
|
||||
ASSERT(result == ADD_CHILD_OK);
|
||||
|
||||
node_t* lookup_child = GET_CHILD_BY_NAME_STR(parent, "child");
|
||||
node_t *lookup_child = GET_CHILD_BY_NAME_STR(parent, "child");
|
||||
ASSERT(lookup_child == child);
|
||||
}
|
||||
|
||||
@ -35,9 +35,9 @@ void test_simple_parent_child() {
|
||||
* bunch of differently sized parents and adding a child.
|
||||
*/
|
||||
void test_space() {
|
||||
for (uint16_t name_sz = 1; name_sz <= 8; name_sz ++) {
|
||||
node_t* parent = alloc_node("abcdefgh", name_sz, 1);
|
||||
node_t* child = ALLOC_NODE_STR("child", 0);
|
||||
for (uint16_t name_sz = 1; name_sz <= 8; name_sz++) {
|
||||
node_t *parent = alloc_node("abcdefgh", name_sz, 1);
|
||||
node_t *child = ALLOC_NODE_STR("child", 0);
|
||||
parent->in_use = true;
|
||||
parent->type = TYPE_IMPLICIT;
|
||||
child->in_use = true;
|
||||
@ -46,7 +46,7 @@ void test_space() {
|
||||
node_add_child_result_t result = add_child(parent, child);
|
||||
ASSERT(result == ADD_CHILD_OK);
|
||||
|
||||
node_t* lookup_child = GET_CHILD_BY_NAME_STR(parent, "child");
|
||||
node_t *lookup_child = GET_CHILD_BY_NAME_STR(parent, "child");
|
||||
ASSERT(lookup_child == child);
|
||||
}
|
||||
}
|
||||
@ -55,9 +55,9 @@ void test_space() {
|
||||
* Try to add a child to a node that does not have enough space.
|
||||
*/
|
||||
void test_insufficient_space() {
|
||||
node_t* parent = ALLOC_NODE_STR("parent", 1);
|
||||
node_t* child1 = ALLOC_NODE_STR("child1", 0);
|
||||
node_t* child2 = ALLOC_NODE_STR("child2", 0);
|
||||
node_t *parent = ALLOC_NODE_STR("parent", 1);
|
||||
node_t *child1 = ALLOC_NODE_STR("child1", 0);
|
||||
node_t *child2 = ALLOC_NODE_STR("child2", 0);
|
||||
parent->in_use = true;
|
||||
parent->type = TYPE_IMPLICIT;
|
||||
child1->in_use = true;
|
||||
@ -70,7 +70,7 @@ void test_insufficient_space() {
|
||||
result = add_child(parent, child2);
|
||||
ASSERT(result == NEEDS_LARGER_NODE);
|
||||
|
||||
node_t* lookup_child = GET_CHILD_BY_NAME_STR(parent, "child1");
|
||||
node_t *lookup_child = GET_CHILD_BY_NAME_STR(parent, "child1");
|
||||
ASSERT(lookup_child == child1);
|
||||
lookup_child = GET_CHILD_BY_NAME_STR(parent, "child2");
|
||||
ASSERT(lookup_child == NULL);
|
||||
@ -87,29 +87,30 @@ typedef struct {
|
||||
int child_type;
|
||||
node_add_child_result_t expected_result;
|
||||
} parent_child_test_cases_t;
|
||||
|
||||
void test_add_child_combinations() {
|
||||
parent_child_test_cases_t cases[] =
|
||||
{
|
||||
// parent or child not in use.
|
||||
{false, TYPE_IMPLICIT, true, TYPE_LEAF, ADD_CHILD_ILLEGAL_PARENT},
|
||||
{true, TYPE_IMPLICIT, false, TYPE_LEAF, ADD_CHILD_ILLEGAL_CHILD},
|
||||
{
|
||||
// parent or child not in use.
|
||||
{false, TYPE_IMPLICIT, true, TYPE_LEAF, ADD_CHILD_ILLEGAL_PARENT},
|
||||
{true, TYPE_IMPLICIT, false, TYPE_LEAF, ADD_CHILD_ILLEGAL_CHILD},
|
||||
|
||||
// parent type invalid.
|
||||
{true, TYPE_LEAF, true, TYPE_LEAF, ADD_CHILD_ILLEGAL_PARENT},
|
||||
// parent type invalid.
|
||||
{true, TYPE_LEAF, true, TYPE_LEAF, ADD_CHILD_ILLEGAL_PARENT},
|
||||
|
||||
// child type invalid.
|
||||
{true, TYPE_IMPLICIT, false, TYPE_UNDEFINED, ADD_CHILD_ILLEGAL_CHILD},
|
||||
// child type invalid.
|
||||
{true, TYPE_IMPLICIT, false, TYPE_UNDEFINED, ADD_CHILD_ILLEGAL_CHILD},
|
||||
|
||||
// some good outcomes.
|
||||
{true, TYPE_IMPLICIT, true, TYPE_LEAF, ADD_CHILD_OK},
|
||||
{true, TYPE_IMPLICIT, true, TYPE_IMPLICIT, ADD_CHILD_OK},
|
||||
};
|
||||
// some good outcomes.
|
||||
{true, TYPE_IMPLICIT, true, TYPE_LEAF, ADD_CHILD_OK},
|
||||
{true, TYPE_IMPLICIT, true, TYPE_IMPLICIT, ADD_CHILD_OK},
|
||||
};
|
||||
|
||||
for (int ix = 0;
|
||||
ix < sizeof(cases) / sizeof(parent_child_test_cases_t);
|
||||
ix ++) {
|
||||
node_t* parent;
|
||||
node_t* child;
|
||||
ix++) {
|
||||
node_t *parent;
|
||||
node_t *child;
|
||||
|
||||
parent = ALLOC_NODE_STR("parent", 1);
|
||||
child = ALLOC_NODE_STR("child", 0);
|
||||
@ -131,13 +132,14 @@ void test_add_child_combinations() {
|
||||
*/
|
||||
#define TEST_MANY_CHILDREN_NAME_STR "abcdefgh"
|
||||
#define TEST_MANY_CHILDREN_COUNT 8
|
||||
|
||||
void test_many_children() {
|
||||
node_t* parent = ALLOC_NODE_STR("parent", TEST_MANY_CHILDREN_COUNT);
|
||||
node_t* children[TEST_MANY_CHILDREN_COUNT]; // this should be ordered as we
|
||||
node_t *parent = ALLOC_NODE_STR("parent", TEST_MANY_CHILDREN_COUNT);
|
||||
node_t *children[TEST_MANY_CHILDREN_COUNT]; // this should be ordered as we
|
||||
// expect to find them in the
|
||||
// parent's list of children.
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_MANY_CHILDREN_COUNT; name_sz ++) {
|
||||
node_t* child = alloc_node(
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_MANY_CHILDREN_COUNT; name_sz++) {
|
||||
node_t *child = alloc_node(
|
||||
TEST_MANY_CHILDREN_NAME_STR,
|
||||
name_sz,
|
||||
0);
|
||||
@ -152,8 +154,8 @@ void test_many_children() {
|
||||
children[name_sz - 1] = child;
|
||||
}
|
||||
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_MANY_CHILDREN_COUNT; name_sz ++) {
|
||||
node_t* result = get_child_by_name(
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_MANY_CHILDREN_COUNT; name_sz++) {
|
||||
node_t *result = get_child_by_name(
|
||||
parent,
|
||||
TEST_MANY_CHILDREN_NAME_STR,
|
||||
name_sz);
|
||||
@ -169,12 +171,12 @@ void test_many_children() {
|
||||
* TEST_MANY_CHILDREN_CHILD_COUNT
|
||||
*/
|
||||
void test_many_children_reverse() {
|
||||
node_t* parent = ALLOC_NODE_STR("parent", TEST_MANY_CHILDREN_COUNT);
|
||||
node_t* children[TEST_MANY_CHILDREN_COUNT]; // this should be ordered as we
|
||||
node_t *parent = ALLOC_NODE_STR("parent", TEST_MANY_CHILDREN_COUNT);
|
||||
node_t *children[TEST_MANY_CHILDREN_COUNT]; // this should be ordered as we
|
||||
// expect to find them in the
|
||||
// parent's list of children.
|
||||
for (uint16_t name_sz = TEST_MANY_CHILDREN_COUNT; name_sz > 0; name_sz --) {
|
||||
node_t* child = alloc_node(
|
||||
for (uint16_t name_sz = TEST_MANY_CHILDREN_COUNT; name_sz > 0; name_sz--) {
|
||||
node_t *child = alloc_node(
|
||||
TEST_MANY_CHILDREN_NAME_STR,
|
||||
name_sz,
|
||||
0);
|
||||
@ -189,8 +191,8 @@ void test_many_children_reverse() {
|
||||
children[name_sz - 1] = child;
|
||||
}
|
||||
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_MANY_CHILDREN_COUNT; name_sz ++) {
|
||||
node_t* result = get_child_by_name(
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_MANY_CHILDREN_COUNT; name_sz++) {
|
||||
node_t *result = get_child_by_name(
|
||||
parent,
|
||||
TEST_MANY_CHILDREN_NAME_STR,
|
||||
name_sz);
|
||||
@ -207,13 +209,14 @@ void test_many_children_reverse() {
|
||||
*/
|
||||
#define TEST_CLONE_NAME_STR "abcdefgh"
|
||||
#define TEST_CLONE_COUNT 8
|
||||
|
||||
void test_clone() {
|
||||
node_t* parent = ALLOC_NODE_STR("parent", TEST_CLONE_COUNT);
|
||||
node_t* children[TEST_CLONE_COUNT]; // this should be ordered as we
|
||||
node_t *parent = ALLOC_NODE_STR("parent", TEST_CLONE_COUNT);
|
||||
node_t *children[TEST_CLONE_COUNT]; // this should be ordered as we
|
||||
// expect to find them in the
|
||||
// parent's list of children.
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_CLONE_COUNT; name_sz ++) {
|
||||
node_t* child = alloc_node(
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_CLONE_COUNT; name_sz++) {
|
||||
node_t *child = alloc_node(
|
||||
TEST_CLONE_NAME_STR,
|
||||
name_sz,
|
||||
0);
|
||||
@ -228,10 +231,10 @@ void test_clone() {
|
||||
children[name_sz - 1] = child;
|
||||
}
|
||||
|
||||
node_t* clone = clone_node(parent);
|
||||
node_t *clone = clone_node(parent);
|
||||
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_CLONE_COUNT; name_sz ++) {
|
||||
node_t* result = get_child_by_name(
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_CLONE_COUNT; name_sz++) {
|
||||
node_t *result = get_child_by_name(
|
||||
clone,
|
||||
TEST_CLONE_NAME_STR,
|
||||
name_sz);
|
||||
@ -250,14 +253,15 @@ void test_clone() {
|
||||
*/
|
||||
#define TEST_REMOVE_CHILD_NAME_STR "1234ffgg"
|
||||
#define TEST_REMOVE_CHILD_COUNT 8
|
||||
|
||||
void test_remove_child() {
|
||||
node_t* parent = ALLOC_NODE_STR("parent", TEST_REMOVE_CHILD_COUNT);
|
||||
node_t* children[TEST_REMOVE_CHILD_COUNT]; // this should be ordered as we
|
||||
node_t *parent = ALLOC_NODE_STR("parent", TEST_REMOVE_CHILD_COUNT);
|
||||
node_t *children[TEST_REMOVE_CHILD_COUNT]; // this should be ordered as we
|
||||
// expect to find them in the
|
||||
// parent's list of children.
|
||||
bool valid[TEST_REMOVE_CHILD_COUNT];
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_REMOVE_CHILD_COUNT; name_sz ++) {
|
||||
node_t* child = alloc_node(
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_REMOVE_CHILD_COUNT; name_sz++) {
|
||||
node_t *child = alloc_node(
|
||||
TEST_REMOVE_CHILD_NAME_STR,
|
||||
name_sz,
|
||||
0);
|
||||
@ -273,9 +277,9 @@ void test_remove_child() {
|
||||
valid[name_sz - 1] = true;
|
||||
}
|
||||
|
||||
for (uint16_t ix = 0; ix < TEST_REMOVE_CHILD_COUNT; ix ++) {
|
||||
for (uint16_t ix = 0; ix < TEST_REMOVE_CHILD_COUNT; ix++) {
|
||||
uint16_t victim_index = 0;
|
||||
for (uint16_t jx = 0; jx < TEST_REMOVE_CHILD_COUNT + 1; jx ++) {
|
||||
for (uint16_t jx = 0; jx < TEST_REMOVE_CHILD_COUNT + 1; jx++) {
|
||||
do {
|
||||
victim_index = (victim_index + 1) % TEST_REMOVE_CHILD_COUNT;
|
||||
} while (valid[victim_index] == false);
|
||||
@ -291,12 +295,12 @@ void test_remove_child() {
|
||||
valid[victim_index] = false;
|
||||
|
||||
ASSERT(remove_child(parent, search_result.child_num) ==
|
||||
REMOVE_CHILD_OK);
|
||||
REMOVE_CHILD_OK);
|
||||
|
||||
// go through the items that should still be children, and make sure they're
|
||||
// still reachable.
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_REMOVE_CHILD_COUNT; name_sz ++) {
|
||||
node_t* child = get_child_by_name(
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_REMOVE_CHILD_COUNT; name_sz++) {
|
||||
node_t *child = get_child_by_name(
|
||||
parent,
|
||||
TEST_REMOVE_CHILD_NAME_STR,
|
||||
name_sz);
|
||||
@ -317,15 +321,16 @@ void test_remove_child() {
|
||||
*/
|
||||
#define TEST_ENLARGE_CHILD_CAPACITY_NAME_STR "abcdefgh"
|
||||
#define TEST_ENLARGE_CHILD_CAPACITY_COUNT 8
|
||||
|
||||
void test_enlarge_child_capacity() {
|
||||
node_t* parent = ALLOC_NODE_STR(
|
||||
node_t *parent = ALLOC_NODE_STR(
|
||||
"parent",
|
||||
TEST_MANY_CHILDREN_COUNT);
|
||||
node_t* children[TEST_MANY_CHILDREN_COUNT]; // this should be ordered as we
|
||||
node_t *children[TEST_MANY_CHILDREN_COUNT]; // this should be ordered as we
|
||||
// expect to find them in the
|
||||
// parent's list of children.
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_MANY_CHILDREN_COUNT; name_sz ++) {
|
||||
node_t* child = alloc_node(
|
||||
for (uint16_t name_sz = 1; name_sz <= TEST_MANY_CHILDREN_COUNT; name_sz++) {
|
||||
node_t *child = alloc_node(
|
||||
TEST_ENLARGE_CHILD_CAPACITY_NAME_STR,
|
||||
name_sz,
|
||||
0);
|
||||
@ -344,15 +349,15 @@ void test_enlarge_child_capacity() {
|
||||
enlarge_child_capacity(parent, 0);
|
||||
ASSERT(enlarge_child_capacity_result.code == ENLARGE_OK);
|
||||
ASSERT(enlarge_child_capacity_result.old_child ==
|
||||
children[0]);
|
||||
children[0]);
|
||||
|
||||
node_t* enlarged = get_child_by_index(parent, 0);
|
||||
node_t *enlarged = get_child_by_index(parent, 0);
|
||||
ASSERT(max_children(enlarged) > 0);
|
||||
ASSERT(name_compare(enlarged->name, enlarged->name_sz,
|
||||
enlarge_child_capacity_result.old_child) == 0);
|
||||
enlarge_child_capacity_result.old_child) == 0);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int main(int argc, char *argv[]) {
|
||||
test_simple_parent_child();
|
||||
test_space();
|
||||
test_insufficient_space();
|
||||
|
@ -4,6 +4,6 @@
|
||||
//
|
||||
// no-check-code
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int main(int argc, char *argv[]) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ typedef enum {
|
||||
|
||||
typedef struct _get_path_result_t {
|
||||
get_path_code_t code;
|
||||
struct _node_t* node;
|
||||
struct _node_t *node;
|
||||
} get_path_result_t;
|
||||
|
||||
typedef enum {
|
||||
@ -48,7 +48,7 @@ typedef enum {
|
||||
} convert_from_flat_code_t;
|
||||
typedef struct _convert_from_flat_result_t {
|
||||
convert_from_flat_code_t code;
|
||||
struct _tree_t* tree;
|
||||
struct _tree_t *tree;
|
||||
} convert_from_flat_result_t;
|
||||
|
||||
typedef enum {
|
||||
@ -58,7 +58,7 @@ typedef enum {
|
||||
} convert_to_flat_code_t;
|
||||
typedef struct _convert_to_flat_result_t {
|
||||
convert_to_flat_code_t code;
|
||||
char* flat_manifest;
|
||||
char *flat_manifest;
|
||||
size_t flat_manifest_sz;
|
||||
} convert_to_flat_result_t;
|
||||
|
||||
|
@ -12,13 +12,13 @@
|
||||
#include "tree.h"
|
||||
#include "tree_arena.h"
|
||||
|
||||
bool valid_path(const char* path, const size_t path_sz) {
|
||||
bool valid_path(const char *path, const size_t path_sz) {
|
||||
if (path_sz > 0 && (path[0] == '/' || path[path_sz] == '/')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t last_slash = (size_t) -1;
|
||||
for (size_t off = 0; off < path_sz; off ++) {
|
||||
for (size_t off = 0; off < path_sz; off++) {
|
||||
if (path[off] == '/') {
|
||||
if (last_slash == off - 1) {
|
||||
return false;
|
||||
@ -39,8 +39,8 @@ bool valid_path(const char* path, const size_t path_sz) {
|
||||
* first_component('abc/def') => 'abc'
|
||||
* first_component('abc') => ''
|
||||
*/
|
||||
static size_t first_component(const char* path, size_t path_sz) {
|
||||
for (size_t off = 0; off < path_sz; off ++) {
|
||||
static size_t first_component(const char *path, size_t path_sz) {
|
||||
for (size_t off = 0; off < path_sz; off++) {
|
||||
if (path[off] == '/') {
|
||||
return off;
|
||||
}
|
||||
@ -80,9 +80,10 @@ typedef enum {
|
||||
} tree_add_child_code_t;
|
||||
typedef struct _tree_add_child_result_t {
|
||||
tree_add_child_code_t code;
|
||||
node_t* newroot;
|
||||
node_t* newchild;
|
||||
node_t *newroot;
|
||||
node_t *newchild;
|
||||
} tree_add_child_result_t;
|
||||
|
||||
/**
|
||||
* Adds a child to `root`. Because `root` may need to be resized to accomodate
|
||||
* the new child, we need the *parent* of `root`. On success (`result.code` ==
|
||||
@ -94,11 +95,11 @@ typedef struct _tree_add_child_result_t {
|
||||
* accounting structure.
|
||||
*/
|
||||
static tree_add_child_result_t tree_add_child(
|
||||
tree_t* tree,
|
||||
node_t* const root_parent,
|
||||
node_t* root,
|
||||
const char* name, const size_t name_sz,
|
||||
tree_state_changes_t* changes) {
|
||||
tree_t *tree,
|
||||
node_t *const root_parent,
|
||||
node_t *root,
|
||||
const char *name, const size_t name_sz,
|
||||
tree_state_changes_t *changes) {
|
||||
tree_add_child_result_t result;
|
||||
|
||||
// create a new child node, and record the deltas in the change
|
||||
@ -109,10 +110,10 @@ static tree_add_child_result_t tree_add_child(
|
||||
// this is a potential optimization opportunity. we could theoretically try
|
||||
// to allocate the new node in the arena and maintain compacted state of the
|
||||
// tree.
|
||||
node_t* node = alloc_node(name, name_sz, 0);
|
||||
node_t *node = alloc_node(name, name_sz, 0);
|
||||
if (node == NULL) {
|
||||
return (tree_add_child_result_t) {
|
||||
TREE_ADD_CHILD_OOM, NULL, NULL };
|
||||
TREE_ADD_CHILD_OOM, NULL, NULL};
|
||||
}
|
||||
|
||||
// accounting changes.
|
||||
@ -133,17 +134,17 @@ static tree_add_child_result_t tree_add_child(
|
||||
uint32_t index = get_child_index(root_parent, root);
|
||||
if (index == UINT32_MAX) {
|
||||
return (tree_add_child_result_t) {
|
||||
TREE_ADD_CHILD_WTF, NULL, NULL };
|
||||
TREE_ADD_CHILD_WTF, NULL, NULL};
|
||||
}
|
||||
node_enlarge_child_capacity_result_t enlarge_result =
|
||||
enlarge_child_capacity(root_parent, index);
|
||||
|
||||
if (enlarge_result.code == ENLARGE_OOM) {
|
||||
return (tree_add_child_result_t) {
|
||||
TREE_ADD_CHILD_OOM, NULL, NULL };
|
||||
TREE_ADD_CHILD_OOM, NULL, NULL};
|
||||
} else if (enlarge_result.code != ENLARGE_OK) {
|
||||
return (tree_add_child_result_t) {
|
||||
TREE_ADD_CHILD_WTF, NULL, NULL };
|
||||
TREE_ADD_CHILD_WTF, NULL, NULL};
|
||||
}
|
||||
|
||||
// update accounting.
|
||||
@ -161,11 +162,11 @@ static tree_add_child_result_t tree_add_child(
|
||||
add_child_result = add_child(root, node);
|
||||
if (add_child_result != ADD_CHILD_OK) {
|
||||
return (tree_add_child_result_t) {
|
||||
TREE_ADD_CHILD_WTF, NULL, NULL };
|
||||
TREE_ADD_CHILD_WTF, NULL, NULL};
|
||||
}
|
||||
} else if (add_child_result != ADD_CHILD_OK) {
|
||||
return (tree_add_child_result_t) {
|
||||
TREE_ADD_CHILD_WTF, NULL, NULL };
|
||||
TREE_ADD_CHILD_WTF, NULL, NULL};
|
||||
}
|
||||
|
||||
result.code = TREE_ADD_CHILD_OK;
|
||||
@ -176,18 +177,18 @@ static tree_add_child_result_t tree_add_child(
|
||||
typedef enum {
|
||||
// walks the tree. if the path cannot be found, exit with
|
||||
// `FIND_PATH_NOT_FOUND`.
|
||||
BASIC_WALK,
|
||||
BASIC_WALK,
|
||||
|
||||
// walks the tree. if the intermediate paths cannot be found, create them.
|
||||
// if a leaf node exists where an intermediate path node needs to be
|
||||
// created, then return `FIND_PATH_CONFLICT`.
|
||||
CREATE_IF_MISSING,
|
||||
CREATE_IF_MISSING,
|
||||
|
||||
// walks the tree. if the path cannot be found, exit with
|
||||
// `FIND_PATH_NOT_FOUND`. if the operation is successful, then check
|
||||
// intermediate nodes to ensure that they still have children. any nodes
|
||||
// that do not should be removed.
|
||||
REMOVE_EMPTY_IMPLICIT_NODES,
|
||||
REMOVE_EMPTY_IMPLICIT_NODES,
|
||||
} find_path_operation_type;
|
||||
typedef enum {
|
||||
FIND_PATH_OK,
|
||||
@ -198,8 +199,9 @@ typedef enum {
|
||||
} find_path_result_t;
|
||||
typedef struct _find_path_callback_result_t {
|
||||
find_path_result_t code;
|
||||
node_t* newroot;
|
||||
node_t *newroot;
|
||||
} find_path_callback_result_t;
|
||||
|
||||
/**
|
||||
* Find the directory node enclosing `path`. If `create_if_not_found` is true,
|
||||
* then any intermediate directories that do not exist will be created. Once
|
||||
@ -242,7 +244,7 @@ static find_path_result_t find_path(
|
||||
root = callback_result.newroot;
|
||||
} else {
|
||||
// resolve the first component.
|
||||
node_t* child = get_child_by_name(root, path, first_component_sz);
|
||||
node_t *child = get_child_by_name(root, path, first_component_sz);
|
||||
if (child == NULL) {
|
||||
if (operation_type == CREATE_IF_MISSING) {
|
||||
// create the new child.
|
||||
@ -357,8 +359,8 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void destroy_tree_helper(tree_t* tree, node_t* node) {
|
||||
for (int ix = 0; ix < node->num_children; ix ++) {
|
||||
static void destroy_tree_helper(tree_t *tree, node_t *node) {
|
||||
for (int ix = 0; ix < node->num_children; ix++) {
|
||||
destroy_tree_helper(tree, get_child_by_index(node, ix));
|
||||
}
|
||||
|
||||
@ -367,7 +369,7 @@ static void destroy_tree_helper(tree_t* tree, node_t* node) {
|
||||
}
|
||||
}
|
||||
|
||||
void destroy_tree(tree_t* tree) {
|
||||
void destroy_tree(tree_t *tree) {
|
||||
if (tree->compacted == false) {
|
||||
destroy_tree_helper(tree, tree->shadow_root);
|
||||
}
|
||||
@ -379,15 +381,16 @@ void destroy_tree(tree_t* tree) {
|
||||
}
|
||||
|
||||
typedef struct _get_path_metadata_t {
|
||||
node_t* node;
|
||||
node_t *node;
|
||||
} get_path_metadata_t;
|
||||
|
||||
find_path_callback_result_t get_path_callback(
|
||||
tree_t* tree,
|
||||
node_t* const root_parent,
|
||||
node_t* root,
|
||||
const char* name, const size_t name_sz,
|
||||
tree_state_changes_t* changes,
|
||||
void* context) {
|
||||
tree_t *tree,
|
||||
node_t *const root_parent,
|
||||
node_t *root,
|
||||
const char *name, const size_t name_sz,
|
||||
tree_state_changes_t *changes,
|
||||
void *context) {
|
||||
get_path_metadata_t *metadata =
|
||||
(get_path_metadata_t *) context;
|
||||
|
||||
@ -400,21 +403,21 @@ find_path_callback_result_t get_path_callback(
|
||||
|
||||
metadata->node = child;
|
||||
|
||||
return (find_path_callback_result_t) { FIND_PATH_OK, root };
|
||||
return (find_path_callback_result_t) {FIND_PATH_OK, root};
|
||||
}
|
||||
|
||||
get_path_result_t get_path(
|
||||
tree_t* tree,
|
||||
const char* path,
|
||||
tree_t *tree,
|
||||
const char *path,
|
||||
const size_t path_sz) {
|
||||
tree_state_changes_t changes = { 0 };
|
||||
tree_state_changes_t changes = {0};
|
||||
get_path_metadata_t metadata;
|
||||
|
||||
node_t* shadow_root = tree->shadow_root;
|
||||
node_t* real_root = get_child_by_index(shadow_root, 0);
|
||||
node_t *shadow_root = tree->shadow_root;
|
||||
node_t *real_root = get_child_by_index(shadow_root, 0);
|
||||
|
||||
if (real_root == NULL) {
|
||||
return (get_path_result_t) { GET_PATH_WTF, NULL };
|
||||
return (get_path_result_t) {GET_PATH_WTF, NULL};
|
||||
}
|
||||
|
||||
find_path_result_t result =
|
||||
@ -434,34 +437,35 @@ get_path_result_t get_path(
|
||||
|
||||
switch (result) {
|
||||
case FIND_PATH_OK:
|
||||
return (get_path_result_t) { GET_PATH_OK, metadata.node };
|
||||
return (get_path_result_t) {GET_PATH_OK, metadata.node};
|
||||
case FIND_PATH_NOT_FOUND:
|
||||
case FIND_PATH_CONFLICT:
|
||||
// `FIND_PATH_CONFLICT` is returned if there is a leaf node where we
|
||||
// expect a directory node. this is treated the same as a NOT_FOUND.
|
||||
return (get_path_result_t) { GET_PATH_NOT_FOUND, NULL };
|
||||
return (get_path_result_t) {GET_PATH_NOT_FOUND, NULL};
|
||||
default:
|
||||
return (get_path_result_t) { GET_PATH_WTF, NULL };
|
||||
return (get_path_result_t) {GET_PATH_WTF, NULL};
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _add_or_update_path_metadata_t {
|
||||
const uint8_t* checksum;
|
||||
const uint8_t *checksum;
|
||||
const uint8_t checksum_sz;
|
||||
const uint8_t flags;
|
||||
} add_or_update_path_metadata_t;
|
||||
|
||||
find_path_callback_result_t add_or_update_path_callback(
|
||||
tree_t* tree,
|
||||
node_t* const root_parent,
|
||||
node_t* root,
|
||||
const char* name, const size_t name_sz,
|
||||
tree_state_changes_t* changes,
|
||||
void* context) {
|
||||
add_or_update_path_metadata_t* metadata =
|
||||
(add_or_update_path_metadata_t*) context;
|
||||
tree_t *tree,
|
||||
node_t *const root_parent,
|
||||
node_t *root,
|
||||
const char *name, const size_t name_sz,
|
||||
tree_state_changes_t *changes,
|
||||
void *context) {
|
||||
add_or_update_path_metadata_t *metadata =
|
||||
(add_or_update_path_metadata_t *) context;
|
||||
|
||||
// does the path already exist?
|
||||
node_t* child = get_child_by_name(root, name, name_sz);
|
||||
node_t *child = get_child_by_name(root, name, name_sz);
|
||||
if (child == NULL) {
|
||||
tree_add_child_result_t tree_add_child_result =
|
||||
tree_add_child(
|
||||
@ -473,10 +477,10 @@ find_path_callback_result_t add_or_update_path_callback(
|
||||
switch (tree_add_child_result.code) {
|
||||
case TREE_ADD_CHILD_OOM:
|
||||
return (find_path_callback_result_t) {
|
||||
FIND_PATH_OOM, NULL };
|
||||
FIND_PATH_OOM, NULL};
|
||||
case TREE_ADD_CHILD_WTF:
|
||||
return (find_path_callback_result_t) {
|
||||
FIND_PATH_WTF, NULL };
|
||||
FIND_PATH_WTF, NULL};
|
||||
case TREE_ADD_CHILD_OK:
|
||||
break;
|
||||
}
|
||||
@ -487,19 +491,19 @@ find_path_callback_result_t add_or_update_path_callback(
|
||||
child->type = TYPE_LEAF;
|
||||
|
||||
// update the accounting.
|
||||
changes->num_leaf_node_change ++;
|
||||
changes->num_leaf_node_change++;
|
||||
} else {
|
||||
if (child->type == TYPE_IMPLICIT) {
|
||||
// was previously a directory
|
||||
return (find_path_callback_result_t) {
|
||||
FIND_PATH_CONFLICT, NULL };
|
||||
FIND_PATH_CONFLICT, NULL};
|
||||
}
|
||||
}
|
||||
|
||||
// update the node.
|
||||
if (metadata->checksum_sz > CHECKSUM_BYTES) {
|
||||
return (find_path_callback_result_t) {
|
||||
FIND_PATH_WTF, NULL };
|
||||
FIND_PATH_WTF, NULL};
|
||||
}
|
||||
|
||||
memcpy(child->checksum, metadata->checksum, metadata->checksum_sz);
|
||||
@ -507,25 +511,25 @@ find_path_callback_result_t add_or_update_path_callback(
|
||||
child->checksum_valid = true;
|
||||
child->flags = metadata->flags;
|
||||
|
||||
return (find_path_callback_result_t) { FIND_PATH_OK, root };
|
||||
return (find_path_callback_result_t) {FIND_PATH_OK, root};
|
||||
}
|
||||
|
||||
add_update_path_result_t add_or_update_path(
|
||||
tree_t* tree,
|
||||
const char* path,
|
||||
tree_t *tree,
|
||||
const char *path,
|
||||
const size_t path_sz,
|
||||
const uint8_t* checksum,
|
||||
const uint8_t *checksum,
|
||||
const uint8_t checksum_sz,
|
||||
const uint8_t flags) {
|
||||
tree_state_changes_t changes = { 0 };
|
||||
tree_state_changes_t changes = {0};
|
||||
add_or_update_path_metadata_t metadata = {
|
||||
checksum,
|
||||
checksum_sz,
|
||||
flags,
|
||||
checksum,
|
||||
checksum_sz,
|
||||
flags,
|
||||
};
|
||||
|
||||
node_t* shadow_root = tree->shadow_root;
|
||||
node_t* real_root = get_child_by_index(shadow_root, 0);
|
||||
node_t *shadow_root = tree->shadow_root;
|
||||
node_t *real_root = get_child_by_index(shadow_root, 0);
|
||||
|
||||
if (real_root == NULL) {
|
||||
return ADD_UPDATE_PATH_WTF;
|
||||
@ -562,12 +566,12 @@ add_update_path_result_t add_or_update_path(
|
||||
}
|
||||
|
||||
find_path_callback_result_t remove_path_callback(
|
||||
tree_t* tree,
|
||||
node_t* const root_parent,
|
||||
node_t* root,
|
||||
const char* name, const size_t name_sz,
|
||||
tree_state_changes_t* changes,
|
||||
void* context) {
|
||||
tree_t *tree,
|
||||
node_t *const root_parent,
|
||||
node_t *root,
|
||||
const char *name, const size_t name_sz,
|
||||
tree_state_changes_t *changes,
|
||||
void *context) {
|
||||
// does the path already exist?
|
||||
node_search_children_result_t search_result =
|
||||
search_children(root, name, name_sz);
|
||||
@ -579,7 +583,7 @@ find_path_callback_result_t remove_path_callback(
|
||||
|
||||
// record the metadata changes.
|
||||
changes->checksum_dirty = true;
|
||||
changes->num_leaf_node_change --;
|
||||
changes->num_leaf_node_change--;
|
||||
changes->size_change -= search_result.child->block_sz;
|
||||
|
||||
node_remove_child_result_t remove_result =
|
||||
@ -593,13 +597,13 @@ find_path_callback_result_t remove_path_callback(
|
||||
}
|
||||
|
||||
remove_path_result_t remove_path(
|
||||
tree_t* tree,
|
||||
const char* path,
|
||||
tree_t *tree,
|
||||
const char *path,
|
||||
const size_t path_sz) {
|
||||
tree_state_changes_t changes = { 0 };
|
||||
tree_state_changes_t changes = {0};
|
||||
|
||||
node_t* shadow_root = tree->shadow_root;
|
||||
node_t* real_root = get_child_by_index(shadow_root, 0);
|
||||
node_t *shadow_root = tree->shadow_root;
|
||||
node_t *real_root = get_child_by_index(shadow_root, 0);
|
||||
|
||||
if (real_root == NULL) {
|
||||
return REMOVE_PATH_WTF;
|
||||
|
@ -40,9 +40,12 @@ typedef struct _tree_t {
|
||||
uint32_t num_leaf_nodes;
|
||||
|
||||
// these fields are not preserved during serialization.
|
||||
struct _node_t* shadow_root; /* this is a literal pointer. */
|
||||
void* arena; /* this is also a literal pointer. */
|
||||
void* arena_free_start; /* this is also a literal pointer. */
|
||||
struct _node_t *shadow_root;
|
||||
/* this is a literal pointer. */
|
||||
void *arena;
|
||||
/* this is also a literal pointer. */
|
||||
void *arena_free_start;
|
||||
/* this is also a literal pointer. */
|
||||
size_t arena_sz;
|
||||
bool compacted;
|
||||
|
||||
@ -59,36 +62,44 @@ typedef struct _tree_t {
|
||||
* 2) The path must not start nor end with the path separator '/'.
|
||||
* 3) The path must not have consecutive path separators.
|
||||
*/
|
||||
extern bool valid_path(const char* path, const size_t path_sz);
|
||||
extern bool valid_path(const char *path, const size_t path_sz);
|
||||
|
||||
extern tree_t* alloc_tree();
|
||||
extern void destroy_tree(tree_t* tree);
|
||||
extern tree_t *alloc_tree();
|
||||
|
||||
extern void destroy_tree(tree_t *tree);
|
||||
|
||||
extern tree_t *copy(const tree_t *src);
|
||||
|
||||
extern tree_t* copy(const tree_t* src);
|
||||
extern get_path_result_t get_path(
|
||||
tree_t* const tree,
|
||||
const char* path,
|
||||
tree_t *const tree,
|
||||
const char *path,
|
||||
const size_t path_sz);
|
||||
|
||||
extern add_update_path_result_t add_or_update_path(
|
||||
tree_t* const tree,
|
||||
const char* path,
|
||||
tree_t *const tree,
|
||||
const char *path,
|
||||
const size_t path_sz,
|
||||
const uint8_t* checksum,
|
||||
const uint8_t *checksum,
|
||||
const uint8_t checksum_sz,
|
||||
const uint8_t flags);
|
||||
|
||||
extern remove_path_result_t remove_path(
|
||||
tree_t* const tree,
|
||||
const char* path,
|
||||
const size_t path_sz);
|
||||
extern bool contains_path(
|
||||
const tree_t* tree,
|
||||
const char* path,
|
||||
tree_t *const tree,
|
||||
const char *path,
|
||||
const size_t path_sz);
|
||||
|
||||
extern tree_t* read_from_file(char* fname);
|
||||
extern write_to_file_result_t write_to_file(tree_t* tree, char* fname);
|
||||
extern bool contains_path(
|
||||
const tree_t *tree,
|
||||
const char *path,
|
||||
const size_t path_sz);
|
||||
|
||||
extern tree_t *read_from_file(char *fname);
|
||||
|
||||
extern write_to_file_result_t write_to_file(tree_t *tree, char *fname);
|
||||
|
||||
extern convert_from_flat_result_t convert_from_flat(
|
||||
char* manifest, size_t manifest_sz);
|
||||
extern convert_to_flat_result_t convert_to_flat(tree_t* tree);
|
||||
char *manifest, size_t manifest_sz);
|
||||
|
||||
extern convert_to_flat_result_t convert_to_flat(tree_t *tree);
|
||||
|
||||
#endif /* #ifndef __FASTMANIFEST_TREE_H__ */
|
||||
|
@ -15,7 +15,7 @@
|
||||
#define ARENA_MIN_STORAGE_INCREMENT (1024 * 1024)
|
||||
#define ARENA_MAX_STORAGE_INCREMENT (16 * 1024 * 1024)
|
||||
|
||||
static inline size_t calculate_arena_free(const tree_t* tree) {
|
||||
static inline size_t calculate_arena_free(const tree_t *tree) {
|
||||
intptr_t arena_start = (intptr_t) tree->arena;
|
||||
intptr_t arena_free_start = (intptr_t) tree->arena_free_start;
|
||||
intptr_t arena_end = arena_start + tree->arena_sz;
|
||||
@ -26,22 +26,22 @@ static inline size_t calculate_arena_free(const tree_t* tree) {
|
||||
|
||||
arena_alloc_node_result_t arena_alloc_node_helper(
|
||||
arena_policy_t policy,
|
||||
tree_t* tree,
|
||||
const char* name, size_t name_sz,
|
||||
tree_t *tree,
|
||||
const char *name, size_t name_sz,
|
||||
size_t max_children) {
|
||||
// since name_sz and max_chlidren are going to be downcasted, we should verify
|
||||
// that they're not too large for the types in node.h
|
||||
if (!VERIFY_NAME_SZ(name_sz) ||
|
||||
!VERIFY_CHILD_NUM(max_children)) {
|
||||
return (arena_alloc_node_result_t) {
|
||||
ARENA_ALLOC_EXCEEDED_LIMITS, NULL };
|
||||
ARENA_ALLOC_EXCEEDED_LIMITS, NULL};
|
||||
}
|
||||
|
||||
do {
|
||||
size_t arena_free = calculate_arena_free(tree);
|
||||
|
||||
node_t* candidate = (node_t*) tree->arena_free_start;
|
||||
void* next = setup_node(
|
||||
node_t *candidate = (node_t *) tree->arena_free_start;
|
||||
void *next = setup_node(
|
||||
tree->arena_free_start, arena_free,
|
||||
name, name_sz,
|
||||
max_children);
|
||||
@ -49,7 +49,7 @@ arena_alloc_node_result_t arena_alloc_node_helper(
|
||||
if (next == NULL) {
|
||||
if (policy == ARENA_POLICY_FAIL) {
|
||||
return (arena_alloc_node_result_t) {
|
||||
ARENA_ALLOC_OOM, NULL };
|
||||
ARENA_ALLOC_OOM, NULL};
|
||||
} else {
|
||||
size_t new_arena_sz =
|
||||
(tree->arena_sz * (100 + ARENA_INCREMENT_PERCENTAGE)) / 100;
|
||||
@ -84,8 +84,8 @@ arena_alloc_node_result_t arena_alloc_node_helper(
|
||||
intptr_t shadow_root = (intptr_t) tree->shadow_root;
|
||||
ptrdiff_t shadow_root_offset = shadow_root - arena_start;
|
||||
|
||||
tree->shadow_root = (node_t*) (new_arena_start +
|
||||
shadow_root_offset);
|
||||
tree->shadow_root = (node_t *) (new_arena_start +
|
||||
shadow_root_offset);
|
||||
}
|
||||
|
||||
intptr_t new_arena_free_start = new_arena_start;
|
||||
@ -99,14 +99,14 @@ arena_alloc_node_result_t arena_alloc_node_helper(
|
||||
tree->arena_free_start = next;
|
||||
tree->consumed_memory += candidate->block_sz;
|
||||
return (arena_alloc_node_result_t) {
|
||||
ARENA_ALLOC_OK, candidate };
|
||||
ARENA_ALLOC_OK, candidate};
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
tree_t* alloc_tree_with_arena(size_t arena_sz) {
|
||||
void* arena = malloc(arena_sz);
|
||||
tree_t* tree = (tree_t*) calloc(1, sizeof(tree_t));
|
||||
tree_t *alloc_tree_with_arena(size_t arena_sz) {
|
||||
void *arena = malloc(arena_sz);
|
||||
tree_t *tree = (tree_t *) calloc(1, sizeof(tree_t));
|
||||
|
||||
if (arena == NULL || tree == NULL) {
|
||||
if (arena != NULL) {
|
||||
@ -135,7 +135,7 @@ tree_t* alloc_tree_with_arena(size_t arena_sz) {
|
||||
if (alloc_result.code != ARENA_ALLOC_OK) {
|
||||
return NULL;
|
||||
}
|
||||
node_t* shadow_root = alloc_result.node;
|
||||
node_t *shadow_root = alloc_result.node;
|
||||
shadow_root->type = TYPE_ROOT;
|
||||
|
||||
tree->shadow_root = shadow_root;
|
||||
|
@ -27,10 +27,10 @@ typedef enum {
|
||||
|
||||
typedef struct _arena_alloc_node_result_t {
|
||||
arena_alloc_node_code_t code;
|
||||
node_t* node;
|
||||
node_t *node;
|
||||
} arena_alloc_node_result_t;
|
||||
|
||||
static inline bool in_arena(const tree_t* tree, void* _ptr) {
|
||||
static inline bool in_arena(const tree_t *tree, void *_ptr) {
|
||||
intptr_t arena_start = (intptr_t) tree->arena;
|
||||
intptr_t arena_end = arena_start + tree->arena_sz - 1;
|
||||
intptr_t ptr = (intptr_t) _ptr;
|
||||
@ -48,13 +48,13 @@ static inline bool in_arena(const tree_t* tree, void* _ptr) {
|
||||
*/
|
||||
extern arena_alloc_node_result_t arena_alloc_node_helper(
|
||||
arena_policy_t policy,
|
||||
tree_t* tree,
|
||||
const char* name, size_t name_sz,
|
||||
tree_t *tree,
|
||||
const char *name, size_t name_sz,
|
||||
size_t max_children);
|
||||
|
||||
static inline arena_alloc_node_result_t arena_alloc_node(
|
||||
tree_t* tree,
|
||||
const char* name, size_t name_sz,
|
||||
tree_t *tree,
|
||||
const char *name, size_t name_sz,
|
||||
size_t max_children) {
|
||||
return arena_alloc_node_helper(
|
||||
ARENA_POLICY_REALLOC,
|
||||
@ -64,8 +64,8 @@ static inline arena_alloc_node_result_t arena_alloc_node(
|
||||
}
|
||||
|
||||
static inline arena_alloc_node_result_t arena_alloc_node_strict(
|
||||
tree_t* tree,
|
||||
const char* name, size_t name_sz,
|
||||
tree_t *tree,
|
||||
const char *name, size_t name_sz,
|
||||
size_t max_children) {
|
||||
return arena_alloc_node_helper(
|
||||
ARENA_POLICY_FAIL,
|
||||
@ -78,6 +78,6 @@ static inline arena_alloc_node_result_t arena_alloc_node_strict(
|
||||
* Creates a tree and sets up the shadow root node. This does *not* initialize
|
||||
* the real root node. It is the responsibility of the caller to do so.
|
||||
*/
|
||||
extern tree_t* alloc_tree_with_arena(size_t arena_sz);
|
||||
extern tree_t *alloc_tree_with_arena(size_t arena_sz);
|
||||
|
||||
#endif /* #ifndef __FASTMANIFEST_TREE_ARENA_H__ */
|
||||
|
@ -18,7 +18,7 @@
|
||||
#define BUFFER_MINIMUM_GROWTH 1048576
|
||||
#define BUFFER_MAXIMUM_GROWTH (32 * 1024 * 1024)
|
||||
|
||||
#define CONVERT_BUFFER_APPEND(buffer, buffer_idx, buffer_sz, \
|
||||
#define CONVERT_BUFFER_APPEND(buffer, buffer_idx, buffer_sz, \
|
||||
input, input_sz) \
|
||||
buffer_append(buffer, buffer_idx, buffer_sz, input, input_sz, \
|
||||
BUFFER_GROWTH_FACTOR, \
|
||||
@ -32,10 +32,11 @@
|
||||
BUFFER_MAXIMUM_GROWTH)
|
||||
|
||||
typedef struct _open_folder_t {
|
||||
const char* subfolder_name; /* this is a reference to the flat
|
||||
* manifest's memory. we do not own
|
||||
* this memory, and we must copy it
|
||||
* before the conversion completes. */
|
||||
const char *subfolder_name;
|
||||
/* this is a reference to the flat
|
||||
* manifest's memory. we do not own
|
||||
* this memory, and we must copy it
|
||||
* before the conversion completes. */
|
||||
size_t subfolder_name_sz;
|
||||
|
||||
// readers may wonder why we store a relative pointer. this is because
|
||||
@ -44,7 +45,7 @@ typedef struct _open_folder_t {
|
||||
// store an offset from the start of the arena.
|
||||
ptrdiff_t closed_children_prealloc[DEFAULT_CHILDREN_CAPACITY];
|
||||
|
||||
ptrdiff_t* closed_children;
|
||||
ptrdiff_t *closed_children;
|
||||
size_t closed_children_count;
|
||||
size_t closed_children_capacity;
|
||||
|
||||
@ -52,39 +53,39 @@ typedef struct _open_folder_t {
|
||||
} open_folder_t;
|
||||
|
||||
typedef struct _from_flat_state_t {
|
||||
tree_t* tree;
|
||||
tree_t *tree;
|
||||
open_folder_t folders[MAX_FOLDER_DEPTH];
|
||||
size_t open_folder_count;
|
||||
} from_flat_state_t;
|
||||
|
||||
typedef struct _to_flat_state_t {
|
||||
const tree_t* tree;
|
||||
char* dirpath_build_buffer;
|
||||
const tree_t *tree;
|
||||
char *dirpath_build_buffer;
|
||||
size_t dirpath_build_buffer_idx;
|
||||
size_t dirpath_build_buffer_sz;
|
||||
|
||||
char* output_buffer;
|
||||
char *output_buffer;
|
||||
size_t output_buffer_idx;
|
||||
size_t output_buffer_sz;
|
||||
} to_flat_state_t;
|
||||
|
||||
static int8_t hextable[256] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0-9 */
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A-F */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* a-f */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0-9 */
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A-F */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* a-f */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
|
||||
};
|
||||
|
||||
static char chartable[16] = {
|
||||
@ -95,13 +96,13 @@ static char chartable[16] = {
|
||||
/*
|
||||
* Turn a hex-encoded string into binary. Returns false on failure.
|
||||
*/
|
||||
static bool unhexlify(const char* input, int len, uint8_t* dst) {
|
||||
static bool unhexlify(const char *input, int len, uint8_t *dst) {
|
||||
if (len != SHA1_BYTES * 2) {
|
||||
// wtf.
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t ix = 0; ix < len; ix += 2, dst ++) {
|
||||
for (size_t ix = 0; ix < len; ix += 2, dst++) {
|
||||
int hi = hextable[(unsigned char) input[ix]];
|
||||
int lo = hextable[(unsigned char) input[ix + 1]];
|
||||
|
||||
@ -117,8 +118,8 @@ static bool unhexlify(const char* input, int len, uint8_t* dst) {
|
||||
/*
|
||||
* Turn binary data into a hex-encoded string.
|
||||
*/
|
||||
static void hexlify(const uint8_t* input, int len, char* dst) {
|
||||
for (size_t ix = 0; ix < len; ix ++, dst += 2) {
|
||||
static void hexlify(const uint8_t *input, int len, char *dst) {
|
||||
for (size_t ix = 0; ix < len; ix++, dst += 2) {
|
||||
unsigned char ch = (unsigned char) input[ix];
|
||||
char hi = chartable[ch >> 4];
|
||||
char lo = chartable[ch & 0xf];
|
||||
@ -139,11 +140,11 @@ static void hexlify(const uint8_t* input, int len, char* dst) {
|
||||
* in folder.
|
||||
*/
|
||||
static inline int folder_name_compare(
|
||||
const char* name,
|
||||
const char *name,
|
||||
size_t name_sz,
|
||||
const open_folder_t* folder) {
|
||||
const open_folder_t *folder) {
|
||||
uint32_t min_sz = (name_sz < folder->subfolder_name_sz) ?
|
||||
name_sz : folder->subfolder_name_sz;
|
||||
name_sz : folder->subfolder_name_sz;
|
||||
int sz_compare = name_sz - folder->subfolder_name_sz;
|
||||
|
||||
int cmp = strncmp(name, folder->subfolder_name, min_sz);
|
||||
@ -154,20 +155,20 @@ static inline int folder_name_compare(
|
||||
}
|
||||
}
|
||||
|
||||
static void init_open_folder(open_folder_t* folder) {
|
||||
static void init_open_folder(open_folder_t *folder) {
|
||||
folder->in_use = false;
|
||||
folder->closed_children = folder->closed_children_prealloc;
|
||||
folder->closed_children_count = 0;
|
||||
folder->closed_children_capacity = DEFAULT_CHILDREN_CAPACITY;
|
||||
}
|
||||
|
||||
static from_flat_state_t* init_from_state(size_t flat_sz) {
|
||||
static from_flat_state_t *init_from_state(size_t flat_sz) {
|
||||
from_flat_state_t *state = malloc(sizeof(from_flat_state_t));
|
||||
if (state == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int ix = 0; ix < MAX_FOLDER_DEPTH; ix ++) {
|
||||
for (int ix = 0; ix < MAX_FOLDER_DEPTH; ix++) {
|
||||
init_open_folder(&state->folders[ix]);
|
||||
}
|
||||
state->open_folder_count = 0;
|
||||
@ -181,7 +182,7 @@ static from_flat_state_t* init_from_state(size_t flat_sz) {
|
||||
if (alloc_result.code != ARENA_ALLOC_OK) {
|
||||
return NULL;
|
||||
}
|
||||
node_t* shadow_root = alloc_result.node;
|
||||
node_t *shadow_root = alloc_result.node;
|
||||
shadow_root->type = TYPE_ROOT;
|
||||
|
||||
state->tree->shadow_root = shadow_root;
|
||||
@ -194,9 +195,9 @@ static from_flat_state_t* init_from_state(size_t flat_sz) {
|
||||
* Adds a child to a folder, expanding it as needed.
|
||||
*/
|
||||
static bool folder_add_child(
|
||||
from_flat_state_t* state,
|
||||
open_folder_t* folder,
|
||||
node_t* child) {
|
||||
from_flat_state_t *state,
|
||||
open_folder_t *folder,
|
||||
node_t *child) {
|
||||
if (folder->closed_children_count + 1 == folder->closed_children_capacity) {
|
||||
// time to expand the folder
|
||||
size_t new_capacity = folder->closed_children_capacity * 2;
|
||||
@ -226,19 +227,20 @@ static bool folder_add_child(
|
||||
intptr_t child_start = (intptr_t) child;
|
||||
folder->closed_children[folder->closed_children_count] =
|
||||
child_start - arena_start;
|
||||
folder->closed_children_count ++;
|
||||
folder->closed_children_count++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
CLOSE_FOLDER_OK,
|
||||
CLOSE_FOLDER_OOM,
|
||||
CLOSE_FOLDER_OK,
|
||||
CLOSE_FOLDER_OOM,
|
||||
} close_folder_code_t;
|
||||
typedef struct _close_folder_result_t {
|
||||
close_folder_code_t code;
|
||||
node_t* node;
|
||||
node_t *node;
|
||||
} close_folder_result_t;
|
||||
|
||||
/**
|
||||
* Close the folder at index `folder_index`. This may require closing nested
|
||||
* folders. If folder_index is > 0, then add the closed folder to its parent.
|
||||
@ -246,9 +248,9 @@ typedef struct _close_folder_result_t {
|
||||
* returned node to the shadow root.
|
||||
*/
|
||||
static close_folder_result_t close_folder(
|
||||
from_flat_state_t* state,
|
||||
from_flat_state_t *state,
|
||||
size_t folder_index) {
|
||||
open_folder_t* folder = &state->folders[folder_index];
|
||||
open_folder_t *folder = &state->folders[folder_index];
|
||||
assert(folder->in_use == true);
|
||||
|
||||
if (folder_index < MAX_FOLDER_DEPTH - 1) {
|
||||
@ -260,7 +262,7 @@ static close_folder_result_t close_folder(
|
||||
|
||||
if (close_folder_result.code != CLOSE_FOLDER_OK) {
|
||||
return (close_folder_result_t) {
|
||||
close_folder_result.code, NULL };
|
||||
close_folder_result.code, NULL};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -275,9 +277,9 @@ static close_folder_result_t close_folder(
|
||||
|
||||
if (arena_alloc_node_result.code == ARENA_ALLOC_OOM) {
|
||||
return (close_folder_result_t) {
|
||||
CLOSE_FOLDER_OOM, NULL };
|
||||
CLOSE_FOLDER_OOM, NULL};
|
||||
}
|
||||
node_t* node = arena_alloc_node_result.node;
|
||||
node_t *node = arena_alloc_node_result.node;
|
||||
node->type = TYPE_IMPLICIT;
|
||||
node->num_children = folder->closed_children_count; // this is a huge
|
||||
// abstraction violation,
|
||||
@ -288,7 +290,7 @@ static close_folder_result_t close_folder(
|
||||
|
||||
// node is set up. now add all the children!
|
||||
intptr_t arena_start = (intptr_t) state->tree->arena;
|
||||
for (size_t ix = 0; ix < folder->closed_children_count; ix ++) {
|
||||
for (size_t ix = 0; ix < folder->closed_children_count; ix++) {
|
||||
ptrdiff_t child_offset = (intptr_t) folder->closed_children[ix];
|
||||
intptr_t address = arena_start + child_offset;
|
||||
|
||||
@ -296,31 +298,31 @@ static close_folder_result_t close_folder(
|
||||
}
|
||||
|
||||
init_open_folder(folder); // zap the folder so it can be reused.
|
||||
state->open_folder_count --;
|
||||
state->open_folder_count--;
|
||||
|
||||
// attach to parent folder if it's not the root folder.
|
||||
assert(folder_index == state->open_folder_count);
|
||||
if (folder_index > 0) {
|
||||
open_folder_t* parent_folder = &state->folders[folder_index - 1];
|
||||
open_folder_t *parent_folder = &state->folders[folder_index - 1];
|
||||
if (folder_add_child(state, parent_folder, node) == false) {
|
||||
return (close_folder_result_t) {
|
||||
CLOSE_FOLDER_OOM, NULL };
|
||||
CLOSE_FOLDER_OOM, NULL};
|
||||
}
|
||||
}
|
||||
|
||||
return (close_folder_result_t) {
|
||||
CLOSE_FOLDER_OK, node };
|
||||
CLOSE_FOLDER_OK, node};
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
PROCESS_PATH_OK,
|
||||
PROCESS_PATH_OOM,
|
||||
PROCESS_PATH_CORRUPT,
|
||||
PROCESS_PATH_OK,
|
||||
PROCESS_PATH_OOM,
|
||||
PROCESS_PATH_CORRUPT,
|
||||
} process_path_code_t;
|
||||
typedef struct _process_path_result_t {
|
||||
process_path_code_t code;
|
||||
// the following are only set when the code is `PROCESS_PATH_OK`.
|
||||
node_t* node; // do *NOT* save this pointer.
|
||||
node_t *node; // do *NOT* save this pointer.
|
||||
// immediately do what is needed with
|
||||
// this pointer and discard. the reason
|
||||
// is that it's part of the arena, and
|
||||
@ -328,6 +330,7 @@ typedef struct _process_path_result_t {
|
||||
size_t bytes_consumed; // this is the number of bytes consumed,
|
||||
// including the null pointer.
|
||||
} process_path_result_t;
|
||||
|
||||
/**
|
||||
* Process a null-terminated path, closing any directories and building the
|
||||
* nodes as needed, and opening the new directories to support the current path.
|
||||
@ -336,21 +339,21 @@ typedef struct _process_path_result_t {
|
||||
* the folder.
|
||||
*/
|
||||
static process_path_result_t process_path(
|
||||
from_flat_state_t* state,
|
||||
const char* path, size_t max_len) {
|
||||
from_flat_state_t *state,
|
||||
const char *path, size_t max_len) {
|
||||
size_t path_scan_index;
|
||||
size_t current_path_start;
|
||||
size_t open_folder_index;
|
||||
|
||||
// match as many path components as we can
|
||||
for (path_scan_index = 0,
|
||||
current_path_start = 0,
|
||||
open_folder_index = 0;
|
||||
current_path_start = 0,
|
||||
open_folder_index = 0;
|
||||
path[path_scan_index] != 0;
|
||||
path_scan_index ++) {
|
||||
path_scan_index++) {
|
||||
if (path_scan_index == max_len) {
|
||||
return (process_path_result_t) {
|
||||
PROCESS_PATH_CORRUPT, NULL, 0 };
|
||||
PROCESS_PATH_CORRUPT, NULL, 0};
|
||||
}
|
||||
|
||||
// check for a path separator.
|
||||
@ -364,17 +367,17 @@ static process_path_result_t process_path(
|
||||
// component we just found.
|
||||
if (open_folder_index + 1 < state->open_folder_count) {
|
||||
if (folder_name_compare(
|
||||
&path[current_path_start],
|
||||
path_scan_index - current_path_start,
|
||||
&state->folders[open_folder_index + 1]) == 0) {
|
||||
&path[current_path_start],
|
||||
path_scan_index - current_path_start,
|
||||
&state->folders[open_folder_index + 1]) == 0) {
|
||||
// we found the folder we needed, so we can just reuse it.
|
||||
open_new_folder = false;
|
||||
open_folder_index ++;
|
||||
open_folder_index++;
|
||||
} else {
|
||||
close_folder_result_t close_folder_result =
|
||||
close_folder(state, open_folder_index + 1);
|
||||
if (close_folder_result.code == CLOSE_FOLDER_OOM) {
|
||||
return (process_path_result_t) { PROCESS_PATH_OOM, NULL, 0 };
|
||||
return (process_path_result_t) {PROCESS_PATH_OOM, NULL, 0};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -383,9 +386,9 @@ static process_path_result_t process_path(
|
||||
// if we're opening a new folder, that means there should be no child
|
||||
// folders open.
|
||||
assert(state->open_folder_count == open_folder_index + 1);
|
||||
open_folder_index ++;
|
||||
state->open_folder_count ++;
|
||||
open_folder_t* folder = &state->folders[open_folder_index];
|
||||
open_folder_index++;
|
||||
state->open_folder_count++;
|
||||
open_folder_t *folder = &state->folders[open_folder_index];
|
||||
|
||||
assert(folder->in_use == false);
|
||||
assert(folder->closed_children == folder->closed_children_prealloc);
|
||||
@ -406,7 +409,7 @@ static process_path_result_t process_path(
|
||||
close_folder_result_t close_folder_result =
|
||||
close_folder(state, open_folder_index + 1);
|
||||
if (close_folder_result.code == CLOSE_FOLDER_OOM) {
|
||||
return (process_path_result_t) { PROCESS_PATH_OOM, NULL, 0 };
|
||||
return (process_path_result_t) {PROCESS_PATH_OOM, NULL, 0};
|
||||
}
|
||||
}
|
||||
|
||||
@ -420,30 +423,30 @@ static process_path_result_t process_path(
|
||||
0);
|
||||
|
||||
if (arena_alloc_node_result.code == ARENA_ALLOC_OOM) {
|
||||
return (process_path_result_t) { PROCESS_PATH_OOM, NULL, 0 };
|
||||
return (process_path_result_t) {PROCESS_PATH_OOM, NULL, 0};
|
||||
}
|
||||
|
||||
arena_alloc_node_result.node->type = TYPE_LEAF;
|
||||
|
||||
// jam the new node into the currently open folder.
|
||||
open_folder_t* folder = &state->folders[open_folder_index];
|
||||
open_folder_t *folder = &state->folders[open_folder_index];
|
||||
folder_add_child(state, folder, arena_alloc_node_result.node);
|
||||
|
||||
return (process_path_result_t) {
|
||||
PROCESS_PATH_OK, arena_alloc_node_result.node, path_scan_index + 1 };
|
||||
PROCESS_PATH_OK, arena_alloc_node_result.node, path_scan_index + 1};
|
||||
}
|
||||
|
||||
|
||||
static convert_from_flat_result_t convert_from_flat_helper(
|
||||
from_flat_state_t *state, char* manifest, size_t manifest_sz) {
|
||||
from_flat_state_t *state, char *manifest, size_t manifest_sz) {
|
||||
// open the root directory node.
|
||||
open_folder_t* folder = &state->folders[0];
|
||||
open_folder_t *folder = &state->folders[0];
|
||||
folder->subfolder_name = "/";
|
||||
folder->subfolder_name_sz = 1;
|
||||
folder->in_use = true;
|
||||
state->open_folder_count ++;
|
||||
state->open_folder_count++;
|
||||
|
||||
for (size_t ptr = 0; ptr < manifest_sz; ) {
|
||||
for (size_t ptr = 0; ptr < manifest_sz;) {
|
||||
// filename is up to the first null.
|
||||
process_path_result_t pp_result = process_path(
|
||||
state, &manifest[ptr], manifest_sz - ptr);
|
||||
@ -451,29 +454,29 @@ static convert_from_flat_result_t convert_from_flat_helper(
|
||||
switch (pp_result.code) {
|
||||
case PROCESS_PATH_OOM:
|
||||
return (convert_from_flat_result_t) {
|
||||
CONVERT_FROM_FLAT_OOM, NULL };
|
||||
CONVERT_FROM_FLAT_OOM, NULL};
|
||||
case PROCESS_PATH_CORRUPT:
|
||||
return (convert_from_flat_result_t) {
|
||||
CONVERT_FROM_FLAT_WTF, NULL };
|
||||
CONVERT_FROM_FLAT_WTF, NULL};
|
||||
case PROCESS_PATH_OK:
|
||||
break;
|
||||
}
|
||||
|
||||
assert(pp_result.code == PROCESS_PATH_OK);
|
||||
node_t* node = pp_result.node;
|
||||
node_t *node = pp_result.node;
|
||||
ptr += pp_result.bytes_consumed;
|
||||
size_t remaining = manifest_sz - ptr;
|
||||
if (remaining <= SHA1_BYTES * 2) {
|
||||
// not enough characters for the checksum and the NL. well, that's a
|
||||
// fail.
|
||||
return (convert_from_flat_result_t) {
|
||||
CONVERT_FROM_FLAT_WTF, NULL };
|
||||
CONVERT_FROM_FLAT_WTF, NULL};
|
||||
}
|
||||
|
||||
if (unhexlify(&manifest[ptr], SHA1_BYTES * 2, node->checksum) ==
|
||||
false) {
|
||||
return (convert_from_flat_result_t) {
|
||||
CONVERT_FROM_FLAT_WTF, NULL };
|
||||
CONVERT_FROM_FLAT_WTF, NULL};
|
||||
}
|
||||
node->checksum_sz = SHA1_BYTES;
|
||||
node->checksum_valid = true;
|
||||
@ -483,13 +486,13 @@ static convert_from_flat_result_t convert_from_flat_helper(
|
||||
// it as the flags field.
|
||||
if (manifest[ptr] != '\n') {
|
||||
node->flags = manifest[ptr];
|
||||
ptr ++;
|
||||
ptr++;
|
||||
} else {
|
||||
node->flags = 0;
|
||||
}
|
||||
ptr ++;
|
||||
ptr++;
|
||||
|
||||
state->tree->num_leaf_nodes ++;
|
||||
state->tree->num_leaf_nodes++;
|
||||
}
|
||||
|
||||
// close the root folder.
|
||||
@ -502,15 +505,15 @@ static convert_from_flat_result_t convert_from_flat_helper(
|
||||
add_child(state->tree->shadow_root, close_result.node);
|
||||
|
||||
return (convert_from_flat_result_t) {
|
||||
CONVERT_FROM_FLAT_OK, state->tree };
|
||||
CONVERT_FROM_FLAT_OK, state->tree};
|
||||
}
|
||||
|
||||
static convert_to_flat_code_t convert_to_flat_iterator(
|
||||
to_flat_state_t* state,
|
||||
const node_t* node) {
|
||||
to_flat_state_t *state,
|
||||
const node_t *node) {
|
||||
assert(node->type == TYPE_IMPLICIT);
|
||||
|
||||
for (uint32_t ix = 0; ix < node->num_children; ix ++) {
|
||||
for (uint32_t ix = 0; ix < node->num_children; ix++) {
|
||||
node_t *child = get_child_by_index(node, ix);
|
||||
|
||||
if (child->type == TYPE_LEAF) {
|
||||
@ -542,7 +545,7 @@ static convert_to_flat_code_t convert_to_flat_iterator(
|
||||
|
||||
// copy the filename over to the output buffer.
|
||||
state->output_buffer[state->output_buffer_idx] = '\000';
|
||||
state->output_buffer_idx ++;
|
||||
state->output_buffer_idx++;
|
||||
|
||||
// transcribe the sha over.
|
||||
hexlify(child->checksum, SHA1_BYTES,
|
||||
@ -551,11 +554,11 @@ static convert_to_flat_code_t convert_to_flat_iterator(
|
||||
|
||||
if (child->flags != '\000') {
|
||||
state->output_buffer[state->output_buffer_idx] = child->flags;
|
||||
state->output_buffer_idx ++;
|
||||
state->output_buffer_idx++;
|
||||
}
|
||||
|
||||
state->output_buffer[state->output_buffer_idx] = '\n';
|
||||
state->output_buffer_idx ++;
|
||||
state->output_buffer_idx++;
|
||||
|
||||
assert(state->output_buffer_idx < state->output_buffer_sz);
|
||||
} else {
|
||||
@ -580,7 +583,7 @@ static convert_to_flat_code_t convert_to_flat_iterator(
|
||||
state->dirpath_build_buffer_idx += child->name_sz;
|
||||
|
||||
state->dirpath_build_buffer[state->dirpath_build_buffer_idx] = '/';
|
||||
state->dirpath_build_buffer_idx ++;
|
||||
state->dirpath_build_buffer_idx++;
|
||||
|
||||
convert_to_flat_iterator(state, child);
|
||||
|
||||
@ -592,21 +595,21 @@ static convert_to_flat_code_t convert_to_flat_iterator(
|
||||
}
|
||||
|
||||
static convert_to_flat_code_t convert_to_flat_helper(
|
||||
to_flat_state_t* state,
|
||||
const tree_t* tree) {
|
||||
to_flat_state_t *state,
|
||||
const tree_t *tree) {
|
||||
// get the real root.
|
||||
node_t* shadow_root = tree->shadow_root;
|
||||
node_t *shadow_root = tree->shadow_root;
|
||||
if (shadow_root->num_children != 1) {
|
||||
return CONVERT_TO_FLAT_WTF;
|
||||
}
|
||||
|
||||
node_t* real_root = get_child_by_index(shadow_root, 0);
|
||||
node_t *real_root = get_child_by_index(shadow_root, 0);
|
||||
|
||||
return convert_to_flat_iterator(state, real_root);
|
||||
}
|
||||
|
||||
convert_from_flat_result_t convert_from_flat(
|
||||
char* manifest, size_t manifest_sz) {
|
||||
char *manifest, size_t manifest_sz) {
|
||||
from_flat_state_t *state = init_from_state(manifest_sz);
|
||||
|
||||
if (state->tree == NULL) {
|
||||
@ -615,7 +618,7 @@ convert_from_flat_result_t convert_from_flat(
|
||||
}
|
||||
if (state == NULL) {
|
||||
return (convert_from_flat_result_t) {
|
||||
CONVERT_FROM_FLAT_OOM, NULL };
|
||||
CONVERT_FROM_FLAT_OOM, NULL};
|
||||
}
|
||||
|
||||
convert_from_flat_result_t result =
|
||||
@ -629,7 +632,7 @@ convert_from_flat_result_t convert_from_flat(
|
||||
return result;
|
||||
}
|
||||
|
||||
convert_to_flat_result_t convert_to_flat(tree_t* tree) {
|
||||
convert_to_flat_result_t convert_to_flat(tree_t *tree) {
|
||||
to_flat_state_t state;
|
||||
state.dirpath_build_buffer = malloc(DEFAULT_BUILD_BUFFER_SZ);
|
||||
state.dirpath_build_buffer_idx = 0;
|
||||
@ -655,10 +658,10 @@ convert_to_flat_result_t convert_to_flat(tree_t* tree) {
|
||||
result != CONVERT_TO_FLAT_OK) {
|
||||
// free the buffer if any error occurred.
|
||||
free(state.output_buffer);
|
||||
return (convert_to_flat_result_t) { result, NULL, 0 };
|
||||
return (convert_to_flat_result_t) {result, NULL, 0};
|
||||
} else {
|
||||
return (convert_to_flat_result_t) {
|
||||
CONVERT_TO_FLAT_OK, state.output_buffer, state.output_buffer_idx };
|
||||
CONVERT_TO_FLAT_OK, state.output_buffer, state.output_buffer_idx};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include "tree.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "Usage: %s <manifestfile> <outputfile>\n", argv[0]);
|
||||
exit(1);
|
||||
@ -79,9 +79,9 @@ int main(int argc, char* argv[]) {
|
||||
uint64_t usecs_after_from = after_from.tv_sec * 1000000 +
|
||||
after_from.tv_usec;
|
||||
uint64_t usecs_before_to = before_to.tv_sec * 1000000 +
|
||||
before_to.tv_usec;
|
||||
before_to.tv_usec;
|
||||
uint64_t usecs_after_to = after_to.tv_sec * 1000000 +
|
||||
after_to.tv_usec;
|
||||
after_to.tv_usec;
|
||||
|
||||
printf("flat -> tree: %lld us\n", (usecs_after_from - usecs_before_from));
|
||||
printf("tree -> flat: %lld us\n", (usecs_after_to - usecs_before_to));
|
||||
|
@ -23,12 +23,12 @@ void test_simple_convert() {
|
||||
|
||||
ASSERT(convert_result.code == CONVERT_FROM_FLAT_OK);
|
||||
|
||||
tree_t* tree = convert_result.tree;
|
||||
tree_t *tree = convert_result.tree;
|
||||
ASSERT(tree->compacted == true);
|
||||
ASSERT(tree->num_leaf_nodes == 3);
|
||||
|
||||
get_path_result_t get_result;
|
||||
node_t* node;
|
||||
node_t *node;
|
||||
|
||||
get_result = get_path(tree, STRPLUSLEN("abc"));
|
||||
ASSERT(get_result.code == GET_PATH_OK);
|
||||
@ -37,7 +37,7 @@ void test_simple_convert() {
|
||||
ASSERT(node->checksum_sz == SHA1_BYTES);
|
||||
ASSERT(memcmp(node->checksum,
|
||||
"\xb8\x0d\xe5\xd1\x38\x75\x85\x41\xc5\xf0\x52\x65\xad\x14\x4a\xb9\xfa"
|
||||
"\x86\xd1"
|
||||
"\x86\xd1"
|
||||
"\xdb", SHA1_BYTES) == 0);
|
||||
ASSERT(node->flags == 0);
|
||||
|
||||
@ -124,7 +124,7 @@ void test_convert_bidirectionally() {
|
||||
memcmp(input, to_result.flat_manifest, to_result.flat_manifest_sz) == 0);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int main(int argc, char *argv[]) {
|
||||
test_simple_convert();
|
||||
test_convert_tree();
|
||||
test_convert_bidirectionally();
|
||||
|
@ -23,9 +23,9 @@ typedef enum {
|
||||
* `child_num` must be <= `dst_parent->num_children`.
|
||||
*/
|
||||
copy_helper_result_t copy_helper(
|
||||
tree_t* dst_tree,
|
||||
const node_t* src,
|
||||
node_t* dst_parent,
|
||||
tree_t *dst_tree,
|
||||
const node_t *src,
|
||||
node_t *dst_parent,
|
||||
size_t child_num) {
|
||||
arena_alloc_node_result_t alloc_result = arena_alloc_node_strict(
|
||||
dst_tree, src->name, src->name_sz, src->num_children);
|
||||
@ -39,7 +39,7 @@ copy_helper_result_t copy_helper(
|
||||
}
|
||||
|
||||
// copy the attributes
|
||||
node_t* dst = alloc_result.node;
|
||||
node_t *dst = alloc_result.node;
|
||||
if (src->checksum_valid) {
|
||||
memcpy(dst->checksum, src->checksum, src->checksum_sz);
|
||||
dst->checksum_sz = src->checksum_sz;
|
||||
@ -53,9 +53,9 @@ copy_helper_result_t copy_helper(
|
||||
dst->num_children = src->num_children;
|
||||
|
||||
if (dst->type == TYPE_LEAF) {
|
||||
dst_tree->num_leaf_nodes ++;
|
||||
dst_tree->num_leaf_nodes++;
|
||||
} else {
|
||||
for (int ix = 0; ix < src->num_children; ix ++) {
|
||||
for (int ix = 0; ix < src->num_children; ix++) {
|
||||
copy_helper_result_t copy_result =
|
||||
copy_helper(
|
||||
dst_tree,
|
||||
@ -74,8 +74,8 @@ copy_helper_result_t copy_helper(
|
||||
return COPY_OK;
|
||||
}
|
||||
|
||||
tree_t* copy(const tree_t* src) {
|
||||
tree_t* dst = alloc_tree_with_arena(src->consumed_memory);
|
||||
tree_t *copy(const tree_t *src) {
|
||||
tree_t *dst = alloc_tree_with_arena(src->consumed_memory);
|
||||
|
||||
// prerequisite for using copy_helper is that child_num must be <
|
||||
// dst_parent->num_children, so we artificially bump up the num_chlidren
|
||||
|
@ -9,8 +9,8 @@
|
||||
#include "tree.h"
|
||||
|
||||
void test_copy_empty() {
|
||||
tree_t* src = alloc_tree();
|
||||
tree_t* dst = copy(src);
|
||||
tree_t *src = alloc_tree();
|
||||
tree_t *dst = copy(src);
|
||||
|
||||
ASSERT(dst != NULL);
|
||||
ASSERT(dst->compacted == true);
|
||||
@ -22,19 +22,19 @@ void test_copy_empty() {
|
||||
}
|
||||
|
||||
void test_copy_empty_chain() {
|
||||
tree_t* original = alloc_tree();
|
||||
tree_t *original = alloc_tree();
|
||||
|
||||
tree_t* src = original;
|
||||
tree_t *src = original;
|
||||
|
||||
for (int ix = 0; ix < 10; ix ++) {
|
||||
tree_t* dst = copy(src);
|
||||
for (int ix = 0; ix < 10; ix++) {
|
||||
tree_t *dst = copy(src);
|
||||
|
||||
ASSERT(dst != NULL);
|
||||
ASSERT(dst->compacted == true);
|
||||
ASSERT(dst->num_leaf_nodes == 0);
|
||||
ASSERT(dst->consumed_memory == src->consumed_memory);
|
||||
|
||||
tree_t* old_src = src;
|
||||
tree_t *old_src = src;
|
||||
src = dst;
|
||||
|
||||
destroy_tree(old_src);
|
||||
@ -42,9 +42,9 @@ void test_copy_empty_chain() {
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char* path;
|
||||
char *path;
|
||||
size_t path_sz;
|
||||
uint8_t* checksum;
|
||||
uint8_t *checksum;
|
||||
uint8_t flags;
|
||||
} copy_normal_tree_data_t;
|
||||
#define COPY_NORMAL_TREE_DATA(path, checksum, flags) \
|
||||
@ -55,6 +55,7 @@ typedef struct {
|
||||
(uint8_t*) checksum, \
|
||||
flags, \
|
||||
}
|
||||
|
||||
void test_copy_normal_tree() {
|
||||
copy_normal_tree_data_t input[] = {
|
||||
COPY_NORMAL_TREE_DATA("abc",
|
||||
@ -74,10 +75,10 @@ void test_copy_normal_tree() {
|
||||
"\x5b\xf4\xba\x7c",
|
||||
0x44),
|
||||
};
|
||||
size_t input_sz = sizeof(input) / sizeof(copy_normal_tree_data_t) ;
|
||||
tree_t* src = alloc_tree();
|
||||
size_t input_sz = sizeof(input) / sizeof(copy_normal_tree_data_t);
|
||||
tree_t *src = alloc_tree();
|
||||
|
||||
for (size_t ix = 0; ix < input_sz; ix ++) {
|
||||
for (size_t ix = 0; ix < input_sz; ix++) {
|
||||
add_update_path_result_t result =
|
||||
add_or_update_path(
|
||||
src,
|
||||
@ -90,9 +91,9 @@ void test_copy_normal_tree() {
|
||||
ASSERT(src->compacted == false);
|
||||
ASSERT(src->num_leaf_nodes == input_sz);
|
||||
|
||||
tree_t* dst = copy(src);
|
||||
tree_t *dst = copy(src);
|
||||
|
||||
for (size_t ix = 0; ix < input_sz; ix ++) {
|
||||
for (size_t ix = 0; ix < input_sz; ix++) {
|
||||
get_path_result_t get_result =
|
||||
get_path(dst, input[ix].path, input[ix].path_sz);
|
||||
|
||||
@ -105,7 +106,7 @@ void test_copy_normal_tree() {
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int main(int argc, char *argv[]) {
|
||||
test_copy_empty();
|
||||
test_copy_empty_chain();
|
||||
test_copy_normal_tree();
|
||||
|
@ -13,13 +13,13 @@
|
||||
* correctly.
|
||||
*/
|
||||
void tree_init_test() {
|
||||
tree_t* tree = alloc_tree();
|
||||
node_t* shadow_root = tree->shadow_root;
|
||||
tree_t *tree = alloc_tree();
|
||||
node_t *shadow_root = tree->shadow_root;
|
||||
|
||||
ASSERT(shadow_root != NULL);
|
||||
ASSERT(shadow_root->num_children == 1);
|
||||
|
||||
node_t* real_root = get_child_by_index(shadow_root, 0);
|
||||
node_t *real_root = get_child_by_index(shadow_root, 0);
|
||||
ASSERT(real_root != NULL);
|
||||
ASSERT(real_root->num_children == 0);
|
||||
|
||||
@ -30,10 +30,10 @@ void tree_init_test() {
|
||||
* Initializes a tree and adds a node.
|
||||
*/
|
||||
void tree_add_child() {
|
||||
tree_t* tree = alloc_tree();
|
||||
tree_t *tree = alloc_tree();
|
||||
uint8_t checksum[SHA1_BYTES];
|
||||
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix ++) {
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix++) {
|
||||
checksum[ix] = (uint8_t) ix;
|
||||
}
|
||||
|
||||
@ -49,40 +49,40 @@ void tree_add_child() {
|
||||
* Initializes a tree and adds a file and a directory containing a file.
|
||||
*/
|
||||
void tree_add_0_cousin_once_removed() {
|
||||
tree_t* tree = alloc_tree();
|
||||
tree_t *tree = alloc_tree();
|
||||
uint8_t checksum[SHA1_BYTES];
|
||||
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix ++) {
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix++) {
|
||||
checksum[ix] = (uint8_t) ix;
|
||||
}
|
||||
|
||||
add_update_path_result_t result;
|
||||
|
||||
result = add_or_update_path(tree, STRPLUSLEN("ab"),
|
||||
checksum, SHA1_BYTES, 0);
|
||||
checksum, SHA1_BYTES, 0);
|
||||
ASSERT(result == ADD_UPDATE_PATH_OK);
|
||||
|
||||
result = add_or_update_path(tree, STRPLUSLEN("abc/de"),
|
||||
checksum, SHA1_BYTES, 0);
|
||||
checksum, SHA1_BYTES, 0);
|
||||
ASSERT(result == ADD_UPDATE_PATH_OK);
|
||||
|
||||
// verify the shadow root.
|
||||
ASSERT(tree->shadow_root->num_children == 1);
|
||||
|
||||
// obtain the true root, verify that.
|
||||
node_t* real_root = get_child_by_index(tree->shadow_root, 0);
|
||||
node_t *real_root = get_child_by_index(tree->shadow_root, 0);
|
||||
|
||||
// verify the real root.
|
||||
ASSERT(real_root->num_children == 2);
|
||||
|
||||
// first child should be 'ab'
|
||||
node_t* root_first_child = get_child_by_index(real_root, 0);
|
||||
node_t *root_first_child = get_child_by_index(real_root, 0);
|
||||
ASSERT(root_first_child->num_children == 0);
|
||||
ASSERT(root_first_child->type == TYPE_LEAF);
|
||||
ASSERT(name_compare("ab", 2, root_first_child) == 0);
|
||||
|
||||
// second child should be 'abc'
|
||||
node_t* root_second_child = get_child_by_index(real_root, 1);
|
||||
node_t *root_second_child = get_child_by_index(real_root, 1);
|
||||
ASSERT(root_second_child->num_children == 1);
|
||||
ASSERT(root_second_child->type == TYPE_IMPLICIT);
|
||||
ASSERT(name_compare("abc", 3, root_second_child) == 0);
|
||||
@ -92,29 +92,29 @@ void tree_add_0_cousin_once_removed() {
|
||||
* Initializes a tree and adds a long skinny branch.
|
||||
*/
|
||||
void tree_add_long_skinny_branch() {
|
||||
tree_t* tree = alloc_tree();
|
||||
tree_t *tree = alloc_tree();
|
||||
uint8_t checksum[SHA1_BYTES];
|
||||
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix ++) {
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix++) {
|
||||
checksum[ix] = (uint8_t) ix;
|
||||
}
|
||||
|
||||
add_update_path_result_t result;
|
||||
|
||||
result = add_or_update_path(tree, STRPLUSLEN("ab"),
|
||||
checksum, SHA1_BYTES, 0);
|
||||
checksum, SHA1_BYTES, 0);
|
||||
ASSERT(result == ADD_UPDATE_PATH_OK);
|
||||
|
||||
result = add_or_update_path(tree, STRPLUSLEN("abc/de"),
|
||||
checksum, SHA1_BYTES, 0);
|
||||
checksum, SHA1_BYTES, 0);
|
||||
ASSERT(result == ADD_UPDATE_PATH_OK);
|
||||
|
||||
result = add_or_update_path(tree, STRPLUSLEN("abc/def/gh"),
|
||||
checksum, SHA1_BYTES, 0);
|
||||
checksum, SHA1_BYTES, 0);
|
||||
ASSERT(result == ADD_UPDATE_PATH_OK);
|
||||
|
||||
result = add_or_update_path(tree, STRPLUSLEN("abc/def/ghi/jkl"),
|
||||
checksum, SHA1_BYTES, 0);
|
||||
checksum, SHA1_BYTES, 0);
|
||||
ASSERT(result == ADD_UPDATE_PATH_OK);
|
||||
|
||||
ASSERT(tree->compacted == false);
|
||||
@ -125,22 +125,22 @@ void tree_add_long_skinny_branch() {
|
||||
* Initializes a tree and adds a bushy branch.
|
||||
*/
|
||||
void tree_add_bushy_branch() {
|
||||
tree_t* tree = alloc_tree();
|
||||
tree_t *tree = alloc_tree();
|
||||
uint8_t checksum[SHA1_BYTES];
|
||||
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix ++) {
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix++) {
|
||||
checksum[ix] = (uint8_t) ix;
|
||||
}
|
||||
|
||||
add_update_path_result_t result;
|
||||
|
||||
result = add_or_update_path(tree, STRPLUSLEN("ab"),
|
||||
checksum, SHA1_BYTES, 0);
|
||||
checksum, SHA1_BYTES, 0);
|
||||
ASSERT(result == ADD_UPDATE_PATH_OK);
|
||||
|
||||
char tempbuffer[] = "abc/de?";
|
||||
|
||||
for (int ix = 0; ix < 26; ix ++) {
|
||||
for (int ix = 0; ix < 26; ix++) {
|
||||
tempbuffer[6] = 'a' + ix;
|
||||
result = add_or_update_path(tree, STRPLUSLEN(tempbuffer),
|
||||
checksum, SHA1_BYTES, 0);
|
||||
@ -156,10 +156,10 @@ void tree_add_bushy_branch() {
|
||||
* would require a directory be created where N0 is.
|
||||
*/
|
||||
void tree_add_conflict() {
|
||||
tree_t* tree = alloc_tree();
|
||||
tree_t *tree = alloc_tree();
|
||||
uint8_t checksum[SHA1_BYTES];
|
||||
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix ++) {
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix++) {
|
||||
checksum[ix] = (uint8_t) ix;
|
||||
}
|
||||
|
||||
@ -181,7 +181,7 @@ void tree_add_conflict() {
|
||||
* Initializes a tree and attempt to retrieve a couple paths that are not there.
|
||||
*/
|
||||
void tree_get_empty() {
|
||||
tree_t* tree = alloc_tree();
|
||||
tree_t *tree = alloc_tree();
|
||||
|
||||
get_path_result_t result = get_path(tree, STRPLUSLEN("abc"));
|
||||
ASSERT(result.code == GET_PATH_NOT_FOUND);
|
||||
@ -194,18 +194,19 @@ void tree_get_empty() {
|
||||
* Initializes a tree, adds a single path, and attempt to retrieve it.
|
||||
*/
|
||||
#define ADD_GET_SIMPLE_FLAGS 0x2e
|
||||
|
||||
void tree_add_get_simple() {
|
||||
tree_t* tree = alloc_tree();
|
||||
tree_t *tree = alloc_tree();
|
||||
|
||||
uint8_t checksum[SHA1_BYTES];
|
||||
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix ++) {
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix++) {
|
||||
checksum[ix] = (uint8_t) ix;
|
||||
}
|
||||
|
||||
add_update_path_result_t add_result =
|
||||
add_or_update_path(tree, STRPLUSLEN("abc"),
|
||||
checksum, SHA1_BYTES, ADD_GET_SIMPLE_FLAGS);
|
||||
checksum, SHA1_BYTES, ADD_GET_SIMPLE_FLAGS);
|
||||
ASSERT(add_result == ADD_UPDATE_PATH_OK);
|
||||
ASSERT(tree->compacted == false);
|
||||
ASSERT(tree->num_leaf_nodes == 1);
|
||||
@ -227,7 +228,7 @@ void tree_add_get_simple() {
|
||||
* Removes a non-existent path.
|
||||
*/
|
||||
void tree_remove_nonexistent() {
|
||||
tree_t* tree = alloc_tree();
|
||||
tree_t *tree = alloc_tree();
|
||||
|
||||
remove_path_result_t remove_result = remove_path(tree, STRPLUSLEN("abc"));
|
||||
ASSERT(remove_result == REMOVE_PATH_NOT_FOUND);
|
||||
@ -238,11 +239,11 @@ void tree_remove_nonexistent() {
|
||||
* removed.
|
||||
*/
|
||||
void tree_add_remove() {
|
||||
tree_t* tree = alloc_tree();
|
||||
tree_t *tree = alloc_tree();
|
||||
|
||||
uint8_t checksum[SHA1_BYTES];
|
||||
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix ++) {
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix++) {
|
||||
checksum[ix] = (uint8_t) ix;
|
||||
}
|
||||
|
||||
@ -262,10 +263,10 @@ void tree_add_remove() {
|
||||
get_path_result_t get_result = get_path(tree, STRPLUSLEN("abc"));
|
||||
ASSERT(get_result.code == GET_PATH_NOT_FOUND);
|
||||
|
||||
node_t* shadow_root = tree->shadow_root;
|
||||
node_t *shadow_root = tree->shadow_root;
|
||||
ASSERT(shadow_root->num_children == 1);
|
||||
|
||||
node_t* real_root = get_child_by_index(shadow_root, 0);
|
||||
node_t *real_root = get_child_by_index(shadow_root, 0);
|
||||
ASSERT(real_root->num_children == 0);
|
||||
|
||||
// because the directory nodes may have undergone expansion, we may not
|
||||
@ -277,28 +278,28 @@ void tree_add_remove() {
|
||||
* Adds a multiple paths and then remove them.
|
||||
*/
|
||||
void tree_add_remove_multi() {
|
||||
tree_t* tree = alloc_tree();
|
||||
tree_t *tree = alloc_tree();
|
||||
|
||||
uint8_t checksum[SHA1_BYTES];
|
||||
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix ++) {
|
||||
for (int ix = 0; ix < SHA1_BYTES; ix++) {
|
||||
checksum[ix] = (uint8_t) ix;
|
||||
}
|
||||
|
||||
char* paths_to_add[] = {
|
||||
"abc",
|
||||
"ab/def",
|
||||
"ab/defg/hi",
|
||||
"ab/defg/h/ijk",
|
||||
"ab/defg/h/i/jkl/mn/op/qr",
|
||||
"ab/defg/h/i/jkl/mn/op/qrs",
|
||||
char *paths_to_add[] = {
|
||||
"abc",
|
||||
"ab/def",
|
||||
"ab/defg/hi",
|
||||
"ab/defg/h/ijk",
|
||||
"ab/defg/h/i/jkl/mn/op/qr",
|
||||
"ab/defg/h/i/jkl/mn/op/qrs",
|
||||
};
|
||||
|
||||
const size_t num_paths = sizeof(paths_to_add) / sizeof(*paths_to_add);
|
||||
|
||||
for (size_t ix = 0;
|
||||
ix < num_paths;
|
||||
ix ++) {
|
||||
ix < num_paths;
|
||||
ix++) {
|
||||
add_update_path_result_t add_result =
|
||||
add_or_update_path(tree, STRPLUSLEN(paths_to_add[ix]),
|
||||
checksum, SHA1_BYTES, 0);
|
||||
@ -307,22 +308,22 @@ void tree_add_remove_multi() {
|
||||
|
||||
for (size_t ix = 0;
|
||||
ix < num_paths;
|
||||
ix ++) {
|
||||
ix++) {
|
||||
remove_path_result_t remove_result =
|
||||
remove_path(tree, STRPLUSLEN(paths_to_add[num_paths - ix - 1]));
|
||||
ASSERT(remove_result == REMOVE_CHILD_OK);
|
||||
|
||||
for (size_t jx = 0; jx < num_paths - ix - 1; jx ++) {
|
||||
for (size_t jx = 0; jx < num_paths - ix - 1; jx++) {
|
||||
get_path_result_t get_result =
|
||||
get_path(tree, STRPLUSLEN(paths_to_add[jx]));
|
||||
ASSERT(get_result.code == GET_PATH_OK);
|
||||
}
|
||||
}
|
||||
|
||||
node_t* shadow_root = tree->shadow_root;
|
||||
node_t *shadow_root = tree->shadow_root;
|
||||
ASSERT(shadow_root->num_children == 1);
|
||||
|
||||
node_t* real_root = get_child_by_index(shadow_root, 0);
|
||||
node_t *real_root = get_child_by_index(shadow_root, 0);
|
||||
ASSERT(real_root->num_children == 0);
|
||||
|
||||
ASSERT(tree->num_leaf_nodes == 0);
|
||||
@ -333,7 +334,7 @@ void tree_add_remove_multi() {
|
||||
ASSERT(tree->consumed_memory == shadow_root->block_sz + real_root->block_sz);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int main(int argc, char *argv[]) {
|
||||
tree_init_test();
|
||||
|
||||
tree_add_child();
|
||||
|
Loading…
Reference in New Issue
Block a user