untermud/DOC/
untermud/DOC/U/
untermud/DOC/U/U-examples/
untermud/DOC/internals/
untermud/DOC/wizard/
untermud/MISC/
untermud/MISC/dbchk/
untermud/RWHO/
untermud/RWHO/rwhod/
/*
    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);
  }
}