summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEkaitz Zarraga <ekaitz@elenq.tech>2025-08-15 01:13:54 +0200
committerEkaitz Zarraga <ekaitz@elenq.tech>2025-08-15 20:06:11 +0200
commitf76234700febab324f6a4b0eb3cdf449fc732c51 (patch)
tree21aad9e8b144c99b6ff59b45f45d84f10efc6705
parent8cbc692173392f329a5105c87b7444d70eaa738e (diff)
test: piece-table-internals: Add test and pass it
Fixes the optimization that avoids adding a new piece when the addition happens in the end of the buffer. Fixes leaks produced in piece_table_optimize
-rw-r--r--Makefile3
-rw-r--r--src/piece-table.c13
-rw-r--r--tests/piece-table-internals.c66
3 files changed, 76 insertions, 6 deletions
diff --git a/Makefile b/Makefile
index 7123907..95f3c1e 100644
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,8 @@ HEADERS = $(wildcard src/*.h)
TEST := \
piece-table-delete \
- piece-table-insert
+ piece-table-insert \
+ piece-table-internals
TEST_FILES = $(addprefix tests/, $(TEST))
TEST_SOURCES = $(addsuffix .c, $(addprefix tests/, $(TEST)))
diff --git a/src/piece-table.c b/src/piece-table.c
index 36556ae..40d8407 100644
--- a/src/piece-table.c
+++ b/src/piece-table.c
@@ -119,7 +119,8 @@ void
piece_buffer_empty (piece_buffer *pb)
{
piece_buffer_destroy (pb->next);
- pb->start -= pb->used;
+ pb->next = NULL;
+ pb->used = 0;
}
piece *
@@ -270,7 +271,7 @@ piece_table_insert (piece_table *pt, size_t pos, char *in, size_t len)
if ( pt->add.used != 0 &&
start->buffer == &pt->add &&
pt->cached_offset + start->length == pos &&
- pt->add.used == start->start + start->length ) {
+ pt->add.used == start->start + start->length + len ) {
pt->length += len;
start->length += len;
return;
@@ -421,12 +422,11 @@ piece_table_optimize (piece_table *pt)
piece *p;
char *buff = malloc (sizeof (*buff) * pt->length + 1); /*TODO remove +1*/
piece_table_to_string (pt, buff, pt->length);
-
text_buffer_fill (&pt->orig, buff, pt->length);
+ free (buff);
+ text_buffer_empty (&pt->add);
text_buffer_init (&pt->add);
- for (p = pt->sentinel->next; p != pt->sentinel; p = p->next)
- piece_table_piece_mark_empty (pt, p);
piece_buffer_empty (pt->pieces);
pt->sentinel = piece_buffer_bump (pt->pieces);
@@ -441,4 +441,7 @@ piece_table_optimize (piece_table *pt)
p->start = 0;
p->length = pt->length;
p->buffer = &pt->orig;
+
+ pt->cached_offset = 0;
+ pt->cached = p;
}
diff --git a/tests/piece-table-internals.c b/tests/piece-table-internals.c
new file mode 100644
index 0000000..d59da17
--- /dev/null
+++ b/tests/piece-table-internals.c
@@ -0,0 +1,66 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "../src/piece-table-internals.h"
+
+size_t
+count_pieces (piece_table *pt)
+{
+ size_t count;
+ piece *p;
+ for (count = 0, p = pt->sentinel->next; p != pt->sentinel; p = p->next)
+ count++;
+ return count;
+}
+
+int
+main ()
+{
+ char tmp[100];
+ size_t expected_count;
+ piece_table *pt = piece_table_create_from ("0123456789", 10);
+ /** Inserting **/
+ /* Should add pieces... */
+ expected_count = 1;
+ if (count_pieces (pt) != expected_count) return 10;
+
+ piece_table_insert (pt, 10, "abcdefgh", 8);
+ expected_count++;
+ if (count_pieces (pt) != expected_count) return 11;
+
+ /* ... but not always **/
+ piece_table_insert (pt, 18, "abcdefgh", 8);
+ if (count_pieces (pt) != expected_count) return 12;
+
+
+ /** Deleting **/
+ piece_table_delete (pt, 23, 3);
+ if (count_pieces (pt) != expected_count) return 20;
+
+ piece_table_delete (pt, 13, 4);
+ expected_count++;
+ if (count_pieces (pt) != expected_count) return 21;
+
+ piece_table_delete (pt, 0, 10);
+ expected_count--;
+ if (count_pieces (pt) != expected_count) return 22;
+
+
+ /** Result **/
+ piece_table_to_string (pt, tmp, 99);
+ if (strcmp (tmp, "abchabcde"))
+ return 30;
+
+ /** Optimize **/
+ piece_table_optimize (pt);
+ expected_count = 1;
+ if (count_pieces (pt) != expected_count) return 40;
+
+ /** Result **/
+ piece_table_to_string (pt, tmp, 99);
+ if (strcmp (tmp, "abchabcde"))
+ return 50;
+
+ piece_table_destroy (pt);
+ return 0;
+}