commit 936af64091d463485cd5df7a4a60886de31e8f6f
parent 78db499bbb1371ff05d832c65ea3da4466567007
Author: gearsix <gearsix@tuta.io>
Date: Mon, 4 Jul 2022 15:28:06 +0100
added pfree; palloc recycles free'd pieces; test_bufins now passes.
Diffstat:
M | buf.c | | | 80 | +++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------- |
M | buf.h | | | 2 | ++ |
M | test.c | | | 43 | ++++++++++++++++++++++++------------------- |
3 files changed, 80 insertions(+), 45 deletions(-)
diff --git a/buf.c b/buf.c
@@ -5,24 +5,49 @@
#include <stdlib.h>
#include <string.h>
-Piece *palloc()
+static const size_t blksiz = BUFSIZ/sizeof(Piece);
+static Piece **nextp = NULL;
+
+static size_t pfree(Piece *p)
{
- static Piece *pieceblk = NULL;
- static size_t nblk = 0, npieces = 0;
- static const size_t blksiz = BUFSIZ/sizeof(Piece);
+ static Piece **freeblk = NULL;
+ static size_t nblk = 0, nfree = 0;
+
+ if (!p) {
+ if (!nextp && nfree > 0)
+ nextp = &freeblk[--nfree];
+ return nfree;
+ }
+
+ if (nfree + 1 > blksiz * nblk)
+ freeblk = realloc(freeblk, (++nblk * blksiz) * sizeof(Piece *));
+ if (!freeblk) { perror("failed to allocate freeblk"); exit(1); }
- if (npieces + 1 > blksiz * nblk)
- pieceblk = realloc(pieceblk, (++nblk * blksiz) * sizeof(Piece));
- if (!pieceblk) { perror("failed to allocate pieceblk memory"); exit(1); }
- return &pieceblk[npieces++];
+ freeblk[nfree++] = p;
+ nextp = &freeblk[nfree - 1];
+ return nfree;
}
-void pfree(Piece *p)
+static Piece *palloc()
{
+ Piece *p;
+ static Piece *pieceblk = NULL;
+ static size_t nblk = 0, npieces = 0;
+ if (pfree(NULL) > 0) {
+ p = *nextp;
+ nextp = NULL;
+ } else {
+ if (npieces + 1 > blksiz * nblk)
+ pieceblk = realloc(pieceblk, (++nblk * blksiz) * sizeof(Piece));
+ if (!pieceblk) { perror("failed to allocate pieceblk"); exit(1); }
+ p = &pieceblk[npieces++];
+ }
+
+ return memset(p, 0, sizeof(Piece));
}
-Piece *psplit(Piece *p, long int offset)
+static Piece *psplit(Piece *p, long int offset)
{
Piece *q = palloc();
if (offset > 0) {
@@ -32,7 +57,8 @@ Piece *psplit(Piece *p, long int offset)
q->len -= p->len = offset;
q->next = p->next;
q->prev = p;
- p->next = q->next->prev =q;
+ p->next = q;
+ if (q->next) q->next->prev = q;
p = q;
}
@@ -42,13 +68,9 @@ Piece *psplit(Piece *p, long int offset)
struct Buf *bufinit(const char *fpath)
{
Buf *b = calloc(1, sizeof(Buf));
-
- b->append = tmpfile();
- b->pos = palloc();
- b->pos->prev = b->tail = palloc();
- b->pos->next = b->head = palloc();
- b->head->prev = b->tail->next = b->pos;
+ b->append = tmpfile();
+ b->tail = b->pos = b->head = palloc();
if (fpath) {
b->read = fopen(fpath, "rb");
@@ -85,33 +107,39 @@ Piece *bufidx(Buf *b, size_t pos)
} else {
offset = (idx >= pos) ? idx - pos : pos - idx;
b->pos = psplit(p, offset);
+ if (!b->pos->next) b->head = b->pos;
b->idx = pos;
}
return b->pos;
}
-void bufins(Buf *b, size_t pos, const char *s)
+size_t bufins(Buf *b, size_t pos, const char *s)
{
const size_t slen = strlen(s);
Piece *p = palloc();
- bufidx(pos);
+ b->pos = bufidx(b, pos)->prev;
p->f = b->append;
p->off = ftell(b->append);
- p->len = strlen(buf);
+ p->len = slen;
/* p->undo = ?? */
p->redo = NULL;
- p->prev = b->pos->prev;
+ p->prev = b->pos;
p->next = b->pos->next;
- b->pos->next = p;
- fprintf(b->append, "%s", buf);
+ b->pos->next = b->pos->next->prev = p;
+
+ fprintf(b->append, "%s", s);
if (ferror(b->append)) {
perror("failed to write to append file");
- --npieces;
- memset(ins, 0, sizeof(Piece));
+ pfree(p);
+ p = 0;
+ } else {
+ b->idx += slen;
+ b->pos = p->next;
}
- return (ins->f == 0) ? b->size : (b->size += slen);
+
+ return (p == 0) ? b->size : (b->size += slen);
}
diff --git a/buf.h b/buf.h
@@ -18,3 +18,5 @@ typedef struct Buf {
Buf *bufinit(const char *fpath);
Piece *bufidx(Buf *b, size_t pos);
+
+size_t bufins(Buf *b, size_t pos, const char *s);
diff --git a/test.c b/test.c
@@ -39,30 +39,16 @@ void test_bufinit()
assert(b->read);
assert(b->append);
- p = b->tail;
- assert(p);
- assert(p->f == NULL);
- assert(p->off == 0);
- assert(p->len == 0);
- assert(p->next == b->pos);
- assert(p->prev == NULL);
+ assert(b->pos == b->tail);
+ assert(b->pos == b->head);
p = b->pos;
assert(p);
assert(p->f == b->read);
assert(p->off == 0);
assert(p->len == strlen(INBUF));
- assert(p->prev == b->tail);
- assert(p->next == b->head);
-
- p = b->head;
- assert(p);
- assert(p);
- assert(p->f == NULL);
- assert(p->off == 0);
- assert(p->len == 0);
+ assert(p->prev == NULL);
assert(p->next == NULL);
- assert(p->prev == b->pos);
}
void test_bufidx()
@@ -71,11 +57,29 @@ void test_bufidx()
p = bufidx(b, idx);
assert(p == b->pos);
+ assert(p == b->head);
+ assert(p->prev == b->tail);
assert(p->f == b->read);
assert(p->off == idx);
assert(p->len == strlen(INBUF) - idx);
- assert(p->prev != b->tail);
- assert(p->next == b->head);
+}
+
+void test_bufins()
+{
+ const char *buf = "y";
+ const size_t idx = 2, len = strlen(buf);
+ bufins(b, idx, buf);
+
+ assert(b->size == strlen(INBUF) + len);
+ assert(b->idx == idx + len);
+ assert(b->pos == b->tail->next->next);
+ assert(b->pos->f == b->read);
+ assert(b->pos->off == 2);
+ assert(b->pos->len == 3);
+ assert(b->pos->undo == NULL);
+ assert(b->pos->redo == NULL);
+ assert(b->pos->prev == b->tail->next);
+ assert(b->pos->next == b->head);
}
int main()
@@ -83,6 +87,7 @@ int main()
setup();
test_bufinit();
test_bufidx();
+ test_bufins();
puts("success - no assertions failed");
return 0;
}