⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bitio.cpp

📁 自适应huffman编码
💻 CPP
字号:
#include "StdAfx.h"
#include ".\BitIO.h"

// Add pre in the front of bits
// Input:   char   * bits
//         int     & bits_len
//         char   * pre
//         int       pre_len
// Output:  char   * bits 
//         int     & bits_len
void BitOp::AddPrefix(char * bits, int & bits_len, char * pre, int pre_len)
{
    if (bits_len + pre_len > 8 * sizeof(long))  // NT_REVISITED, the longest length of code is 8*sizeof(long)
        return;

    unsigned long * pl_bits = (unsigned long *)bits;
    unsigned long * pl_pre  = (unsigned long *)pre;
  
	*pl_bits = *pl_bits << pre_len;

    unsigned long mask = 0xFFFFFFFF;
    mask <<= pre_len;

    *pl_bits |= (*pl_pre & (~mask));
	bits_len += pre_len;
}

BitIO::BitIO(void)
{
}

BitIO::~BitIO(void)
{
}

bool BitIO::Write(const char * bits, int bits_len)
{
	return true;
}

void BitIO::Flush()
{
}

void BitIO::Close()
{
}

int  BitIO::ReadABit(char * c, int start)
{
	return 0;
}

bool BitIO::ReadAByte(char & c)
{
	return(true);
}

int  BitIO::GetMode()  // return the working mode of current object
{
	return this->mode;
}


bool FileBitIO::Init(fstream * p_fs)
{
	return (this->Init(p_fs, 1024 * 1024, 2));
}

bool FileBitIO::Init(fstream * p_fs, int bufsize, int work_mode, unsigned long leng)
{
	this->max_bits_num = leng * 8;
	this->bits_num = 0;
	
	this->mode = work_mode;
	this->fs = p_fs;

	this->buf_size = bufsize;
	buf = new char[bufsize];
	memset(buf, 0, bufsize);
	this->used = 0;
	this->handled = 0;
	this->unhandled = 0;

	return true;
}

bool FileBitIO::Init(fstream * p_fs, int bufsize, int work_mode)
{
	return(this->Init(p_fs, bufsize, work_mode, 0));
}

// write "code_len" bits from "code" to buffer.
bool FileBitIO::Write(const char * code, int code_len)
{
	unsigned long byte_idx = used / 8;
	int bit_idx  = used % 8;

	assert(code_len + bit_idx <= 8*sizeof(long)); // now, it's only for less than 32bits each time.

	if (byte_idx + sizeof(long) + 1 > this->buf_size) {  // NT_REVISITED, sizeof(long)
		this->fs->write(this->buf, byte_idx);
		memset(this->buf, 0, byte_idx);
		if (bit_idx)
		    this->buf[0] = this->buf[byte_idx]; 
		used = bit_idx;
		byte_idx = 0;
	}

	assert(byte_idx + sizeof(long) + 1 <= this->buf_size);

	union u {
		unsigned long   l;
	    char   code[4];   // NT_REVISISTED
	} un;

	un.l = 0;
	
	un.code[0] = code[0];
	if (code_len > 8)
		un.code[1] = code[1];
	if (code_len > 16)
		un.code[2] = code[2];
	if (code_len > 24)
		un.code[3] = code[3];
	
	un.l <<= bit_idx;

	int j = 0;  
	while ( 8*j < bit_idx + code_len)
	{
		buf[byte_idx + j] |= un.code[j];
		j++;
	}

	unsigned char mask = 0xff;
	int shift = (8 - (bit_idx + code_len) % 8) %8;
	buf[byte_idx + j-1] &= (mask >> shift);

	used += code_len;

	this->bits_num += code_len;

	return true;
}

int  FileBitIO::RenewReadBuf()
{
	if (this->unhandled == 0) {
		int read_num;
		int bits_remains = this->max_bits_num - this->bits_num; 
		if (bits_remains % 8 != 0)
			read_num = bits_remains/8 + 1;
		else
			read_num = bits_remains/8;
		
		if (read_num > this->buf_size)
			read_num = this->buf_size;

		this->fs->read(this->buf, read_num);
		// this->fs->get(this->buf[0]);  // can try to read more bits, NT_REVISITED
		
		if (this->fs->eof())
			return -1;

		this->unhandled = read_num*8;
		this->handled = 0;
	}

	return 1;
}

// read next bit from input file. if file ends, return -1
int  FileBitIO::ReadABit()
{
	static unsigned char mask[8] = {(unsigned char)1, (unsigned char)2, (unsigned char)4, (unsigned char)8, 
		 (unsigned char)16, (unsigned char)32, (unsigned char)64, (unsigned char)128};

	if (this->max_bits_num != 0 && this->bits_num+1 > this->max_bits_num)
		return -1;

	if (this->RenewReadBuf() == -1)
		return -1;

	this->bits_num++;
		
	int byte_idx = this->handled >> 3;      // this->handled / 8
	int bit_idx  = this->handled & 0x0007;  // this->handled % 8
	
	this->handled++;
	this->unhandled--;

	if(this->buf[byte_idx] & mask[bit_idx])
		return 1;
	else
		return 0;
}



// read next bit from input file to the start bit of c. if file ends, return -1
int  FileBitIO::ReadABit(char * c, int start)
{
	static unsigned char mask[8] = {(unsigned char)1, (unsigned char)2, (unsigned char)4, (unsigned char)8, 
		 (unsigned char)16, (unsigned char)32, (unsigned char)64, (unsigned char)128};

/*	if (this->used + 1 > this->buf_size) {
		this->fs->read(this->buf, this->buf_size/8);
		this->used = 0;
	}
*/
//	assert(this->used + 1 <= this->buf_size);

	if (this->max_bits_num != 0 && this->bits_num+1 > this->max_bits_num)
		return -1;

	if (this->RenewReadBuf() == -1)
		return -1;

	this->bits_num++;
		
	int byte_idx = this->handled / 8;      // this->handled / 8
	int bit_idx  = this->handled % 8;  // this->handled % 8
	int start_byte_idx = start / 8;
	int start_bit_idx = start % 8;

	int ret_val;
	char tmp = this->buf[byte_idx] & mask[bit_idx];
	if (tmp) {
	    c[start_byte_idx] |= mask[start_bit_idx];
		ret_val = 1;
	} else {
		c[start_byte_idx] &= (~mask[start_bit_idx]);
		ret_val = 0;
	}

	this->handled++;
	this->unhandled--;

	return ret_val;
}

// read next char from input file to c
// now, the function doesn't use buffer and thread. NT_REVISITED
bool FileBitIO::ReadAByte(char & c)
{
	if (!(this->handled & 0x0007)) {  // % 8
		if (this->bits_num >= this->max_bits_num)
			return false;
		if (this->RenewReadBuf() == -1)
		    return false;
		int byte_idx = this->handled >> 3; // this->handled/8
		c = this->buf[byte_idx];
		this->bits_num+=8;
		this->handled += 8;
		this->unhandled -= 8;
	} else {
		for (int i=0; i <= 7; i++) {
			if (this->ReadABit(&c, i) == -1)
				return false;
		}
	}

	return true;
}

void FileBitIO::Flush()
{
	this->fs->write(this->buf, this->used/8);
	memset(this->buf, 0, this->used/8);
	if (used%8 != 0) {
		this->buf[0] = this->buf[this->used/8];
	}
		
	used %= 8;
	this->fs->flush();
}


void FileBitIO::FlushEnd()
{
	if (this->used == 0) 
		return;

	this->fs->write(this->buf, (this->used -1)/8 + 1);
	memset(this->buf, 0, (this->used -1)/8 + 1);
	used = 0;
	this->fs->flush();
}

void FileBitIO::Close()
{
	this->FlushEnd();
	this->fs->close();
}

FileBitIO::FileBitIO(void)
{
}

FileBitIO::~FileBitIO(void)
{
	if (this->buf != NULL)
		delete this->buf;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -