// Common, group Buffers
// Copyright Alexander Liss
#ifndef __COMMBUF_H__
#define __COMMBUF_H__
// ReadControl
// limit zero - no limit
// offset zero - read from write_start()
// last_bits - bits to read in last byte (for crypto)
struct ReadControl
{
int offset, limit, last_bits;
ReadControl():offset(0),limit(0),last_bits(8){}
void reset(){offset=limit=0;last_bits=8;}
void move(int n){offset+=n;}
int check()const
{if(offset<0 || limit<0 || last_bits<0 || last_bits>8) return 1; return 0;}
};
// CommBuffer
// an array of bytes (unsigned char) with a write-offset for headers
// can be interpreted as a string if needed:
// data==0 or start()[data_size]==0
// back_allocated() >= data_size+1
// encoding types are in encoding.h
class CommBuffer
{
public:
int data_size, allocated, write_offset, encoding;
unsigned char * data;
CommBuffer(int Increment=128):
increment(Increment),data_size(0),allocated(0),write_offset(0),encoding(0),data(0)
{allocate(increment);}
CommBuffer(const char * from,int size):
increment(128),data_size(0),allocated(0),write_offset(0),encoding(0),data(0)
{set(from,size);}
CommBuffer(const CommBuffer& s):
increment(s.increment),data_size(0),allocated(0),data(0)
{ if(s.data){allocate(s.allocated); copy(s);}}
~CommBuffer();
CommBuffer& operator=(const CommBuffer& s)
{ if(&s != this){if(!data) allocate(s.allocated); copy(s);}; return *this;}
int front_allocated()const
{return write_offset;}
int back_allocated()const
{return allocated-write_offset;}
int space_left()const
{ int r=allocated-write_offset-data_size;return r>=0?r:0;}
int data_left(const ReadControl& c)const
{ return data_size-c.offset;}
int check(const ReadControl& c)const
{ if(c.check()) return 1; if(data_left(c)<0) return 2; return 0;}
unsigned char * write_start()const
{return data+write_offset;}
unsigned char * read_start(const ReadControl& c)const
{ return write_start()+c.offset;}
int reset(){ data_size=write_offset=0; return 0;}
int reallocate(int new_size);
// set functions override old data
int set(const CommBuffer& s,ReadControl& c)
{ return set(s.read_start(c),s.data_left(c));}
int set(const char * string);
int set(const unsigned char * from,int size);
int set(const char * from,int size)
{return set((unsigned char *)from,size);}
int set(int number, char symbol);
// append functions add data to old data
int append(const CommBuffer& s,ReadControl& c)
{return append(s.read_start(c),s.data_left(c));}
int append(const char * string);
int append(const unsigned char * from,int size);
int append(const char * from,int size)
{return append ((unsigned char *)from,size);}
int append(int number, char symbol);
// prepend functions add data in front of existing data
int prepend(const CommBuffer& s,ReadControl& c)
{return prepend(s.read_start(c),s.data_left(c));}
int prepend(const unsigned char * from,int size);
int prepend(const char * from,int size)
{return prepend((unsigned char *)from,size);}
int prepend(int number, char symbol);
// a byte data[n+write_offset] becomes data[write_offset], drops first written n bytes
int shift(int n);
private:
int increment;
int copy(const CommBuffer& s);
int allocate(int size);
};
/*
// inline functions
inline
unsigned char * read_start(const CommBuffer& b,const ReadControl& c)
{ return b.write_start()+c.offset;}
inline
int data_left(const CommBuffer& b,const ReadControl& c)
{ return b.data_size-c.offset;}
inline
int space_left(const CommBuffer& b)
{ int r=b.allocated-b.write_offset-b.data_size;return r>=0?r:0;}
inline
int check(const CommBuffer& b,const ReadControl& c)
{ if(c.check()) return 1; if(data_left(b,c)<0) return 2; return 0;}
inline
int set(CommBuffer& d,const CommBuffer& s,ReadControl& c)
{ return d.set(read_start(s,c),data_left(s,c));}
inline
int append(CommBuffer& d,const CommBuffer& s,ReadControl& c)
{return d.append(read_start(s,c),data_left(s,c));}
*/
#endif