我常用的buffer有std::vector的动态连续缓存和char buf[]的静态缓存。
char buf[]不能够自动增长;std::vector不方便前向读取、不能直接写缓存。这里是一个即连续、又能够自适应,而且可以直接操作缓存的buffer,缺点是使用麻烦。
/**
* 以下代码由张家旺编写完成于2007-7-5,借用请保留该声明。
*/
#ifndef __BUFFER__
#define __BUFFER__
#include < cassert >
#include < cstring >
namespace useful
{
class buffer
{
public:
buffer( size_t size );
~buffer( void );
const void *buf_data( void ) const;
size_t data_size( void ) const;
void data_dec( size_t size );
void *buf_empty( void );
size_t empty_size( void ) const;
void data_inc( size_t size );
size_t waste_size( void ) const;
void data_recycle( size_t size );
void data_push( const void *data,size_t size );
void arrange( void );
void reserve( size_t size );
private:
buffer( const buffer &rhs );
buffer &operator = ( const buffer &rhs );
char *m_buf;
size_t m_off,m_use,m_empty;
};
inline buffer::buffer( size_t size ) :
m_buf( new char[size] ),m_off( 0 ),m_use( 0 ),m_empty( size )
{
assert( size > 0 );
}
inline buffer::~buffer( void )
{
delete[] m_buf;
}
inline const void *buffer::buf_data( void ) const
{
return m_buf + m_off;
}
inline size_t buffer::data_size( void ) const
{
return m_use;
}
inline void buffer::data_dec( size_t size )
{
assert( size < = data_size() );
m_off += size,m_use -= size;
}
inline void *buffer::buf_empty( void )
{
return m_buf + m_off + m_use;
}
inline size_t buffer::empty_size( void ) const
{
return m_empty;
}
inline void buffer::data_inc( size_t size )
{
assert( size < = empty_size() );
m_use += size,m_empty -= size;
}
inline size_t buffer::waste_size( void ) const
{
return m_off;
}
inline void buffer::data_recycle( size_t size )
{
assert( size < = waste_size() );
m_off -= size,m_use += size;
}
inline void buffer::data_push( const void *data,size_t size )
{
size_t len = empty_size();
if( size < = len )
{
memcpy( buf_empty(),data,size ); data_inc( size );
return;
}
len += waste_size();
if( size < = len )
{
arrange(); memcpy( buf_empty(),data,size ); data_inc( size );
return;
}
const size_t use = size + data_size();
len = ( len + data_size() ) < < 1;
while( use > len ) len = len < < 1;
char *buf = new char[len];
memcpy( buf,buf_data(),data_size() );
memcpy( buf+data_size(),data,size );
delete[] m_buf; m_buf = buf;
m_off = 0,m_use = use,m_empty = len - use;
}
inline void buffer::arrange( void )
{
assert( waste_size() > 0 );
memmove( m_buf,buf_data(),data_size() );
m_empty += m_off,m_off = 0;
}
inline void buffer::reserve( size_t size )
{
size_t now = m_use + m_empty + m_off;
if( size < = now ) return;
char *buf = new char[size];
memcpy( buf,buf_data(),data_size() );
delete[] m_buf; m_buf = buf;
m_off = 0,m_empty = size - data_size();
}
};
#endif /// __BUFFER__