每次读取文件1<<15个字节存在一个数组里面 然后调用子类的GetByte()获得一个字节 GetWord()获得双字节 即一个字
class RBaseStream
{
public:
RBaseStream();
virtual ~RBaseStream();
virtual bool Open(const char * filename);
virtual void Close();
void SetBlockSize(int block_size,int ubGetSize=4);
bool IsOpen();
void SetPos(int pos);
int GetPos();
void Skip(int bytes);
jmp_buf& JumBuf();
protected:
jmp_buf m_jmp_buf;
unsigned char* m_start;
unsigned char* m_end;
unsigned char* m_current;
FILE* m_file;
int m_unGetsize;
int m_block_size;
int m_block_pos;
bool m_jmp_set;
bool m_is_opened;
virtual void ReadBlock();
virtual void Release();
virtual void Allocate();
};
RBaseStream::RBaseStream()
{
m_start=m_end=m_current=0;
m_file=0;
m_block_size=1<<15;
m_unGetsize=4;
m_is_opened=false;
m_jmp_set=false;
}
void RBaseStream::Allocate()
{
if(!m_start)
{
m_start=new unsigned char[m_block_size+m_unGetsize];
m_start+=m_unGetsize;
}
m_end = m_start + m_block_size;
m_current = m_end;
}
void RBaseStream::ReadBlock()
{
unsigned int readed;
// assert( m_file != 0 );
if(m_start)
{
memcpy(m_start - m_unGetsize, m_end - m_unGetsize, m_unGetsize);
}
SetPos( GetPos() );
fseek(m_file , m_block_pos , SEEK_SET);
readed=fread( m_start, 1, m_block_size, m_file );
m_end = m_start + readed;
m_current -= m_block_size;
m_block_pos += m_block_size;
if(readed == 0 || m_current >= m_end)
{
if( m_jmp_set)
longjmp( m_jmp_buf, -123);
}
}
bool RBaseStream::Open( const char * filename )
{
Close();
Allocate();
m_file=fopen( filename, "rb" );
if( m_file )
{
m_is_opened = true;
SetPos(0);
}
return m_file != 0;
}
void RBaseStream::Close()
{
if(m_file)
{
fclose(m_file);
m_file = 0;
}
m_is_opened = false;
}
void RBaseStream::Release()
{
if( m_start )
{
delete [](m_start - m_unGetsize);
}
m_start = m_end = m_current = 0;
}
void RBaseStream::SetBlockSize(int block_size, int unGetsize)
{
if( m_start && block_size == m_block_size && unGetsize == m_unGetsize ) return;
Release();
m_block_size = block_size;
m_unGetsize = unGetsize;
Allocate();
}
void RBaseStream::SetPos(int pos)
{
int offset = pos & (m_block_size - 1); //经典必看 防止pos数据溢出
int block_pos = pos - offset;
if( m_current < m_end && block_pos == m_block_pos - m_block_size )
{
m_current = m_start + offset;
}
else
{
m_block_pos = block_pos;
m_current = m_start + m_block_size + offset;
}
}
int RBaseStream::GetPos()
{
return m_block_pos - m_block_size + (int)(m_current - m_start);
}
void RBaseStream::Skip(int bytes)
{
m_current += bytes;
}
jmp_buf& RBaseStream::JumBuf()
{
m_jmp_set=true;
return m_jmp_buf;
}
RBaseStream::~RBaseStream()
{
}
class RLByteStream : public RBaseStream
{
public:
int GetWord();
int GetByte();
virtual ~RLByteStream();
};
RLByteStream::~RLByteStream()
{
}
int RLByteStream::GetByte()
{
unsigned char *current = m_current;
int val;
if( m_current>=m_end)
{
ReadBlock();
current=m_current;
}
val = *( (unsigned char *)current);
m_current = current + 1;
return val;
}
int RLByteStream::GetWord()
{
unsigned char *current=m_current;
int val;
if(current+1 < m_end)
{
val = current[0] + (current[1] << 8);
m_current = current + 2;
}
else
{
val = GetByte();
val|= GetByte() << 8;
}
return val;
}