home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
compress
/
splint.arc
/
splay.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-03-08
|
7KB
|
367 lines
/* Splint:
* a data compression program
*
* This program refers the Pascal source codes of
* a splay-prefix encoding program in an article of
*
* Jones, Douglas. W,:
* Application of Splay Trees to Data Compression,
* Communications ACM, Vol. 31, No. 8, pp. 996 - 1007. (August 1988)
*
* Written by Kenji Rikitake and Naoshi Wakatabe.
* Copyright (C)1988, 1989 by Kenji Rikitake and Naoshi Wakatabe.
* All rights reserved.
* Permission to copy this program without fee all or part of this
* material is granted, provided that the copies are not made or
* distributed for direct commercial advantage.
*
* If you have any questions and/or suggestions, Contact
*
* Kenji Rikitake
* 4-19-11-102, Sakurajousui, Setagaya-ku,
* Tokyo 156 Japan
* JUNET: rikitake%wadalab.t.u-tokyo.JUNET@relay.cs.net
*/
/* $Header: splay.cv 1.6 89/03/08 01:00:50 kenji Exp $
* $Log: RCS/splay.cv $
* Revision 1.6 89/03/08 01:00:50 kenji
* combined with bitio.c by Kenji
*
* Revision 1.5 89/03/01 14:10:26 kenji
* Kenji welcome Naoshi one of the authors
* Naoshi changed the tree by using "struct".
* This made things a bit faster
*
* Revision 1.3 89/01/06 23:58:50 kenji
* encryption algorithm improved
*
* Revision 1.2 89/01/06 23:36:16 kenji
* added block freeing routine.
* modified for using file pointers.
*
* Revision 1.1 88/12/27 16:06:14 kenji
* Initial revision
*
*/
/* $Header: splay.cv 1.6 89/03/08 01:00:50 kenji Exp $
* $Log: RCS/splay.cv $
* Revision 1.6 89/03/08 01:00:50 kenji
* combined with bitio.c by Kenji
*
* Revision 1.5 89/03/01 14:10:26 kenji
* Kenji welcome Naoshi one of the authors
* Naoshi changed the tree by using "struct".
* This made things a bit faster
*
* Revision 1.4 89/02/22 20:28:14 kenji
* Modified for Microsoft C 5.1 Small Model by Naoshi Wakatabe
*
* Revision 1.3 89/01/06 23:58:50 kenji
* encryption algorithm improved
*
* Revision 1.2 89/01/06 23:36:16 kenji
* added block freeing routine.
* modified for using file pointers.
*
* Revision 1.1 88/12/27 16:06:14 kenji
* Initial revision
*
*/
static char *identfield = "$Header: splay.cv 1.6 89/03/08 01:00:50 kenji Exp $";
/* splaying routines */
#include "splint.h"
/* splay-prefix tree structure */
/*
int sup[MAXSTATE][TWICEMAX+1];
int sleft[MAXSTATE][MAXCHAR+1];
int sright[MAXSTATE][MAXCHAR+1];
*/
#ifndef MSDOS
#define far
#else
#define malloc(size) _fmalloc(size)
#define free(block) _ffree(block)
#endif
struct tree {
int up[TWICEMAX + 1];
int left[MAXCHAR + 1];
int right[MAXCHAR + 1];
};
struct tree far *stree[MAXSTATE];
int state;
#define BIT_OVLIM 16 /* output bit overflow limit */
/* bit buffers */
static int ibuf; /* input waiting bits */
static int ibitstogo; /* # of bits in ibuf */
static int igarbits; /* # of bits past eof */
static int obuf; /* output waiting bits */
static int obitstogo; /* # of bits in obuf */
/* initialize bit i/o buffers */
#define start_inputing_bits() {ibitstogo = 0; igarbits = 0;}
#define start_outputing_bits() {obuf = 0; obitstogo = 8;}
/* output buffer flush */
#define done_outputing_bits(outp) putc((obuf >> obitstogo), outp)
/* input a bit */
int input_bit(inp)
FILE *inp;
{
int t;
if (ibitstogo == 0) {
ibuf = getc(inp);
if (ibuf == EOF) {
igarbits++;
if (igarbits > BIT_OVLIM) {
fprintf(stderr, "splint: input file exceeds EOF\n");
exit(-1);
}
}
ibitstogo = 8;
}
t = ibuf & 1;
ibuf >>= 1;
ibitstogo--;
return t;
}
/* output a bit */
void output_bit(bit, outp)
int bit;
FILE *outp;
{
obuf >>= 1;
if (bit) {
obuf |= 0x80;
}
obitstogo--;
if (obitstogo == 0) {
putc(obuf, outp);
obitstogo = 8;
}
}
/* malloc() with heap check */
static void far *ch_malloc(size)
size_t size;
{
void far *blockp;
if ((blockp = malloc(size)) == NULL) {
fprintf(stderr, "splint: out of memory\n");
exit(-1);
}
return blockp;
}
/* initializing splay tree structure */
void spl_init()
{
int i, j, s;
struct tree far *spp;
void splay();
start_inputing_bits();
start_outputing_bits();
for (s = 0; s < MAXSTATE; s++) {
spp = (struct tree far *)ch_malloc(sizeof(struct tree));
stree[s] = spp;
#ifdef DEBUG
fprintf(stderr, "spl_init: s = %d\n", s);
fprintf(stderr, "coreleft = %ld\n", coreleft());
#endif
for (i = 2; i <= TWICEMAX; i++) {
spp->up[i] = i / 2;
}
for (j = 1; j <= MAXCHAR; j++) {
spp->left[j] = 2 * j;
spp->right[j] = 2 * j + 1;
}
}
/* pre-splaying for cryptography */
j = strlen(spl_passwd) - 1;
for (s = 0; s < MAXSTATE; s++) {
for (i = j; i >= 0; i--) {
state = s;
splay(spl_passwd[i]);
}
}
/* initial state */
state = 0;
}
/* unalloc used trees */
/* free() with reverse sequence of ch_malloc() */
void free_trees()
{
int s;
for (s = MAXSTATE - 1; s >= 0; s--) {
free(stree[s]);
}
}
/* splay the tree with a symbol */
#ifndef ASM
void splay(sym)
int sym;
{
int a, b, c, d;
struct tree far *spp;
a = sym + SUCCMAX;
spp = stree[state];
do {
c = spp->up[a];
if (c != ROOT) {
d = spp->up[c];
b = spp->left[d];
if (c == b) {
b = spp->right[d];
spp->right[d] = a;
}
else {
spp->left[d] = a;
}
if (a == spp->left[c]) {
spp->left[c] = b;
}
else {
spp->right[c] = b;
}
spp->up[a] = d;
spp->up[b] = c;
a = d;
}
else {
a = c;
}
} while (a != ROOT);
state = sym % MAXSTATE;
}
#endif
/* compress a symbol */
void spl_comp(sym, outp)
int sym;
FILE *outp;
{
int sp, a;
int stack[MAXCHAR];
struct tree far *spp;
a = sym + SUCCMAX;
sp = 0;
spp = stree[state];
do {
stack[sp] = (spp->right[spp->up[a]] == a) ? 1 : 0;
sp++;
a = spp->up[a];
} while (a != ROOT);
do {
sp--;
output_bit(stack[sp], outp);
} while (sp > 0);
splay(sym);
}
/* expand a code into its symbol */
int spl_exp(inp)
FILE *inp;
{
int a, sym;
struct tree far *spp;
a = ROOT;
spp = stree[state];
do {
if (input_bit(inp) == 0) {
a = spp->left[a];
}
else {
a = spp->right[a];
}
} while (a <= MAXCHAR);
sym = a - SUCCMAX;
splay(sym);
return sym;
}
/* encoding from inp to outp */
void spl_encode(inp, outp)
FILE *inp, *outp;
{
int sym;
spl_init();
for(;;) {
if((sym = getc(inp)) == EOF) break;
spl_comp(sym, outp);
}
#ifdef DEBUG
fprintf(stderr, "spl_encode: got out of for loop\n");
#endif
spl_comp(EOF_CODE, outp);
#ifdef DEBUG
fprintf(stderr, "spl_encode: spl_comp(EOF_SYM) done\n");
#endif
done_outputing_bits(outp);
free_trees();
}
/* decoding from inp to outp */
void spl_decode(inp, outp)
FILE *inp, *outp;
{
int sym;
spl_init();
for(;;) {
sym = spl_exp(inp);
if(sym == EOF_CODE) break;
putc(sym, outp);
}
#ifdef DEBUG
fprintf(stderr, "spl_decode: EOF_CODE received\n");
#endif
free_trees();
}
/* end */