commit 9b76662831fccb39c45ec4cc5e2223fe150a0fbd
Author: gearsix <gearsix@tuta.io>
Date: Sat, 30 Apr 2022 13:39:24 +0100
git init; Piece, Buf, palloc, psplit, bufinit, bufidx.
Diffstat:
A | Makefile | | | 8 | ++++++++ |
A | buf.c | | | 91 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | buf.h | | | 20 | ++++++++++++++++++++ |
A | test.c | | | 88 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
4 files changed, 207 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,8 @@
+SRC := buf.c
+OUT := ec
+OPTS := -g -Wall -Wpedantic -std=c89
+
+all:
+ ${CC} $(OPTS) $(SRC) main.c -o $(OUT)
+test:
+ ${CC} $(OPTS) $(SRC) test.c -o $(OUT)
diff --git a/buf.c b/buf.c
@@ -0,0 +1,91 @@
+
+#include "buf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+Piece *palloc()
+{
+ static Piece *pieceblk = NULL;
+ static size_t nblk = 0, npieces = 0;
+ static const size_t blksiz = BUFSIZ/sizeof(Piece);
+
+ 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++];
+}
+
+Piece *psplit(Piece *p, long int offset)
+{
+ Piece *q = palloc();
+ if (offset > 0) {
+ memcpy(q, p, sizeof(Piece));
+
+ q->off += offset;
+ q->len -= p->len = offset;
+ q->next = p->next;
+ q->prev = p;
+ p->next = q->next->prev =q;
+
+ p = q;
+ }
+ return p;
+}
+
+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;
+
+ if (fpath) {
+ b->read = fopen(fpath, "rb");
+ if (ferror(b->read)) perror(fpath);
+
+ b->pos->f = b->read;
+ fseek(b->read, 0, SEEK_END);
+ b->size = b->pos->len = ftell(b->read);
+ }
+
+ return b;
+}
+
+Piece *bufidx(Buf *b, size_t pos)
+{
+ size_t idx = b->idx, offset;
+ Piece *p = b->pos;
+
+ if (pos >= idx) {
+ while (pos >= idx + p->len && p->next) {
+ idx += p->len;
+ p = p->next;
+ }
+ } else {
+ do {
+ p = p->prev;
+ idx -= p->len;
+ } while(pos > idx && p->prev);
+ }
+
+ if (idx == pos) {
+ b->idx = idx;
+ b->pos = p;
+ } else {
+ offset = (idx >= pos) ? idx - pos : pos - idx;
+ b->pos = psplit(p, offset);
+ b->idx = pos;
+ }
+
+ return b->pos;
+}
+
+void bufins(Buf *b, size_t pos, const char *buf)
+{
+}
diff --git a/buf.h b/buf.h
@@ -0,0 +1,20 @@
+/* TODO */
+#include <stdio.h>
+
+typedef struct Piece {
+ FILE *f;
+ size_t off, len;
+
+ struct Piece *undo, *redo;
+ struct Piece *prev, *next;
+} Piece;
+
+typedef struct Buf {
+ FILE *read, *append;
+ size_t size, idx;
+ struct Piece *tail, *pos, *head;
+} Buf;
+
+Buf *bufinit(const char *fpath);
+
+Piece *bufidx(Buf *b, size_t pos);
diff --git a/test.c b/test.c
@@ -0,0 +1,88 @@
+#include "buf.h"
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#define INFILE "in.txt"
+#define INBUF "hello world"
+#define OUTFILE "out.txt"
+#define OUTBUF "hey buddy!" /* tests will aim to change INBUF to this */
+
+Buf *b;
+
+void setup()
+{
+ FILE *in = fopen(INFILE, "w+b");
+ if (ferror(in)) perror("fopen in.txt");
+ fputs(INBUF, in);
+ fclose(in);
+
+ return;
+}
+
+void print(Buf *b)
+{
+ Piece *p;
+
+ printf("b->tail: %p\tb->pos: %p\tb->head: %p\n\n",
+ (void *)b->tail, (void *)b->pos, (void *)b->head);
+
+ for (p = b->tail; p != NULL; p = p->next)
+ printf("%p\n", (void *)p);
+}
+
+void test_bufinit()
+{
+ Piece *p;
+ b = bufinit(INFILE);
+
+ 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);
+
+ 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->next == NULL);
+ assert(p->prev == b->pos);
+}
+
+void test_bufidx()
+{
+ Piece *p; size_t idx = 5;
+ p = bufidx(b, idx);
+
+ assert(p == b->pos);
+ 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);
+}
+
+int main()
+{
+ setup();
+ test_bufinit();
+ test_bufidx();
+ puts("success - no assertions failed");
+ return 0;
+}