190 lines
5.7 KiB
C++
190 lines
5.7 KiB
C++
/* DEC/CMS REPLACEMENT HISTORY, Element BITS.C */
|
|
/* *1 14-NOV-1996 10:25:36 ANIGBOGU "[113914]Functions to output variable-length bit strings" */
|
|
/* DEC/CMS REPLACEMENT HISTORY, Element BITS.C */
|
|
/* PRIVATE FILE
|
|
******************************************************************************
|
|
**
|
|
** (c) Copyright Schlumberger Technology Corp., unpublished work, created 1996.
|
|
**
|
|
** This computer program includes Confidential, Proprietary Information and is
|
|
** a Trade Secret of Schlumberger Technology Corp. All use, disclosure, and/or
|
|
** reproduction is prohibited unless authorized in writing by Schlumberger.
|
|
** All Rights Reserved.
|
|
**
|
|
******************************************************************************
|
|
**
|
|
** compress/bits.c
|
|
**
|
|
** PURPOSE
|
|
**
|
|
** Output variable-length bit strings. Compression can be done
|
|
** to a buffer or to memory. (The latter is not supported in this version.)
|
|
**
|
|
** CLASSIFICATION TERMS
|
|
**
|
|
** DISCUSSION
|
|
**
|
|
** The PKZIP "deflate" format interprets compressed data
|
|
** as a sequence of bits. Multi-bit strings in the data may cross
|
|
** byte boundaries without restriction.
|
|
**
|
|
** The first bit of each byte is the low-order bit.
|
|
**
|
|
** The routines in this file allow a variable-length bit value to
|
|
** be output right-to-left (useful for literal values). For
|
|
** left-to-right output (useful for code strings from the tree routines),
|
|
** the bits must have been reversed first with ReverseBits().
|
|
**
|
|
** INTERFACE
|
|
**
|
|
** void InitializeBits(LocalBits_t *Bits)
|
|
** Initialize the bit string routines.
|
|
**
|
|
** void SendBits(int Value, int Length, LocalBits_t *Bits,
|
|
** CompParam_t *Comp)
|
|
** Write out a bit string, taking the source bits right to
|
|
** left.
|
|
**
|
|
** int ReverseBits(int Value, int Length)
|
|
** Reverse the bits of a bit string, taking the source bits left to
|
|
** right and emitting them right to left.
|
|
**
|
|
** void WindupBits(LocalBits_t *Bits, CompParam_t *Comp)
|
|
** Write out any remaining bits in an incomplete byte.
|
|
**
|
|
** void CopyBlock(char *Input, unsigned Length, int Header, LocalBits_t *Bits
|
|
** CompParam_t *Comp)
|
|
** Copy a stored block to the zip buffer, storing first the length and
|
|
** its one's complement if requested.
|
|
**
|
|
** SPECIAL REQUIREMENTS & NOTES
|
|
**
|
|
** AUTHOR
|
|
**
|
|
** J. C. Anigbogu
|
|
** Austin Systems Center
|
|
** Nov 1996
|
|
**
|
|
******************************************************************************
|
|
*/
|
|
|
|
#include "comppriv.h"
|
|
|
|
#define BufSize (8 * 2*sizeof(char))
|
|
/* Number of bits used within ValidBits. (ValidBits might be implemented on
|
|
* more than 16 bits on some systems.)
|
|
*/
|
|
|
|
/* ===========================================================================
|
|
* Initialize the bit string routines.
|
|
*/
|
|
void
|
|
InitializeBits(
|
|
LocalBits_t *Bits
|
|
)
|
|
{
|
|
Bits->BitBuffer = 0;
|
|
Bits->ValidBits = 0;
|
|
|
|
}
|
|
|
|
/* ===========================================================================
|
|
* Send a value on a given number of bits.
|
|
* IN assertion: length <= 16 and value fits in length bits.
|
|
*/
|
|
void
|
|
SendBits(
|
|
int Value, /* value to send */
|
|
int Length, /* number of bits */
|
|
LocalBits_t *Bits,
|
|
CompParam_t *Comp
|
|
)
|
|
{
|
|
/* If not enough room in BitBuffer, use (valid) bits from BitBuffer and
|
|
* (16 - ValidBits) bits from value, leaving (width - (16-ValidBits))
|
|
* unused bits in value.
|
|
*/
|
|
if (Bits->ValidBits > (unsigned int)(BufSize - Length))
|
|
{
|
|
Bits->BitBuffer |= ((unsigned int)Value << Bits->ValidBits);
|
|
PutShort(Bits->BitBuffer, Comp);
|
|
Bits->BitBuffer = (unsigned int)Value >> (BufSize - Bits->ValidBits);
|
|
Bits->ValidBits += (unsigned int)(Length - BufSize);
|
|
}
|
|
else
|
|
{
|
|
Bits->BitBuffer |= ((unsigned int)Value << Bits->ValidBits);
|
|
Bits->ValidBits += (unsigned int)Length;
|
|
}
|
|
}
|
|
|
|
/* ===========================================================================
|
|
* Reverse the first length bits of a code, using straightforward code (a faster
|
|
* method would use a table)
|
|
* IN assertion: 1 <= len <= 15
|
|
*/
|
|
unsigned int
|
|
ReverseBits(
|
|
unsigned int Code, /* the value to invert */
|
|
int Length /* its bit length */
|
|
)
|
|
{
|
|
unsigned int Result = 0;
|
|
|
|
do
|
|
{
|
|
Result |= Code & 1;
|
|
Code >>= 1;
|
|
Result <<= 1;
|
|
} while (--Length > 0);
|
|
return Result >> 1;
|
|
}
|
|
|
|
/* ===========================================================================
|
|
* Write out any remaining bits in an incomplete byte.
|
|
*/
|
|
void
|
|
WindupBits(
|
|
LocalBits_t *Bits,
|
|
CompParam_t *Comp
|
|
)
|
|
{
|
|
if (Bits->ValidBits > 8)
|
|
{
|
|
PutShort(Bits->BitBuffer, Comp);
|
|
}
|
|
else if (Bits->ValidBits > 0)
|
|
{
|
|
PutByte(Bits->BitBuffer, Comp);
|
|
}
|
|
Bits->BitBuffer = 0;
|
|
Bits->ValidBits = 0;
|
|
}
|
|
|
|
/* ===========================================================================
|
|
* Copy a stored block to the zip buffer, storing first the length and its
|
|
* one's complement if requested.
|
|
*/
|
|
void
|
|
CopyBlock(
|
|
char *Input, /* the input data */
|
|
unsigned int Length, /* its length */
|
|
int Header, /* true if block header must be written */
|
|
LocalBits_t *Bits,
|
|
CompParam_t *Comp
|
|
)
|
|
{
|
|
WindupBits(Bits, Comp); /* align on byte boundary */
|
|
|
|
if (Header)
|
|
{
|
|
PutShort((unsigned short)Length, Comp);
|
|
PutShort((unsigned short)~Length, Comp);
|
|
}
|
|
|
|
while (Length--)
|
|
{
|
|
PutByte(*Input++, Comp);
|
|
}
|
|
}
|