/*
Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/
/* configure all options BEFORE including system stuff. */
#include "config.h"
#include "mud.h"
#include "sbuf.h"
/* increment to stretch a stretchy buffer by */
#define SBUF_INCR 256
char _sbufgrow (c, b)
char c;
Sbuf *b;
{
char *xp;
if (b == (Sbuf *) 0)
return ('\0');
if (b->buf == (char *) 0) {
b->bsiz = SBUF_INCR;
if ((b->buf = (char *) malloc (b->bsiz)) == (char *) 0)
return ('\0');
b->bc = b->bsiz;
b->bp = b->buf;
} else {
int xoff = (int) (b->bp - b->buf);
b->bsiz += SBUF_INCR;
/* disaster */
if ((xp =
(char *) realloc ((mall_t) b->buf,
(unsigned) b->bsiz)) == (char *) 0) {
b->bp = (char *) 0;
b->bc = 0;
b->bsiz = 0;
return ('\0');
}
b->buf = xp;
b->bp = xp + xoff;
b->bc = SBUF_INCR;
}
b->bc--;
return (*(b->bp)++ = c);
}
/* reset a stretchy buffer to a clean slate. */
void sbuf_reset (b)
Sbuf *b;
{
if (b == (Sbuf *) 0 || b->buf == (char *) 0)
return;
/* figure out the average size used so far - DO FIRST! */
if (b->bp != b->buf && b->rct < 100000) {
b->avg = ((b->avg * b->rct) + sbuf_len (b)) / (b->rct + 1);
b->rct++;
}
b->bp = b->buf;
b->bc = b->bsiz - 1;
*(b->bp) = '\0';
/* if the buffer is statistically rather large, free it */
if ((int) b->bsiz > SBUF_INCR && (int) b->bsiz > (b->avg + SBUF_INCR)) {
(void) free ((mall_t) b->buf);
b->bp = b->buf = (char *) 0;
b->bsiz = 0;
b->bc = 0;
}
}
Sbuf *sbuf_new ()
{
Sbuf *b;
if ((b = (Sbuf *) malloc (sizeof (Sbuf))) == (Sbuf *) 0)
return ((Sbuf *) 0);
b->bp = (char *) 0;
b->buf = (char *) 0;
b->bc = b->bsiz = b->rct = b->avg = 0;
return (b);
}
void sbuf_free (b)
Sbuf *b;
{
if (b == (Sbuf *) 0)
return;
if (b->buf != (char *) 0)
(void) free ((mall_t) b->buf);
/* in case some bonehead tries to use one after deallocation :) */
b->bp = b->buf = (char *) 0;
b->bc = 0;
b->bsiz = 0;
free ((mall_t) b);
}
void sbuf_freestatic (b)
Sbuf *b;
{
if (b->buf != (char *) 0)
(void) free ((mall_t) b->buf);
b->bp = b->buf = (char *) 0;
b->bc = 0;
b->bsiz = 0;
}
void sbuf_initstatic (b)
Sbuf *b;
{
b->bp = b->buf = (char *) 0;
b->bc = 0;
b->bsiz = 0;
b->avg = b->rct = 0;
}
char *sbuf_strcpy (s, sb)
char *s;
Sbuf *sb;
{
sbuf_reset (sb);
while (*s != '\0') {
sbuf_put (*s, sb);
s++;
}
sbuf_put ('\0', sb);
return (sbuf_buf (sb));
}
char *sbuf_strcat (char *s, Sbuf * sb)
{
/* lose trailing null (if one) */
if (sb->bp > sb->buf && *(sb->bp - 1) == '\0')
sbuf_unput (sb);
while (*s != '\0') {
sbuf_put (*s, sb);
s++;
}
sbuf_put ('\0', sb);
return (sbuf_buf (sb));
}
/*
read a line from a Buf into an Sbuf.
*/
char *sbuf_fgets (s, f)
FILE *f;
Sbuf *s;
{
int c;
if (f == (FILE *) 0 || s == (Sbuf *) 0 || ferror (f))
return ((char *) 0);
sbuf_reset (s);
while (1) {
c = getc (f);
if (c == EOF || ferror (f)) {
if (s->bp == s->buf)
return ((char *) 0);
sbuf_put ('\0', s);
return (sbuf_buf (s));
}
if (c == '\n') {
sbuf_put ('\0', s);
return (sbuf_buf (s));
}
sbuf_put (c, s);
}
}