#include "RMFBufferP.h"
#include "al.h"
#include "string.h"

#define DEFAULT_CHUNK 80
/*--------------------------------------------------*/
RMFBuffer RMFBuffer_create(s,Chunk)
char *s;
unsigned Chunk;
{
  RMFBuffer Buff;

  Buff=(RMFBuffer)Memory_allocate(sizeof(struct RMFBuffer_str));
  if (s==NULL)
    s="";
  Buff->StringSize=strlen(s);
  Buff->buff=strcpy(Memory_allocate(Buff->StringSize+1),s);
  if (Chunk<1) {
    Al_warning("RMFBuffer: Chunk size request less than 1: setting Chunk size to default");
    Chunk=DEFAULT_CHUNK;
  }
  Buff->Chunks=Chunk;
  Buff->Index=0;
  Buff->HasBuff=0;
  Buff->BuffSize=Buff->StringSize+1;
  return(Buff);
}

/*--------------------------------------------------*/
char * RMFBuffer_get_next_chunk(Buff,fooc)
RMFBuffer Buff;
int fooc; 
{
  char *s, c;
  unsigned Bi, Si, Ssize, Bsize;
  Ssize=Buff->Chunks;
  s=(char *)Memory_allocate(Ssize);
  Bsize=Buff->StringSize;
  Bi=Buff->Index;
  Si=0;
  if (Buff->buff[Bi]=='\0')  /* at end of RMFBuffer */
    return(NULL);
  do {
    c=Buff->buff[Bi];
    if (Si+1==Ssize)
      s=Memory_reallocate(s,(Ssize+=Buff->Chunks));
    s[Si]=c;
    Si++;
    Bi++;
  } while (c!=(char)fooc && Bi<Bsize);
  if (c==(char)fooc)
    s[Si-1]='\0';  /* do not include the terinating symbol */
  else
    s[Si]='\0';
  Buff->Index=Bi;
  return(s);
}

/*--------------------------------------------------*/
NORET RMFBuffer_destroy_chunk(Buff,chunk)
RMFBuffer Buff;  /* for error checking.  Not used right now */
char *chunk;
{
  Memory_free(chunk);
}

/*--------------------------------------------------*/
NORET RMFBuffer_destroy(Buff)
RMFBuffer Buff;
{
  if (Buff->HasBuff==0)
    Memory_free(Buff->buff);
  Memory_free(Buff);
}

/*--------------------------------------------------*/
NORET RMFBuffer_append(Buff,s)
RMFBuffer Buff;
char *s;
{
  int SSize;

  /* make sure theres enough space in the buffer */
  SSize=strlen(s);
  Buff->StringSize+=SSize;
  while (Buff->BuffSize<=Buff->StringSize) 
    Buff->buff=(char *)Memory_reallocate(Buff->buff,
					 (Buff->BuffSize+=SSize));
  
  Buff->buff=strcat(Buff->buff,s);
}

/*--------------------------------------------------*/
NORET RMFBuffer_append_char(Buff,is)
RMFBuffer Buff;
int is;
{
  char s=(char)is;
  /* make sure theres enough space in the buffer */
  if (Buff->StringSize+2>=Buff->BuffSize)
    Buff->buff=(char *)Memory_reallocate(Buff->buff,
					 (Buff->BuffSize+=Buff->Chunks));
  Buff->buff[Buff->StringSize++]=s;
  Buff->buff[Buff->StringSize]='\0';
}

/*--------------------------------------------------*/
char * RMFBuffer_copy_of_buff(Buff)
RMFBuffer Buff;
{
  char *s;
  if (Buff->HasBuff==1) {
    s=Memory_allocate(Buff->StringSize+1);  /* inneficient space use but */
    s=strcpy(s,Buff->buff);
    return(s);
  }
  else {
    Buff->HasBuff=1;
    return(Buff->buff);
  }
}


/*--------------------------------------------------*/
int RMFBuffer_length_of_string(B)
RMFBuffer B;
{
  return(B->StringSize);
}
