From 40db61eb7a2019ced97f09a9687139f35749f4e0 Mon Sep 17 00:00:00 2001 From: Albert Cervin Date: Sat, 25 Feb 2023 21:37:48 +0100 Subject: Introduce vec and hashmap Convenience macros for a hashmap and a growable vector. --- src/undo.c | 105 +++++++++++++++++++++++++------------------------------------ 1 file changed, 43 insertions(+), 62 deletions(-) (limited to 'src/undo.c') diff --git a/src/undo.c b/src/undo.c index 6ebec12..2780557 100644 --- a/src/undo.c +++ b/src/undo.c @@ -1,72 +1,55 @@ #include "undo.h" #include "string.h" +#include "vec.h" #include #include void undo_init(struct undo_stack *undo, uint32_t initial_capacity) { undo->top = INVALID_TOP; - undo->nrecords = 0; undo->undo_in_progress = false; - - undo->records = calloc(initial_capacity, sizeof(struct undo_record)); - undo->capacity = initial_capacity; -} - -void grow_if_needed(struct undo_stack *undo, uint32_t needed_capacity) { - if (needed_capacity > undo->capacity) { - undo->capacity += undo->capacity + needed_capacity > undo->capacity * 2 - ? needed_capacity - : undo->capacity; - - undo->records = - realloc(undo->records, sizeof(struct undo_record) * undo->capacity); - } + VEC_INIT(&undo->records, initial_capacity); } void undo_clear(struct undo_stack *undo) { undo->top = INVALID_TOP; - undo->nrecords = 0; + VEC_CLEAR(&undo->records); } void undo_destroy(struct undo_stack *undo) { - for (uint32_t i = 0; i < undo->nrecords; ++i) { - struct undo_record *rec = &undo->records[i]; + VEC_FOR_EACH(&undo->records, struct undo_record * rec) { if (rec->type == Undo_Delete && rec->delete.data != NULL && rec->delete.nbytes > 0) { free(rec->delete.data); } } + undo_clear(undo); - undo->capacity = 0; - free(undo->records); - undo->records = NULL; + VEC_DESTROY(&undo->records); } uint32_t undo_push_boundary(struct undo_stack *undo, struct undo_boundary boundary) { - grow_if_needed(undo, undo->nrecords + 1); - undo->records[undo->nrecords].type = Undo_Boundary; - undo->records[undo->nrecords].boundary = boundary; - - if (!undo->undo_in_progress) { - undo->top = undo->nrecords; - } + VEC_APPEND(&undo->records, struct undo_record * rec); + rec->type = Undo_Boundary; + rec->boundary = boundary; // we can only have one save point if (boundary.save_point) { - for (uint32_t i = 0; i < undo->nrecords; ++i) { - if (undo->records[i].type && Undo_Boundary && - undo->records[i].boundary.save_point) { - undo->records[i].boundary.save_point = false; + VEC_FOR_EACH(&undo->records, struct undo_record * rec) { + if (rec->type && Undo_Boundary && rec->boundary.save_point) { + rec->boundary.save_point = false; } } } - ++undo->nrecords; - return undo->nrecords - 1; + if (!undo->undo_in_progress) { + undo->top = VEC_SIZE(&undo->records) - 1; + } + + return VEC_SIZE(&undo->records) - 1; } bool pos_equal(struct position *a, struct position *b) { @@ -74,39 +57,35 @@ bool pos_equal(struct position *a, struct position *b) { } uint32_t undo_push_add(struct undo_stack *undo, struct undo_add add) { - grow_if_needed(undo, undo->nrecords + 1); // "compress" - if (undo->nrecords > 0 && - undo->records[undo->nrecords - 1].type == Undo_Add && - pos_equal(&undo->records[undo->nrecords - 1].add.end, &add.begin)) { - undo->records[undo->nrecords - 1].add.end = add.end; - return undo->nrecords; + if (!VEC_EMPTY(&undo->records) && + VEC_BACK(&undo->records)->type == Undo_Add && + pos_equal(&VEC_BACK(&undo->records)->add.end, &add.begin)) { + VEC_BACK(&undo->records)->add.end = add.end; + } else { + VEC_APPEND(&undo->records, struct undo_record * rec); + rec->type = Undo_Add; + rec->add = add; } - undo->records[undo->nrecords].type = Undo_Add; - undo->records[undo->nrecords].add = add; - if (!undo->undo_in_progress) { - undo->top = undo->nrecords; + undo->top = VEC_SIZE(&undo->records) - 1; } - ++undo->nrecords; - return undo->nrecords - 1; + return VEC_SIZE(&undo->records) - 1; } uint32_t undo_push_delete(struct undo_stack *undo, struct undo_delete delete) { - grow_if_needed(undo, undo->nrecords + 1); - - undo->records[undo->nrecords].type = Undo_Delete; - undo->records[undo->nrecords].delete = delete; + VEC_APPEND(&undo->records, struct undo_record * rec); + rec->type = Undo_Delete; + rec->delete = delete; if (!undo->undo_in_progress) { - undo->top = undo->nrecords; + undo->top = VEC_SIZE(&undo->records) - 1; } - ++undo->nrecords; - return undo->nrecords - 1; + return VEC_SIZE(&undo->records) - 1; } void undo_begin(struct undo_stack *undo) { undo->undo_in_progress = true; } @@ -116,27 +95,30 @@ void undo_next(struct undo_stack *undo, struct undo_record **records_out, *nrecords_out = 0; *records_out = NULL; - if (undo->nrecords == 0) { + if (VEC_EMPTY(&undo->records)) { return; } if (undo->top == INVALID_TOP) { // reset back to the top (redo) - undo->top = undo->nrecords - 1; + undo->top = VEC_SIZE(&undo->records) - 1; } uint32_t nrecords = 1; - struct undo_record *current = &undo->records[undo->top]; + struct undo_record *current = &VEC_ENTRIES(&undo->records)[undo->top]; + + // skip any leading boundaries while (undo->top > 0 && current->type == Undo_Boundary) { ++nrecords; --undo->top; - current = &undo->records[undo->top]; + current = &VEC_ENTRIES(&undo->records)[undo->top]; } + // find the next boundary while (undo->top > 0 && current->type != Undo_Boundary) { ++nrecords; --undo->top; - current = &undo->records[undo->top]; + current = &VEC_ENTRIES(&undo->records)[undo->top]; } if (nrecords > 0) { @@ -148,7 +130,7 @@ void undo_next(struct undo_stack *undo, struct undo_record **records_out, // copy backwards for (uint32_t reci = undo->top + nrecords, outi = 0; reci > undo->top; --reci, ++outi) { - dest[outi] = undo->records[reci - 1]; + dest[outi] = VEC_ENTRIES(&undo->records)[reci - 1]; } } @@ -161,7 +143,7 @@ void undo_next(struct undo_stack *undo, struct undo_record **records_out, void undo_end(struct undo_stack *undo) { undo->undo_in_progress = false; } -uint32_t undo_size(struct undo_stack *undo) { return undo->nrecords; } +uint32_t undo_size(struct undo_stack *undo) { return VEC_SIZE(&undo->records); } uint32_t undo_current_position(struct undo_stack *undo) { return undo->top; } size_t rec_to_str(struct undo_record *rec, char *buffer, size_t n) { @@ -187,8 +169,7 @@ const char *undo_dump(struct undo_stack *undo) { pos[0] = '\0'; char rec_buf[256]; - for (uint32_t reci = 0; reci < undo->nrecords && left > 0; ++reci) { - struct undo_record *rec = &undo->records[reci]; + VEC_FOR_EACH_INDEXED(&undo->records, struct undo_record * rec, reci) { rec_to_str(rec, rec_buf, 256); uint32_t written = snprintf(pos, left, "%d: [%s]%s\n", reci, rec_buf, reci == undo->top ? " <- top" : ""); -- cgit v1.2.3