216 lines
6.1 KiB
C++
216 lines
6.1 KiB
C++
/* DEC/CMS REPLACEMENT HISTORY, Element ZIP.C */
|
|
/* *1 14-NOV-1996 10:27:08 ANIGBOGU "[113914]Compress data to zip format using the deflate algorithm" */
|
|
/* DEC/CMS REPLACEMENT HISTORY, Element ZIP.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/zip.c
|
|
**
|
|
** PURPOSE
|
|
**
|
|
** Compress data using the deflate algorithm
|
|
**
|
|
** SPECIAL REQUIREMENTS & NOTES
|
|
**
|
|
** AUTHOR
|
|
**
|
|
** J. C. Anigbogu
|
|
** Austin Systems Center
|
|
** Nov 1996
|
|
**
|
|
******************************************************************************
|
|
*/
|
|
|
|
#include <ctype.h>
|
|
#include <sys/types.h>
|
|
|
|
#include "comppriv.h"
|
|
|
|
CompressStatus_t Copy(CompParam_t *comp);
|
|
|
|
/* ===========================================================================
|
|
* Deflate in to out.
|
|
* IN assertions: the input and output buffers are cleared.
|
|
*/
|
|
CompressStatus_t
|
|
Zip(
|
|
int CompLevel, /* compression level */
|
|
CompParam_t *Comp
|
|
)
|
|
{
|
|
unsigned char Flags = 0; /* general purpose bit flags */
|
|
unsigned short DeflateFlags = 0; /* pkzip -es, -en or -ex equivalent */
|
|
long TimeStamp = 0; /* time_stamp */
|
|
LocalBits_t *Bits;
|
|
DeflateParam_t *Defl; /* window offset of current block */
|
|
LocalDef_t *Deflt;
|
|
int Method = CompLevel ? DEFLATED : STORED;
|
|
CompressStatus_t Status = COMPRESS_OK;
|
|
|
|
Comp->OutBytes = 0;
|
|
|
|
/* Write the header to the gzip buffer. See algorithm.doc for the format */
|
|
|
|
PutByte(GZIP_MAGIC[0], Comp); /* magic header */
|
|
PutByte(GZIP_MAGIC[1], Comp);
|
|
PutByte(Method, Comp); /* compression method */
|
|
|
|
PutByte(Flags, Comp); /* general flags */
|
|
PutLong(TimeStamp, Comp);
|
|
|
|
Comp->pCRC->Compute(NULL, 0);
|
|
|
|
Comp->HeaderBytes = Comp->OutBytes;
|
|
|
|
if (Method == STORED)
|
|
{
|
|
PutByte((unsigned char)0, Comp); /* extra flags */
|
|
PutByte(OS_CODE, Comp); /* OS identifier */
|
|
|
|
Status = Copy(Comp);
|
|
if (COMPRESS_OK != Status)
|
|
return Status;
|
|
}
|
|
else
|
|
{
|
|
Bits = (LocalBits_t *)CompressMalloc(sizeof(LocalBits_t), &Status);
|
|
if (Status != COMPRESS_OK)
|
|
return Status;
|
|
|
|
InitializeBits(Bits);
|
|
InitMatchBuffer();
|
|
Defl = (DeflateParam_t *)CompressMalloc(sizeof(DeflateParam_t), &Status);
|
|
if (Status != COMPRESS_OK)
|
|
{
|
|
CompressFree(Bits);
|
|
return Status;
|
|
}
|
|
|
|
Deflt = (LocalDef_t *)CompressMalloc(sizeof(LocalDef_t), &Status);
|
|
if (Status != COMPRESS_OK)
|
|
{
|
|
CompressFree(Bits);
|
|
CompressFree(Defl);
|
|
return Status;
|
|
}
|
|
|
|
if ((Status = InitLongestMatch(CompLevel, &DeflateFlags,
|
|
Defl, Deflt, Comp)) != COMPRESS_OK)
|
|
{
|
|
CompressFree(Bits);
|
|
CompressFree(Defl);
|
|
CompressFree(Deflt);
|
|
return Status;
|
|
}
|
|
|
|
PutByte((unsigned char)DeflateFlags, Comp); /* extra flags */
|
|
PutByte(OS_CODE, Comp); /* OS identifier */
|
|
|
|
(void)Deflate(CompLevel, Bits, Defl, Deflt, Comp);
|
|
|
|
CompressFree(Bits);
|
|
CompressFree(Defl);
|
|
CompressFree(Deflt);
|
|
|
|
PutLong((unsigned __int32)(*Comp->pCRC), Comp);
|
|
PutLong(Comp->BytesIn, Comp);
|
|
Comp->HeaderBytes += 2*sizeof(unsigned long);
|
|
|
|
Status = FlushOutputBuffer(Comp);
|
|
if (COMPRESS_OK != Status)
|
|
return Status;
|
|
}
|
|
/* Write the crc and uncompressed size */
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Read new data from the current input buffer and
|
|
* update the crc and input data size.
|
|
* IN assertion: size >= 2 (for end-of-line translation)
|
|
*/
|
|
int
|
|
ReadBuffer(
|
|
char *Input,
|
|
unsigned int Size,
|
|
CompParam_t *Comp
|
|
)
|
|
{
|
|
unsigned long Length;
|
|
Assert(Comp->InputSize == 0, "input buffer not empty");
|
|
|
|
/* Read as much as possible */
|
|
Length = MIN(Comp->GlobalSize - Comp->BytesIn, (unsigned long)Size);
|
|
|
|
if (Length == 0)
|
|
return (int)Length;
|
|
|
|
memcpy((char *)Input, (char *)Comp->GlobalInput + Comp->BytesIn,
|
|
(int)Length);
|
|
|
|
Comp->pCRC->Compute((unsigned char *)Input, (unsigned int)Length);
|
|
Comp->BytesIn += Length;
|
|
return (int)Length;
|
|
}
|
|
|
|
/* ===========================================================================
|
|
* Read a new buffer from the current input.
|
|
*/
|
|
int
|
|
FillBuffer(
|
|
unsigned char *Input,
|
|
unsigned int Size,
|
|
CompParam_t *Comp
|
|
)
|
|
{
|
|
/* Point to the input buffer */
|
|
|
|
Comp->Input = Comp->InputBuffer;
|
|
Comp->GlobalInput = Input;
|
|
Comp->GlobalSize = Size;
|
|
Comp->WindowSize = (unsigned long) DWSIZE;
|
|
ClearBuffers(Comp); /* clear input and output buffers */
|
|
Comp->PtrOutput = NULL;
|
|
return (int)Size;
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Copy input to output unchanged
|
|
* IN assertion: comp->GlobalSize bytes have already been read in comp->GlobalInput.
|
|
*/
|
|
CompressStatus_t
|
|
Copy(
|
|
CompParam_t *Comp
|
|
)
|
|
{
|
|
CompressStatus_t Status = COMPRESS_OK;
|
|
|
|
Comp->pCRC->Compute(Comp->GlobalInput, (unsigned int)Comp->GlobalSize);
|
|
|
|
PutLong((unsigned __int32)(*Comp->pCRC), Comp);
|
|
PutLong(Comp->GlobalSize, Comp);
|
|
Status = FlushOutputBuffer(Comp);
|
|
if (COMPRESS_OK != Status)
|
|
return Status;
|
|
|
|
Status = WriteBuffer(Comp, Comp->GlobalInput,
|
|
(unsigned int)Comp->GlobalSize);
|
|
if (COMPRESS_OK != Status)
|
|
return Status;
|
|
|
|
Comp->BytesOut += Comp->GlobalSize;
|
|
|
|
return Status;
|
|
}
|