#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "compress_rtns.h"
int cmp_compress(char* inputFname, unsigned int fileOffset,
int reqDataSizeBytes, int cmprType,
int* cmprSizeBytes,
int* decmprSizeBytes,
char** pCmprData)
{
char* ibuffer = NULL;
unsigned int fsize = 0;
FILE* infile = NULL;
int sizeBytes = 0;
int rval = 0;
infile = fopen(inputFname,"rb");
if(infile == NULL){
printf("Error opening file %s\n",inputFname);
return -1;
}
fseek(infile,0,SEEK_END);
fsize = ftell(infile);
if(reqDataSizeBytes == 0)
sizeBytes = fsize-fileOffset;
else
sizeBytes = reqDataSizeBytes;
ibuffer = (char*)malloc(sizeBytes);
if(ibuffer == NULL){
printf("Error allocing memory for input data\n");
return -1;
}
fseek(infile,fileOffset,SEEK_SET);
sizeBytes = fread(ibuffer,1,sizeBytes,infile);
fclose(infile);
if(sizeBytes <= 0){
printf("Error reading from input file\n");
return -1;
}
*decmprSizeBytes = sizeBytes;
switch(cmprType){
case BYTE_CMP_TYPE:
{
if(cmpr_8bit(ibuffer,sizeBytes,pCmprData,cmprSizeBytes) < 0){
printf("8-bit compression failed.\n");
rval = -1;
}
}
break;
case SHORT_CMP_TYPE:
{
int numShorts = 0;
numShorts = sizeBytes / 2;
if((sizeBytes % 2) != 0)
numShorts++;
if(cmpr_16bit((short*)ibuffer,numShorts,
(short**)pCmprData,cmprSizeBytes) < 0){
printf("16-bit compression failed.\n");
rval = -1;
}
}
break;
case LONG_CMP_TYPE:
{
int numLongs = 0;
numLongs = sizeBytes / 4;
if((sizeBytes % 4) != 0)
numLongs++;
if(cmpr_32bit((int*)ibuffer,numLongs,
(int**)pCmprData,cmprSizeBytes) < 0){
printf("32-bit compression failed.\n");
rval = -1;
}
}
break;
default:
printf("Error, incorrect compression type specified.\n");
rval = -1;
}
if(ibuffer != NULL)
free(ibuffer);
return rval;
}
int cmpr_8bit(char* pData, int numBytes, char** outData, int* cmprSizeBytes){
int i, pattDetectFlg, maxCmprSizeBytes, unitSizeBytes, runtarget;
unsigned int u_unmatchedCount;
char unmatchedCount, pattern, runLength;
char* pCmrData;
char* startLoc = pData;
char* patternLoc = pData;
pattDetectFlg = 0;
unmatchedCount = 0;
unitSizeBytes = 1;
runtarget = 2;
*cmprSizeBytes = 0;
maxCmprSizeBytes = numBytes*unitSizeBytes;
*outData = (char*)malloc(maxCmprSizeBytes);
if(*outData == NULL){
printf("Error allocating memory for compressed data stream\n");
return -1;
}
pCmrData = *outData;
while(numBytes > 0){
i = 1;
if( (numBytes >= runtarget) &&
( ((runtarget == 2) && (*patternLoc == *(patternLoc+i))) ||
( ((runtarget == 3) && (*patternLoc == *(patternLoc+i)) && (*patternLoc == *(patternLoc+i+1))) )) ){
numBytes-= runtarget;
i+=runtarget-1;
runLength = runtarget-2;
runtarget = 2;
pattDetectFlg = 1;
while((numBytes > 0) && (runLength < MAX_S_BYTE)){
if(*patternLoc == *(patternLoc+i)){
i++;
runLength++;
numBytes--;
}
else
break;
}
}
if(pattDetectFlg){
pattDetectFlg = 0;
if(startLoc != patternLoc){
u_unmatchedCount = (unsigned int)(-1*unmatchedCount);
*cmprSizeBytes += u_unmatchedCount*unitSizeBytes + unitSizeBytes;
if(*cmprSizeBytes > maxCmprSizeBytes){
printf("Error in compression, expansion occurred.\n");
return -1;
}
memcpy(pCmrData,&unmatchedCount,unitSizeBytes); pCmrData++;
memcpy(pCmrData,startLoc,u_unmatchedCount*unitSizeBytes); pCmrData+=u_unmatchedCount;
unmatchedCount = 0;
}
*cmprSizeBytes += (unitSizeBytes*2);
if(*cmprSizeBytes > maxCmprSizeBytes){
printf("Error in compression, expansion occurred.\n");
return -1;
}
memcpy(pCmrData,&runLength,unitSizeBytes); pCmrData++;
pattern = *patternLoc;
memcpy(pCmrData,&pattern,unitSizeBytes); pCmrData++;
patternLoc += i;
startLoc = patternLoc;
}
else{
numBytes--;
patternLoc++;
unmatchedCount--;
if(unmatchedCount == MIN_S_BYTE){
u_unmatchedCount = (unsigned int)(-1*(unmatchedCount+(char)1)) + 1;
*cmprSizeBytes += u_unmatchedCount*unitSizeBytes + unitSizeBytes;
if(*cmprSizeBytes > maxCmprSizeBytes){
printf("Error in compression, expansion occurred.\n");
return -1;
}
memcpy(pCmrData,&unmatchedCount,unitSizeBytes); pCmrData++;
memcpy(pCmrData,startLoc,u_unmatchedCount*unitSizeBytes); pCmrData+=u_unmatchedCount;
startLoc = patternLoc;
unmatchedCount = 0;
runtarget = 2;
}
else if(unmatchedCount == (MIN_S_BYTE+1))
runtarget = 2;
else
runtarget = 3;
}
}
if(startLoc != patternLoc){
u_unmatchedCount = (unsigned int)(-1*unmatchedCount);
*cmprSizeBytes += u_unmatchedCount*unitSizeBytes + unitSizeBytes;
if(*cmprSizeBytes > maxCmprSizeBytes){
printf("Error in compression, expansion occurred.\n");
return -1;
}
memcpy(pCmrData,&unmatchedCount,unitSizeBytes); pCmrData++;
memcpy(pCmrData,startLoc,u_unmatchedCount*unitSizeBytes); pCmrData+=u_unmatchedCount;
}
return 0;
}
int cmpr_16bit(short* pData, int numShorts, short** outData, int* cmprSizeBytes){
int i, pattDetectFlg, unitSizeBytes, maxCmprSizeBytes, runtarget;
unsigned int u_unmatchedCount;
short pattern, runLength, unmatchedCount;
short* pCmrData;
short* startLoc = pData;
short* patternLoc = pData;
pattDetectFlg = 0;
unmatchedCount = 0;
unitSizeBytes = 2;
runtarget = 2;
*cmprSizeBytes = 0;
maxCmprSizeBytes = numShorts*unitSizeBytes;
*outData = (short*)malloc(maxCmprSizeBytes);
if(*outData == NULL){
printf("Error allocating memory for compressed data stream\n");
return -1;
}
pCmrData = *outData;
while(numShorts > 0){
i = 1;
if( (numShorts >= runtarget) &&
( ((runtarget == 2) && (*patternLoc == *(patternLoc+i))) ||
( ((runtarget == 3) && (*patternLoc == *(patternLoc+i)) && (*patternLoc == *(patternLoc+i+1))) )) ){
numShorts -= runtarget;
i+=runtarget-1;
runLength = runtarget-2;
runtarget = 2;
pattDetectFlg = 1;
while((numShorts > 0) && (runLength < MAX_S_SHORT)){
if(*patternLoc == *(patternLoc+i)){
i++;
runLength++;
numShorts--;
}
else
break;
}
}
if(pattDetectFlg){
pattDetectFlg = 0;
if(startLoc != patternLoc){
u_unmatchedCount = (unsigned int)(-1*unmatchedCount);
*cmprSizeBytes += u_unmatchedCount*unitSizeBytes + unitSizeBytes;
if(*cmprSizeBytes > maxCmprSizeBytes){
printf("Error in compression, expansion occurred.\n");
return -1;
}
swap16(&unmatchedCount);
memcpy(pCmrData,&unmatchedCount,unitSizeBytes); pCmrData++;
memcpy(pCmrData,startLoc,u_unmatchedCount*unitSizeBytes); pCmrData+=u_unmatchedCount;
unmatchedCount = 0;
}
*cmprSizeBytes += (unitSizeBytes*2);
if(*cmprSizeBytes > maxCmprSizeBytes){
printf("Error in compression, expansion occurred.\n");
return -1;
}
swap16(&runLength);
memcpy((char*)pCmrData,(char*)&runLength,unitSizeBytes); pCmrData++;
pattern = *patternLoc;
memcpy((char*)pCmrData,(char*)&pattern,unitSizeBytes); pCmrData++;
patternLoc += i;
startLoc = patternLoc;
}
else{
numShorts--;
patternLoc++;
unmatchedCount--;
if(unmatchedCount == MIN_S_SHORT){
u_unmatchedCount = (unsigned int)(-1*(unmatchedCount+(short)1)) + 1;
*cmprSizeBytes += u_unmatchedCount*unitSizeBytes + unitSizeBytes;
if(*cmprSizeBytes > maxCmprSizeBytes){
printf("Error in compression, expansion occurred.\n");
return -1;
}
swap16(&unmatchedCount);
memcpy(pCmrData,&unmatchedCount,unitSizeBytes); pCmrData++;
memcpy(pCmrData,startLoc,u_unmatchedCount*unitSizeBytes); pCmrData+=u_unmatchedCount;
startLoc = patternLoc;
unmatchedCount = 0;
runtarget = 2;
}
else if(unmatchedCount == (MIN_S_SHORT+1))
runtarget = 2;
else
runtarget = 3;
}
}
if(startLoc != patternLoc){
u_unmatchedCount = (unsigned int)(-1*unmatchedCount);
*cmprSizeBytes += u_unmatchedCount*unitSizeBytes + unitSizeBytes;
if(*cmprSizeBytes > maxCmprSizeBytes){
printf("Error in compression, expansion occurred.\n");
return -1;
}
swap16(&unmatchedCount);
memcpy(pCmrData,&unmatchedCount,unitSizeBytes); pCmrData++;
memcpy(pCmrData,startLoc,u_unmatchedCount*unitSizeBytes); pCmrData+=u_unmatchedCount;
}
return 0;
}
int cmpr_32bit(int* pData, int numLongs, int** outData, int* cmprSizeBytes){
int pattern, unitSizeBytes, unmatchedCount;
int i, runLength, runtarget, pattDetectFlg, maxCmprSizeBytes;
unsigned int u_unmatchedCount;
int* pCmrData;
int* startLoc = pData;
int* patternLoc = pData;
pattDetectFlg = 0;
unmatchedCount = 0;
unitSizeBytes = 4;
runtarget = 2;
*cmprSizeBytes = 0;
maxCmprSizeBytes = numLongs*unitSizeBytes;
*outData = (int*)malloc(maxCmprSizeBytes);
if(*outData == NULL){
printf("Error allocating memory for compressed data stream\n");
return -1;
}
pCmrData = *outData;
while(numLongs > 0){
i = 1;
if( (numLongs >= runtarget) &&
( ((runtarget == 2) && (*patternLoc == *(patternLoc+i))) ||
( ((runtarget == 3) && (*patternLoc == *(patternLoc+i)) && (*patternLoc == *(patternLoc+i+1))) )) ){
numLongs-= runtarget;
i+=runtarget-1;
runLength = runtarget-2;
runtarget = 2;
pattDetectFlg = 1;
while((numLongs > 0) && (runLength < MAX_S_LONG)){
if(*patternLoc == *(patternLoc+i)){
i++;
runLength++;
numLongs--;
}
else
break;
}
}
if(pattDetectFlg){
pattDetectFlg = 0;
if(startLoc != patternLoc){
u_unmatchedCount = (unsigned int)(-1*unmatchedCount);
*cmprSizeBytes += u_unmatchedCount*unitSizeBytes + unitSizeBytes;
if(*cmprSizeBytes > maxCmprSizeBytes){
printf("Error in compression, expansion occurred.\n");
return -1;
}
swap32(&unmatchedCount);
memcpy(pCmrData,&unmatchedCount,unitSizeBytes); pCmrData++;
memcpy(pCmrData,startLoc,u_unmatchedCount*unitSizeBytes); pCmrData+=u_unmatchedCount;
unmatchedCount = 0;
}
*cmprSizeBytes += (unitSizeBytes*2);
if(*cmprSizeBytes > maxCmprSizeBytes){
printf("Error in compression, expansion occurred.\n");
return -1;
}
swap32(&runLength);
memcpy(pCmrData,&runLength,unitSizeBytes); pCmrData++;
pattern = *patternLoc;
memcpy(pCmrData,&pattern,unitSizeBytes); pCmrData++;
patternLoc += i;
startLoc = patternLoc;
}
else{
numLongs--;
patternLoc++;
unmatchedCount--;
if(unmatchedCount == MIN_S_LONG){
u_unmatchedCount = (unsigned int)(-1*(unmatchedCount+(int)1)) + 1;
*cmprSizeBytes += u_unmatchedCount*unitSizeBytes + unitSizeBytes;
if(*cmprSizeBytes > maxCmprSizeBytes){
printf("Error in compression, expansion occurred.\n");
return -1;
}
swap32(&unmatchedCount);
memcpy(pCmrData,&unmatchedCount,unitSizeBytes); pCmrData++;
memcpy(pCmrData,startLoc,u_unmatchedCount*unitSizeBytes); pCmrData+=u_unmatchedCount;
startLoc = patternLoc;
unmatchedCount = 0;
runtarget = 2;
}
else if(unmatchedCount == (MIN_S_LONG+1))
runtarget = 2;
else
runtarget = 3;
}
}
if(startLoc != patternLoc){
u_unmatchedCount = (unsigned int)(-1*unmatchedCount);
*cmprSizeBytes += u_unmatchedCount*unitSizeBytes + unitSizeBytes;
if(*cmprSizeBytes > maxCmprSizeBytes){
printf("Error in compression, expansion occurred.\n");
return -1;
}
swap32(&unmatchedCount);
memcpy(pCmrData,&unmatchedCount,unitSizeBytes); pCmrData++;
memcpy(pCmrData,startLoc,u_unmatchedCount*unitSizeBytes); pCmrData+=u_unmatchedCount;
}
return 0;
}