summaryrefslogtreecommitdiff
path: root/src/undo.c
diff options
context:
space:
mode:
authorAlbert Cervin <albert@acervin.com>2023-02-25 21:37:48 +0100
committerAlbert Cervin <albert@acervin.com>2023-02-25 21:38:59 +0100
commit40db61eb7a2019ced97f09a9687139f35749f4e0 (patch)
tree9291e44eb82721732d04146b5042545e1b9e91f9 /src/undo.c
parent44fd8cde61e3e89e5f83c98900a403e922073727 (diff)
downloaddged-40db61eb7a2019ced97f09a9687139f35749f4e0.tar.gz
dged-40db61eb7a2019ced97f09a9687139f35749f4e0.tar.xz
dged-40db61eb7a2019ced97f09a9687139f35749f4e0.zip
Introduce vec and hashmap
Convenience macros for a hashmap and a growable vector.
Diffstat (limited to 'src/undo.c')
-rw-r--r--src/undo.c105
1 files changed, 43 insertions, 62 deletions
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 <stdio.h>
#include <stdlib.h>
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" : "");