// Common, group Buffers
// Copyright Alexander Liss
#include <string.h>
#include "strbuf.h"
// memory allocation in multiples of "increment"
int StrBuffer::allocate(int size)
{
if(size<=0) allocated=increment;
else
{
allocated=size/increment*increment;
if(allocated<size)
allocated+=increment;
}
data=new char[allocated];
if(!data)
{
allocated=0;
return 1;
}
memset(data,0,allocated);
return 0;
}
// copy function used by copy constructor and assignment operator
int StrBuffer::copy(const StrBuffer& s)
{
if(!data) return 1;
int g=0;
if(allocated<s.data_size+1)
g=reallocate(s.data_size+1);
if(g) return 1;
memcpy(data,s.data,s.data_size);
data_size=s.data_size;
return 0;
}
// constructor, which allows direct setting of "increment"
StrBuffer::StrBuffer(int initial_allocation,int Increment):
increment(Increment),data_size(0),allocated(0),data(0)
{
if(increment<=0) increment=8;
if(initial_allocation<=0) return;
allocate(initial_allocation);
}
// destructor clears memory before deleting data
StrBuffer::~StrBuffer()
{
if(data) memset(data,0,allocated);
delete []data;
}
// memory reallocation in multiples of "increment"
int StrBuffer::reallocate(int size)
{
if(size<=0) size=increment;
if(!data)
return allocate(size);
if(size<data_size+1) return 1;
int new_size=size/increment*increment;
if(new_size<size)
new_size+=increment;
char *old_data=data;
int old_allocated=allocated;
data=new char[new_size];
if(!data)
{
// RESTORE
data=old_data;
return 2;
}
allocated=new_size;
memset(data,0,allocated);
if(old_data)
{
memcpy(data,old_data,data_size);
memset(old_data,0,old_allocated);
delete []old_data;
}
return 0;
}
int StrBuffer::set(const char * from,int size)
{
data_size=0;
if(size<=0 || from==0)
{
if(!data)
allocate(increment);
return 1;
}
if(!data)
allocate(size+1);
if(!data) return 2;
return append(from,size);
}
int StrBuffer::set(int size, char s)
{
data_size=0;
if(size<=0)
{
if(!data)
allocate(increment);
return 1;
}
if(!data)
allocate(size+1);
if(!data) return 2;
return append(size,s);
}
int StrBuffer::set(const char * str)
{
return set(str,strlen(str));
}
int StrBuffer::append(const char * from,int size)
{
if(size<=0 || from==0) return 1;
int g=0;
if(data_size+size+1>allocated)
g=reallocate(data_size+size+1);
if(g) return 2;
memcpy(data+data_size,from,size);
data_size+=size;
data[data_size]=0;
return 0;
}
int StrBuffer::append(int size, char s)
{
if(size<=0) return 1;
int g=0;
if(data_size+size+1>allocated)
g=reallocate(data_size+size+1);
if(g) return 2;
memset(data+data_size,s,size);
data_size+=size;
data[data_size]=0;
return 0;
}
int StrBuffer::append(const char * str)
{
return append(str,strlen(str));
}
// byte data[n] becomes data[0], first n bytes are dropped
int StrBuffer::shift(int n)
{
if(n<0) return 1;
if(n==0) return 0;
if(n>=data_size)
{
memset(data,0,allocated);
data_size=0;
return 0;
}
// copy trailing zero
memcpy(data,data+n,data_size-n+1);
data_size-=n;
return 0;
}