📄 ppmd.cpp
字号:
"\t\t-r1 - cut off model (slow)\n"
"\t\t-r2 - freeze model (dangerous)\n"
};
template <class T>
inline T CLAMP(const T& X,const T& LoX,const T& HiX) { return (X >= LoX)?((X <= HiX)?(X):(HiX)):(LoX); }
template <class T>
inline void SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; }
void _STDCALL PrintInfo(_PPMD_FILE* DecodedFile,_PPMD_FILE* EncodedFile)
{
char WrkStr[320];
UINT NDec=ftell(DecodedFile);
NDec += (NDec == 0);
UINT NEnc=ftell(EncodedFile)-StartFilePosition;
UINT n1=(8U*NEnc)/NDec;
UINT n2=(100U*(8U*NEnc-NDec*n1)+NDec/2U)/NDec;
if (n2 == 100) { n1++; n2=0; }
int RunTime=((clock()-StartClock) << 10)/int(CLK_TCK);
UINT Speed=NDec/(RunTime+(RunTime == 0));
UINT UsedMemory=GetUsedMemory() >> 10;
UINT m1=UsedMemory >> 10;
UINT m2=(10U*(UsedMemory-(m1 << 10))+(1 << 9)) >> 10;
if (m2 == 10) { m1++; m2=0; }
if ( !EncodeFlag ) SWAP(NDec,NEnc);
sprintf(WrkStr,"%14s:%7d >%7d, %1d.%02d bpb, used:%3d.%1dMB, speed: %d KB/sec",
pFName,NDec,NEnc,n1,n2,m1,m2,Speed);
printf("%-79.79s\r",WrkStr);
}
static char* _STDCALL ChangeExtRare(const char* In,char* Out,const char* Ext)
{
char* RetVal=Out;
const char* p=strrchr(In,'.');
if (!p || strrchr(In,BACKSLASH) > p) p=In+strlen(In);
do { *Out++ = *In++; } while (In != p);
*Out++='.';
while((*Out++ = *Ext++) != 0) ;
return RetVal;
}
inline BOOL RemoveFile(const char* FName)
{
EnvSetNormAttr(FName); return (remove(FName) == 0);
}
static BOOL _STDCALL TestAccessRare(const char* FName)
{
static BOOL YesToAll=FALSE;
FILE* fp=fopen(FName,"rb");
if ( !fp ) return TRUE;
fclose(fp);
if ( YesToAll ) return RemoveFile(FName);
printf("%s already exists, overwrite?: <Y>es, <N>o, <A>ll, <Q>uit?",FName);
for ( ; ; )
switch ( toupper(EnvGetCh()) ) {
case 'A': YesToAll=TRUE;
case '\r': case 'Y': return RemoveFile(FName);
case 0x1B: case 'Q': printf(MTxt[3]); exit(-1);
case 'N': return FALSE;
}
}
inline FILE* FOpen(const char* FName,const char* mode)
{
FILE* fp=fopen(FName,mode);
if ( !fp ) { printf(MTxt[0],FName); exit(-1); }
setvbuf(fp,NULL,_IOFBF,64*1024); return fp;
}
inline void PrepareCoding(int SASize,FILE* fp)
{
if ( !StartSubAllocator(SASize) ) {
printf(MTxt[2]); exit(-1);
}
StartClock=clock(); StartFilePosition=ftell(fp);
}
inline void EncodeFile(const ENV_FIND_RESULT& efr,int MaxOrder,int SASize,MR_METHOD MRMethod,const char* ArcName)
{
char WrkStr[260];
strcpy(WrkStr,ArcName);
if (!WrkStr[0] && !TestAccessRare(ChangeExtRare(efr.getFName(),WrkStr,"pmd")))
return;
FILE* fpIn = FOpen(efr.getFName(),"rb"), * fpOut = FOpen(WrkStr,"a+b");
pFName=strrchr(efr.getFName(),BACKSLASH);
pFName=( pFName )?(pFName+1):(efr.getFName());
efr.copyDateTimeAttr();
ai.signature=PPMdSignature; ai.FNLen=strlen(pFName)+(MRMethod << 14);
ai.info=(MaxOrder-1) | ((SASize-1) << 4) | ((Variant-'A') << 12);
fwrite(&ai,sizeof(ai),1,fpOut); fwrite(pFName,ai.FNLen & 0x1FF,1,fpOut);
PrepareCoding(SASize,fpOut); EncodeFile(fpOut,fpIn,MaxOrder,MRMethod);
putchar('\n');
if (ferror(fpOut) || ferror(fpIn)) {
printf(MTxt[1],efr.getFName(),WrkStr);
exit(-1);
}
fclose(fpIn); fclose(fpOut);
}
inline BOOL DecodeOneFile(FILE* fpIn)
{
char WrkStr[260];
int MaxOrder, SASize;
MR_METHOD MRMethod;
if ( !fread(&ai,sizeof(ai),1,fpIn) ) return FALSE;
MRMethod=MR_METHOD(ai.FNLen >> 14);
ai.FNLen=CLAMP(int(ai.FNLen & 0x1FF),1,260-1);
fread(WrkStr,ai.FNLen,1,fpIn); WrkStr[ai.FNLen]=0;
if ( !TestAccessRare(WrkStr) ) return FALSE;
FILE* fpOut = FOpen(pFName=WrkStr,"wb");
MaxOrder=(ai.info & 0x0F)+1; SASize=((ai.info >> 4) & 0xFF)+1;
DWORD Variant=(ai.info >> 12)+'A';
if (ai.signature != PPMdSignature || Variant != ::Variant) {
printf(MTxt[0],WrkStr); exit(-1);
}
PrepareCoding(SASize,fpIn); DecodeFile(fpOut,fpIn,MaxOrder,MRMethod);
putchar('\n');
if (ferror(fpOut) || ferror(fpIn) || feof(fpIn)) {
printf(MTxt[1],WrkStr,WrkStr); exit(-1);
}
fclose(fpOut); EnvSetDateTimeAttr(WrkStr);
return TRUE;
}
inline void DecodeFile(const ENV_FIND_RESULT& efr)
{
FILE* fpIn=FOpen(efr.getFName(),"rb");
while ( DecodeOneFile(fpIn) ) ;
fclose(fpIn);
}
inline void TestArchive(char* ArcName,const char* Pattern)
{
if ( !Pattern[0] ) {
char CurDir[260];
EnvGetCWD(CurDir);
const char* p=strrchr(CurDir,BACKSLASH);
p = (p && strlen(p+1))?(p+1):("PPMdFile");
ChangeExtRare(p,ArcName,"pmd");
} else strcpy(ArcName,Pattern);
FILE* fp = fopen(ArcName,"rb");
if ( fp ) {
if (!fread(&ai,sizeof(ai),1,fp) || ai.signature != PPMdSignature ||
(ai.info >> 12)+'A' != ::Variant) {
printf(MTxt[0],ArcName); exit(-1);
}
fclose(fp);
}
}
struct FILE_LIST_NODE {
FILE_LIST_NODE* next;
ENV_FIND_RESULT efr;
FILE_LIST_NODE(const ENV_FIND_RESULT& Data,FILE_LIST_NODE** PrevNode) {
efr=Data; next=*PrevNode;
*PrevNode=this;
}
void destroy(FILE_LIST_NODE** PrevNode) {
*PrevNode=next; delete this;
}
};
int main(int argc, char *argv[])
{
char ArcName[260];
BOOL DeleteFile=FALSE;
int i, MaxOrder=4, SASize=10;
MR_METHOD MRMethod=MRM_RESTART;
printf("Fast PPMII compressor for textual data, variant %c, "__DATE__"\n",char(Variant));
if (argc < 3) { printf(MTxt[6],SASize,MAX_O,MaxOrder); return -1; }
switch ( toupper(argv[1][0]) ) {
case 'E': EncodeFlag=TRUE; break;
case 'D': EncodeFlag=FALSE; break;
default : printf(MTxt[4],argv[1]); return -1;
}
for (ArcName[0]=0,i=2;i < argc && (argv[i][0] == '-' || argv[i][0] == '/');i++)
switch ( toupper(argv[i][1]) ) {
case 'D': DeleteFile=TRUE; break;
case 'F': TestArchive(ArcName,argv[i]+2); break;
case 'M': SASize=CLAMP(atoi(argv[i]+2),1,256); break;
case 'O': MaxOrder=CLAMP(atoi(argv[i]+2),2,MAX_O); break;
case 'R': MRMethod=MR_METHOD(CLAMP(atoi(argv[i]+2),0,2));
break;
default : printf(MTxt[5],argv[i]); return -1;
}
FILE_LIST_NODE* pNode, * pFirstNode=NULL, ** ppNode=&pFirstNode;
for (ENV_FILE_FINDER eff;i < argc;i++) {
if ( eff.findFirst(argv[i]) )
do {
if ( eff.isFileValid() ) {
pNode = new FILE_LIST_NODE(eff.getResult(),ppNode);
if ( !pNode ) {
printf(MTxt[2]); return -1;
}
ppNode=&(pNode->next);
}
} while ( eff.findNext() );
eff.findStop();
}
while ((pNode=pFirstNode) != NULL) {
ENV_FIND_RESULT& efr=pNode->efr;
if ( EncodeFlag ) EncodeFile(efr,MaxOrder,SASize,MRMethod,ArcName);
else DecodeFile(efr);
if ( DeleteFile ) remove(efr.getFName());
pNode->destroy(&pFirstNode);
}
StopSubAllocator();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -