Make vector struct type-safe
This commit is contained in:
parent
3f08bfb264
commit
6fa7eca966
6 changed files with 223 additions and 246 deletions
|
|
@ -37,13 +37,13 @@ int tree_selection_spy_callback(void *data, TSTree *left, TSTree *right) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
void free_pop_results(Vector *pop_results) {
|
||||
void free_pop_results(StackPopResultVector *pop_results) {
|
||||
for (size_t i = 0; i < pop_results->size; i++) {
|
||||
StackPopResult *pop_result = (StackPopResult *)vector_get(pop_results, i);
|
||||
StackPopResult *pop_result = &pop_results->contents[i];
|
||||
|
||||
bool matches_prior_trees = false;
|
||||
for (size_t j = 0; j < i; j++) {
|
||||
StackPopResult *prior_result = (StackPopResult *)vector_get(pop_results, j);
|
||||
StackPopResult *prior_result = &pop_results->contents[j];
|
||||
if (pop_result->trees == prior_result->trees) {
|
||||
matches_prior_trees = true;
|
||||
break;
|
||||
|
|
@ -141,10 +141,10 @@ describe("Stack", [&]() {
|
|||
/*
|
||||
* A0.
|
||||
*/
|
||||
Vector results = ts_stack_pop(stack, 0, 2, false);
|
||||
StackPopResultVector results = ts_stack_pop(stack, 0, 2, false);
|
||||
AssertThat(results.size, Equals<size_t>(1));
|
||||
|
||||
StackPopResult result = *(StackPopResult *)vector_get(&results, 0);
|
||||
StackPopResult result = *vector_get(&results, 0);
|
||||
AssertThat(result.tree_count, Equals<size_t>(2));
|
||||
AssertThat(result.trees[0], Equals(trees[1]));
|
||||
AssertThat(result.trees[1], Equals(trees[2]));
|
||||
|
|
@ -168,10 +168,10 @@ describe("Stack", [&]() {
|
|||
it("does not count 'extra' trees toward the count", [&]() {
|
||||
trees[1]->extra = true;
|
||||
|
||||
Vector results = ts_stack_pop(stack, 0, 2, false);
|
||||
StackPopResultVector results = ts_stack_pop(stack, 0, 2, false);
|
||||
AssertThat(results.size, Equals<size_t>(1));
|
||||
|
||||
StackPopResult result = *(StackPopResult *)vector_get(&results, 0);
|
||||
StackPopResult result = *vector_get(&results, 0);
|
||||
AssertThat(result.tree_count, Equals<size_t>(3));
|
||||
AssertThat(result.trees[0], Equals(trees[0]));
|
||||
AssertThat(result.trees[1], Equals(trees[1]));
|
||||
|
|
@ -182,10 +182,10 @@ describe("Stack", [&]() {
|
|||
});
|
||||
|
||||
it("pops the entire stack when given a negative count", [&]() {
|
||||
Vector results = ts_stack_pop(stack, 0, -1, false);
|
||||
StackPopResultVector results = ts_stack_pop(stack, 0, -1, false);
|
||||
AssertThat(results.size, Equals<size_t>(1));
|
||||
|
||||
StackPopResult result = *(StackPopResult *)vector_get(&results, 0);
|
||||
StackPopResult result = *vector_get(&results, 0);
|
||||
AssertThat(result.tree_count, Equals<size_t>(3));
|
||||
AssertThat(result.trees[0], Equals(trees[0]));
|
||||
AssertThat(result.trees[1], Equals(trees[1]));
|
||||
|
|
@ -213,7 +213,7 @@ describe("Stack", [&]() {
|
|||
* \.
|
||||
*/
|
||||
ts_stack_push(stack, 0, stateD, trees[3]);
|
||||
Vector pop_results = ts_stack_pop(stack, 1, 1, false);
|
||||
StackPopResultVector pop_results = ts_stack_pop(stack, 1, 1, false);
|
||||
|
||||
AssertThat(ts_stack_head_count(stack), Equals(2));
|
||||
AssertThat(*ts_stack_head(stack, 0), Equals<StackEntry>({trees[3], stateD, tree_len * 4}));
|
||||
|
|
@ -381,16 +381,16 @@ describe("Stack", [&]() {
|
|||
* A0__B1__C2.
|
||||
* \__E4.
|
||||
*/
|
||||
Vector pop = ts_stack_pop(stack, 0, 2, false);
|
||||
StackPopResultVector results = ts_stack_pop(stack, 0, 2, false);
|
||||
|
||||
AssertThat(pop.size, Equals<size_t>(2));
|
||||
StackPopResult pop1 = *(StackPopResult *)vector_get(&pop, 0);
|
||||
AssertThat(results.size, Equals<size_t>(2));
|
||||
StackPopResult pop1 = *(StackPopResult *)vector_get(&results, 0);
|
||||
AssertThat(pop1.head_index, Equals(0));
|
||||
AssertThat(pop1.tree_count, Equals<size_t>(2));
|
||||
AssertThat(pop1.trees[0], Equals(trees[3]));
|
||||
AssertThat(pop1.trees[1], Equals(trees[6]));
|
||||
|
||||
StackPopResult pop2 = *(StackPopResult *)vector_get(&pop, 1);
|
||||
StackPopResult pop2 = *(StackPopResult *)vector_get(&results, 1);
|
||||
AssertThat(pop2.head_index, Equals(1));
|
||||
AssertThat(pop2.tree_count, Equals<size_t>(2));
|
||||
AssertThat(pop2.trees[0], Equals(trees[5]));
|
||||
|
|
@ -400,7 +400,7 @@ describe("Stack", [&]() {
|
|||
AssertThat(*ts_stack_head(stack, 0), Equals<StackEntry>({trees[2], stateC, tree_len * 3}));
|
||||
AssertThat(*ts_stack_head(stack, 1), Equals<StackEntry>({trees[4], stateE, tree_len * 3}));
|
||||
|
||||
free_pop_results(&pop);
|
||||
free_pop_results(&results);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -417,12 +417,12 @@ describe("Stack", [&]() {
|
|||
* A0__B1__C2__D3__G6.
|
||||
* \__E4__F5__/
|
||||
*/
|
||||
Vector pop = ts_stack_pop(stack, 0, 1, false);
|
||||
StackPopResultVector results = ts_stack_pop(stack, 0, 1, false);
|
||||
|
||||
AssertThat(pop.size, Equals<size_t>(1));
|
||||
AssertThat(results.size, Equals<size_t>(1));
|
||||
AssertThat(ts_stack_head_count(stack), Equals(1));
|
||||
|
||||
free_pop_results(&pop);
|
||||
free_pop_results(&results);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -439,23 +439,23 @@ describe("Stack", [&]() {
|
|||
* A0__B1__C2__D3.
|
||||
* \__E4__F5.
|
||||
*/
|
||||
Vector pop = ts_stack_pop(stack, 0, 2, false);
|
||||
StackPopResultVector results = ts_stack_pop(stack, 0, 2, false);
|
||||
AssertThat(ts_stack_head_count(stack), Equals(2));
|
||||
|
||||
AssertThat(pop.size, Equals<size_t>(2));
|
||||
StackPopResult pop1 = *(StackPopResult *)vector_get(&pop, 0);
|
||||
AssertThat(results.size, Equals<size_t>(2));
|
||||
StackPopResult pop1 = *(StackPopResult *)vector_get(&results, 0);
|
||||
AssertThat(pop1.head_index, Equals(0));
|
||||
AssertThat(pop1.tree_count, Equals<size_t>(2));
|
||||
AssertThat(pop1.trees[0], Equals(trees[6]));
|
||||
AssertThat(pop1.trees[1], Equals(trees[7]));
|
||||
|
||||
StackPopResult pop2 = *(StackPopResult *)vector_get(&pop, 1);
|
||||
StackPopResult pop2 = *(StackPopResult *)vector_get(&results, 1);
|
||||
AssertThat(pop2.head_index, Equals(1));
|
||||
AssertThat(pop2.tree_count, Equals<size_t>(2));
|
||||
AssertThat(pop2.trees[0], Equals(trees[6]));
|
||||
AssertThat(pop2.trees[1], Equals(trees[7]));
|
||||
|
||||
free_pop_results(&pop);
|
||||
free_pop_results(&results);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -467,17 +467,17 @@ describe("Stack", [&]() {
|
|||
/*
|
||||
* A0__B1.
|
||||
*/
|
||||
Vector pop = ts_stack_pop(stack, 0, 3, false);
|
||||
StackPopResultVector results = ts_stack_pop(stack, 0, 3, false);
|
||||
AssertThat(ts_stack_head_count(stack), Equals(1));
|
||||
AssertThat(*ts_stack_head(stack, 0), Equals<StackEntry>({trees[1], stateB, tree_len * 2}));
|
||||
|
||||
AssertThat(pop.size, Equals<size_t>(1));
|
||||
StackPopResult pop1 = *(StackPopResult *)vector_get(&pop, 0);
|
||||
AssertThat(results.size, Equals<size_t>(1));
|
||||
StackPopResult pop1 = *(StackPopResult *)vector_get(&results, 0);
|
||||
AssertThat(pop1.tree_count, Equals<size_t>(3));
|
||||
AssertThat(pop1.head_index, Equals(0));
|
||||
AssertThat(pop1.trees[0], Equals(trees[2]));
|
||||
|
||||
free_pop_results(&pop);
|
||||
free_pop_results(&results);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -488,17 +488,17 @@ describe("Stack", [&]() {
|
|||
/*
|
||||
* A0__B1.
|
||||
*/
|
||||
Vector pop = ts_stack_pop(stack, 0, 3, false);
|
||||
StackPopResultVector results = ts_stack_pop(stack, 0, 3, false);
|
||||
AssertThat(ts_stack_head_count(stack), Equals(1));
|
||||
AssertThat(*ts_stack_head(stack, 0), Equals<StackEntry>({trees[1], stateB, tree_len * 2}));
|
||||
|
||||
AssertThat(pop.size, Equals<size_t>(1));
|
||||
StackPopResult pop1 = *(StackPopResult *)vector_get(&pop, 0);
|
||||
AssertThat(results.size, Equals<size_t>(1));
|
||||
StackPopResult pop1 = *(StackPopResult *)vector_get(&results, 0);
|
||||
AssertThat(pop1.tree_count, Equals<size_t>(3));
|
||||
AssertThat(pop1.head_index, Equals(0));
|
||||
AssertThat(pop1.trees[0], Equals(trees[4]));
|
||||
|
||||
free_pop_results(&pop);
|
||||
free_pop_results(&results);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -540,31 +540,31 @@ describe("Stack", [&]() {
|
|||
* \__E4__F5.
|
||||
* \__G6__H7.
|
||||
*/
|
||||
Vector pop = ts_stack_pop(stack, 0, 2, false);
|
||||
StackPopResultVector results = ts_stack_pop(stack, 0, 2, false);
|
||||
AssertThat(ts_stack_head_count(stack), Equals(3));
|
||||
|
||||
AssertThat(pop.size, Equals<size_t>(3));
|
||||
AssertThat(results.size, Equals<size_t>(3));
|
||||
|
||||
StackPopResult pop1 = *(StackPopResult *)vector_get(&pop, 0);
|
||||
StackPopResult pop1 = *(StackPopResult *)vector_get(&results, 0);
|
||||
AssertThat(ts_stack_top_tree(stack, 0), Equals(trees[3]));
|
||||
AssertThat(pop1.head_index, Equals(0));
|
||||
AssertThat(pop1.tree_count, Equals<size_t>(2));
|
||||
AssertThat(pop1.trees[0], Equals(trees[8]));
|
||||
AssertThat(pop1.trees[1], Equals(trees[9]));
|
||||
|
||||
StackPopResult pop2 = *(StackPopResult *)vector_get(&pop, 1);
|
||||
StackPopResult pop2 = *(StackPopResult *)vector_get(&results, 1);
|
||||
AssertThat(ts_stack_top_tree(stack, 1), Equals(trees[5]));
|
||||
AssertThat(pop2.head_index, Equals(1));
|
||||
AssertThat(pop2.tree_count, Equals<size_t>(2));
|
||||
AssertThat(pop2.trees, Equals(pop1.trees));
|
||||
|
||||
StackPopResult pop3 = *(StackPopResult *)vector_get(&pop, 2);
|
||||
StackPopResult pop3 = *(StackPopResult *)vector_get(&results, 2);
|
||||
AssertThat(ts_stack_top_tree(stack, 2), Equals(trees[7]));
|
||||
AssertThat(pop3.head_index, Equals(2));
|
||||
AssertThat(pop3.tree_count, Equals<size_t>(2));
|
||||
AssertThat(pop3.trees, Equals(pop1.trees));
|
||||
|
||||
free_pop_results(&pop);
|
||||
free_pop_results(&results);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -575,12 +575,12 @@ describe("Stack", [&]() {
|
|||
* \__E4.
|
||||
* \__G6.
|
||||
*/
|
||||
Vector pop = ts_stack_pop(stack, 0, 3, false);
|
||||
StackPopResultVector results = ts_stack_pop(stack, 0, 3, false);
|
||||
AssertThat(ts_stack_head_count(stack), Equals(3));
|
||||
|
||||
AssertThat(pop.size, Equals<size_t>(3));
|
||||
AssertThat(results.size, Equals<size_t>(3));
|
||||
|
||||
StackPopResult pop1 = *(StackPopResult *)vector_get(&pop, 0);
|
||||
StackPopResult pop1 = *(StackPopResult *)vector_get(&results, 0);
|
||||
AssertThat(ts_stack_top_tree(stack, 0), Equals(trees[2]));
|
||||
AssertThat(pop1.head_index, Equals(0));
|
||||
AssertThat(pop1.tree_count, Equals<size_t>(3));
|
||||
|
|
@ -588,7 +588,7 @@ describe("Stack", [&]() {
|
|||
AssertThat(pop1.trees[1], Equals(trees[8]));
|
||||
AssertThat(pop1.trees[2], Equals(trees[9]));
|
||||
|
||||
StackPopResult pop2 = *(StackPopResult *)vector_get(&pop, 1);
|
||||
StackPopResult pop2 = *(StackPopResult *)vector_get(&results, 1);
|
||||
AssertThat(ts_stack_top_tree(stack, 1), Equals(trees[4]));
|
||||
AssertThat(pop2.head_index, Equals(1));
|
||||
AssertThat(pop2.tree_count, Equals<size_t>(3));
|
||||
|
|
@ -596,7 +596,7 @@ describe("Stack", [&]() {
|
|||
AssertThat(pop2.trees[1], Equals(trees[8]));
|
||||
AssertThat(pop2.trees[2], Equals(trees[9]));
|
||||
|
||||
StackPopResult pop3 = *(StackPopResult *)vector_get(&pop, 2);
|
||||
StackPopResult pop3 = *(StackPopResult *)vector_get(&results, 2);
|
||||
AssertThat(ts_stack_top_tree(stack, 2), Equals(trees[6]));
|
||||
AssertThat(pop3.head_index, Equals(2));
|
||||
AssertThat(pop3.tree_count, Equals<size_t>(3));
|
||||
|
|
@ -604,7 +604,7 @@ describe("Stack", [&]() {
|
|||
AssertThat(pop3.trees[1], Equals(trees[8]));
|
||||
AssertThat(pop3.trees[2], Equals(trees[9]));
|
||||
|
||||
free_pop_results(&pop);
|
||||
free_pop_results(&results);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@
|
|||
|
||||
#define BOOL_STRING(value) (value ? "true" : "false")
|
||||
|
||||
typedef struct {
|
||||
struct LookaheadState {
|
||||
TSTree *reusable_subtree;
|
||||
size_t reusable_subtree_pos;
|
||||
bool is_verifying;
|
||||
} LookaheadState;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
UpdatedStackHead,
|
||||
|
|
@ -47,8 +47,8 @@ static ParseActionResult ts_parser__breakdown_top_of_stack(TSParser *self,
|
|||
TSTree *last_child = NULL;
|
||||
|
||||
do {
|
||||
Vector pop_results = ts_stack_pop(self->stack, head, 1, false);
|
||||
if (!vector_valid(&pop_results))
|
||||
StackPopResultVector pop_results = ts_stack_pop(self->stack, head, 1, false);
|
||||
if (!pop_results.size)
|
||||
return FailedToUpdateStackHead;
|
||||
assert(pop_results.size > 0);
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ static ParseActionResult ts_parser__breakdown_top_of_stack(TSParser *self,
|
|||
ts_tree_total_size(parent).chars);
|
||||
|
||||
for (size_t i = 0; i < pop_results.size; i++) {
|
||||
StackPopResult *pop_result = vector_get(&pop_results, i);
|
||||
StackPopResult *pop_result = &pop_results.contents[i];
|
||||
assert(pop_result->trees == removed_trees);
|
||||
int head_index = pop_result->head_index;
|
||||
|
||||
|
|
@ -238,9 +238,8 @@ static TSTree *ts_parser__get_next_lookahead(TSParser *self, int head) {
|
|||
static int ts_parser__split(TSParser *self, int head) {
|
||||
int result = ts_stack_split(self->stack, head);
|
||||
assert(result == (int)self->lookahead_states.size);
|
||||
LookaheadState lookahead_state =
|
||||
*(LookaheadState *)vector_get(&self->lookahead_states, head);
|
||||
vector_push(&self->lookahead_states, &lookahead_state);
|
||||
LookaheadState lookahead_state = *vector_get(&self->lookahead_states, head);
|
||||
vector_push(&self->lookahead_states, lookahead_state);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -311,14 +310,15 @@ static ParseActionResult ts_parser__reduce(TSParser *self, int head,
|
|||
vector_clear(&self->reduce_parents);
|
||||
const TSSymbolMetadata *all_metadata = self->language->symbol_metadata;
|
||||
TSSymbolMetadata metadata = all_metadata[symbol];
|
||||
Vector pop_results = ts_stack_pop(self->stack, head, child_count, count_extra);
|
||||
if (!vector_valid(&pop_results))
|
||||
StackPopResultVector pop_results =
|
||||
ts_stack_pop(self->stack, head, child_count, count_extra);
|
||||
if (!pop_results.size)
|
||||
return FailedToUpdateStackHead;
|
||||
|
||||
size_t removed_heads = 0;
|
||||
|
||||
for (size_t i = 0; i < pop_results.size; i++) {
|
||||
StackPopResult *pop_result = vector_get(&pop_results, i);
|
||||
StackPopResult *pop_result = &pop_results.contents[i];
|
||||
|
||||
/*
|
||||
* If the same set of trees led to a previous stack head, reuse the parent
|
||||
|
|
@ -328,10 +328,9 @@ static ParseActionResult ts_parser__reduce(TSParser *self, int head,
|
|||
TSTree *parent = NULL;
|
||||
size_t trailing_extra_count = 0;
|
||||
for (size_t j = 0; j < i; j++) {
|
||||
StackPopResult *prior_result = vector_get(&pop_results, j);
|
||||
StackPopResult *prior_result = &pop_results.contents[j];
|
||||
if (pop_result->trees == prior_result->trees) {
|
||||
TSTree **existing_parent = vector_get(&self->reduce_parents, j);
|
||||
parent = *existing_parent;
|
||||
parent = self->reduce_parents.contents[j];
|
||||
trailing_extra_count = pop_result->tree_count - parent->child_count;
|
||||
ts_tree_retain(parent);
|
||||
for (size_t k = parent->child_count; k < pop_result->tree_count; k++)
|
||||
|
|
@ -359,7 +358,7 @@ static ParseActionResult ts_parser__reduce(TSParser *self, int head,
|
|||
}
|
||||
}
|
||||
|
||||
if (!vector_push(&self->reduce_parents, &parent))
|
||||
if (!vector_push(&self->reduce_parents, parent))
|
||||
goto error;
|
||||
|
||||
int new_head = pop_result->head_index - removed_heads;
|
||||
|
|
@ -372,13 +371,14 @@ static ParseActionResult ts_parser__reduce(TSParser *self, int head,
|
|||
}
|
||||
|
||||
/*
|
||||
* If the stack has split in the process of popping, create a duplicate of
|
||||
* If the stack has split in the process of popping, create a duplicate
|
||||
* of
|
||||
* the lookahead state for this head, for the new head.
|
||||
*/
|
||||
LOG("split_during_reduce new_head:%d", new_head);
|
||||
LookaheadState lookahead_state =
|
||||
*(LookaheadState *)vector_get(&self->lookahead_states, head);
|
||||
if (!vector_push(&self->lookahead_states, &lookahead_state))
|
||||
*vector_get(&self->lookahead_states, head);
|
||||
if (!vector_push(&self->lookahead_states, lookahead_state))
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
@ -565,18 +565,18 @@ static ParseActionResult ts_parser__start(TSParser *self, TSInput input,
|
|||
.is_verifying = false,
|
||||
};
|
||||
vector_clear(&self->lookahead_states);
|
||||
vector_push(&self->lookahead_states, &lookahead_state);
|
||||
vector_push(&self->lookahead_states, lookahead_state);
|
||||
self->finished_tree = NULL;
|
||||
return UpdatedStackHead;
|
||||
}
|
||||
|
||||
static ParseActionResult ts_parser__accept(TSParser *self, int head) {
|
||||
Vector pop_results = ts_stack_pop(self->stack, head, -1, true);
|
||||
StackPopResultVector pop_results = ts_stack_pop(self->stack, head, -1, true);
|
||||
if (!pop_results.size)
|
||||
goto error;
|
||||
|
||||
for (size_t j = 0; j < pop_results.size; j++) {
|
||||
StackPopResult *pop_result = vector_get(&pop_results, j);
|
||||
StackPopResult *pop_result = &pop_results.contents[j];
|
||||
|
||||
for (size_t i = 0; i < pop_result->tree_count; i++) {
|
||||
if (!pop_result->trees[i]->extra) {
|
||||
|
|
@ -622,7 +622,7 @@ static ParseActionResult ts_parser__accept(TSParser *self, int head) {
|
|||
|
||||
error:
|
||||
if (pop_results.size) {
|
||||
StackPopResult *pop_result = vector_get(&pop_results, 0);
|
||||
StackPopResult *pop_result = vector_front(&pop_results);
|
||||
for (size_t i = 0; i < pop_result->tree_count; i++)
|
||||
ts_tree_release(pop_result->trees[i]);
|
||||
ts_free(pop_result->trees);
|
||||
|
|
@ -745,8 +745,8 @@ bool ts_parser_init(TSParser *self) {
|
|||
ts_lexer_init(&self->lexer);
|
||||
self->finished_tree = NULL;
|
||||
self->stack = NULL;
|
||||
self->lookahead_states = vector_new(sizeof(LookaheadState));
|
||||
self->reduce_parents = vector_new(sizeof(TSTree *));
|
||||
vector_init(&self->lookahead_states);
|
||||
vector_init(&self->reduce_parents);
|
||||
|
||||
self->stack = ts_stack_new();
|
||||
if (!self->stack)
|
||||
|
|
|
|||
|
|
@ -8,12 +8,14 @@ extern "C" {
|
|||
#include "runtime/stack.h"
|
||||
#include "runtime/vector.h"
|
||||
|
||||
typedef struct LookaheadState LookaheadState;
|
||||
|
||||
typedef struct {
|
||||
TSLexer lexer;
|
||||
Stack *stack;
|
||||
const TSLanguage *language;
|
||||
Vector lookahead_states;
|
||||
Vector reduce_parents;
|
||||
Vector(LookaheadState) lookahead_states;
|
||||
Vector(TSTree *) reduce_parents;
|
||||
TSTree *finished_tree;
|
||||
bool is_split;
|
||||
} TSParser;
|
||||
|
|
|
|||
|
|
@ -19,23 +19,23 @@ typedef struct StackNode {
|
|||
short unsigned int ref_count;
|
||||
} StackNode;
|
||||
|
||||
struct Stack {
|
||||
Vector heads;
|
||||
Vector pop_results;
|
||||
Vector pop_paths;
|
||||
Vector node_pool;
|
||||
void *tree_selection_payload;
|
||||
TreeSelectionFunction tree_selection_function;
|
||||
};
|
||||
typedef Vector(TSTree *) TreeVector;
|
||||
|
||||
typedef struct {
|
||||
size_t goal_tree_count;
|
||||
StackNode *node;
|
||||
Vector trees;
|
||||
TreeVector trees;
|
||||
bool is_shared;
|
||||
} PopPath;
|
||||
|
||||
static StackNode *NULL_NODE = NULL;
|
||||
struct Stack {
|
||||
Vector(StackNode *) heads;
|
||||
StackPopResultVector pop_results;
|
||||
Vector(PopPath) pop_paths;
|
||||
Vector(StackNode *) node_pool;
|
||||
void *tree_selection_payload;
|
||||
TreeSelectionFunction tree_selection_function;
|
||||
};
|
||||
|
||||
/*
|
||||
* Section: Stack lifecycle
|
||||
|
|
@ -50,10 +50,10 @@ Stack *ts_stack_new() {
|
|||
if (!self)
|
||||
goto error;
|
||||
|
||||
self->heads = vector_new(sizeof(StackNode *));
|
||||
self->pop_results = vector_new(sizeof(StackPopResult));
|
||||
self->pop_paths = vector_new(sizeof(PopPath));
|
||||
self->node_pool = vector_new(sizeof(StackNode *));
|
||||
vector_init(&self->heads);
|
||||
vector_init(&self->pop_results);
|
||||
vector_init(&self->pop_paths);
|
||||
vector_init(&self->node_pool);
|
||||
self->tree_selection_payload = NULL;
|
||||
self->tree_selection_function = ts_stack__default_tree_selection;
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ Stack *ts_stack_new() {
|
|||
if (!vector_grow(&self->node_pool, 20))
|
||||
goto error;
|
||||
|
||||
vector_push(&self->heads, &NULL_NODE);
|
||||
vector_push(&self->heads, NULL);
|
||||
|
||||
return self;
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ TSTree *ts_stack_top_tree(const Stack *self, int head) {
|
|||
}
|
||||
|
||||
StackEntry *ts_stack_head(Stack *self, int head) {
|
||||
StackNode *node = *(StackNode **)vector_get(&self->heads, head);
|
||||
StackNode *node = self->heads.contents[head];
|
||||
return node ? &node->entry : NULL;
|
||||
}
|
||||
|
||||
|
|
@ -148,7 +148,7 @@ static bool stack_node_release(Stack *self, StackNode *node) {
|
|||
if (self->node_pool.size >= MAX_NODE_POOL_SIZE)
|
||||
ts_free(node);
|
||||
else
|
||||
vector_push(&self->node_pool, &node);
|
||||
vector_push(&self->node_pool, node);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
|
|
@ -156,7 +156,8 @@ static bool stack_node_release(Stack *self, StackNode *node) {
|
|||
}
|
||||
}
|
||||
|
||||
static StackNode *stack_node_new(Stack *self, StackNode *next, TSStateId state, TSTree *tree) {
|
||||
static StackNode *stack_node_new(Stack *self, StackNode *next, TSStateId state,
|
||||
TSTree *tree) {
|
||||
assert(tree->ref_count > 0);
|
||||
StackNode *node;
|
||||
if (self->node_pool.size == 0) {
|
||||
|
|
@ -164,7 +165,7 @@ static StackNode *stack_node_new(Stack *self, StackNode *next, TSStateId state,
|
|||
if (!node)
|
||||
return NULL;
|
||||
} else {
|
||||
node = *(StackNode **)vector_pop(&self->node_pool);
|
||||
node = vector_pop(&self->node_pool);
|
||||
}
|
||||
|
||||
ts_tree_retain(tree);
|
||||
|
|
@ -184,8 +185,8 @@ static StackNode *stack_node_new(Stack *self, StackNode *next, TSStateId state,
|
|||
static void ts_stack__add_alternative_tree(Stack *self, StackNode *node,
|
||||
TSTree *tree) {
|
||||
if (tree != node->entry.tree) {
|
||||
int comparison = self->tree_selection_function(
|
||||
self->tree_selection_payload, node->entry.tree, tree);
|
||||
int comparison = self->tree_selection_function(self->tree_selection_payload,
|
||||
node->entry.tree, tree);
|
||||
|
||||
if (comparison > 0) {
|
||||
ts_tree_retain(tree);
|
||||
|
|
@ -211,7 +212,8 @@ static void ts_stack__add_alternative_pop_result(Stack *self,
|
|||
for (size_t i = 0; i < result->tree_count; i++) {
|
||||
TSTree *tree = result->trees[i];
|
||||
TSTree *new_tree = new_result->trees[i];
|
||||
int comparison = self->tree_selection_function(self->tree_selection_payload, tree, new_tree);
|
||||
int comparison = self->tree_selection_function(
|
||||
self->tree_selection_payload, tree, new_tree);
|
||||
if (comparison < 0) {
|
||||
break;
|
||||
} else if (comparison > 0) {
|
||||
|
|
@ -230,7 +232,6 @@ static void ts_stack__add_alternative_pop_result(Stack *self,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void ts_stack__add_node_successor(Stack *self, StackNode *node,
|
||||
StackNode *new_successor) {
|
||||
for (int i = 0; i < node->successor_count; i++) {
|
||||
|
|
@ -259,7 +260,7 @@ static void ts_stack__add_node_successor(Stack *self, StackNode *node,
|
|||
*/
|
||||
|
||||
static int ts_stack__add_head(Stack *self, StackNode *node) {
|
||||
if (vector_push(&self->heads, &node)) {
|
||||
if (vector_push(&self->heads, node)) {
|
||||
stack_node_retain(node);
|
||||
return self->heads.size - 1;
|
||||
} else {
|
||||
|
|
@ -269,16 +270,15 @@ static int ts_stack__add_head(Stack *self, StackNode *node) {
|
|||
|
||||
static int ts_stack__find_head(Stack *self, StackNode *node) {
|
||||
for (size_t i = 0; i < self->heads.size; i++) {
|
||||
StackNode **existing_node = vector_get(&self->heads, i);
|
||||
if (*existing_node == node)
|
||||
if (self->heads.contents[i] == node)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ts_stack_remove_head(Stack *self, int head_index) {
|
||||
StackNode **node = vector_get(&self->heads, head_index);
|
||||
stack_node_release(self, *node);
|
||||
StackNode *node = *vector_get(&self->heads, head_index);
|
||||
stack_node_release(self, node);
|
||||
vector_erase(&self->heads, head_index);
|
||||
}
|
||||
|
||||
|
|
@ -288,57 +288,55 @@ void ts_stack_remove_head(Stack *self, int head_index) {
|
|||
|
||||
StackPushResult ts_stack_push(Stack *self, int head_index, TSStateId state,
|
||||
TSTree *tree) {
|
||||
assert((size_t)head_index < self->heads.size);
|
||||
assert(tree);
|
||||
|
||||
TSLength position = ts_tree_total_size(tree);
|
||||
StackNode **current_head = vector_get(&self->heads, head_index);
|
||||
if (*current_head)
|
||||
position = ts_length_add((*current_head)->entry.position, position);
|
||||
StackNode *current_head = *vector_get(&self->heads, head_index);
|
||||
if (current_head)
|
||||
position = ts_length_add(current_head->entry.position, position);
|
||||
|
||||
for (int i = 0; i < head_index; i++) {
|
||||
StackNode **prior_node = vector_get(&self->heads, i);
|
||||
StackEntry prior_entry = (*prior_node)->entry;
|
||||
if (prior_entry.state == state && ts_length_eq(prior_entry.position, position)) {
|
||||
ts_stack__add_alternative_tree(self, *prior_node, tree);
|
||||
ts_stack__add_node_successor(self, *prior_node, *current_head);
|
||||
StackNode *prior_node = self->heads.contents[i];
|
||||
StackEntry prior_entry = prior_node->entry;
|
||||
if (prior_entry.state == state &&
|
||||
ts_length_eq(prior_entry.position, position)) {
|
||||
ts_stack__add_alternative_tree(self, prior_node, tree);
|
||||
ts_stack__add_node_successor(self, prior_node, current_head);
|
||||
ts_stack_remove_head(self, head_index);
|
||||
return StackPushResultMerged;
|
||||
}
|
||||
}
|
||||
|
||||
StackNode *new_head = stack_node_new(self, *current_head, state, tree);
|
||||
StackNode *new_head = stack_node_new(self, current_head, state, tree);
|
||||
if (!new_head)
|
||||
return StackPushResultFailed;
|
||||
|
||||
stack_node_release(self, *current_head);
|
||||
vector_set(&self->heads, head_index, &new_head);
|
||||
stack_node_release(self, current_head);
|
||||
self->heads.contents[head_index] = new_head;
|
||||
return StackPushResultContinued;
|
||||
}
|
||||
|
||||
int ts_stack_split(Stack *self, int head_index) {
|
||||
StackNode **head = vector_get(&self->heads, head_index);
|
||||
return ts_stack__add_head(self, *head);
|
||||
StackNode *head = self->heads.contents[head_index];
|
||||
return ts_stack__add_head(self, head);
|
||||
}
|
||||
|
||||
Vector ts_stack_pop(Stack *self, int head_index, int child_count,
|
||||
bool count_extra) {
|
||||
StackPopResultVector ts_stack_pop(Stack *self, int head_index, int child_count,
|
||||
bool count_extra) {
|
||||
vector_clear(&self->pop_results);
|
||||
vector_clear(&self->pop_paths);
|
||||
|
||||
StackNode *previous_head = *(StackNode **)vector_get(&self->heads, head_index);
|
||||
StackNode *previous_head = *vector_get(&self->heads, head_index);
|
||||
int capacity = (child_count == -1) ? STARTING_TREE_CAPACITY : child_count;
|
||||
PopPath initial_path = {
|
||||
.goal_tree_count = child_count,
|
||||
.node = previous_head,
|
||||
.trees = vector_new(sizeof(TSTree *)),
|
||||
.is_shared = false,
|
||||
};
|
||||
vector_init(&initial_path.trees);
|
||||
|
||||
if (!vector_grow(&initial_path.trees, capacity))
|
||||
goto error;
|
||||
|
||||
if (!vector_push(&self->pop_paths, &initial_path))
|
||||
if (!vector_push(&self->pop_paths, initial_path))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
|
|
@ -350,7 +348,7 @@ Vector ts_stack_pop(Stack *self, int head_index, int child_count,
|
|||
all_paths_done = true;
|
||||
|
||||
for (size_t i = 0; i < self->pop_paths.size; i++) {
|
||||
PopPath *path = vector_get(&self->pop_paths, i);
|
||||
PopPath *path = &self->pop_paths.contents[i];
|
||||
StackNode *node = path->node;
|
||||
|
||||
if (!node || path->trees.size == path->goal_tree_count)
|
||||
|
|
@ -369,23 +367,19 @@ Vector ts_stack_pop(Stack *self, int head_index, int child_count,
|
|||
* the additional successors.
|
||||
*/
|
||||
if (path->is_shared) {
|
||||
path->trees = vector_copy(&path->trees);
|
||||
for (size_t j = 0; j < path->trees.size; j++) {
|
||||
TSTree **tree = vector_get(&path->trees, j);
|
||||
ts_tree_retain(*tree);
|
||||
}
|
||||
|
||||
path->trees = (TreeVector)vector_copy(&path->trees);
|
||||
for (size_t j = 0; j < path->trees.size; j++)
|
||||
ts_tree_retain(path->trees.contents[j]);
|
||||
path->is_shared = false;
|
||||
}
|
||||
|
||||
ts_tree_retain(node->entry.tree);
|
||||
if (!vector_push(&path->trees, &node->entry.tree))
|
||||
if (!vector_push(&path->trees, node->entry.tree))
|
||||
goto error;
|
||||
|
||||
path->node = path->node->successors[0];
|
||||
PopPath path_copy = *path;
|
||||
for (int j = 1; j < node->successor_count; j++) {
|
||||
if (!vector_push(&self->pop_paths, &path_copy))
|
||||
if (!vector_push(&self->pop_paths, *path))
|
||||
goto error;
|
||||
|
||||
PopPath *next_path = vector_back(&self->pop_paths);
|
||||
|
|
@ -396,7 +390,7 @@ Vector ts_stack_pop(Stack *self, int head_index, int child_count,
|
|||
}
|
||||
|
||||
for (size_t i = 0; i < self->pop_paths.size; i++) {
|
||||
PopPath *path = vector_get(&self->pop_paths, i);
|
||||
PopPath *path = &self->pop_paths.contents[i];
|
||||
|
||||
if (!path->is_shared)
|
||||
vector_reverse(&path->trees);
|
||||
|
|
@ -409,7 +403,7 @@ Vector ts_stack_pop(Stack *self, int head_index, int child_count,
|
|||
|
||||
if (i == 0) {
|
||||
stack_node_retain(path->node);
|
||||
vector_set(&self->heads, head_index, &path->node);
|
||||
self->heads.contents[head_index] = path->node;
|
||||
result.head_index = head_index;
|
||||
} else {
|
||||
result.head_index = ts_stack__find_head(self, path->node);
|
||||
|
|
@ -420,7 +414,7 @@ Vector ts_stack_pop(Stack *self, int head_index, int child_count,
|
|||
} else {
|
||||
bool merged_result = false;
|
||||
for (size_t j = 0; j < self->pop_results.size; j++) {
|
||||
StackPopResult *prior_result = vector_get(&self->pop_results, j);
|
||||
StackPopResult *prior_result = &self->pop_results.contents[j];
|
||||
if (prior_result->head_index == result.head_index) {
|
||||
ts_stack__add_alternative_pop_result(self, prior_result, &result);
|
||||
merged_result = true;
|
||||
|
|
@ -432,7 +426,7 @@ Vector ts_stack_pop(Stack *self, int head_index, int child_count,
|
|||
}
|
||||
}
|
||||
|
||||
if (!vector_push(&self->pop_results, &result))
|
||||
if (!vector_push(&self->pop_results, result))
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
@ -441,30 +435,29 @@ Vector ts_stack_pop(Stack *self, int head_index, int child_count,
|
|||
|
||||
error:
|
||||
vector_delete(&initial_path.trees);
|
||||
return vector_new(0);
|
||||
StackPopResultVector result;
|
||||
vector_init(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void ts_stack_shrink(Stack *self, int head_index, int count) {
|
||||
StackNode **head = vector_get(&self->heads, head_index);
|
||||
StackNode *new_head = *head;
|
||||
StackNode *head = *vector_get(&self->heads, head_index);
|
||||
StackNode *new_head = head;
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (new_head->successor_count == 0)
|
||||
break;
|
||||
new_head = new_head->successors[0];
|
||||
}
|
||||
stack_node_retain(new_head);
|
||||
stack_node_release(self, *head);
|
||||
vector_set(&self->heads, head_index, new_head);
|
||||
stack_node_release(self, head);
|
||||
self->heads.contents[head_index] = new_head;
|
||||
}
|
||||
|
||||
void ts_stack_clear(Stack *self) {
|
||||
for (size_t i = 0; i < self->heads.size; i++) {
|
||||
StackNode **head = vector_get(&self->heads, i);
|
||||
stack_node_release(self, *head);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < self->heads.size; i++)
|
||||
stack_node_release(self, self->heads.contents[i]);
|
||||
vector_clear(&self->heads);
|
||||
vector_push(&self->heads, &NULL_NODE);
|
||||
vector_push(&self->heads, NULL);
|
||||
}
|
||||
|
||||
void ts_stack_set_tree_selection_callback(Stack *self, void *payload,
|
||||
|
|
@ -479,12 +472,11 @@ void ts_stack_delete(Stack *self) {
|
|||
if (self->pop_paths.contents)
|
||||
vector_delete(&self->pop_paths);
|
||||
ts_stack_clear(self);
|
||||
for (size_t i = 0; i < self->node_pool.size; i++) {
|
||||
StackNode **node = vector_get(&self->node_pool, i);
|
||||
ts_free(*node);
|
||||
}
|
||||
if (self->node_pool.contents)
|
||||
if (self->node_pool.contents) {
|
||||
for (size_t i = 0; i < self->node_pool.size; i++)
|
||||
ts_free(self->node_pool.contents[i]);
|
||||
vector_delete(&self->node_pool);
|
||||
}
|
||||
vector_delete(&self->heads);
|
||||
ts_free(self);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ typedef enum {
|
|||
StackPushResultContinued,
|
||||
} StackPushResult;
|
||||
|
||||
typedef Vector(StackPopResult) StackPopResultVector;
|
||||
|
||||
typedef int (*TreeSelectionFunction)(void *, TSTree *, TSTree *);
|
||||
|
||||
/*
|
||||
|
|
@ -90,7 +92,8 @@ StackPushResult ts_stack_push(Stack *, int head, TSStateId, TSTree *);
|
|||
* which had previously been merged. It returns a struct that indicates the
|
||||
* index of each revealed head and the trees removed from that head.
|
||||
*/
|
||||
Vector ts_stack_pop(Stack *, int head, int count, bool count_extra);
|
||||
StackPopResultVector ts_stack_pop(Stack *, int head, int count,
|
||||
bool count_extra);
|
||||
|
||||
/*
|
||||
* Remove the given number of entries from the given head of the stack.
|
||||
|
|
|
|||
|
|
@ -11,120 +11,100 @@ extern "C" {
|
|||
#include <stdbool.h>
|
||||
#include "runtime/alloc.h"
|
||||
|
||||
typedef struct {
|
||||
void *contents;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
size_t element_size;
|
||||
} Vector;
|
||||
#define Vector(T) \
|
||||
struct { \
|
||||
T *contents; \
|
||||
size_t size; \
|
||||
size_t capacity; \
|
||||
}
|
||||
|
||||
static inline Vector vector_new(size_t element_size) {
|
||||
Vector result;
|
||||
result.contents = NULL;
|
||||
result.size = 0;
|
||||
result.capacity = 0;
|
||||
result.element_size = element_size;
|
||||
return result;
|
||||
#define vector_init(self) \
|
||||
((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL)
|
||||
|
||||
#define vector_get(self, index) \
|
||||
(assert((size_t)index < (self)->size), &(self)->contents[index])
|
||||
|
||||
#define vector_front(self) vector_get(self, 0)
|
||||
|
||||
#define vector_back(self) vector_get(self, (self)->size - 1)
|
||||
|
||||
#define vector_clear(self) ((self)->size = 0)
|
||||
|
||||
#define vector_grow(self, new_capacity) \
|
||||
vector__grow((VoidVector *)(self), vector__elem_size(self), new_capacity)
|
||||
|
||||
#define vector_erase(self, index) \
|
||||
vector__erase((VoidVector *)(self), vector__elem_size(self), index)
|
||||
|
||||
#define vector_delete(self) vector__delete((VoidVector *)self)
|
||||
|
||||
#define vector_push(self, element) \
|
||||
(((self)->size < (self)->capacity || \
|
||||
vector_grow((self), (self)->capacity * 2)) && \
|
||||
((self)->contents[(self)->size++] = (element), true))
|
||||
|
||||
#define vector_pop(self) ((self)->contents[--(self)->size])
|
||||
|
||||
#define vector_reverse(self) \
|
||||
vector__reverse((VoidVector *)(self), vector__elem_size(self))
|
||||
|
||||
#define vector_copy(self) \
|
||||
{ \
|
||||
memcpy(ts_calloc((self)->capacity, vector__elem_size(self)), \
|
||||
(self)->contents, (self)->size *vector__elem_size(self)), \
|
||||
(self)->size, (self)->capacity, \
|
||||
}
|
||||
|
||||
// Private
|
||||
|
||||
typedef Vector(void) VoidVector;
|
||||
|
||||
#define vector__elem_size(self) sizeof(*(self)->contents)
|
||||
|
||||
static inline void vector__delete(VoidVector *self) {
|
||||
ts_free(self->contents);
|
||||
self->contents = NULL;
|
||||
self->size = 0;
|
||||
self->capacity = 0;
|
||||
}
|
||||
|
||||
static inline bool vector_grow(Vector *self, size_t capacity) {
|
||||
if (capacity == 0)
|
||||
static inline void vector__erase(VoidVector *self, size_t element_size,
|
||||
size_t index) {
|
||||
assert(index < self->size);
|
||||
char *contents = (char *)self->contents;
|
||||
memmove(contents + index * element_size, contents + (index + 1) * element_size,
|
||||
(self->size - index - 1) * element_size);
|
||||
self->size--;
|
||||
}
|
||||
|
||||
static inline bool vector__grow(VoidVector *self, size_t element_size,
|
||||
size_t new_capacity) {
|
||||
if (new_capacity == 0)
|
||||
return true;
|
||||
|
||||
void *new_contents;
|
||||
if (self->contents)
|
||||
new_contents = ts_realloc(self->contents, capacity * self->element_size);
|
||||
new_contents = ts_realloc(self->contents, new_capacity * element_size);
|
||||
else
|
||||
new_contents = ts_calloc(capacity, self->element_size);
|
||||
new_contents = ts_calloc(new_capacity, element_size);
|
||||
|
||||
if (!new_contents)
|
||||
return false;
|
||||
self->capacity = capacity;
|
||||
self->capacity = new_capacity;
|
||||
self->contents = new_contents;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool vector_valid(Vector *self) {
|
||||
return self->element_size > 0;
|
||||
}
|
||||
|
||||
static inline void vector_delete(Vector *self) {
|
||||
if (self->contents) {
|
||||
ts_free(self->contents);
|
||||
self->contents = NULL;
|
||||
self->size = 0;
|
||||
self->capacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void *vector_get(Vector *self, size_t index) {
|
||||
assert(index < self->size);
|
||||
return (void *)((char *)self->contents + index * self->element_size);
|
||||
}
|
||||
|
||||
static inline void vector_set(Vector *self, size_t index, void *entry) {
|
||||
assert(index < self->size);
|
||||
char *location = (char *)self->contents + index * self->element_size;
|
||||
memcpy(location, (char *)entry, self->element_size);
|
||||
}
|
||||
|
||||
static inline void *vector_back(Vector *self) {
|
||||
assert(self->size > 0);
|
||||
return vector_get(self, self->size - 1);
|
||||
}
|
||||
|
||||
static inline void *vector_pop(Vector *self) {
|
||||
void *result = vector_back(self);
|
||||
self->size--;
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void vector_clear(Vector *self) {
|
||||
self->size = 0;
|
||||
}
|
||||
|
||||
static inline void vector_erase(Vector *self, size_t index) {
|
||||
assert(index < self->size);
|
||||
static inline void vector__reverse(VoidVector *self, size_t element_size) {
|
||||
char swap[element_size];
|
||||
char *contents = (char *)self->contents;
|
||||
memmove(contents + index * self->element_size,
|
||||
contents + (index + 1) * self->element_size,
|
||||
(self->size - index - 1) * self->element_size);
|
||||
self->size--;
|
||||
}
|
||||
|
||||
static inline bool vector_push(Vector *self, void *entry) {
|
||||
if (self->size == self->capacity) {
|
||||
self->capacity += 4;
|
||||
void *contents =
|
||||
ts_realloc(self->contents, self->capacity * self->element_size);
|
||||
if (!contents)
|
||||
return false;
|
||||
self->contents = contents;
|
||||
for (size_t i = 0, limit = self->size / 2; i < limit; i++) {
|
||||
size_t offset = i * element_size;
|
||||
size_t reverse_offset = (self->size - 1 - i) * element_size;
|
||||
memcpy(&swap, contents + offset, element_size);
|
||||
memcpy(contents + offset, contents + reverse_offset, element_size);
|
||||
memcpy(contents + reverse_offset, &swap, element_size);
|
||||
}
|
||||
|
||||
self->size++;
|
||||
vector_set(self, self->size - 1, entry);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void vector_reverse(Vector *self) {
|
||||
char swap[self->element_size];
|
||||
char *contents = (char *)self->contents;
|
||||
size_t limit = self->size / 2;
|
||||
for (size_t i = 0; i < limit; i++) {
|
||||
size_t offset = i * self->element_size;
|
||||
size_t reverse_offset = (self->size - 1 - i) * self->element_size;
|
||||
memcpy(&swap, contents + offset, self->element_size);
|
||||
memcpy(contents + offset, contents + reverse_offset, self->element_size);
|
||||
memcpy(contents + reverse_offset, &swap, self->element_size);
|
||||
}
|
||||
}
|
||||
|
||||
static inline Vector vector_copy(Vector *self) {
|
||||
Vector copy = *self;
|
||||
copy.contents = memcpy(ts_calloc(self->capacity, self->element_size),
|
||||
self->contents, self->size * self->element_size);
|
||||
return copy;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue