CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

LZWPIPE.CPP (14784B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/LZWPIPE.CPP 1     3/03/97 10:25a Joe_bostic $ */
     17 /***********************************************************************************************
     18  ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : LZWPIPE.CPP                                                  *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : 06/30/96                                                     *
     28  *                                                                                             *
     29  *                  Last Update : July 4, 1996 [JLB]                                           *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   LZWPipe::Flush -- Flushes any partially accumulated block.                                *
     34  *   LZWPipe::LZWPipe -- Constructor for the LZW processor pipe.                               *
     35  *   LZWPipe::Put -- Send some data through the LZW processor pipe.                            *
     36  *   LZWPipe::~LZWPipe -- Deconstructor for the LZW pipe object.                               *
     37  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     38 
     39 
     40 #include	"lzwpipe.h"
     41 #include	"lzw.h"
     42 #include	"buff.h"
     43 #include	<string.h>
     44 #include	<assert.h>
     45 
     46 
     47 /***********************************************************************************************
     48  * LZWPipe::LZWPipe -- Constructor for the LZW processor pipe.                                 *
     49  *                                                                                             *
     50  *    This will initialize the LZWPipe object so that it is prepared for compression or        *
     51  *    decompression as indicated.                                                              *
     52  *                                                                                             *
     53  * INPUT:   decrypt  -- Should decompression be performed?                                     *
     54  *                                                                                             *
     55  *          blocksize-- The size of the data blocks to process.                                *
     56  *                                                                                             *
     57  * OUTPUT:  none                                                                               *
     58  *                                                                                             *
     59  * WARNINGS:   none                                                                            *
     60  *                                                                                             *
     61  * HISTORY:                                                                                    *
     62  *   07/04/1996 JLB : Created.                                                                 *
     63  *=============================================================================================*/
     64 LZWPipe::LZWPipe(CompControl control, int blocksize) :
     65 		Control(control),
     66 		Counter(0),
     67 		Buffer(NULL),
     68 		Buffer2(NULL),
     69 		BlockSize(blocksize)
     70 {
     71 	SafetyMargin = BlockSize;
     72 //	SafetyMargin = BlockSize/128+1;
     73 	Buffer = new char[BlockSize+SafetyMargin];
     74 	Buffer2 = new char[BlockSize+SafetyMargin];
     75 	BlockHeader.CompCount = 0xFFFF;
     76 }
     77 
     78 
     79 /***********************************************************************************************
     80  * LZWPipe::~LZWPipe -- Deconstructor for the LZW pipe object.                                 *
     81  *                                                                                             *
     82  *    This will free any buffers it may have allocated.                                        *
     83  *                                                                                             *
     84  * INPUT:   none                                                                               *
     85  *                                                                                             *
     86  * OUTPUT:  none                                                                               *
     87  *                                                                                             *
     88  * WARNINGS:   none                                                                            *
     89  *                                                                                             *
     90  * HISTORY:                                                                                    *
     91  *   07/04/1996 JLB : Created.                                                                 *
     92  *=============================================================================================*/
     93 LZWPipe::~LZWPipe(void)
     94 {
     95 	delete [] Buffer;
     96 	Buffer = NULL;
     97 
     98 	delete [] Buffer2;
     99 	Buffer2 = NULL;
    100 }
    101 
    102 
    103 /***********************************************************************************************
    104  * LZWPipe::Put -- Send some data through the LZW processor pipe.                              *
    105  *                                                                                             *
    106  *    This routine will take the data requested and process it (decompression or compression). *
    107  *    It does this by accumulating the necessary bytes to make a whole block. Then the block   *
    108  *    is processed and the entire contents are flushed to the next pipe segment in the chain.  *
    109  *                                                                                             *
    110  * INPUT:   source   -- Pointer to the data to be fed to this LZW processor.                   *
    111  *                                                                                             *
    112  *          length   -- The number of bytes received.                                          *
    113  *                                                                                             *
    114  * OUTPUT:  Returns with the actual number of bytes output at the far distant final link in    *
    115  *          the pipe chain.                                                                    *
    116  *                                                                                             *
    117  * WARNINGS:   The compression process may be slow as well as consuming two buffers.           *
    118  *                                                                                             *
    119  * HISTORY:                                                                                    *
    120  *   07/04/1996 JLB : Created.                                                                 *
    121  *=============================================================================================*/
    122 int LZWPipe::Put(void const * source, int slen)
    123 {
    124 	if (source == NULL || slen < 1) {
    125 		return(Pipe::Put(source, slen));
    126 	}
    127 
    128 	assert(Buffer != NULL);
    129 
    130 	int total = 0;
    131 
    132 	/*
    133 	**	Copy as much as can fit into the buffer from the source data supplied.
    134 	*/
    135 	if (Control ==  DECOMPRESS) {
    136 
    137 		while (slen > 0) {
    138 
    139 			/*
    140 			**	First check to see if we are in the block header accumulation phase.
    141 			**	When a whole block header has been accumulated, only then will the regular
    142 			**	data processing begin for the block.
    143 			*/
    144 			if (BlockHeader.CompCount == 0xFFFF) {
    145 				int len = (slen < ((int)sizeof(BlockHeader)-Counter)) ? slen : (sizeof(BlockHeader)-Counter);
    146 				memmove(&Buffer[Counter], source, len);
    147 				source = ((char *)source) + len;
    148 				slen -= len;
    149 				Counter += len;
    150 
    151 				/*
    152 				**	A whole block header has been accumulated. Store it for safekeeping.
    153 				*/
    154 				if (Counter == sizeof(BlockHeader)) {
    155 					memmove(&BlockHeader, Buffer, sizeof(BlockHeader));
    156 					Counter = 0;
    157 				}
    158 			}
    159 
    160 			/*
    161 			**	Fill the buffer with compressed data until there is enough to make a whole
    162 			**	data block.
    163 			*/
    164 			if (slen > 0) {
    165 				int len = (slen < (BlockHeader.CompCount-Counter)) ? slen : (BlockHeader.CompCount-Counter);
    166 
    167 				memmove(&Buffer[Counter], source, len);
    168 				slen -= len;
    169 				source = ((char *)source) + len;
    170 				Counter += len;
    171 
    172 				/*
    173 				**	If an entire block has been accumulated, then uncompress it and feed it
    174 				**	through the pipe.
    175 				*/
    176 				if (Counter == BlockHeader.CompCount) {
    177 					LZW_Uncompress(Buffer, Buffer2);
    178 					total += Pipe::Put(Buffer2, BlockHeader.UncompCount);
    179 					Counter = 0;
    180 					BlockHeader.CompCount = 0xFFFF;
    181 				}
    182 			}
    183 		}
    184 
    185 	} else {
    186 
    187 		/*
    188 		**	If the buffer already contains some data, then any new data must be stored
    189 		**	into the staging buffer until a full set has been accumulated.
    190 		*/
    191 		if (Counter > 0) {
    192 			int tocopy = (slen < (BlockSize-Counter)) ? slen : (BlockSize-Counter);
    193 			memmove(&Buffer[Counter], source, tocopy);
    194 			source = ((char *)source) + tocopy;
    195 			slen -= tocopy;
    196 			Counter += tocopy;
    197 
    198 			if (Counter == BlockSize) {
    199 				int len = LZW_Compress(::Buffer(Buffer, BlockSize), Buffer2);
    200 
    201 				BlockHeader.CompCount = (unsigned short)len;
    202 				BlockHeader.UncompCount = (unsigned short)BlockSize;
    203 				total += Pipe::Put(&BlockHeader, sizeof(BlockHeader));
    204 				total += Pipe::Put(Buffer2, len);
    205 				Counter = 0;
    206 			}
    207 		}
    208 
    209 		/*
    210 		**	Process the source data in whole block chunks until there is insufficient
    211 		**	source data left for a whole data block.
    212 		*/
    213 		while (slen >= BlockSize) {
    214 			int len = LZW_Compress(::Buffer((void*)source, BlockSize), Buffer2);
    215 
    216 			source = ((char *)source) + BlockSize;
    217 			slen -= BlockSize;
    218 
    219 			BlockHeader.CompCount = (unsigned short)len;
    220 			BlockHeader.UncompCount = (unsigned short)BlockSize;
    221 			total += Pipe::Put(&BlockHeader, sizeof(BlockHeader));
    222 			total += Pipe::Put(Buffer2, len);
    223 		}
    224 
    225 		/*
    226 		**	If there is any remaining data, then it is stored into the buffer
    227 		**	until a full data block has been accumulated.
    228 		*/
    229 		if (slen > 0) {
    230 			memmove(Buffer, source, slen);
    231 			Counter = slen;
    232 		}
    233 	}
    234 
    235 	return(total);
    236 }
    237 
    238 
    239 /***********************************************************************************************
    240  * LZWPipe::Flush -- Flushes any partially accumulated block.                                  *
    241  *                                                                                             *
    242  *    This routine is called when any buffered data must be flushed out the pipe. For the      *
    243  *    compression process, this will generate the sub-sized compressed block. For              *
    244  *    decompression, this routine should not have any data in the buffer. In such a case, it   *
    245  *    means that the data source was prematurely truncated. In such a case, just dump the      *
    246  *    accumulated data through the pipe.                                                       *
    247  *                                                                                             *
    248  * INPUT:   none                                                                               *
    249  *                                                                                             *
    250  * OUTPUT:  Returns with the actual number of data bytes output to the distant final link in   *
    251  *          the pipe chain.                                                                    *
    252  *                                                                                             *
    253  * WARNINGS:   none                                                                            *
    254  *                                                                                             *
    255  * HISTORY:                                                                                    *
    256  *   07/04/1996 JLB : Created.                                                                 *
    257  *=============================================================================================*/
    258 int LZWPipe::Flush(void)
    259 {
    260 	assert(Buffer != NULL);
    261 
    262 	int total = 0;
    263 
    264 	/*
    265 	**	If there is accumulated data, then it must processed.
    266 	*/
    267 	if (Counter > 0) {
    268 		if (Control == DECOMPRESS) {
    269 
    270 			/*
    271 			**	If the accumulated data is insufficient to make a block header, then
    272 			**	this means the data has been truncated. Just dump the data through
    273 			**	as if were already decompressed.
    274 			*/
    275 			if (BlockHeader.CompCount == 0xFFFF) {
    276 				total += Pipe::Put(Buffer, Counter);
    277 				Counter = 0;
    278 			}
    279 
    280 			/*
    281 			**	There appears to be a partial block accumulated in the buffer. It would
    282 			**	be disastrous to try to decompress the data since there wouldn't be
    283 			**	the special end of data code that LZW decompression needs. In this
    284 			**	case, dump the data out as if it were already decompressed.
    285 			*/
    286 			if (Counter > 0) {
    287 				total += Pipe::Put(&BlockHeader, sizeof(BlockHeader));
    288 				total += Pipe::Put(Buffer, Counter);
    289 				Counter = 0;
    290 				BlockHeader.CompCount = 0xFFFF;
    291 			}
    292 
    293 		} else {
    294 
    295 			/*
    296 			**	A partial block in the compression process is a normal occurrence. Just
    297 			**	compress the partial block and output normally.
    298 			*/
    299 			int len = LZW_Compress(::Buffer(Buffer, Counter), Buffer2);
    300 
    301 			BlockHeader.CompCount = (unsigned short)len;
    302 			BlockHeader.UncompCount = (unsigned short)Counter;
    303 			total += Pipe::Put(&BlockHeader, sizeof(BlockHeader));
    304 			total += Pipe::Put(Buffer2, len);
    305 			Counter = 0;
    306 		}
    307 	}
    308 
    309 	total += Pipe::Flush();
    310 	return(total);
    311 }
    312