?? lzss.c
字號(hào):
// no, restore the local variables...
blDone = pCtx->blSaveDone;
nI = pCtx->nSaveI;
nC = pCtx->nSaveC;
nLen = pCtx->nSaveLen;
nR = pCtx->nSaveR;
nS = pCtx->nSaveS;
nLastMatchLength = pCtx->nSaveLastMatchLength;
bMask = pCtx->bSaveMask;
memcpy(code_buf, pCtx->saveCode_buf, 17);
// ...and jump to the last interruption point
switch (pCtx->wInterruptPoint) {
case 2 : goto ENTRYPOINT2;
case 3 : goto ENTRYPOINT3;
}
// here we start with the engine setup
ENTRYPOINT1:
initTree(pCtx); // initialize trees
code_buf[0] = 0; // code_buf[1..16] saves eight units of code, and
// code_buf[0] works as eight flags, "1" representing that
// the unit is an unencoded letter (1 byte), "0" a position
// -and-length pair (2 bytes). Thus, eight units require at
// most 16 bytes of code.
nCodeBufPtr = bMask =1;
nS = 0;
nR = LZSS_N - LZSS_F;
// clear the buffer with any character that might appear often (SPACE)
for (nI = nS; nI < nR; nI++) pCtx->text_buf[nI] = ' ';
nLen = 0;
blDone = BOOL_FALSE;
while (blDone == BOOL_FALSE)
{
// the following entry point will guarantee, that the readByte() call will
// be repeated when the engine is re-activated, same technique used below
ENTRYPOINT2:
wTemp = readByte(pCtx);
// must we interrupt the engine?
if (wTemp == LZSS_EOB)
{
COMPRESS_SAVE_LOCAL_VAR
pCtx->wInterruptPoint = 2;
// return the number of bytes written (will be zero here)
return pCtx->lBytesWritten;
}
// has the stream come to its end?
if (wTemp == LZSS_EOD) blDone = BOOL_TRUE;
else
{
// read LZSS_F bytes into the last LZSS_F bytes of the buffer
pCtx->text_buf[nR + nLen] = (WORD8) wTemp;
if (++nLen >= LZSS_F) blDone = BOOL_TRUE;
}
}
// nothing to compress at all?
if (nLen == 0) return 0;
// Insert the LZSS_F strings, each of which begins with one or more 'space'
// characters. Note the order in which these strings are inserted. This way,
// degenerated trees will be less likely to occur.
for (nI = 1; nI <= LZSS_F; nI++) insertNode(pCtx, nR - nI);
// Finally, insert the whole string just read. The context variables
// nMatchLength and nMatchPosition are set.
insertNode(pCtx, nR);
do
{
// match_length may be spuriously long near the end of text.
if (pCtx->nMatchLength > nLen) pCtx->nMatchLength = nLen;
if (pCtx->nMatchLength <= LZSS_THRESHOLD)
{
pCtx->nMatchLength = 1; // not long enough match, send one byte
code_buf[0] |= bMask; // "send one byte" flag
code_buf[nCodeBufPtr++] = pCtx->text_buf[nR]; // send uncoded
}
else
{
code_buf[nCodeBufPtr++] = (WORD8) pCtx->nMatchPosition;
// send position and length pair, note nMatchLength > LZSS_THRESHOLD.
code_buf[nCodeBufPtr++] = (WORD8) (((pCtx->nMatchPosition >> 4) & 0xf0) |
(pCtx->nMatchLength - (LZSS_THRESHOLD + 1)));
}
// shift mask left one bit
if ((bMask <<= 1) == 0)
{
// send at most 8 units of code together
for (nI = 0; nI < nCodeBufPtr; nI++)
cWriteByte(pCtx, code_buf[nI]);
code_buf[0] = 0;
nCodeBufPtr = bMask = 1;
}
nLastMatchLength = pCtx->nMatchLength;
nI = 0;
blDone = BOOL_FALSE;
while (blDone == BOOL_FALSE)
{
ENTRYPOINT3:
wTemp = readByte(pCtx);
// must we interrupt the engine?
if (wTemp == LZSS_EOB)
{
COMPRESS_SAVE_LOCAL_VAR
pCtx->wInterruptPoint = 3;
// return the number of bytes written
return pCtx->lBytesWritten;
}
// has the stream come to its end?
if (wTemp == LZSS_EOD)
blDone = BOOL_TRUE;
else
{
nC = wTemp;
// delete old strings and read new bytes
deleteNode(pCtx, nS);
pCtx->text_buf[nS] = (WORD8) nC;
// if the position is near the end of buffer, extend the buffer to
// make string comparison easier
if (nS < (LZSS_F - 1)) pCtx->text_buf[nS + LZSS_N] = (WORD8) nC;
// since this is a ring buffer, increment the position modulo LZSS_N
nS = (nS + 1) & (LZSS_N - 1);
nR = (nR + 1) & (LZSS_N - 1);
// register the string in text_buf[nR..nR + LZSS_F - 1]
insertNode(pCtx, nR);
if (++nI >= nLastMatchLength) blDone = BOOL_TRUE;
}
}
// after the end of text,no need to read, but buffer may not be empty
while (nI++ < nLastMatchLength)
{
deleteNode(pCtx, nS);
nS = (nS + 1) & (LZSS_N - 1);
nR = (nR + 1) & (LZSS_N - 1);
if (--nLen) insertNode(pCtx, nR);
}
}
while (nLen > 0); // (until all data has been compressed)
// send remaining code
if (nCodeBufPtr > 1)
for (nI = 0; nI < nCodeBufPtr; nI++) cWriteByte(pCtx, code_buf[nI]);
// remember that lCodeSize just contains the number of all compressed bytes
return pCtx->lBytesWritten;
}
// macro to save the local variables in a context, used in LZSS_Decompress()
#define DECOMPRESS_SAVE_LOCAL_VAR pCtx->blSaveDone = blDone; \
pCtx->nSaveI = nI; \
pCtx->nSaveJ = nJ; \
pCtx->nSaveK = nK; \
pCtx->nSaveR = nR; \
pCtx->nSaveC = nC; \
pCtx->wSaveFlags = wFlags;
WORD32 CRYPTPAK_API LZSS_Decompress
(PLZSSCTX pCtx,
const void* pSource,
void* pTarget,
WORD32 lNumOfBytes,
WORD32 lSizeOfOutputBuffer,
WORD8 bCondition,
BYTEBOOL* pblRepeatMe)
{
BYTEBOOL blDone;
int nI, nJ, nK, nR, nC;
WORD16 wFlags;
WORD16 wTemp; // (this variable mustn't be saved)
// first set up the i/o pointers and the counters
pCtx->pDataSource = (WORD8*) pSource;
pCtx->pDataDrain = (WORD8*) pTarget;
pCtx->lDrainSize = lSizeOfOutputBuffer;
pCtx->lSourceSize = lNumOfBytes;
if (*pblRepeatMe == BOOL_FALSE) pCtx->lBytesRead = 0;
pCtx->lBytesWritten = 0;
// end of data stream?
if ((bCondition & LZSS_STOP) == LZSS_STOP)
pCtx->blEOD = BOOL_TRUE;
else
pCtx->blEOD = BOOL_FALSE;
// must we first launch the compression engine?
if ((bCondition & LZSS_START) == LZSS_START)
{
blDone = BOOL_FALSE;
nJ = nK = nC = 0;
goto ENTRYPOINT1;
}
// if not, restore the local variables...
blDone = pCtx->blSaveDone;
nI = pCtx->nSaveI;
nJ = pCtx->nSaveJ;
nK = pCtx->nSaveK;
nR = pCtx->nSaveR;
nC = pCtx->nSaveC;
wFlags = pCtx->wSaveFlags;
// ...and jump to the last interrupt point
switch (pCtx->wInterruptPoint)
{
case 2 : goto ENTRYPOINT2;
case 3 : goto ENTRYPOINT3;
case 4 : goto ENTRYPOINT4;
case 5 : goto ENTRYPOINT5;
case 6 : goto ENTRYPOINT6;
case 7 : goto ENTRYPOINT7;
}
// here we start with the engine setup
ENTRYPOINT1:
for (nI = 0; nI < LZSS_N - LZSS_F; nI++)
pCtx->text_buf[nI] = ' ';
nR = LZSS_N - LZSS_F;
wFlags = 0;
for (;;)
{
if (((wFlags >>= 1) & 256) == 0)
{
ENTRYPOINT2:
wTemp = readByte(pCtx);
// must we interrupt the engine?
if (wTemp == LZSS_EOB)
{
DECOMPRESS_SAVE_LOCAL_VAR
pCtx->wInterruptPoint = 2;
*pblRepeatMe = BOOL_FALSE;
return pCtx->lBytesWritten;
}
// has the stream come to its end?
if (wTemp == LZSS_EOD)
{
// yes, everything's finished now
*pblRepeatMe = BOOL_FALSE;
return pCtx->lBytesWritten;
}
nC = wTemp;
wFlags = (WORD16) (nC | 0xff00); // uses higher byte cleverly to count 8
}
if (wFlags & 1)
{
ENTRYPOINT3:
wTemp = readByte(pCtx);
// (same input technique as above)
if (wTemp == LZSS_EOB)
{
DECOMPRESS_SAVE_LOCAL_VAR
pCtx->wInterruptPoint = 3;
*pblRepeatMe = BOOL_FALSE;
return pCtx->lBytesWritten;
}
if (wTemp == LZSS_EOD)
{
*pblRepeatMe = BOOL_FALSE;
return pCtx->lBytesWritten;
}
nC = wTemp;
// can we put out a byte?
ENTRYPOINT4:
if (dWriteByte(pCtx, (WORD8) nC) == BOOL_FALSE)
{
// no -> set the repeat flag and interrupt the routine
DECOMPRESS_SAVE_LOCAL_VAR
pCtx->wInterruptPoint = 4;
*pblRepeatMe = BOOL_TRUE;
return pCtx->lBytesWritten;
}
pCtx->text_buf[nR++] = (WORD8) nC;
nR &= (LZSS_N - 1);
}
else
{
// (same input techniques as above)
ENTRYPOINT5:
wTemp = readByte(pCtx);
if (wTemp == LZSS_EOB)
{
DECOMPRESS_SAVE_LOCAL_VAR
pCtx->wInterruptPoint = 5;
*pblRepeatMe = BOOL_FALSE;
return pCtx->lBytesWritten;
}
if (wTemp == LZSS_EOD)
{
*pblRepeatMe = BOOL_FALSE;
return pCtx->lBytesWritten;
}
nI = wTemp;
ENTRYPOINT6:
wTemp = readByte(pCtx);
if (wTemp == LZSS_EOB)
{
DECOMPRESS_SAVE_LOCAL_VAR
pCtx->wInterruptPoint = 6;
*pblRepeatMe = BOOL_FALSE;
return pCtx->lBytesWritten;
}
if (wTemp == LZSS_EOD)
{
*pblRepeatMe = BOOL_FALSE;
return pCtx->lBytesWritten;
}
nJ = wTemp;
nI |= ((nJ & 0xf0) << 4);
nJ = (nJ & 0x0f) + LZSS_THRESHOLD;
nK = 0;
while (nK <= nJ)
{
nC = pCtx->text_buf[(nI + nK) & (LZSS_N - 1)];
ENTRYPOINT7:
// (same output technique as above)
if (dWriteByte(pCtx, (WORD8) nC) == BOOL_FALSE)
{
DECOMPRESS_SAVE_LOCAL_VAR
pCtx->wInterruptPoint = 7;
*pblRepeatMe = BOOL_TRUE;
return pCtx->lBytesWritten;
}
pCtx->text_buf[nR++] = (WORD8) nC;
nR &= (LZSS_N - 1);
nK++;
}
}
} // of while()
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -