/* strbuff.c -- Support code for strCache class
   
   This is a dynamically resizing string buffer.  Output is written to
   an external buffer, and then appended to the internal buffer.
   Internal state maintains a pointer to the current end of the
   string.  If the buffer to be appended would cause an overflow of
   the internal buffer, the internal string is doubled in size before
   the copy.

   Based on an idea by Jeremy Buhler (jbuhler@rice.edu). */


#include "strbuff.h"
#include "commondefs.h"

#define INITSIZE 1024

/* exits with an error message -- for use in non-parallel mode */
void errExit(errmsg)
char* errmsg;
{
  fprintf(stderr, "%s\n", errmsg);
  exit(-1);
}


/* "Constructor" for strBuff.
   Allocates space for a single strBuff object. */
strBuff* newStrBuff()
{
#if PARALLEL
  strBuff* newBuff = (strBuff*) Tmk_malloc(sizeof(strBuff));
  if (newBuff == NULL)
    Tmk_errexit("MALLOC ERROR - newStrBuff\n");

  newBuff->string = (char*) Tmk_malloc(INITSIZE * sizeof(char));
  if (newBuff->string == NULL)
    Tmk_errexit("MALLOC ERROR - newBuff->string\n");
#else  /* if PARALLEL */
  strBuff* newBuff = (strBuff*) malloc(sizeof(strBuff));
  if (newBuff == NULL)
    errExit("couldn't malloc newBuff");

  newBuff->string = (char*) calloc(INITSIZE, sizeof(char));
  if (newBuff->string == NULL)
    errExit("couldn't malloc newBuff->string");
#endif  /* if PARALLEL */
  
  newBuff->string[0] = '\0';
  newBuff->size = INITSIZE;
  newBuff->stindex = 0;
  
  return newBuff;
}


/* Appends string in buffer to the internal string in a strBuff
   object.  If appending the string in buffer would cause an
   overflow, the internal string is doubled in size first. */
void append(sBuff, buffer)
strBuff* sBuff;
char* buffer;
{
  int length = strlen(buffer);
  
  if (sBuff->stindex + length >= sBuff->size)
    {
      char* newString;
      /* double the size of the string */
      sBuff->size <<= 1;
#if PARALLEL
      newString = (char*) Tmk_malloc(sBuff->size * sizeof(char));
      if (newString == NULL)
	Tmk_errexit("MALLOC ERROR - resizing in append\n");
#else  /* if PARALLEL */
      newString = (char*) calloc(sBuff->size, sizeof(char));
      if (newString == NULL)
	errExit("couldn't malloc newString");
#endif
      strcpy(newString, sBuff->string);
#if PARALLEL
      Tmk_free(sBuff->string);
#else
      free(sBuff->string);
#endif
      sBuff->string = newString;
    }
  
  /* append buffer to the internal string */
  strcpy(sBuff->string + sBuff->stindex, buffer);
  sBuff->stindex += length;
}


