0666 nwnss: import compression codec helper providers

This commit is contained in:
ChatGPT
2026-06-16 19:20:14 +00:00
committed by Mario Fetka
parent 411772c63a
commit 75efef8f16
3 changed files with 885 additions and 0 deletions

View File

@@ -204,7 +204,9 @@ add_library(nwnss SHARED
comn/compression/nwAlgo.c
nss/msg/switchboard.c
comn/compression/cdcomp.c
comn/compression/cdcompa.c
comn/compression/cduncomp.c
comn/compression/cduncompa.c
comn/common/zPool.c
library/misc/format.c
comn/common/ndpIdBrokerShared.c

View File

@@ -0,0 +1,219 @@
/****************************************************************************
|
| (C) Copyright 1985, 1991, 1993, 1996-1999 Novell, Inc.
| All Rights Reserved.
|
| This program is free software; you can redistribute it and/or
| modify it under the terms of version 2 of the GNU General Public
| License as published by the Free Software Foundation.
|
| This program is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| GNU General Public License for more details.
|
| You should have received a copy of the GNU General Public License
| along with this program; if not, contact Novell, Inc.
|
| To contact Novell about this file by physical or electronic mail,
| you may find current contact information at www.novell.com
|
|***************************************************************************
|
| Netware file compression algorithm ported to NSS
|
|---------------------------------------------------------------------------
|
| $Author: taysom $
| $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $
|
| $RCSfile$
| $Revision: 465 $
|
|---------------------------------------------------------------------------
| Module Description:
|
+-------------------------------------------------------------------------*/
#include "nwAlgo.h"
#include "cdcomp.h"
#define WRITE_BIT0( cd ) \
cd->WriteBitIndex--; \
if (!cd->WriteBitIndex) { \
if (cd->WriteCurrentPointer == cd->WriteBufferEnd) \
if ((ccode=CCDCompressFlushWriteBuffer(cd))!=0) \
return(ccode); \
*(LONG*)cd->WriteCurrentPointer = cd->WriteBitBuffer; \
cd->WriteCurrentPointer += sizeof(cd->WriteBitBuffer); \
cd->WriteBitIndex = 32; cd->WriteBitBuffer = 0; \
} \
cd->WriteBitBuffer >>= 1;
#define WRITE_BIT1( cd ) \
cd->WriteBitIndex--; \
if (!cd->WriteBitIndex) { \
if (cd->WriteCurrentPointer == cd->WriteBufferEnd) \
if ((ccode=CCDCompressFlushWriteBuffer(cd))!=0) \
return(ccode); \
*(LONG*)cd->WriteCurrentPointer = cd->WriteBitBuffer; \
cd->WriteCurrentPointer += sizeof(cd->WriteBitBuffer); \
cd->WriteBitIndex = 32; cd->WriteBitBuffer = 0; \
} \
cd->WriteBitBuffer >>= 1; \
cd->WriteBitBuffer |= 0x80000000;
#define WRITE_BITS( cd, tw, len ) \
data = tw; \
for (i=0; i<len; i++) { \
if (data & 1) { WRITE_BIT1( cd ) } \
else { WRITE_BIT0( cp ) } \
data >>= 1; \
}
LONG
CCDCheckSumBlock( LONG *data, LONG lengthInDwords )
{
LONG i, checkSum;
for (i=0, checkSum=0; i<lengthInDwords; i++, data++ )
checkSum += *data;
return( checkSum );
}
LONG
CCDCheckSumBlock4KMinus1( LONG *data )
{
LONG checkSum;
checkSum = (~CCDCheckSumBlock( data, CD_SYSTEM_CACHE_BUFFER_LONGS - 1)) + 1;
return( checkSum );
}
LONG
CCDCompressFlushWriteBuffer( compressData_tp cd )
{
LONG ccode;
if ( zStopCompression( cd->FileVolume ) ) return(COMPRESS_ERROR_ABORTED);
if ( cd->AbortCompression ) return( COMPRESS_ERROR_ABORTED );
*((LONG *)cd->WriteBufferEnd) =
CCDCheckSumBlock4KMinus1( (LONG *)cd->WriteBufferBegin );
if ((ccode = NSSCCDReturnWriteCacheBlock( cd->WriteBufferHandle,
cd->WriteHandle, CD_SYSTEM_SECTORS_PER_BUFFER, (LONG)0)) !=0)
{
cd->WriteBufferBegin = 0;
return(ccode);
}
cd->WriteBufferBegin = 0;
cd->WriteBlockNumber++;
if ((ccode = NSSCCDGetWriteCacheBlock( cd->WriteHandle,
cd->WriteBlockNumber, (LONG)0, & cd->WriteCurrentPointer,
& cd->WriteBufferHandle )) != 0)
{
return(ccode);
}
cd->WriteBufferBegin = cd->WriteCurrentPointer;
cd->WriteBufferEnd = cd->WriteCurrentPointer + CD_SYSTEM_CACHE_BUFFER_SIZE - 4;
return((LONG)0);
}
LONG CCDCompressWriteBits( compressData_tp cp, LONG length, LONG toWriteBits )
{
LONG data;
LONG i;
LONG ccode;
WRITE_BITS( cp, toWriteBits, length );
return((LONG)0);
}
LONG CCDCompressWriteOneBit( compressData_tp cp )
{
LONG ccode;
WRITE_BIT1( cp )
return((LONG)0);
}
LONG CCDCompressWriteZeroBit( compressData_tp cp )
{
LONG ccode;
WRITE_BIT0( cp )
return((LONG)0);
}
LONG
CCDCheckSumSwappedBlock( LONG *data, LONG lengthInDwords )
{
LONG i, checkSum;
for (i=0, checkSum=0; i<lengthInDwords; i++, data++ )
checkSum += SWAP_LONG(*data);
return( checkSum );
}
LONG
CCDCheckSumSwappedBlock4K( LONG *data )
{
return( CCDCheckSumSwappedBlock( data, (LONG)CD_SYSTEM_CACHE_BUFFER_LONGS ));
}
LONG
CCDCheckSumBlock4K( LONG *data )
{
return(CCDCheckSumBlock( data, CD_SYSTEM_CACHE_BUFFER_LONGS ));
}
void
CCDFreeShannonTree( compressNode_tp treePointer )
{
if (treePointer)
{
if (treePointer->left)
CCDFreeShannonTree( treePointer->left );
if (treePointer->right)
CCDFreeShannonTree( treePointer->right );
CD_FREE( treePointer );
}
}
void
CDCountTreeNodes( compressNode_tp treePointer, LONG *count )
{
if (treePointer->left)
CDCountTreeNodes( treePointer->left, count );
if (treePointer->right)
CDCountTreeNodes( treePointer->right, count );
(*count)++;
}
LONG
CCDCountTreeNodes( compressNode_tp treePointer, LONG *count )
{
*count = 0;
CDCountTreeNodes( treePointer, count );
return((LONG)0);
}

View File

@@ -0,0 +1,664 @@
/****************************************************************************
|
| (C) Copyright 1985, 1991, 1993, 1996-1999 Novell, Inc.
| All Rights Reserved.
|
| This program is free software; you can redistribute it and/or
| modify it under the terms of version 2 of the GNU General Public
| License as published by the Free Software Foundation.
|
| This program is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| GNU General Public License for more details.
|
| You should have received a copy of the GNU General Public License
| along with this program; if not, contact Novell, Inc.
|
| To contact Novell about this file by physical or electronic mail,
| you may find current contact information at www.novell.com
|
|***************************************************************************
|
| Netware file compression algorithm ported to NSS
|
|---------------------------------------------------------------------------
|
| $Author: vandana $
| $Date: 2005-08-10 01:03:51 +0530 (Wed, 10 Aug 2005) $
|
| $RCSfile$
| $Revision: 1177 $
|
|---------------------------------------------------------------------------
| Module Description:
|
+-------------------------------------------------------------------------*/
#include "nwAlgo.h"
/****************************************************************************/
#define READ_BIT(ud, bit) \
ud->BitBufferIndex--; \
if (!ud->BitBufferIndex) { \
if (ud->BitMapCurrentPointer == ud->BitMapCurrentEnd) \
if ((ccode=CCDDecompressFillBitBuffer(ud))!=0) \
return(ccode); \
ud->BitBuffer = *ud->BitMapCurrentPointer; \
ud->BitMapCurrentPointer++; \
ud->BitBufferIndex = 32; \
} \
bit = (ud->BitBuffer & 0x1) ? 1 : 0; \
ud->BitBuffer >>=1;
#define READ_BITS( ud, bits, len ) \
bits = 0; \
for(i=0; i<len; i++) { \
READ_BIT( ud, bit ); \
if (bit) bits |= (1 << i); \
}
#define READ_BIT_HILO(ud, bit) \
ud->BitBufferIndex--; \
if (!ud->BitBufferIndex) { \
if (ud->BitMapCurrentPointer == ud->BitMapCurrentEnd) \
if ((ccode=CCDDecompressFillBitBufferHiLo(ud))!=0) \
return(ccode); \
ud->BitBuffer = SWAP_LONG(*ud->BitMapCurrentPointer); \
ud->BitMapCurrentPointer++; \
ud->BitBufferIndex = 32; \
} \
bit = (ud->BitBuffer & 0x1) ? 1 : 0; \
ud->BitBuffer >>=1;
#define READ_BITS_HILO( ud, bits, len ) \
bits = 0; \
for(i=0; i<len; i++) { \
READ_BIT_HILO( ud, bit ); \
if (bit) bits |= (1 << i); \
}
/*
* Warning! Don't replace this with memmove!
* The Netware decompression algorithm uses this routine to copy bytes between
* overlapping memory ranges. A side-effect of this copy is to duplicate some
* of the src memory range bytes across the entire destination memory range.
* This side-effect is EXPECTED by the Netware decompression algorithm.
* For this to happen, the src address must be < dest address.
*/
STATIC void
memmovePropagate(BYTE *src, BYTE *dest, LONG size)
{
SNINT i;
SLONG mydiff = (dest - src);
if ((mydiff > 0) && (size > mydiff))
{
NWALGO_DBG_PRINTF((NWALGO_DBG_COLOR, "memmove src=0x%p, dest=0x%p, diff=0x%lx, size=0x%lx\n",
src, dest, mydiff, size));
}
for (i = 0; i < size; i++)
dest[i] = src[i];
}
extern LONG CCDCheckSumBlock( LONG *data, LONG length );
extern LONG CCDCheckSumBlock4K( LONG *data );
extern LONG CCDCheckSumBlock4KMinus1( LONG *data );
extern LONG CCDCheckSumSwappedBlock( LONG *data, LONG length );
extern LONG CCDCheckSumSwappedBlock4K( LONG *data );
extern struct ScreenStruct *CompressScreen;
/* ******************************************************************** */
LONG
CCDDecompressGetWriteBuffer( uncompressData_tp ud )
{
LONG ccode;
decompressHoleMark_tp toFree;
if (ud->WriteEOFPointer != (BYTE *)-1 ) return(UNCOMPRESS_ERROR_WRITE_BEYOND_EOF);
if (ud->ThreadExitNow) return(UNCOMPRESS_ERROR_ABORTED);
if (ud->WriteCacheBufferCount < (UNCOMPRESS_WRITE_CACHE_BUFFER_RANGE-1))
{
ud->WriteCacheBufferCount++;
ud->BytesInWriteCacheSoFar += CD_SYSTEM_CACHE_BUFFER_SIZE;
}
else
{
LONG handle;
handle = ud->WriteCacheHandle[0];
/* mark this block since as tried once to return */
ud->WriteCacheHandle[0] = 0;
if((ccode=NSSCCDReturnWriteCacheBlock( handle,
ud->WriteHandle, CD_SYSTEM_SECTORS_PER_BUFFER, (LONG)0)) !=0)
return(ccode);
ud->WriteCachePointers[0] = ud->WriteCachePointers[1];
ud->WriteCacheBlockNumber[0] = ud->WriteCacheBlockNumber[1];
ud->WriteCacheHandle[0] = ud->WriteCacheHandle[1];
ud->WriteCacheBufferEnd[0] = ud->WriteCacheBufferEnd[1];
ud->WriteCachePointers[1] = ud->WriteCachePointers[2];
ud->WriteCacheBlockNumber[1] = ud->WriteCacheBlockNumber[2];
ud->WriteCacheHandle[1] = ud->WriteCacheHandle[2];
ud->WriteCacheBufferEnd[1] = ud->WriteCacheBufferEnd[2];
}
if (ud->HoleListHead)
{
while (ud->HoleListHead &&
ud->HoleListHead->offset == (ud->WriteCacheNextBlockToGet << CD_SYSTEM_CACHE_BUFFER_SHIFT ))
{
ud->WriteCacheNextBlockToGet += (ud->HoleListHead->size >> CD_SYSTEM_CACHE_BUFFER_SHIFT );
toFree = ud->HoleListHead;
ud->HoleListHead = ud->HoleListHead->next;
CD_FREE(toFree);
}
/* This file can't be ended with a hole because ud->WriteFileSize is not 0 */
CD_ASSERT ((ud->WriteCacheNextBlockToGet !=
ud->decompressStatus.status.totalBlocksToDecompress));
}
NSSCCDUpdateDecompressPosition( ud->WriteHandle,
ud->WriteCacheNextBlockToGet << CD_SYSTEM_CACHE_BUFFER_SHIFT);
if ((ccode=NSSCCDGetWriteCacheBlock(ud->WriteHandle,
ud->WriteCacheNextBlockToGet, (LONG)0,
&ud->WriteCachePointers[ ud->WriteCacheBufferCount ],
&ud->WriteCacheHandle[ ud->WriteCacheBufferCount ]))!=0)
return(ccode);
ud->WriteCacheBlockNumber[ ud->WriteCacheBufferCount ] =
ud->WriteCacheNextBlockToGet;
ud->WriteCacheNextBlockToGet++;
ud->WriteCacheBufferEnd[ ud->WriteCacheBufferCount ] =
ud->WriteCachePointers[ ud->WriteCacheBufferCount ]
+ CD_SYSTEM_CACHE_BUFFER_SIZE;
ud->WriteCurrentBufferEnd =
ud->WriteCacheBufferEnd[ ud->WriteCacheBufferCount ];
ud->WriteCurrentBufferBegin = ud->WriteCurrentPointer =
ud->WriteCachePointers[ ud->WriteCacheBufferCount ];
ud->WriteFileSize -= CD_SYSTEM_CACHE_BUFFER_SIZE;
if (ud->WriteFileSize <= CD_SYSTEM_CACHE_BUFFER_SIZE)
ud->WriteEOFPointer = ud->WriteCurrentPointer + ud->WriteFileSize;
if (ud->ThreadExitNow) return(UNCOMPRESS_ERROR_ABORTED);
return((LONG)0);
}
/* ******************************************************************** */
LONG
CCDDecompressFillBitBuffer( uncompressData_tp ud )
{
LONG ccode, holeFlag, validBytes;
if (ud->ThreadExitNow) return(UNCOMPRESS_ERROR_ABORTED);
if (!ud->CompressedFileSize) return ( UNCOMPRESS_ERROR_CORRUPT_COMPRESSED_FILE );
if ((ccode = NSSCCDFreeReadAheadBuffer( ud->ReadCache )) != 0) return(ccode);
if ((ccode = NSSCCDGetReadAheadBuffer( ud->ReadCache,
(BYTE **)&ud->BitMapCurrentPointer, &validBytes, &holeFlag )) != 0)
return(ccode);
if (holeFlag) return( UNCOMPRESS_ERROR_INVALID_HOLES );
if (ud->CompressedFileSize < CD_SYSTEM_CACHE_BUFFER_SIZE)
{
if (CCDCheckSumBlock( ud->BitMapCurrentPointer,
ud->CompressedFileSize >> 2 ))
return( UNCOMPRESS_ERROR_CORRUPT_COMPRESSED_FILE );
ud->CompressedFileSize = 0;
ud->BitMapCurrentEnd = ud->BitMapCurrentPointer +
(ud->CompressedFileSize >> 2) - 1;
}
else
{
if ( CCDCheckSumBlock4K( ud->BitMapCurrentPointer ) )
return( UNCOMPRESS_ERROR_CORRUPT_COMPRESSED_FILE );
ud->CompressedFileSize -= CD_SYSTEM_CACHE_BUFFER_SIZE;
ud->BitMapCurrentEnd = ud->BitMapCurrentPointer +
CD_SYSTEM_CACHE_BUFFER_LONGS - 1;
}
return((LONG)0);
}
/* ******************************************************************** */
LONG
CCDDecompressFillBitBufferHiLo( uncompressData_tp ud )
{
LONG ccode, holeFlag, validBytes;
/*LONG *lptr, i;*/
if (ud->ThreadExitNow) return(UNCOMPRESS_ERROR_ABORTED);
if (!ud->CompressedFileSize) return ( UNCOMPRESS_ERROR_CORRUPT_COMPRESSED_FILE );
if ((ccode = NSSCCDFreeReadAheadBuffer( ud->ReadCache )) != 0) return(ccode);
if ((ccode = NSSCCDGetReadAheadBuffer( ud->ReadCache,
(BYTE **)&ud->BitMapCurrentPointer, &validBytes, &holeFlag )) != 0)
return(ccode);
if (holeFlag) return( UNCOMPRESS_ERROR_INVALID_HOLES );
if (ud->CompressedFileSize < CD_SYSTEM_CACHE_BUFFER_SIZE)
{
if (CCDCheckSumBlock( ud->BitMapCurrentPointer,
ud->CompressedFileSize >> 2 ))
return( UNCOMPRESS_ERROR_CORRUPT_COMPRESSED_FILE );
ud->CompressedFileSize = 0;
ud->BitMapCurrentEnd = ud->BitMapCurrentPointer +
(ud->CompressedFileSize >> 2) - 1;
}
else
{
if ( CCDCheckSumBlock4K( ud->BitMapCurrentPointer ) )
return( UNCOMPRESS_ERROR_CORRUPT_COMPRESSED_FILE );
ud->CompressedFileSize -= CD_SYSTEM_CACHE_BUFFER_SIZE;
ud->BitMapCurrentEnd = ud->BitMapCurrentPointer +
CD_SYSTEM_CACHE_BUFFER_LONGS - 1;
}
return((LONG)0);
}
/* ******************************************************************** */
LONG
CDReadShannonTreeHiLo(
uncompressData_tp ud,
uncompressNode_tpp parentPtr,
uncompressNode_tpp allocPool,
LONG *count )
{
LONG ccode;
LONG bit,i;
uncompressNode_tp prevChild;
if (!*count) return (UNCOMPRESS_ERROR_TREE_TOO_BIG);
*parentPtr = prevChild = *allocPool;
(*allocPool)++;
(*count)--;
READ_BIT_HILO( ud, bit )
if (bit)
{
READ_BITS_HILO( ud, prevChild->value, 8 )
return((LONG)0);
}
if ((ccode = CDReadShannonTreeHiLo( ud, &(prevChild->left), allocPool,
count)) != 0)
return(ccode);
if ((ccode = CDReadShannonTreeHiLo( ud, &(prevChild->right), allocPool,
count)) != 0)
return(ccode);
return((LONG)0);
}
/* ******************************************************************** */
LONG
CCDReadShannonTreeHiLo( uncompressData_tp ud, uncompressNode_tpp tree,
LONG *nodeCount)
{
uncompressNode_tp hold;
LONG ccode;
hold = *tree;
if ((ccode=CDReadShannonTreeHiLo( ud, tree, tree, nodeCount)) != 0)
return( ccode );
*tree = hold;
return((LONG)0);
}
/* ******************************************************************** */
LONG
CCDDecompressFileHiLo( uncompressData_tp ud )
{
LONG ccode, bit, length, offset, toCopy;
long byteIndex;
BYTE *previousStringPointer,i;
uncompressNode_tp tree;
while ( ud->WriteCurrentPointer != ud->WriteEOFPointer )
{
READ_BIT_HILO( ud, bit );
if (bit)
{
tree = ud->DataTree;
while( tree->left )
{
READ_BIT_HILO( ud, bit );
tree = bit ? tree->right : tree->left;
}
if (ud->WriteCurrentPointer == ud->WriteCurrentBufferEnd)
{
if ((ccode = CCDDecompressGetWriteBuffer( ud )) != 0) return(ccode);
}
*ud->WriteCurrentPointer = (BYTE)tree->value;
ud->WriteCurrentPointer ++;
continue;
}
tree = ud ->LengthTree;
while( tree->left )
{
READ_BIT_HILO( ud, bit );
tree = bit ? tree->right : tree->left;
}
if (tree->value == 0xFE)
{
READ_BITS_HILO( ud, length, 13 );
}
else
{
length = tree->value;
}
READ_BITS_HILO(ud, offset, 5 );
tree = ud->OffsetTree;
while( tree->left )
{
READ_BIT_HILO( ud, bit );
tree = bit ? tree->right : tree->left;
}
offset += ( tree->value << 5 );
if (((ud->WriteCurrentPointer - offset) < ud->WriteCurrentBufferBegin)
|| ((ud->WriteCurrentPointer + length) >= ud->WriteCurrentBufferEnd))
{
byteIndex = ((ud->WriteCurrentPointer - ud->WriteCurrentBufferBegin)
+ ud->BytesInWriteCacheSoFar) - offset;
if (byteIndex < 0) return(UNCOMPRESS_ERROR_INVALID_OFFSET);
ud->WritePreviousBufferIndex = byteIndex >> CD_SYSTEM_CACHE_BUFFER_SHIFT;
if (length > (CD_SYSTEM_CACHE_BUFFER_SIZE * 2))
return( UNCOMPRESS_ERROR_INVALID_LENGTH );
previousStringPointer = ud->WriteCachePointers[ ud->WritePreviousBufferIndex ]
+ (byteIndex & CD_SYSTEM_CACHE_BUFFER_MASK) ;
ud->WritePreviousBufferEnd = ud->WriteCacheBufferEnd[ ud->WritePreviousBufferIndex ];
toCopy = length;
while (length)
{
if (ud->WriteCurrentPointer == ud->WriteCurrentBufferEnd)
{
if (ud->WriteCacheBufferCount == (UNCOMPRESS_WRITE_CACHE_BUFFER_RANGE-1))
ud->WritePreviousBufferIndex--;
if ((ccode = CCDDecompressGetWriteBuffer( ud )) != 0)
return( ccode );
}
if (previousStringPointer == ud->WritePreviousBufferEnd)
{
ud->WritePreviousBufferIndex ++;
ud->WritePreviousBufferEnd = ud->WriteCacheBufferEnd[ ud->WritePreviousBufferIndex ];
previousStringPointer = ud->WriteCachePointers[ ud->WritePreviousBufferIndex ];
}
if (toCopy > (ud->WritePreviousBufferEnd - previousStringPointer ))
toCopy = ud->WritePreviousBufferEnd - previousStringPointer ;
if (toCopy > (ud->WriteCurrentBufferEnd - ud->WriteCurrentPointer))
toCopy = ud->WriteCurrentBufferEnd - ud->WriteCurrentPointer;
memmovePropagate(previousStringPointer, ud->WriteCurrentPointer, toCopy);
previousStringPointer += toCopy;
ud->WriteCurrentPointer += toCopy;
length -= toCopy;
toCopy = length;
}
continue;
}
memmovePropagate(ud->WriteCurrentPointer - offset, ud->WriteCurrentPointer, length);
ud->WriteCurrentPointer += length;
}
return((LONG)0);
}
/* ******************************************************************** */
LONG
CDReadShannonTree(
uncompressData_tp ud,
uncompressNode_tpp parentPtr,
uncompressNode_tpp allocPool,
LONG *count )
{
LONG ccode;
LONG bit,i;
uncompressNode_tp prevChild;
if (!*count) return ( UNCOMPRESS_ERROR_TREE_TOO_BIG );
*parentPtr = prevChild = *allocPool;
(*allocPool)++;
(*count)--;
READ_BIT( ud, bit )
if (bit)
{
READ_BITS( ud, prevChild->value, 8 )
return((LONG)0);
}
if ((ccode = CDReadShannonTree( ud, &(prevChild->left), allocPool, count)) != 0)
return(ccode);
if ((ccode = CDReadShannonTree( ud, &(prevChild->right), allocPool, count)) != 0)
return(ccode);
return((LONG)0);
}
/* ******************************************************************** */
LONG
CCDReadShannonTree( uncompressData_tp ud, uncompressNode_tpp tree,
LONG *nodeCount)
{
uncompressNode_tp hold;
LONG ccode;
hold = *tree;
if ((ccode=CDReadShannonTree( ud, tree, tree, nodeCount)) != 0)
return(ccode );
*tree = hold;
return((LONG)0);
}
/* ******************************************************************** */
LONG
CCDDecompressFile( uncompressData_tp ud )
{
LONG ccode, bit, length, offset, toCopy;
long byteIndex;
BYTE *previousStringPointer,i;
uncompressNode_tp tree;
/* unCompPrintTree( ud->DataTree, 0 ); */
while ( ud->WriteCurrentPointer != ud->WriteEOFPointer )
{
READ_BIT( ud, bit );
if (bit)
{
tree = ud->DataTree;
while( tree->left )
{
READ_BIT( ud, bit );
tree = bit ? tree->right : tree->left;
}
if (ud->WriteCurrentPointer == ud->WriteCurrentBufferEnd)
{
if ((ccode = CCDDecompressGetWriteBuffer( ud )) != 0) return(ccode);
}
*ud->WriteCurrentPointer = (BYTE)tree->value;
ud->WriteCurrentPointer ++;
continue;
}
tree = ud ->LengthTree;
while( tree->left )
{
READ_BIT( ud, bit );
tree = bit ? tree->right : tree->left;
}
if (tree->value == 0xFE)
{
/* length cannot exceed 8196 because only 13 bits */
READ_BITS( ud, length, 13 );
}
else
{
length = tree->value;
}
READ_BITS(ud, offset, 5 );
tree = ud->OffsetTree;
while( tree->left )
{
READ_BIT( ud, bit );
tree = bit ? tree->right : tree->left;
}
offset += ( tree->value << 5 );
if (((ud->WriteCurrentPointer - offset) < ud->WriteCurrentBufferBegin)
|| ((ud->WriteCurrentPointer + length) >= ud->WriteCurrentBufferEnd))
{
byteIndex = ((ud->WriteCurrentPointer - ud->WriteCurrentBufferBegin)
+ ud->BytesInWriteCacheSoFar) - offset;
if (byteIndex < 0) return( UNCOMPRESS_ERROR_INVALID_OFFSET );
ud->WritePreviousBufferIndex = byteIndex >> CD_SYSTEM_CACHE_BUFFER_SHIFT;
previousStringPointer = ud->WriteCachePointers[ ud->WritePreviousBufferIndex ]
+ (byteIndex & CD_SYSTEM_CACHE_BUFFER_MASK) ;
ud->WritePreviousBufferEnd = ud->WriteCacheBufferEnd[ ud->WritePreviousBufferIndex ];
toCopy = length;
while (length)
{
if (ud->WriteCurrentPointer == ud->WriteCurrentBufferEnd)
{
if (ud->WriteCacheBufferCount == (UNCOMPRESS_WRITE_CACHE_BUFFER_RANGE-1))
ud->WritePreviousBufferIndex--;
if ((ccode = CCDDecompressGetWriteBuffer( ud )) != 0)
return( ccode );
}
if (previousStringPointer == ud->WritePreviousBufferEnd)
{
ud->WritePreviousBufferIndex ++;
previousStringPointer = ud->WriteCachePointers[ ud->WritePreviousBufferIndex ];
ud->WritePreviousBufferEnd = ud->WriteCacheBufferEnd[ ud->WritePreviousBufferIndex ];
}
if (toCopy > (ud->WritePreviousBufferEnd - previousStringPointer ))
toCopy = ud->WritePreviousBufferEnd - previousStringPointer ;
if (toCopy > (ud->WriteCurrentBufferEnd - ud->WriteCurrentPointer))
toCopy = ud->WriteCurrentBufferEnd - ud->WriteCurrentPointer;
memmovePropagate(previousStringPointer, ud->WriteCurrentPointer, toCopy);
previousStringPointer += toCopy;
ud->WriteCurrentPointer += toCopy;
length -= toCopy;
toCopy = length;
}
continue;
}
memmovePropagate( ud->WriteCurrentPointer - offset, ud->WriteCurrentPointer, length);
ud->WriteCurrentPointer += length;
}
return((LONG)0);
}
/* ******************************************************************** */