00001
00008 #include "dkcLZSS.h"
00009 #include "dkcStdio.h"
00010
00011
00012
00013
00014
00015
00016 #define NIL LZSS_RING_LENGTH
00017
00018 #ifdef _MSC_VER
00019 # pragma warning(disable:4127)
00020 #endif
00021
00022
00023
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00059
00060 static void InitTree( DKC_LZSS *pWork )
00061 {
00062 long i;
00063 for (i = LZSS_RING_LENGTH+1; i <= LZSS_RING_LENGTH+256; i++ )
00064 {
00065 pWork->RSon[i] = NIL;
00066 }
00067
00068 for (i = 0; i < LZSS_RING_LENGTH; i++ )
00069 {
00070 pWork->Dad[i] = NIL;
00071 }
00072 }
00073
00074
00080
00081 static void InsertNode( DKC_LZSS *pWork,long r )
00082 {
00083 long cmp = 1;
00084 unsigned char *pKey = &pWork->Text[r];
00085 long p = LZSS_RING_LENGTH + 1 + pKey[0];
00086 long i = 0;
00087
00088 pWork->RSon[r] = pWork->LSon[r] = NIL;
00089 pWork->MatchLen = 0;
00090
00091 while( TRUE )
00092 {
00093 if ( cmp >= 0 )
00094 {
00095 if ( pWork->RSon[p] != NIL )
00096 {
00097 p = pWork->RSon[p];
00098 }
00099 else
00100 {
00101 pWork->RSon[p] = r;
00102 pWork->Dad[r] = p;
00103 return;
00104 }
00105 }
00106 else
00107 {
00108 if ( pWork->LSon[p] != NIL )
00109 {
00110 p = pWork->LSon[p];
00111 }
00112 else
00113 {
00114 pWork->LSon[p] = r;
00115 pWork->Dad[r] = p;
00116 return;
00117 }
00118 }
00119
00120
00121 for ( i = 1; i < LZSS_LONGEST_MATCH; i++ )
00122 {
00123 cmp = pKey[i] - pWork->Text[p + i];
00124 if ( cmp != 0 )
00125 {
00126 break;
00127 }
00128 }
00129
00130 if ( i > pWork->MatchLen )
00131 {
00132 pWork->MatchPos = p;
00133 pWork->MatchLen = i;
00134 if ( pWork->MatchLen >= LZSS_LONGEST_MATCH )
00135 {
00136 break;
00137 }
00138 }
00139 }
00140
00141 pWork->Dad[r] = pWork->Dad[p];
00142 pWork->LSon[r] = pWork->LSon[p];
00143 pWork->RSon[r] = pWork->RSon[p];
00144 pWork->Dad[pWork->LSon[p]] = r;
00145 pWork->Dad[pWork->RSon[p]] = r;
00146
00147 if ( pWork->RSon[pWork->Dad[p]] == p )
00148 {
00149 pWork->RSon[pWork->Dad[p]] = r;
00150 }
00151 else
00152 {
00153 pWork->LSon[pWork->Dad[p]] = r;
00154 }
00155
00156 pWork->Dad[p] = NIL;
00157 }
00158
00159
00165
00166 static void DeleteNode( DKC_LZSS *pWork,long p )
00167 {
00168 long q = -1;
00169
00170 if ( pWork->Dad[p] == NIL ) return;
00171
00172 if ( pWork->RSon[p] == NIL )
00173 {
00174 q = pWork->LSon[p];
00175 }
00176 else if( pWork->LSon[p] == NIL )
00177 {
00178 q = pWork->RSon[p];
00179 }
00180 else
00181 {
00182 q = pWork->LSon[p];
00183
00184 if ( pWork->RSon[q] != NIL )
00185 {
00186 do { q = pWork->RSon[q]; } while ( pWork->RSon[q] != NIL );
00187
00188 pWork->RSon[pWork->Dad[q]] = pWork->LSon[q];
00189 pWork->Dad[pWork->LSon[q]] = pWork->Dad[q];
00190 pWork->LSon[q] = pWork->LSon[p];
00191 pWork->Dad[pWork->LSon[p]] = q;
00192 }
00193
00194 pWork->RSon[q] = pWork->RSon[p];
00195 pWork->Dad[pWork->RSon[p]] = q;
00196 }
00197
00198 pWork->Dad[q] = pWork->Dad[p];
00199 if ( pWork->RSon[pWork->Dad[p]] == p )
00200 {
00201 pWork->RSon[pWork->Dad[p]] = q;
00202 }
00203 else
00204 {
00205 pWork->LSon[pWork->Dad[p]] = q;
00206 }
00207
00208 pWork->Dad[p] = NIL;
00209 }
00210
00211
00212
00213
00223
00224 static BOOL Decode(DKC_LZSS *pWork,DKC_LZSS_HEADER *ph,
00225 const void *pSrc, void *pDst )
00226 {
00227 long r = LZSS_RING_LENGTH - LZSS_LONGEST_MATCH;
00228 unsigned long Flags = 0;
00229 unsigned char c;
00230
00231 unsigned char *pDstData = (unsigned char*)pDst;
00232
00233 unsigned char *pSrcData = (unsigned char*)pSrc;
00234
00235
00236
00237
00238 unsigned long DstSize = ph->mOriginSize;
00239
00240 long k = 0;
00241
00242 memset(pWork->Text,0,sizeof(pWork->Text) );
00252
00253
00254
00255 while ( TRUE )
00256 {
00257 Flags >>= 1;
00258 if ( (Flags & 256) == 0 )
00259 {
00260 c = *( pSrcData++ );
00261 Flags = c | 0xff00;
00262 }
00263
00264 if ( Flags & 1 )
00265 {
00266 c = *(pSrcData++);
00267 *(pDstData++) = c;
00268 if ( --DstSize == 0 ) return TRUE;
00269
00270 pWork->Text[r++] = c;
00271 r &= (LZSS_RING_LENGTH - 1);
00272 }
00273 else
00274 {
00275 long i = *(pSrcData++);
00276 long j = *(pSrcData++);
00277 i |= ((j & 0xF0) << 4);
00278 j = (j & 0x0F) + 2;
00279
00280
00281 for ( k = 0; k <= j; k++ )
00282 {
00283 c = pWork->Text[(i + k) & (LZSS_RING_LENGTH - 1)];
00284 *(pDstData++) = c;
00285 if ( --DstSize == 0 ) return TRUE;
00286
00287 pWork->Text[r++] = c;
00288 r &= (LZSS_RING_LENGTH - 1);
00289 }
00290 }
00291 }
00292
00293
00294 }
00295
00296
00308
00309 static BOOL Encode(DKC_LZSS *pWork,
00310 const void *pSrc,unsigned long SrcSize,
00311 void *pDst,size_t DstSize
00312 , unsigned long *pDstSize,
00313 size_t CloseProcessSize)
00314 {
00315 unsigned char Code[17] = { 0 };
00316 unsigned char Mask = 1;
00317 long i = 0;
00318 long Len = 0;
00319 long CodePtr = 1;
00320 long LastMatchLen = 0;
00321 long s = 0;
00322 long r = LZSS_RING_LENGTH - LZSS_LONGEST_MATCH;
00323
00324
00325
00326
00327 unsigned long SrcCheckSize = CloseProcessSize;
00328
00329
00330 unsigned char *pDstData = (unsigned char *)pDst;
00331 unsigned char *pSrcData = (unsigned char *)pSrc;
00332
00333
00334
00335 unsigned char c;
00336
00337 ULONG CompressByte = 0;
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 (*pDstSize) = 0;
00355
00356
00357
00358 InitTree(pWork );
00359
00360
00361
00362
00363 for ( i = s; i < r; i++ ) pWork->Text[i] = 0;
00364
00365 for ( Len = 0; Len < LZSS_LONGEST_MATCH ; Len++ )
00366 {
00367 unsigned char c = *(pSrcData++);
00368 if ( --SrcSize <= 0 ) break;
00369 pWork->Text[r + Len] = c;
00370 }
00371
00372 if ( Len == 0 ) return FALSE;
00373
00374 for ( i = 1; i <= LZSS_LONGEST_MATCH; i++ )
00375 {
00376 InsertNode(pWork, r - i );
00377 }
00378
00379 InsertNode(pWork, r );
00380
00381
00382
00383
00384 do
00385 {
00386 if ( pWork->MatchLen > Len )
00387 {
00388 pWork->MatchLen = Len;
00389 }
00390
00391 if ( pWork->MatchLen < 3 )
00392 {
00393 pWork->MatchLen = 1;
00394 Code[0] |= Mask;
00395 Code[CodePtr++] = pWork->Text[r];
00396 }
00397 else
00398 {
00399 Code[CodePtr++] = (unsigned char)pWork->MatchPos;
00400 Code[CodePtr++] = (unsigned char)(((pWork->MatchPos >> 4) & 0xF0) | (pWork->MatchLen - 3) );
00401 }
00402
00403 if ( (Mask <<= 1) == 0 )
00404 {
00405 (*pDstSize) += CodePtr;
00406
00407 if ( SrcCheckSize <= (*pDstSize) )
00408 {
00409
00410
00411 return edk_NoValueToProcess;
00412 }
00413
00414 CompressByte += CodePtr;
00415 if(CompressByte >= DstSize)
00416 {
00417 return edk_BufferOverFlow;
00418 }
00419
00420 for ( i = 0; i < CodePtr; i++ )
00421 {
00422 *(pDstData++) = Code[i];
00423
00424
00425 }
00426 Code[0] = 0;
00427 CodePtr = Mask = 1;
00428 }
00429
00430 LastMatchLen = pWork->MatchLen;
00431
00432 for ( i = 0; i < LastMatchLen; i++ )
00433 {
00434 if ( SrcSize == 0 ) break;
00435 SrcSize--;
00436
00437
00438 c = *(pSrcData++);
00439
00440 DeleteNode(pWork,s);
00441 pWork->Text[s] = c;
00442 if ( s < LZSS_LONGEST_MATCH - 1 )
00443 {
00444 pWork->Text[s + LZSS_RING_LENGTH] = c;
00445 }
00446 s = (s + 1) & (LZSS_RING_LENGTH - 1);
00447 r = (r + 1) & (LZSS_RING_LENGTH - 1);
00448 InsertNode(pWork, r );
00449 }
00450
00451 while ( i++ < LastMatchLen )
00452 {
00453 DeleteNode(pWork, s );
00454 s = (s + 1) & (LZSS_RING_LENGTH - 1);
00455 r = (r + 1) & (LZSS_RING_LENGTH - 1);
00456 if ( --Len ) InsertNode(pWork, r );
00457 }
00458 }
00459 while ( Len > 0 );
00460
00461
00462
00463
00464 if ( CodePtr > 1 )
00465 {
00466 (*pDstSize) += CodePtr;
00467
00468 if ( SrcCheckSize > (*pDstSize) )
00469 {
00470
00471 CompressByte += CodePtr;
00472 if(CompressByte >= DstSize){
00473 return edk_BufferOverFlow;
00474 }
00475 for ( i = 0; i < CodePtr; i++ )
00476 {
00477 *(pDstData++) = Code[i];
00478
00479 }
00480 }
00481 }
00482
00483
00485
00486 return edk_SUCCEEDED;
00487 }
00488
00489
00490 #ifdef _MSC_VER
00491 # pragma warning(default:4127)
00492 #endif
00493
00494
00495 DKC_LZSS *WINAPI dkcAllocLZSS()
00496 {
00497 DKC_LZSS *p = dkcAllocate(sizeof(DKC_LZSS));
00498 return p;
00499 }
00500
00501 int WINAPI dkcFreeLZSS(DKC_LZSS **p){
00502 if(NULL==p || NULL==*p) return edk_FAILED;
00503 return dkcFree(p);
00504 }
00505
00506
00507 int WINAPI dkcLZSSDecode(DKC_LZSS *ptr,DKC_LZSS_HEADER *ph,
00508 BYTE *dest,size_t dsize,const BYTE *src,size_t ssize,ULONG sig)
00509 {
00510 if(NULL==ptr || NULL==ph)
00511 return edk_ArgumentException;
00512
00513 if(ph->mOriginSize > dsize){
00514 return edk_BufferOverFlow;
00515 }
00516
00517 if(ph->mSignature != sig){
00518 return edk_FAILED;
00519 }
00520
00521 if(FALSE==Decode(ptr,ph,src,dest)){
00522 return edk_FAILED;
00523 }
00524
00525 return edk_SUCCEEDED;
00526
00527 }
00528
00529 int WINAPI dkcLZSSEncode(DKC_LZSS *ptr,DKC_LZSS_HEADER *ph,
00530 BYTE *dest,size_t dsize,const BYTE *src,size_t ssize,
00531 size_t CloseProcessSize,ULONG sig)
00532 {
00533 unsigned long comped;
00534 int result;
00535
00536 if(NULL==ptr || NULL==ph)
00537 return edk_ArgumentException;
00538
00539 dkcmNOT_ASSERT(NULL==dest || 0==dsize);
00540
00541
00542 result = Encode(ptr,src,ssize,dest,dsize,&comped,CloseProcessSize);
00543 if(DKUTIL_FAILED(result))
00544 {
00545 return result;
00546 }
00547 ph->mOriginSize = (size_t)ssize;
00548 ph->mCompressedSize = comped;
00549 ph->mSignature = sig;
00550
00551 return result;
00552
00553 }
00554