1 #include "DataCompressor.h"
2 #include "DS_HuffmanEncodingTree.h"
3 #include "RakAssert.h"
4 #include <string.h> // Use string.h rather than memory.h for a console
5 
Compress(unsigned char * userData,unsigned sizeInBytes,RakNet::BitStream * output)6 void DataCompressor::Compress( unsigned char *userData, unsigned sizeInBytes, RakNet::BitStream * output )
7 {
8 	// Don't use this for small files as you will just make them bigger!
9 	RakAssert(sizeInBytes > 2048);
10 
11 	unsigned int frequencyTable[ 256 ];
12 	unsigned int i;
13 	memset(frequencyTable,0,256*sizeof(unsigned int));
14 	for (i=0; i < sizeInBytes; i++)
15 		++frequencyTable[userData[i]];
16 	HuffmanEncodingTree tree;
17 	BitSize_t writeOffset1, writeOffset2, bitsUsed1, bitsUsed2;
18 	tree.GenerateFromFrequencyTable(frequencyTable);
19 	output->WriteCompressed(sizeInBytes);
20 	for (i=0; i < 256; i++)
21 		output->WriteCompressed(frequencyTable[i]);
22 	output->AlignWriteToByteBoundary();
23 	writeOffset1=output->GetWriteOffset();
24 	output->Write((unsigned int)0);	// Dummy value
25 	bitsUsed1=output->GetNumberOfBitsUsed();
26 	tree.EncodeArray(userData, sizeInBytes, output);
27 	bitsUsed2=output->GetNumberOfBitsUsed();
28 	writeOffset2=output->GetWriteOffset();
29 	output->SetWriteOffset(writeOffset1);
30 	output->Write(bitsUsed2-bitsUsed1); // Go back and write how many bits were used for the encoding
31 	output->SetWriteOffset(writeOffset2);
32 }
33 
DecompressAndAllocate(RakNet::BitStream * input,unsigned char ** output)34 unsigned DataCompressor::DecompressAndAllocate( RakNet::BitStream * input, unsigned char **output )
35 {
36 	HuffmanEncodingTree tree;
37 	unsigned int bitsUsed, destinationSizeInBytes;
38 	unsigned int decompressedBytes;
39 	unsigned int frequencyTable[ 256 ];
40 	unsigned i;
41 
42 	input->ReadCompressed(destinationSizeInBytes);
43 	for (i=0; i < 256; i++)
44 		input->ReadCompressed(frequencyTable[i]);
45 	input->AlignReadToByteBoundary();
46 	if (input->Read(bitsUsed)==false)
47 	{
48 		// Read error
49 #ifdef _DEBUG
50 		RakAssert(0);
51 #endif
52 		return 0;
53 	}
54 	*output = (unsigned char*) rakMalloc_Ex(destinationSizeInBytes, __FILE__, __LINE__);
55 	tree.GenerateFromFrequencyTable(frequencyTable);
56 	decompressedBytes=tree.DecodeArray(input, bitsUsed, destinationSizeInBytes, *output );
57 	RakAssert(decompressedBytes==destinationSizeInBytes);
58 	return destinationSizeInBytes;
59 }
60