#include "Bpack.h"
//#include <trie.h>
#include <iostream>
#include <iomanip>

using namespace std;

const int Bpack::LPOS = 8*sizeof(int) -1;

const Uint Bpack::Mask[24] = {
	0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF,
	0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF,
	0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF
	};

Uint 
Bpack::pack(Uint bits, int code_len)
{
Uint ret;

	if(code_len < bx+1) {		//there's room
		;
		buf |= bits << bx+1-code_len;
		bx -= code_len;
		ret = 0;			//return 0 if no buffer full
	}
	else if(code_len == bx+1) {
		buf |= bits;
		ret = buf;
		buf = 0;
		bx = LPOS;
	}
	else {					//bits straddles two bufs
		buf |= bits >> code_len-bx-1;
		ret = buf;
		buf = 0;
		buf = bits << LPOS-code_len+bx+2;
		bx = LPOS-code_len+bx+1;
	}
	return ret;
}


Uint 
Bpack::upack(int nbit)
{
Uint mask = getmask(nbit);
Uint ret;

	if(buf == 0)		return 0;

	if(nbit < bx+1) {											//no straddle
		ret = ((mask <<bx-nbit+1) & buf) >> bx-nbit+1 & mask;
		bx -= nbit;
	}
	else if(nbit == bx+1) {
		ret = mask & buf;
		bx = LPOS;
	}
	else {
		Uint Lmask = getmask(bx+1);
		ret = (Lmask & buf) << nbit-bx-1;
		Uint Rmask = getmask(nbit-bx-1);
		ret |= (buf & Rmask << LPOS-nbit+bx+2) >> LPOS-nbit+bx+2 & mask;
		bx = LPOS-nbit+bx+1;
	}
	return ret;
}

void
Bpack::display(Uint val)
{
	if(val==0)
		cout << setbase(16) << buf << endl;
	else
		cout << setbase(16) << val << endl;
}
