CSE320/hw2/src/buffer.c
Renge c1c2feb549 fix: implemented errmsg
feat: implemented errmsg
2022-03-04 12:24:48 -05:00

210 lines
4.5 KiB
C

/*********************/
/* buffer.c */
/* for Par 3.20 */
/* Copyright 1993 by */
/* Adam M. Costello */
/*********************/
/* This is ANSI C code. */
/* additem(), copyitems(), and nextitem() rely on the fact that */
/* sizeof (char) is 1. See section A7.4.8 of The C Programming */
/* Language, Second Edition, by Kerninghan and Ritchie. */
#include "buffer.h" /* Makes sure we're consistent with the */
/* prototypes. Also includes <stddef.h> */
#include "errmsg.h"
#include <stdlib.h>
#include <string.h>
#undef NULL
#define NULL ((void *) 0)
struct buffer {
struct block *firstblk, /* The first block. */
*current, /* The last non-empty block, or */
/* firstblk if all are empty. */
*nextblk; /* The block containing the item to be */
/* returned by nextitem(), or NULL. */
int nextindex; /* Index of item in nextblock->items. */
size_t itemsize; /* The size of an item. */
};
struct block {
struct block *next; /* The next block, or NULL if none. */
void *items; /* Storage for the items in this block. */
int maxhere, /* Number of items that fit in *items. */
numprevious, /* Total of numhere for all previous blocks. */
numhere; /* The first numhere slots in *items are filled. */
};
struct buffer *newbuffer(size_t itemsize)
{
struct buffer *buf;
struct block *blk;
void *items;
int maxhere;
maxhere = 124 / itemsize;
if (maxhere < 4) maxhere = 4;
buf = (struct buffer *) malloc(sizeof (struct buffer));
blk = (struct block *) malloc(sizeof (struct block));
items = malloc(maxhere * itemsize);
if (!buf || !blk || !items) {
set_error(outofmem);
goto nberror;
}
buf->itemsize = itemsize;
buf->firstblk = buf->current = buf->nextblk = blk;
buf->nextindex = 0;
blk->numprevious = blk->numhere = 0;
blk->maxhere = maxhere;
blk->items = items;
blk->next = NULL;
clear_error();
return buf;
nberror:
if (buf) free(buf);
if (blk) free(blk);
if (items) free(items);
return NULL;
}
void freebuffer(struct buffer *buf)
{
struct block *blk, *tmp;
blk = buf->firstblk;
while (blk) {
tmp = blk;
blk = blk->next;
if (tmp->items) free(tmp->items);
free(tmp);
}
free(buf);
}
void clearbuffer(struct buffer *buf)
{
struct block *blk;
for (blk = buf->firstblk; blk; blk = blk->next)
blk->numhere = 0;
buf->current = buf->firstblk;
}
void additem(struct buffer *buf, const void *item)
{
struct block *blk, *new;
void *items;
int maxhere;
size_t itemsize = buf->itemsize;
blk = buf->current;
if (blk->numhere == blk->maxhere) {
new = blk->next;
if (!new) {
maxhere = 2 * blk->maxhere;
new = (struct block * ) malloc(sizeof (struct block));
items = malloc(maxhere * itemsize);
if (!new || !items) {
set_error(outofmem);
goto aierror;
}
blk->next = new;
new->next = NULL;
new->maxhere = maxhere;
new->numprevious = blk->numprevious + blk->numhere;
new->numhere = 0;
new->items = items;
}
blk = buf->current = new;
}
memcpy( ((char *) blk->items) + (blk->numhere * itemsize), item, itemsize );
++blk->numhere;
clear_error();
return;
aierror:
if (new) free(new);
if (items) free(items);
}
int numitems(struct buffer *buf)
{
struct block *blk = buf->current;
return blk->numprevious + blk->numhere;
}
void *copyitems(struct buffer *buf)
{
int n;
void *r;
struct block *blk, *b;
size_t itemsize = buf->itemsize;
b = buf->current;
n = b->numprevious + b->numhere;
if (!n) return NULL;
r = malloc(n * itemsize);
if (!r) {
set_error(outofmem);
return NULL;
}
b = b->next;
for (blk = buf->firstblk; blk != b; blk = blk->next)
memcpy( ((char *) r) + (blk->numprevious * itemsize),
blk->items, blk->numhere * itemsize);
clear_error();
return r;
}
void rewindbuffer(struct buffer *buf)
{
buf->nextblk = buf->firstblk;
buf->nextindex = 0;
}
void *nextitem(struct buffer *buf)
{
void *r;
if (!buf->nextblk || buf->nextindex >= buf->nextblk->numhere)
return NULL;
r = ((char *) buf->nextblk->items) + (buf->nextindex * buf->itemsize);
if (++buf->nextindex >= buf->nextblk->maxhere) {
buf->nextblk = buf->nextblk->next;
buf->nextindex = 0;
}
return r;
}