?? huffypacker.cpp
字號:
// HuffyPacker.cpp: implementation of the HuffyPacker class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HuffmanTest.h"
#include "HuffyPacker.h"
#include "HuffmanCoder.h"
#include "HuffyDict.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
HuffyPacker::HuffyPacker()
{
InFN=OutFN=NULL;
MyLog=NULL;
MyListener=NULL;
}
HuffyPacker::~HuffyPacker()
{
delete[] InFN;
delete[] OutFN;
}
void HuffyPacker::SetUIHelpers(ProgressListener *NewListener, WinLog *NewLogTarget)
{
MyListener=NewListener;
MyLog=NewLogTarget;
}
void HuffyPacker::SetFileNames(const char *InFileName, const char *OutFileName)
{
delete[] InFN;
unsigned short FNLen=strlen(InFileName);
InFN=new char[FNLen+1];
strcpy(InFN,InFileName);
InFN[FNLen]='\0';
delete[] OutFN;
FNLen=strlen(OutFileName);
OutFN=new char[FNLen+1];
strcpy(OutFN,OutFileName);
OutFN[FNLen]='\0';
}
unsigned int HuffyPacker::ThreadEncoder(void *Self)
{
return ((HuffyPacker *)Self)->Encode();
}
unsigned int HuffyPacker::ThreadDecoder(void *Self)
{
return ((HuffyPacker *)Self)->Decode();
}
unsigned int HuffyPacker::Encode()
{
if ((!MyListener) || (!MyLog))
return 2;
char TmpBuff[64];
sprintf(TmpBuff,"Huffy packer v%d.%2d started.",HUFFYMAJORVER,HUFFYMINORVER);
MyLog->LogText(TmpBuff);
FILE *InFile=Loggedfopen(InFN,true);
if (!InFile)
return 1;
unsigned int InFileLength=GetFileLength(InFN);
MyLog->LogText("Creating adaptive dictionary...");
MyListener->SetMax(InFileLength);
MyListener->SetProgressMsg("Counting: %d%%");
HuffyDict CurrDict;
CurrDict.SetUIHelper(MyListener);
CurrDict.CreateAdaptedDict(InFile);
fclose(InFile);
unsigned char MaxLen,MinLen;
MyLog->LogText("Dictionary stats:");
sprintf(TmpBuff," Symbol count: %d",CurrDict.GetStats(MaxLen,MinLen));
MyLog->LogText(TmpBuff);
sprintf(TmpBuff," Min / Max code length: %d / %d",MinLen,MaxLen);
MyLog->LogText(TmpBuff);
InFile=Loggedfopen(InFN,true);
FILE *OutFile=Loggedfopen(OutFN,false);
if ((!InFile) || (!OutFile))
return 1;
MyLog->LogText("Writing packed file...");
//First, write the header...
WritePackedHeader(OutFile,InFileLength);
//...then the dictionary...
MyLog->LogText(" Writing dictionary...");
CurrDict.Serialize(OutFile);
//...and finally, the encoded file itself.
MyLog->LogText(" Encoding source file...");
MyListener->SetProgressMsg("Encoding: %d%%");
MyListener->Reset();
HuffmanCoder MyCoder;
MyCoder.SetProgressHelper(MyListener);
MyCoder.SetEncDict(&CurrDict);
MyCoder.Encode(InFile,OutFile);
fclose(InFile);
fclose(OutFile);
MyListener->Reset();
MyLog->LogText("Packing finished.");
sprintf(TmpBuff,"Compression ratio was %.2f",GetFileLength(OutFN)/(float)InFileLength);
MyLog->LogText(TmpBuff);
return 0;
}
unsigned int HuffyPacker::Decode()
{
if ((!MyListener) || (!MyLog))
return 2;
char TmpBuff[64];
sprintf(TmpBuff,"Huffy packer v%d.%2d started.",HUFFYMAJORVER,HUFFYMINORVER);
MyLog->LogText(TmpBuff);
FILE *InFile=Loggedfopen(InFN,true);
if (!InFile)
return 1;
unsigned int InFileLength=GetFileLength(InFN);
unsigned int OrigSize;
unsigned char HeaderRet=ReadPackedHeader(InFile,OrigSize);
if (HeaderRet==1)
{
MyLog->LogText("Input file is not Huffy-compressed.");
return 2;
}
else if (HeaderRet==2)
{
MyLog->LogText("Input file was compressed by another Huffy version.");
return 2;
}
MyLog->LogText("Reading dictonary...");
HuffyDict CurrDict;
CurrDict.SetUIHelper(MyListener);
CurrDict.Deserialize(InFile);
MyLog->LogText("Generating node transition table...");
unsigned int StateCount;
CurrDict.GetNTTable(StateCount);
sprintf(TmpBuff," State count: %d",StateCount);
MyLog->LogText(TmpBuff);
FILE *OutFile=Loggedfopen(OutFN,false);
if (!OutFile)
return 1;
MyLog->LogText("Decoding source file...");
MyListener->SetProgressMsg("Decoding: %d%%");
MyListener->SetMax(OrigSize);
HuffmanCoder MyCoder;
MyCoder.SetProgressHelper(MyListener);
MyCoder.SetDecDict(&CurrDict);
MyCoder.Decode(InFile,OutFile,OrigSize);
fclose(InFile);
fclose(OutFile);
MyListener->Reset();
MyLog->LogText("Unpacking finished.");
return 0;
}
void HuffyPacker::WritePackedHeader(FILE *TargetFile, unsigned int OrigSize)
{
fwrite("Huffy",5,1,TargetFile);
unsigned char MajVer=HUFFYMAJORVER, MinVer=HUFFYMINORVER;
fwrite(&MajVer,1,1,TargetFile);
fwrite(&MinVer,1,1,TargetFile);
fwrite(&OrigSize,4,1,TargetFile);
}
unsigned char HuffyPacker::ReadPackedHeader(FILE *SourceFile, unsigned int &RetOrigSize)
{
char HeaderTmp[5];
fread(HeaderTmp,5,1,SourceFile);
//Header mismatch.
if (memcmp("Huffy",HeaderTmp,5))
return 1;
unsigned char MajVer,MinVer;
fread(&MajVer,1,1,SourceFile);
fread(&MinVer,1,1,SourceFile);
//Archive version mismatch.
if ((MajVer!=HUFFYMAJORVER) || (MinVer!=HUFFYMINORVER))
return 2;
fread(&RetOrigSize,4,1,SourceFile);
return 0;
}
unsigned int HuffyPacker::GetFileLength(const char *FileName)
{
//Ugly and not portable.
struct _stat TmpOut;
_stat(FileName,&TmpOut);
return TmpOut.st_size;
}
FILE *HuffyPacker::Loggedfopen(const char *FileName, bool Read)
{
FILE *RetFile;
if (Read)
RetFile=fopen(FileName,"rb");
else
RetFile=fopen(FileName,"wb");
if (RetFile)
{
std::string TmpMsg="Opened file \"";
TmpMsg+=FileName;
TmpMsg+="\" for ";
if (Read)
TmpMsg+="reading.";
else
TmpMsg+="writing.";
MyLog->LogText(TmpMsg.data());
}
else
{
std::string TmpMsg="FAILED to open file \"";
TmpMsg+=FileName;
TmpMsg+="\" for ";
if (Read)
TmpMsg+="reading!";
else
TmpMsg+="writing!";
MyLog->LogText(TmpMsg.data());
}
return RetFile;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -