1
1
forked from 0ad/0ad
0ad/source/dcdt/se/sr_buffer.h

171 lines
7.1 KiB
C++

# ifndef SR_BUFFER_H
# define SR_BUFFER_H
/** \file sr_buffer.h
* fast buffer memory management template */
# include "sr.h"
# include "sr_input.h"
# include "sr_output.h"
/*! Allocates memory with sizeofx*newsize bytes using the C function realloc.
If newsize is zero, buffer is freed and both buffer and size becomes zero.
After the function call, size has the value of newsize. No effect if
size==newsize. */
void* sr_buffer_size ( void* buffer, int sizeofx, int& size, int newsize );
/*! Inserts dp*sizeofx bytes at i position, moving correctly the buffer contents. */
void* sr_buffer_insert ( void* buffer, int sizeofx, int& size, int i, int dp );
/*! Inserts dp*sizeofx bytes at i position, moving correctly the buffer contents. */
void* sr_buffer_remove ( void* buffer, int sizeofx, int& size, int i, int dp );
/*! Put buffers with same size and copy them. No effect if buffers pointers are equal. */
void* sr_buffer_copy ( void* buffer, int sizeofx, int& size, const void* buffertocp, int sizetocp );
/*! \class SrBuffer sr_buffer.h
\brief fast buffer memory management template
All memory management functions of SrBuffer are written using the four buffer
functions available in this header. Be aware that constructors and destructors
of class X are not called. SrBuffer can thus be used only with classes or structs
that do not have any internal allocated data.
Internally, SrBuffer keeps only a pointer to the allocated
buffer memory and the buffer size. For a more featured class see SrArray. */
template <class X>
class SrBuffer
{ private:
void* _data;
int _size;
public:
/*! Default constructor. */
SrBuffer () : _data(0), _size(0) {}
/*! Copy constructor. */
SrBuffer ( const SrBuffer& b ) : _data(0), _size(0)
{ _data=sr_buffer_copy(_data,sizeof(X),_size,b._data,b._size); }
/*! Constructor with a given size. */
SrBuffer ( int s ) : _data(0), _size(0) { _data=sr_buffer_size(_data,sizeof(X),_size,s); }
/*! Constructor from a user allocated buffer. See also leave_data(). */
SrBuffer ( X* pt, int s ) : _data(pt), _size(s) {}
/*! Destructor frees the buffer. Elements' destructors are not called ! */
~SrBuffer () { sr_buffer_size ( _data, sizeof(X), _size, 0 ); }
/*! Returns true if size()==0; and false otherwise. */
bool empty () const { return _size==0? true:false; }
/*! Returns the current size of the Buffer. */
int size () const { return _size; }
/*! Allows to change the size of the buffer. */
void size ( int ns )
{ _data=sr_buffer_size(_data,sizeof(X),_size,ns); }
/*! Sets all elements as x, copying each element using operator = */
void setall ( const X& x )
{ for ( int i=0; i<_size; i++ ) ((X*)_data)[i]=x; }
/*! Get a const reference to the element of index i. Indices start from 0
and must be smaller than size(). No checkings are done to ensure that
i is in a valid range. */
const X& const_get ( int i ) const { return ((X*)_data)[i]; }
/*! Get a reference to the element of index i. Indices start from 0
and must be smaller than size(). No checkings are done to ensure that
i is in a valid range. */
X& get ( int i ) { return ((X*)_data)[i]; }
/*! Sets an element. Operator = is used here. Indices start from 0 and must
be smaller than size(). No checkings are done to ensure that i is valid. */
void set ( int i, const X& x ) { ((X*)_data)[i]=x; }
/*! Operator version of X& get(int i), but returning a non const reference.
No checkings are done to ensure that i is valid. */
X& operator[] ( int i ) { return ((X*)_data)[i]; }
/*! Returns a const pointer of the internal buffer. The internal buffer
will always contain a contigous storage space of size() elements.
See also take_data() and leave_data() methods. */
operator const X* () const { return (X*)_data; }
/*! Returns a reference to the last element, ie, with index size()-1.
The Buffer must not be empty when calling this method. */
X& top () { return ((X*)_data)[_size-1]; }
/* Reduces the size of the buffer by one. */
void pop () { _data=sr_buffer_size(_data,sizeof(X),_size,_size-1); }
/* Increases the size of the buffer by one. */
void push ( int dp=1 ) { _data=sr_buffer_size(_data,sizeof(X),_size,_size+1); }
/*! Inserts dp positions, starting at pos i, moving all data correctly.
Parameter i can be between 0 and size(), if i==size(), dp positions are
appended. */
void insert ( int i, int dp=1 ) { _data=sr_buffer_insert(_data,sizeof(X),_size,i,dp); }
/*! Removes dp positions starting from pos i, moving all data correctly;
dp has a default value of 1. Attention: elements' destructors are not
called ! */
void remove ( int i, int dp=1 ) { _data=sr_buffer_remove(_data,sizeof(X),_size,i,dp); }
/*! Copies all internal data of a to SrBuffer, with fast memcpy() functions,
so that the operator=() that X might have is not used. This method has no
effect if a "self copy" is called. */
void operator = ( const SrBuffer<X>& b )
{ _data=sr_buffer_copy(_data,sizeof(X),_size,b._data,b._size); }
/*! Makes the given xpt pointer to point to the internal buffer, without
reallocation; xpt will then be null or contain the address of the memory
used and that was allocated with malloc(). The user will then be responsible
to free this allocated memory with free(). After this call, SrBuffer will
become an empty but valid buffer. */
void leave_data ( X*& xpt, int& size )
{ xpt=_data; size=_size; _data=0; _size=0; }
/*! Frees the data of SrBuffer, and then makes SrBuffer be the given buffer b.
After this, b is set to be a valid empty buffer. The data is moved without
reallocation. */
void take_data ( SrBuffer<X>& b ) { size(0); b.leave_data(_data,_size); }
/*! Outputs all elements of the Buffer. Element type X must have its ouput operator <<
available. This is the only method of SrBuffer that is not inline. */
friend SrOutput& operator<< ( SrOutput& o, const SrBuffer<X>& b )
{ o << '[';
int i;
for ( i=0; i<b.size()-1; i++ ) o << b.const_get(i) << srspc;
if ( i<b.size() ) o << b.const_get(i);
return o << ']';
}
/*! Inputs all elements of the buffer. Element type X must have its input operator <<
available. */
friend SrInput& operator>> ( SrInput& in, SrBuffer<X>& b )
{ int s=0;
b.size(128);
in.get_token();
while (true)
{ in.get_token();
if ( in.last_token()[0]==']' ) break;
in.unget_token();
in >> b[s];
s++;
if ( s>=b.size() ) b.size ( b.size()+128 );
}
b.size ( s );
return in;
}
};
//============================== end of file ===============================
#endif // SR_BUFFER_H