Example Source Code: hhdbzip.c
/*
**********************************************************************
* hhdbzip.c *
* This is free software; you can use, copy, distribute and/or modify *
* it freely under the disclaimer that no warranties are offered nor *
* liabilities assumed through such actions. *
**********************************************************************
************************************************
> hhdbzip fname
Compresses a binary file composed of 4-byte
ints and 4-byte floats. Result is fname.hgz
> hhdbzip -r fname.hgz
Recovers the associated file fname.
Must have 4 byte ints [MS-byte,,,LS-byte], and
4 byte ieee floats [sign-bit,exp,frac] with 8
bits of exp (0-255 normalized) and 23 frac bits.
************************************************/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
/*#define DEBUG*/
#define GZIP "gzip -c > "
#define GUNZIP "gzip -cd "
#define MAGIC_NUMBER 1212432974
#define EXPONENT_MASK (255<<23)
#define SPLIT(val,buf0,buf1,buf2,buf3) { \
unsigned int split4; \
split4 = *((unsigned int*)&(val));\
buf3 = 255 & split4; \
split4 >>= 8; \
buf2 = 255 & split4; \
split4 >>= 8; \
if( 32768 & split4 ) \
buf1 = (127 & split4) | 128; \
else \
buf1 = (127 & split4); \
split4 >>= 7; \
buf0 = (255 & split4); \
}
#define UNSPLIT(val,buf0,buf1,buf2,buf3) { \
if( 128 & buf1 ) \
val = ((unsigned int)1<<31) \
|((buf1)&127)<<16; \
else \
val = (buf1)<<16; \
val |= ((buf0)<<23) \
|((buf2)<<8)|(buf3); \
}
/***************************************************************/
main(argc,argv)
int argc;
char *argv[];
{
FILE *finp,*foutp,*pout,*pin;
char *fin,mode,fout[256],pcmd[512];
int size,status,n,nints,nflts;
unsigned char *buf,
*exps,
*ints1,*ints2,*ints3,
*flts1,*flts2,*flts3;
if( sizeof(int) != 4 || sizeof(float) != 4 ) {
fprintf(stderr,"Ints and flts are not 4 bytes.\n");
fprintf(stderr,"Sorry...\n");
exit(1);
}
if( argc < 2 ) {
fprintf(stderr,"Usage: %s fname [-r]\n",argv[0]);
exit(1);
}
mode = 'c';
fin = NULL;
for( n = 1; n < argc; n++) {
char *arg;
arg = argv[n];
if( arg[0] == '-' ) {
if( arg[1] == 'r' )
mode = 'r';
else {
fprintf(stderr,"Usage: %s fname [-r]\n",argv[0]);
exit(1);
}
}
else
fin = arg;
}
if( !fin ) {
fprintf(stderr,"Usage: %s fname [-r]\n",argv[0]);
exit(1);
}
if( mode == 'r' ) goto Recover;
/*** Compress ***/
finp = fopen(fin,"rb");
if( !finp ) {
fprintf(stderr,"Error opening input file %s.\n",fin);
exit(1);
}
fseek(finp,(long)0,SEEK_END);
size = ftell(finp);
fseek(finp,(long)0,SEEK_SET);
if( size & 3 ) {
fprintf(stderr,"Size of %s is not a multiple of 4.\n",fin);
goto CError;
}
size = size/4;
buf = (unsigned char*)malloc(12+size+3*size+3*size);
if( !buf ) {
fprintf(stderr,"Error allocating memory.\n");
goto CError;
}
exps = buf+12;
ints1 = exps+size;
ints2 = ints1+size;
ints3 = ints2+size;
flts1 = ints3+size;
flts2 = flts1+size;
flts3 = flts2+size;
n = nints = nflts = 0;
while( 1 ) {
unsigned int val;
status = fread(&val,4,1,finp);
switch( status ) {
case 1:
switch( val & EXPONENT_MASK ) {
case 0:
case EXPONENT_MASK:
#ifdef DEBUG
{ int *ival=(int*)&val;
printf("int = %d\n",*ival);
}
#endif
SPLIT(val,exps[n],ints1[nints],ints2[nints],ints3[nints]);
n++; nints++;
break;
default:
#ifdef DEBUG
{ float *rval=(float*)&val;
printf("flt = %f\n",*rval);
}
#endif
SPLIT(val,exps[n],flts1[nflts],flts2[nflts],flts3[nflts]);
n++; nflts++;
}
break;
case 0:
if( feof(finp) ) goto Done;
default:
fprintf(stderr,"Error reading word from %s.\n",fin);
goto CError;
}
}
Done:
fclose(finp);
strcpy(pcmd,GZIP);
status = strlen(pcmd)+strlen(fin)+5;
if( status > 512 ) {
fprintf(stderr,"Output file name %s.hgz is too long.\n",fin);
exit(1);
}
strcat(pcmd,fin);
strcat(pcmd,".hgz");
pout = (FILE*)popen(pcmd,"wb");
if( !pout ) {
fprintf(stderr,"Error starting %s\n",pcmd);
exit(1);
}
((unsigned int*)buf)[0] = MAGIC_NUMBER;
((unsigned int*)buf)[1] = nints;
((unsigned int*)buf)[2] = nflts;
fwrite(buf,1,12+size,pout);
fwrite(ints1,1,nints,pout);
fwrite(ints2,1,nints,pout);
fwrite(ints3,1,nints,pout);
fwrite(flts1,1,nflts,pout);
fwrite(flts2,1,nflts,pout);
fwrite(flts3,1,nflts,pout);
free(buf);
exit(pclose(pout));
CError:
fclose(finp);
exit(1);
/*** Uncompress ***/
Recover:
status = strlen(fin);
if( status >= 4 && status < 256 ) {
if( strcmp(&fin[status-4],".hgz") == 0 ) {
strncpy(fout,fin,status-4);
fout[status-4] = '\0';
}
else {
fprintf(stderr,"Incorrect filename suffix.\n");
exit(1);
}
}
else {
fprintf(stderr,"Incorrect filename suffix.\n");
exit(1);
}
foutp = fopen(fout,"wb");
if( !foutp ) {
fprintf(stderr,"Can not open %s for writing.\n",fout);
exit(1);
}
strcpy(pcmd,GUNZIP);
status = strlen(pcmd)+strlen(fin)+1;
if( status > 512 ) {
fprintf(stderr,"Input file name is too long.\n",fin);
goto RError;
}
strcat(pcmd,fin);
pin = (FILE*)popen(pcmd,"rb");
if( !pout ) {
fprintf(stderr,"Error starting %s\n",pcmd);
goto RError;
}
if( fread(&status,4,1,pin) != 1 || status != MAGIC_NUMBER ) {
fprintf(stderr,"%s has incorrect magic number.\n",fin);
pclose(pin);
goto RError;
}
fread(&nints,4,1,pin);
fread(&nflts,4,1,pin);
size = (nints+nflts);
buf = (unsigned char*)malloc(4*size);
if( !buf ) {
fprintf(stderr,"Error allocating memory.\n");
pclose(pin);
goto RError;
}
if( fread(buf,4,size,pin) != size ) {
fprintf(stderr,"Error uncompressing data.\n");
pclose(pin);
goto RError;
}
if( pclose(pin) ) {
fprintf(stderr,"Error uncompressing data.\n");
goto RError;
}
exps = buf;
ints1 = exps+size;
ints2 = ints1+nints;
ints3 = ints2+nints;
flts1 = ints3+nints;
flts2 = flts1+nflts;
flts3 = flts2+nflts;
for(n = 0; n < size; n++) {
unsigned int val;
switch( *exps ) {
case 0:
case 255:
UNSPLIT(val,*exps,*ints1,*ints2,*ints3);
#ifdef DEBUG
{ int *ival=(int*)&val;
printf("int = %d (%d %d %d %d)\n",*ival,*exps,*ints1,*ints2,*ints3);
}
#else
fwrite(&val,4,1,foutp);
#endif
exps++; ints1++; ints2++; ints3++;
break;
default:
UNSPLIT(val,*exps,*flts1,*flts2,*flts3);
#ifdef DEBUG
{ float *rval=(float*)&val;
printf("flt = %f (%d %d %d %d)\n",*rval,*exps,*flts1,*flts2,*flts3);
}
#else
fwrite(&val,4,1,foutp);
#endif
exps++; flts1++; flts2++; flts3++;
}
}
fclose(foutp);
free(buf);
exit(0);
RError:
fclose(foutp);
exit(1);
}
Last modified: Fri Sep 11 14:17:29 MET DST 1998