#include "ebuffer.h"

#define BUFFERSIZE 1024

estrbuffer::estrbuffer(): _strlen(BUFFERSIZE), _str(new char[BUFFERSIZE]), full(false), ipos(0), epos(0) {}
estrbuffer::estrbuffer(const estrbuffer& oldbuffer): _strlen(oldbuffer._strlen), _str(new char[oldbuffer._strlen]), full(oldbuffer.full), ipos(0),epos(0)
{
  if (oldbuffer.ipos==oldbuffer.epos && !oldbuffer.full) return;

  if (oldbuffer.ipos < oldbuffer.epos){
    memcpy(_str,&oldbuffer._str[oldbuffer.ipos],oldbuffer.epos-oldbuffer.ipos);
    return;
  }

  memcpy(_str,&oldbuffer._str[oldbuffer.ipos],oldbuffer._strlen-oldbuffer.ipos);
  memcpy(&_str[oldbuffer._strlen-oldbuffer.ipos],oldbuffer._str,oldbuffer.epos);
  epos=oldbuffer._strlen-oldbuffer.ipos+oldbuffer.epos;
}

estrbuffer::~estrbuffer()
{
  delete[] _str;
}

void estrbuffer::resize(int newsize)
{
  if (newsize<=_strlen) return;

  int oldstrlen=_strlen;
  char *oldstr=_str;
  _str=new char[newsize];
  _strlen=newsize;
  if (ipos<epos){
    memcpy(_str,&oldstr[ipos],epos-ipos);
    delete[] oldstr;
    epos-=ipos;
    ipos=0;
    return;
  }
  if (ipos==epos && !full) { ipos=0; epos=0; return; }

  full=false;
  memcpy(_str,&oldstr[ipos],oldstrlen-ipos);
  memcpy(&_str[oldstrlen-ipos],oldstr,epos);
  epos=epos+oldstrlen-ipos;
  ipos=0;
}

bool estrbuffer::getline(estr& line)
{
  line.clear();
  if (ipos==epos && !full) return(false);

  int i;
  if (epos>ipos){
    for (i=ipos; i<epos && _str[i]!=0x0A; ++i);
    if (i==epos) return(false); // newline not found
    line.reserve(i-ipos);
    memcpy(line._str,&_str[ipos],i-ipos);
    line._strlen=i-ipos;
    ipos=(i+1)%_strlen;
    if (size()==0) { ipos=0; epos=0; }
    return(true);
  }

  for (i=ipos; i<_strlen && _str[i]!=0x0A; ++i);
  if (i==_strlen)
    for (i=0; i<epos && _str[i]!=0x0A; ++i);
  if (i==epos) return(false); // newline not found 

  full=false;
  if (i >= ipos){
    line.reserve(i-ipos);
    memcpy(line._str,&_str[ipos],i-ipos);
    line._strlen=i-ipos;
    ipos=(i+1)%_strlen;
    if (size()==0) { ipos=0; epos=0; }
    return(true);
  }

  line.reserve(i+_strlen-ipos);
  memcpy(line._str,&_str[ipos],_strlen-ipos);
  memcpy(&line._str[_strlen-ipos],_str,i);
  line._strlen=i+_strlen-ipos;
  ipos=(i+1)%_strlen;
  if (size()==0) { ipos=0; epos=0; }
  return(true);
}

void estrbuffer::getstr(estr& line)
{
  line.clear();
  if (ipos==epos && !full) return;

  int i;
  if (epos>ipos){
    line.reserve(epos-ipos);
    memcpy(line._str,&_str[ipos],epos-ipos);
    line._strlen=epos-ipos;
    return;
  }

  line.reserve(epos+_strlen-ipos);
  memcpy(line._str,&_str[ipos],_strlen-ipos);
  memcpy(&line._str[_strlen-ipos],_str,epos);
  line._strlen=epos+_strlen-ipos;
}

