每次读取文件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; }
