home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Black Box 4
/
BlackBox.cdr
/
archiver
/
zip10ex.arj
/
IM_BITS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-03
|
5KB
|
185 lines
/*
Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
Permission is granted to any individual or institution to use, copy, or
redistribute this software so long as all of the original files are included
unmodified, that it is not sold for profit, and that this copyright notice
is retained.
*/
/*
* im_bits.c by Richard B. Wales & Jean-loup Gailly.
*
* PURPOSE
*
* Output variable-length bit strings.
*
* DISCUSSION
*
* The PKZIP "imploded" file format interprets compressed file data
* as a sequence of bits. Multi-bit strings in the file 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 bi_reverse().
*
* INTERFACE
*
* ImpErr bi_init (FILE *fp)
* Initialize the bit string routines and specify the output
* file to be written to in subsequent calls.
*
* ImpErr bi_rlout (int value, int length)
* Write out a bit string, taking the source bits right to
* left.
*
* int bi_reverse (int value, int length)
* Reverse the bits of a bit string, taking the source bits left to
* right and emitting them right to left.
*
* ImpErr bi_windup (void)
* Write out any remaining bits in an incomplete byte.
*/
#include "implode.h"
/***********************************************************************
*
* Local data used by the "bit string" routines.
*/
/* Current file stream pointer. */
local FILE * bi_fp;
local unsigned short bi_buf;
/* Output buffer. bits are inserted starting at the bottom (least significant
* bits).
*/
#define Buf_size (8 * 2*sizeof(char))
/* Number of bits used within bi_buf. (bi_buf might be implemented on
* more than 16 bits on some systems.)
*/
local int bi_valid; /* number of valid bits in bi_buf */
/* All bits above the last valid bit are always zero.
*/
/* Output a 16 bit value to the bit stream, lower (oldest) byte first */
#define PUTSHORT(w) \
{ (void) zputc ((char)((w) & 0xff), bi_fp); \
(void) zputc ((char)((US_INT)(w) >> 8), bi_fp); \
if (ferror (bi_fp)) return IM_IOERR; \
}
/* Output an 8 bit value to the bit stream, bits right to left */
#define PUTBYTE(w) \
{ (void) zputc ((char)((w) & 0xff), bi_fp); \
if (ferror (bi_fp)) return IM_IOERR; \
}
/***********************************************************************
*
* Initialize the bit string routines.
*/
ImpErr
bi_init (fp)
FILE *fp;
{ if (fp == NULL)
{ fprintf (stderr, "\nError in bi_init: null file pointer");
return IM_LOGICERR;
}
bi_fp = fp;
bi_buf = 0;
bi_valid = 0;
return IM_OK;
}
/***********************************************************************
*
* Output bits from right to left.
*/
ImpErr
bi_rlout (value, length)
int value;
int length; /* must be <= 16 */
{
/* Send value on length bits. If not enough room in bi_buf, use
* (valid) bits from bi_buf and (16 - bi_valid) bits from value, leaving
* (width - (16-bi_valid)) unused bits in value.
*/
if (bi_valid > Buf_size - length) {
bi_buf |= (value << bi_valid);
PUTSHORT(bi_buf);
bi_buf = (unsigned short)value >> (Buf_size - bi_valid);
bi_valid += length - Buf_size;
} else {
bi_buf |= value << bi_valid;
bi_valid += length;
}
#ifdef IMPDEBUG
fprintf (stderr, " / ");
while (length-- > 0)
{
putc ((value & 1) ? '1' : '0', stderr);
value >>= 1;
}
#endif /* IMPDEBUG */
return IM_OK;
}
/***********************************************************************
*
* Reverse the bits of a bit string, taking the source bits left to
* right (starting at 2^15) and emitting them right to left.
*/
int
bi_reverse (value, length)
int value;
int length;
{
int result = 0;
unsigned short lbit = 0x8000;
unsigned short rbit = 1;
while (length-- > 0) {
if (value & lbit) result |= rbit;
lbit >>= 1, rbit <<= 1;
}
return result;
}
/***********************************************************************
*
* Flush any remaining bits.
*/
ImpErr
bi_windup ()
{
if (bi_valid > 8) {
PUTSHORT(bi_buf);
} else if (bi_valid > 0) {
PUTBYTE(bi_buf);
}
bi_buf = 0;
bi_valid = 0;
return IM_OK;
}
/**********************************************************************/