From 75efef8f16bacc8a92685421cc4a480db83b9f73 Mon Sep 17 00:00:00 2001 From: ChatGPT Date: Tue, 16 Jun 2026 19:20:14 +0000 Subject: [PATCH] 0666 nwnss: import compression codec helper providers --- src/nwnss/CMakeLists.txt | 2 + src/nwnss/comn/compression/cdcompa.c | 219 ++++++++ src/nwnss/comn/compression/cduncompa.c | 664 +++++++++++++++++++++++++ 3 files changed, 885 insertions(+) create mode 100644 src/nwnss/comn/compression/cdcompa.c create mode 100644 src/nwnss/comn/compression/cduncompa.c diff --git a/src/nwnss/CMakeLists.txt b/src/nwnss/CMakeLists.txt index 349ca8f..54aed6a 100644 --- a/src/nwnss/CMakeLists.txt +++ b/src/nwnss/CMakeLists.txt @@ -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 diff --git a/src/nwnss/comn/compression/cdcompa.c b/src/nwnss/comn/compression/cdcompa.c new file mode 100644 index 0000000..553bed9 --- /dev/null +++ b/src/nwnss/comn/compression/cdcompa.c @@ -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>= 1; \ + } + +LONG +CCDCheckSumBlock( LONG *data, LONG lengthInDwords ) +{ + LONG i, checkSum; + + for (i=0, checkSum=0; iFileVolume ) ) 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; ileft) + 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); +} diff --git a/src/nwnss/comn/compression/cduncompa.c b/src/nwnss/comn/compression/cduncompa.c new file mode 100644 index 0000000..c74e1f1 --- /dev/null +++ b/src/nwnss/comn/compression/cduncompa.c @@ -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; iBitBufferIndex--; \ + 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 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); +} +/* ******************************************************************** */