You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

268 lines
7.3 KiB

//
// 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 <http://www.htdig.org/>
// 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
// <http://www.gnu.org/copyleft/lgpl.html>
//
// $Id: WordBitCompress.h,v 1.7 2004/05/28 13:15:26 lha Exp $
//
#ifndef _WordBitCompress_h
#define _WordBitCompress_h
#include<stdio.h>
#include<stdlib.h>
#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<tags.size();i++){free(tags[i]);}
}
BitStream(int size0)
{
buff.reserve((size0+7)/8);
init();
}
BitStream()
{
init();
}
private:
void init()
{
bitpos=0;
buff.push_back(0);
freezeon=0;
use_tags=0;
}
};
// **************************************************
// *************** Compressor ***********************
// **************************************************
// Constants used by Compressor
// number of bits to code the number of values in an array
#define NBITS_NVALS 16
// number of bits to code the values in an unsigned int array (=sizeof(unsigned int))
#define NBITS_VAL 32
// number of bits to code he number of bits used by an unsigned int value
#define NBITS_NBITS_VAL 5
// number of bits to code the number of bits used by a byte value
#define NBITS_NBITS_CHARVAL 4
class Compressor : public BitStream
{
public:
int verbose;
// get/put an integer using a variable number of bits
void put_uint_vl(unsigned int v,int maxn,const char *tag=(char*)"NOTAG");
unsigned int get_uint_vl( int maxn,const char *tag=(char*)NULL);
// get/put an integer checking for an expected value
void put_uint_ex(unsigned int v,unsigned int ex,int maxn,const char *tag=(char*)"NOTAG")
{
if(v==ex){put(1,tag);}
else{put(0,tag);put_uint(v,maxn,(char*)NULL);}
}
unsigned int get_uint_ex( unsigned int ex,int maxn,const char *tag=(char*)NULL)
{
if(get(tag)){return ex;}
else{return get_uint(maxn,(char*)NULL);}
}
// compress/decompress an array of unsigned ints (choosing best method)
int put_vals(unsigned int *vals,int n,const char *tag);
int get_vals(unsigned int **pres,const char *tag=(char*)"BADTAG!");
// compress/decompress an array of bytes (very simple)
int put_fixedbitl(byte *vals,int n,const char *tag);
int get_fixedbitl(byte **pres,const char *tag=(char*)"BADTAG!");
// compress/decompress an array of unsigned ints (very simple)
void get_fixedbitl(unsigned int *res,int n);
void put_fixedbitl(unsigned int *vals,int n);
// compress/decompress an array of unsigned ints (sophisticated)
void get_decr(unsigned int *res,int n);
void put_decr(unsigned int *vals,int n);
Compressor():BitStream()
{
verbose=0;
}
Compressor(int size0):BitStream(size0)
{
verbose=0;
}
};
#endif