00001 #ifndef ZEBUFFER_H
00002 #define ZEBUFFER_H
00003 #include <abuse/nomem_error.h>
00004 #include <abuse/Debug.h>
00005 #include <string>
00006
00007 #define CHUNK 4096
00008 typedef unsigned int uint;
00009
00010 template<class T>
00011 class ZeBuffer
00012 {
00013 private:
00014 uint m_size;
00015 uint m_allocated;
00016 uint* m_pCounter;
00017 T* m_ptr;
00018 void release()
00019 {
00020 Track("ZeBuffer::release");
00021 if(m_pCounter)
00022 {
00023 DebugOut("Counter: ");
00024 DebugOut(*m_pCounter-1);
00025 if(!(--(*m_pCounter)))
00026 {
00027 DebugOut("Releasing buffer");
00028 delete m_pCounter;
00029 delete[] m_ptr;
00030 }
00031 }
00032 }
00033
00034 void copy()throw (std::nomem_error)
00035 {
00036 Track("ZeBuffer::copy");
00037 if(m_pCounter && (*m_pCounter)>1)
00038 {
00039 uint *tmpCounter=NULL;
00040 T* tmpptr=new T[m_allocated+sizeof(T)];
00041 tmpCounter=new uint(1);
00042 if(!tmpptr || !tmpCounter)
00043 {
00044 delete tmpptr;
00045 delete tmpCounter;
00046 throw std::nomem_error();
00047 }
00048 memcpy((void*)tmpptr,(void*)m_ptr,m_size*sizeof(T));
00049 release();
00050 m_pCounter=tmpCounter;
00051 m_ptr=tmpptr;
00052 }
00053 #ifdef _DEBUG
00054 else
00055 DebugOut("Nothing to copy");
00056 #endif
00057 }
00058 void realloc(uint newsize)throw(std::nomem_error)
00059 {
00060 Track("ZeBuffer::realloc");
00061 DebugOut("Reallocating to bytes ");
00062 DebugOut(newsize);
00063 T* ptr=new T[newsize+sizeof(T)];
00064 if(!ptr)
00065 throw std::nomem_error();
00066 if(m_pCounter)
00067 {
00068 memcpy((void*)ptr,(void*)m_ptr,m_size*sizeof(T));
00069 delete[] ptr;
00070 }
00071 else
00072 m_pCounter=new uint(1);
00073 m_ptr=ptr;
00074 m_allocated=newsize;
00075 }
00076 public:
00077 ZeBuffer(uint initial=0)throw(std::nomem_error)
00078 :m_ptr(NULL),m_size(0),m_allocated(0),m_pCounter(NULL)
00079 {
00080 Track("ZeBuffer::default ctor");
00081 if(initial)
00082 {
00083 m_ptr=new T[initial+sizeof(T)];
00084 m_pCounter=new uint(1);
00085 if(!m_ptr || !m_pCounter)
00086 {
00087 delete m_pCounter;
00088 delete[] m_ptr;
00089 throw std::nomem_error();
00090 }
00091 m_allocated=initial;
00092 }
00093 }
00094
00095 ZeBuffer(T* ptr,uint _size)throw(std::nomem_error)
00096 :m_ptr(ptr),m_size(_size),m_allocated(_size),m_pCounter(NULL)
00097 {
00098 Track("ZeBuffer::ctor grabbing ptr");
00099 if((m_pCounter=new uint(1))==NULL)
00100 {
00101 throw std::nomem_error();
00102 }
00103 }
00104
00105 ZeBuffer(const ZeBuffer& other):
00106 m_ptr(NULL),m_pCounter(NULL)
00107 {
00108 Track("ZeBuffer::copy ctor");
00109 operator=(other);
00110 }
00111 virtual ~ZeBuffer()
00112 {
00113 Track("ZeBuffer::dtor");
00114 release();
00115 }
00116 void operator=(const ZeBuffer& other)
00117 {
00118 Track("ZeBuffer::operator=");
00119 if(this!=&other)
00120 {
00121 release();
00122 m_ptr=other.m_ptr;
00123 m_pCounter=other.m_pCounter;
00124 if(m_pCounter)
00125 {
00126 ++(*m_pCounter);
00127 DebugOut(*m_pCounter);
00128 }
00129 m_size=other.m_size;
00130 m_allocated=other.m_allocated;
00131 }
00132 }
00133 void append(T* ptr,uint _size)throw(std::nomem_error)
00134 {
00135 Track("ZeBuffer::append");
00136 copy();
00137 uint newsize=m_size+_size;
00138 if(newsize>m_allocated)
00139 realloc(roundup(newsize,CHUNK));
00140 memcpy((void*)(m_ptr+m_size),(void*)ptr,_size);
00141 m_size=newsize;
00142 }
00143 ZeBuffer& operator+=(const ZeBuffer& copy)throw(std::nomem_error)
00144 {
00145 Track("ZeBuffer::operator+=(const ZeBuffer&)");
00146 append(copy.m_ptr,copy.m_size);
00147 return *this;
00148 }
00149 ZeBuffer operator+(const ZeBuffer& copy)const throw(std::nomem_error)
00150 {
00151 Track("ZeBuffer::operator+(const ZeBuffer&)");
00152 return ZeBuffer(this).operator+=(copy);
00153 }
00154 ZeBuffer& operator+=(const T& data)throw(std::nomem_error)
00155 {
00156 Track("ZeBuffer::operator+=(const T&)");
00157 copy();
00158 if((++m_size)>m_allocated)
00159 realloc(m_allocated+CHUNK);
00160 m_ptr[m_size-1]=data;
00161 return *this;
00162 }
00163 ZeBuffer operator+(const T& data)const
00164 {
00165 Track("ZeBuffer::operator+(const T&)");
00166 return ZeBuffer(this).operator+=(data);
00167 }
00168 uint size()const
00169 {
00170 Track("ZeBuffer::size");
00171 return m_size;
00172 }
00173 uint allocated()const
00174 {
00175 Track("ZeBuffer::allocated");
00176 return m_allocated;
00177 }
00178 const T* data()const
00179 {
00180 Track("ZeBuffer::data()const");
00181 return m_ptr;
00182 }
00183 T* data()
00184 {
00185 Track("ZeBuffer::data()");
00186 copy();
00187 return m_ptr;
00188 }
00189
00190 std::string str()const
00191 {
00192
00193 if(m_size)
00194 {
00195 m_ptr[m_size]=T(0);
00196 return std::string((const char*)m_ptr);
00197 }
00198 else
00199 return std::string("");
00200 }
00201 };
00202
00203 #endif