//
// WordBitCompress.h
//
// BitStream: put and get bits into a buffer
// *tagging: add tags to keep track of the position of data
// inside the bitstream for debuging purposes.
// *freezing: saves current position. further inserts in the BitStream
// aren't really done. This way you can try different
// compression algorithms and chose the best.
//
// Compressor: BitStream with extended fuctionalities
//
//
// Part of the ht://Dig package
// Copyright (c) 1999-2004 The ht://Dig Group
// For copyright details, see the file COPYING in your distribution
// or the GNU Library General Public License (LGPL) version 2 or later
//
//
// $Id: WordBitCompress.h,v 1.7 2004/05/28 13:15:26 lha Exp $
//
#ifndef _WordBitCompress_h
#define _WordBitCompress_h
#include
#include
#include"HtVector_int.h"
#include"HtMaxMin.h"
typedef unsigned char byte;
// ******** HtVector_byte (header)
#define GType byte
#define HtVectorGType HtVector_byte
#include "HtVectorGeneric.h"
typedef char * charptr;
// ******** HtVector_charptr (header)
#define GType charptr
#define HtVectorGType HtVector_charptr
#include "HtVectorGeneric.h"
// ******** Utility inline functions and macros
// error checking
#define FATAL_ABORT fflush(stdout);fprintf(stderr,"FATAL ERROR at file:%s line:%d !!!\n",__FILE__,__LINE__);fflush(stderr);(*(int *)NULL)=1
#define errr(s) {fprintf(stderr,"FATAL ERROR:%s\n",s);FATAL_ABORT;}
#define CHECK_MEM(p) if(!p) errr("mifluz: Out of memory!");
// max/min of 2 values
#define TMax(a,b) (((a)>(b)) ? (a) : (b))
#define TMin(a,b) (((a)<(b)) ? (a) : (b))
// compute integer log2
// == minimum number of bits needed to code value
inline int
num_bits(unsigned int maxval )
{
unsigned int mv=maxval;
int nbits;
for(nbits=0;mv;nbits++){mv>>=1;}
return(nbits);
}
// compute 2^x
#define pow2(x) (1<<(x))
// function declarations
char *label_str(const char *s,int n);
void show_bits(int v,int n=16);
// unsigned short max_v(unsigned short *vals,int n);
// unsigned int max_v(unsigned int *vals,int n);
// unsigned short min_v(unsigned short *vals,int n);
// unsigned int min_v(unsigned int *vals,int n);
// **************************************************
// *************** BitStream ***********************
// **************************************************
// compression is done in Compressor not in BitStream
class BitStream
{
protected:
// the buffer were the bitstream is stored
HtVector_byte buff;
// current bit position within the buffer
int bitpos;
// tags for debuging
HtVector_int tagpos;
HtVector_charptr tags;
int use_tags;
// freezing the bitstream
HtVector_int freeze_stack;
int freezeon;
public:
void freeze();
int unfreeze();
// puts a bit into the bitstream
inline void put(unsigned int v)
{
// SPEED CRITICAL SECTION
if(freezeon){bitpos++;return;}
if(v){buff.back()|=pow2(bitpos & 0x07);}
bitpos++;
if(!(bitpos & 0x07))// new byte
{
buff.push_back(0);
}
}
inline void put(unsigned int v,const char *tag)
{
if(!freezeon){add_tag(tag);}
put(v);
}
// gets a bit from the bitstream
inline byte get(const char *tag=(char*)NULL)
{
// SPEED CRITICAL SECTION
if(check_tag(tag)==NOTOK){errr("BitStream::get() check_tag failed");}
if(bitpos>=(buff.size()<<3)){errr("BitStream::get reading past end of BitStream!");}
byte res=buff[bitpos>>3] & pow2(bitpos & 0x07);
// printf("get:res:%d bitpos:%5d/%d buff[%3d]=%x\n",res,bitpos,bitpos%8,bitpos/8,buff[bitpos/8]);
bitpos++;
return(res);
}
// get/put an integer using n bits
void put_uint(unsigned int v,int n,const char *tag=(char*)"NOTAG");
unsigned int get_uint( int n,const char *tag=(char*)NULL);
// get/put n bits of data stored in vals
void put_zone(byte *vals,int n,const char *tag);
void get_zone(byte *vals,int n,const char *tag);
//
inline void add_tag(const char *tag)
{
if(!use_tags || !tag || freezeon){return;}
add_tag1(tag);
}
void add_tag1(const char *tag);
inline int check_tag(const char *tag,int pos=-1)
{
if(!use_tags || !tag){return OK;}
return(check_tag1(tag,pos));
}
int check_tag1(const char *tag,int pos);
void set_use_tags(){use_tags=1;}
int find_tag(const char *tag);
int find_tag(int pos,int posaftertag=1);
void show_bits(int a,int n);
void show(int a=0,int n=-1);
// position accesors
int size(){return(bitpos);}
int buffsize(){return(buff.size());}
// get a copy of the buffer
byte *get_data();
// set the buffer from outside data (current buffer must be empty)
void set_data(const byte *nbuff,int nbits);
// use this for reading a BitStream after you have written in it
// (generally for debuging)
void rewind(){bitpos=0;}
~BitStream()
{
int i;
for(i=0;i