summaryrefslogtreecommitdiff
path: root/src/piece-table.c
diff options
context:
space:
mode:
authorEkaitz Zarraga <ekaitz@elenq.tech>2024-03-03 22:21:15 +0100
committerEkaitz Zarraga <ekaitz@elenq.tech>2024-03-03 22:21:15 +0100
commitdfb7d4b2bd6a5bd7a2bf63927c84c46bf88ba379 (patch)
tree21b4933da1355141f313f88784a2e17ec5b2fa2e /src/piece-table.c
parent14fb4ab4a19bbb281f614ef93a009a07e86ebf14 (diff)
piece-table: fix memory and implement delete
Diffstat (limited to 'src/piece-table.c')
-rw-r--r--src/piece-table.c107
1 files changed, 86 insertions, 21 deletions
diff --git a/src/piece-table.c b/src/piece-table.c
index be9f1b2..5f2b171 100644
--- a/src/piece-table.c
+++ b/src/piece-table.c
@@ -1,58 +1,83 @@
#include <assert.h>
+#include <stdio.h>
#include "piece-table.h"
+/*
+ * We probably should have a pool of pieces and go using them and deleting them
+ * from there instead of malloc/free but we are lazy
+ */
+static void print_string(char *str, size_t size) {
+ size_t i;
+ printf("\"");
+ for ( i=0; i < size; i++) {
+ printf("%c", str[i]);
+ }
+ printf("\"");
+}
+
+void print_piece_table (piece_table *pt) {
+ piece *cur;
+ printf("piece_table {");
+ printf("\n\toriginal: "); print_string(pt->orig.content, pt->orig.size);
+ printf("\n\tadd: "); print_string(pt->add.content, pt->add.used);
+ printf("\n\tlength: %ld", pt->length);
+ printf("\n\tpieces: ");
+ for ( cur = pt->sentinel->next; cur != pt->sentinel; cur = cur->next ) {
+ printf("\n\t\ttext: "); print_string(cur->start, cur->length);
+ }
+ printf("\n}\n");
+}
+
static piece *make_piece() {
return malloc(sizeof(piece));
}
-static piece *make_sentinel() {
+static piece *make_piece_list() {
+ /* Makes a sentinel connected to itself in a ring*/
piece *p = make_piece();
+ p->next = p;
+ p->prev = p;
p->length = 0;
- p->next = NULL;
- p->prev = NULL;
p->start = NULL;
return p;
}
-bool init_piece_table(piece_table *pt, char *orig) {
- piece *pc, *sentinel;
+void init_piece_table(piece_table *pt, char *orig) {
+ piece *pc;
init_growable_buffer(&pt->add);
init_fixed_buffer(&pt->orig, orig);
pt->length = pt->orig.size;
+ pt->sentinel = make_piece_list();
+
pc = make_piece();
- if(pc == NULL){
- return false;
- }
- sentinel = make_sentinel();
- if(sentinel == NULL){
- return false;
- }
pc->start = pt->orig.content;
pc->length = pt->orig.size;
- pc->prev = sentinel;
- pc->next = sentinel;
+ pc->prev = pt->sentinel;
+ pc->next = pt->sentinel;
+
+ pt->sentinel->next = pc;
+ pt->sentinel->prev = pc;
pt->cached_offset = 0;
pt->cached = pc;
- return true;
}
static void free_piece_list(piece *p) {
piece *cur, *next;
assert(p != NULL);
- for ( cur = p; cur != p; cur = next ) {
+ for ( cur = p->next; cur != p; cur = next ) {
next = cur->next;
free( cur );
}
+ free(cur);
}
void free_piece_table(piece_table *pt) {
free_growable_buffer(&pt->add);
- free_fixed_buffer(&pt->orig);
free_piece_list(pt->sentinel);
pt->sentinel = NULL;
pt->cached = NULL;
@@ -67,7 +92,7 @@ static void find_piece_by_pos(piece_table *pt, size_t pos) {
if ( pos >= pt->cached_offset ) {
/* Search forward */
for ( cur = pt->cached; ; cur = cur->next ) {
- if ( pt->cached_offset + pt->length > pos ) {
+ if ( pt->cached_offset + cur->length > pos ) {
pt->cached = cur;
assert(pt->cached != pt->sentinel);
return;
@@ -93,15 +118,55 @@ char index_piece_table(piece_table *pt, size_t pos) {
return pt->cached->start[pos - pt->cached_offset];
}
+
+static void split_piece(piece *p, size_t pos) {
+ assert(pos < p->length);
+ assert(p->start != NULL); /* Not a sentinel piece */
+ assert(p->start != 0); /* Not an empty piece (they should not exist) */
+ piece *second = make_piece();
+ second->length = p->length - pos;
+ p->length = pos;
+ second->next = p->next;
+ p->next = second;
+ second->prev = p;
+ second->start = p->start + pos;
+}
+
void insert_piece_table(piece_table *pt, char val, size_t pos) {
/* At the moment inserts only one char */
- append_growable_buffer(&pt->add, &val, 1);
-
- find_piece_by_pos(pt, pos);
+ // piece *cur;
+ assert(pos <= pt->length );
+ append_growable_buffer(&pt->add, &val, 1);
// TODO
}
void delete_piece_table(piece_table *pt, size_t pos, size_t len) {
+ piece *cur, *next, *start, *end;
+ assert( pos + len <= pt->length );
+ if ( pos == 0) {
+ start = pt->sentinel;
+ } else {
+ find_piece_by_pos(pt, pos);
+ split_piece(pt->cached, pos - pt->cached_offset);
+ start = pt->cached;
+ }
+
+ if (pos + len == pt->length) {
+ end = pt->sentinel;
+ } else {
+ find_piece_by_pos(pt, pos + len);
+ split_piece(pt->cached, pos + len - pt->cached_offset);
+ end = pt->cached->next;
+ }
+
+ /* Free unneeded pieces */
+ for ( cur = start->next; cur != end ; cur = next ) {
+ next = cur->next;
+ free(cur);
+ }
+ start->next = end;
+ end->prev = start;
+ pt->length -= len;
}