// Copyright (c) 2002 David Muse // See the COPYING file for more information #include #include #include #include #ifdef RUDIMENTS_NAMESPACE namespace rudiments { #endif class variablebufferprivate { friend class variablebuffer; private: unsigned char *_buffer; size_t _buffersize; size_t _initialsize; size_t _increment; size_t _position; size_t _endofbuffer; }; variablebuffer::variablebuffer(size_t initialsize, size_t increment) { init(new unsigned char[initialsize],initialsize,increment); } variablebuffer::variablebuffer(unsigned char *initialcontents, size_t initialsize, size_t increment) { init(initialcontents,initialsize,increment); } void variablebuffer::init(unsigned char *initialcontents, size_t initialsize, size_t increment) { pvt=new variablebufferprivate; pvt->_buffer=initialcontents; pvt->_buffersize=initialsize; pvt->_initialsize=initialsize; pvt->_increment=increment; pvt->_position=0; pvt->_endofbuffer=0; } variablebuffer::variablebuffer(const variablebuffer &v) { variablebufferClone(v); } variablebuffer &variablebuffer::operator=(const variablebuffer &v) { if (this!=&v) { delete[] pvt->_buffer; delete pvt; variablebufferClone(v); } return *this; } variablebuffer::~variablebuffer() { delete[] pvt->_buffer; delete pvt; } void variablebuffer::variablebufferClone(const variablebuffer &v) { pvt=new variablebufferprivate; pvt->_initialsize=v.pvt->_initialsize; pvt->_increment=v.pvt->_increment; pvt->_buffersize=v.pvt->_buffersize; pvt->_position=v.pvt->_position; pvt->_endofbuffer=v.pvt->_endofbuffer; pvt->_buffer=new unsigned char[v.pvt->_buffersize]; rawbuffer::copy(pvt->_buffer,v.pvt->_buffer,pvt->_buffersize); } ssize_t variablebuffer::read(unsigned char *data, size_t size) { size_t bytestoread=size; if (pvt->_position>pvt->_endofbuffer) { bytestoread=0; } else if (pvt->_position+size>pvt->_endofbuffer) { bytestoread=pvt->_endofbuffer-pvt->_position; } rawbuffer::copy(data,pvt->_buffer+pvt->_position,bytestoread); pvt->_position=pvt->_position+bytestoread; return bytestoread; } variablebuffer *variablebuffer::write(const unsigned char *data, size_t size) { // if the buffer is too small, extend it if (pvt->_position>=pvt->_buffersize) { extend(pvt->_position-pvt->_buffersize+size); } else if (size>=pvt->_buffersize-pvt->_position) { extend(pvt->_buffersize-pvt->_position+size); } // copy the data into the buffer rawbuffer::copy(pvt->_buffer+pvt->_position,data,size); // increment the position indices pvt->_position=pvt->_position+size; if (pvt->_position>pvt->_endofbuffer) { pvt->_endofbuffer=pvt->_position; } return this; } variablebuffer *variablebuffer::write(const char *string) { return write(reinterpret_cast(string), charstring::length(string)); } variablebuffer *variablebuffer::write(const char *string, size_t size) { return write(reinterpret_cast(string),size); } variablebuffer *variablebuffer::write(char character) { return write(reinterpret_cast(&character), sizeof(char)); } variablebuffer *variablebuffer::write(int16_t number) { return write(reinterpret_cast(&number), sizeof(int16_t)); } variablebuffer *variablebuffer::write(int32_t number) { return write(reinterpret_cast(&number), sizeof(int32_t)); } variablebuffer *variablebuffer::write(int64_t number) { return write(reinterpret_cast(&number), sizeof(int64_t)); } variablebuffer *variablebuffer::write(unsigned char character) { return write(reinterpret_cast(&character), sizeof(unsigned char)); } variablebuffer *variablebuffer::write(uint16_t number) { return write(reinterpret_cast(&number), sizeof(uint16_t)); } variablebuffer *variablebuffer::write(uint32_t number) { return write(reinterpret_cast(&number), sizeof(uint32_t)); } variablebuffer *variablebuffer::write(uint64_t number) { return write(reinterpret_cast(&number), sizeof(uint64_t)); } variablebuffer *variablebuffer::write(float number) { return write(reinterpret_cast(&number), sizeof(float)); } variablebuffer *variablebuffer::write(double number) { return write(reinterpret_cast(&number), sizeof(double)); } void variablebuffer::clear() { delete[] pvt->_buffer; pvt->_buffer=new unsigned char[pvt->_initialsize]; pvt->_buffersize=pvt->_initialsize; pvt->_position=0; pvt->_endofbuffer=0; } void variablebuffer::extend(size_t size) { size_t newbuffersize=pvt->_buffersize+ ((size/pvt->_increment)*pvt->_increment)+ (((size%pvt->_increment)>0)*pvt->_increment); unsigned char *newbuffer=new unsigned char[newbuffersize]; rawbuffer::copy(newbuffer,pvt->_buffer,pvt->_buffersize); delete[] pvt->_buffer; pvt->_buffer=newbuffer; pvt->_buffersize=newbuffersize; } const unsigned char *variablebuffer::getBuffer() { return pvt->_buffer; } unsigned char *variablebuffer::detachBuffer() { unsigned char *retval=pvt->_buffer; pvt->_buffer=new unsigned char[pvt->_initialsize]; pvt->_buffersize=pvt->_initialsize; pvt->_position=0; pvt->_endofbuffer=0; return retval; } size_t variablebuffer::getSize() { return pvt->_endofbuffer; } size_t variablebuffer::getPosition() { return pvt->_position; } size_t variablebuffer::getEnd() { return pvt->_endofbuffer; } size_t variablebuffer::getActualSize() { return pvt->_buffersize; } void variablebuffer::setPosition(size_t pos) { pvt->_position=pos; } variablebuffer *variablebuffer::append(const unsigned char *data, size_t size) { pvt->_position=pvt->_endofbuffer; return write(data,size); } variablebuffer *variablebuffer::append(const char *string) { return append(reinterpret_cast(string), charstring::length(string)); } variablebuffer *variablebuffer::append(const char *string, size_t size) { return append(reinterpret_cast(string),size); } variablebuffer *variablebuffer::append(char character) { return append(reinterpret_cast(&character), sizeof(char)); } variablebuffer *variablebuffer::append(int16_t number) { return append(reinterpret_cast(&number), sizeof(int16_t)); } variablebuffer *variablebuffer::append(int32_t number) { return append(reinterpret_cast(&number), sizeof(int32_t)); } variablebuffer *variablebuffer::append(int64_t number) { return append(reinterpret_cast(&number), sizeof(int64_t)); } variablebuffer *variablebuffer::append(unsigned char character) { return append(reinterpret_cast(&character), sizeof(unsigned char)); } variablebuffer *variablebuffer::append(uint16_t number) { return append(reinterpret_cast(&number), sizeof(uint16_t)); } variablebuffer *variablebuffer::append(uint32_t number) { return append(reinterpret_cast(&number), sizeof(uint32_t)); } variablebuffer *variablebuffer::append(uint64_t number) { return append(reinterpret_cast(&number), sizeof(uint64_t)); } variablebuffer *variablebuffer::append(float number) { return append(reinterpret_cast(&number), sizeof(float)); } variablebuffer *variablebuffer::append(double number) { return append(reinterpret_cast(&number), sizeof(double)); } unsigned char *variablebuffer::_buffer() { return pvt->_buffer; } size_t variablebuffer::_endofbuffer() { return pvt->_endofbuffer; } void variablebuffer::_endofbuffer(size_t eob) { pvt->_endofbuffer=eob; } size_t variablebuffer::_position() { return pvt->_position; } void variablebuffer::_position(size_t pos) { pvt->_position=pos; } #ifdef RUDIMENTS_NAMESPACE } #endif