commit 2f3ea34be6b3b10dcf43e89941a6a35394c3c2af
parent 003fd961221b10fd75960257c508b107e252bb27
Author: gearsix <gearsix@tuta.io>
Date: Sat, 9 Jul 2022 15:42:05 +0100
added comment doc to buf.{h,c}; removed unused undo, redo in Piece.
Diffstat:
M | buf.c | | | 33 | ++++++++++++++++++++++++++------- |
M | buf.h | | | 18 | +++++++++++++++++- |
M | test.c | | | 6 | ------ |
3 files changed, 43 insertions(+), 14 deletions(-)
diff --git a/buf.c b/buf.c
@@ -4,9 +4,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
-static Piece *pieceblk = NULL; /* block of all pieces */
-static Piece **freeblk = NULL; /* ptr block to all free'd `pieceblk` items */
+static Piece *pieceblk = NULL;
+static Piece **freeblk = NULL;
static void pclean()
{
@@ -14,6 +15,10 @@ static void pclean()
free(pieceblk);
}
+/* adds `p` to `freeblk` and returns the last added `freeblk` item.
+ If `p` is NULL, the last added `freeblk` item will be returned,
+ or NULL if `freeblk` is empty.
+ `freeblk` is dynamically allocated. */
static Piece *pfree(Piece *p)
{
static size_t nblk = 0, nfree = 0;
@@ -28,6 +33,12 @@ static Piece *pfree(Piece *p)
return freeblk[nfree++] = p;
}
+/* returns the next available `Piece` item in `pieceblk`.
+ If `freeblk` is not empty, it's last item pointed to by it will be
+ returned (recycling `pieceblk` items). The returned `Piece` will
+ always have it's values set to 0. `pieceblk` is dynamically
+ allocated.
+ `atexit(pclean)` is called the first time the function is called. */
static Piece *palloc()
{
Piece *p;
@@ -36,7 +47,7 @@ static Piece *palloc()
static const size_t blksiz = BUFSIZ/sizeof(Piece);
static int hook = 0;
- if (hook == 0) { atexit(pclean); hook = 1; }
+ if (!hook) { atexit(pclean); hook = 1; }
if ( !(p = pfree(NULL)) ) {
if (nalloc + 1 > blksiz * nblk)
@@ -48,10 +59,18 @@ static Piece *palloc()
return memset(p, 0, sizeof(Piece));
}
+/* splits `p` into two `Piece` items. The values of `p` will be
+ modified to fit the first `Piece`; a new `Piece` will be allocated
+ for the second.
+ The `prev` and `next` items of these & associated `Piece` items will
+ be updated to reflect the new `Piece`.
+ `offset` should be the offset within `p->len` to split at. If offset
+ is not within the boundry of `p->len`, then `p` will be returned.
+ The *first* `Piece` in the split is returned. */
static Piece *psplit(Piece *p, long int offset)
{
Piece *q = palloc();
- if (offset > 0) {
+ if (offset > 0 && offset <= (int)p->len) {
memcpy(q, p, sizeof(Piece));
q->off += offset;
@@ -70,7 +89,7 @@ struct Buf *bufinit(FILE *read, FILE *append)
{
Buf *b = calloc(1, sizeof(Buf));
- if (!read || !append) return NULL;
+ if (!append) return NULL;
b->read = read;
b->append = append;
@@ -133,8 +152,6 @@ size_t bufins(Buf *b, size_t pos, const char *s)
p->f = b->append;
p->off = ftell(b->append);
p->len = slen;
- p->undo = NULL;
- p->redo = NULL;
p->prev = b->pos;
p->next = b->pos->next;
@@ -183,7 +200,9 @@ int bufout(Buf *b, FILE *f)
do {
buf[0] = '\0';
fread(buf, 1, p->len, p->f);
+ if (ferror(p->f)) { perror("bufout: fread failed"); break; }
fsiz += fwrite(buf, 1, p->len, f);
+ if (ferror(f)) { perror("bufout: fwrite failed"); break; }
} while (p->len - (BUFSIZ*n++) > BUFSIZ);
p = p->next;
diff --git a/buf.h b/buf.h
@@ -1,11 +1,14 @@
/* TODO */
#include <stdio.h>
+/* Points to a file (`f`), which contains a string which
+ starts within `f` at `off` and has a length of `len`.
+ `prev` and `next` point to the previous and next
+ `Piece` elements in the intended double-linked list. */
typedef struct Piece {
FILE *f;
size_t off, len;
- struct Piece *undo, *redo;
struct Piece *prev, *next;
} Piece;
@@ -15,14 +18,27 @@ typedef struct Buf {
struct Piece *tail, *pos, *head;
} Buf;
+/* Allocates & initialises a `Buf`. If `append` is NULL,
+ nothing is allocated or initialised and NULL is
+ returned. */
Buf *bufinit(FILE *read, FILE *append);
+/* Frees `b` and all `Piece` items associated with it. */
void buffree(Buf *b);
+/* Set `b->idx` to `pos` and `b->pos` to the `Piece`
+ in the chain, where the start of `b->pos->next`
+ is `pos`. */
Piece *bufidx(Buf *b, size_t pos);
+/* Adds a new `Piece` to the chain, at `pos` (found
+ using `bufidx`). `s` will be appended to `b->append`
+ and the new `Piece` will reflect the appended data. */
size_t bufins(Buf *b, size_t pos, const char *s);
+/* Removed all pieces from index `pos` to `pos+num`.
+ `pos` and `pos+num` are found using `bufidx`. */
size_t bufdel(Buf *b, size_t pos, size_t num);
+/* writes all data in `b` to `f`. */
int bufout(Buf *b, FILE *f);
diff --git a/test.c b/test.c
@@ -100,8 +100,6 @@ void test_bufins()
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);
}
@@ -120,8 +118,6 @@ void test_bufdel()
assert(b->pos->f == b->read);
assert(b->pos->off == 11);
assert(b->pos->len == 0);
- assert(b->pos->undo == NULL);
- assert(b->pos->redo == NULL);
assert(b->pos->prev == b->tail->next);
assert(b->pos->next == NULL);
}
@@ -141,8 +137,6 @@ void test_bufins1()
assert(b->pos->prev->f == b->append);
assert(b->pos->prev->off == 1);
assert(b->pos->prev->len == len);
- assert(b->pos->undo == NULL);
- assert(b->pos->redo == NULL);
assert(b->pos->prev == b->tail->next->next);
assert(b->pos->next == NULL);
}