Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 #include "DS_HuffmanEncodingTree.h"
00009 #include "DS_Queue.h"
00010 #include "BitStream.h"
00011 #include "RakAssert.h"
00012
00013 #ifdef _MSC_VER
00014 #pragma warning( push )
00015 #endif
00016
00017 HuffmanEncodingTree::HuffmanEncodingTree()
00018 {
00019 root = 0;
00020 }
00021
00022 HuffmanEncodingTree::~HuffmanEncodingTree()
00023 {
00024 FreeMemory();
00025 }
00026
00027 void HuffmanEncodingTree::FreeMemory( void )
00028 {
00029 if ( root == 0 )
00030 return ;
00031
00032
00033 DataStructures::Queue<HuffmanEncodingTreeNode *> nodeQueue;
00034
00035 HuffmanEncodingTreeNode *node;
00036
00037 nodeQueue.Push( root, __FILE__, __LINE__ );
00038
00039 while ( nodeQueue.Size() > 0 )
00040 {
00041 node = nodeQueue.Pop();
00042
00043 if ( node->left )
00044 nodeQueue.Push( node->left, __FILE__, __LINE__ );
00045
00046 if ( node->right )
00047 nodeQueue.Push( node->right, __FILE__, __LINE__ );
00048
00049 RakNet::OP_DELETE(node, __FILE__, __LINE__);
00050 }
00051
00052
00053 for ( int i = 0; i < 256; i++ )
00054 rakFree_Ex(encodingTable[ i ].encoding, __FILE__, __LINE__ );
00055
00056 root = 0;
00057 }
00058
00059
00061
00062
00063 void HuffmanEncodingTree::GenerateFromFrequencyTable( unsigned int frequencyTable[ 256 ] )
00064 {
00065 int counter;
00066 HuffmanEncodingTreeNode * node;
00067 HuffmanEncodingTreeNode *leafList[ 256 ];
00068
00069 DataStructures::LinkedList<HuffmanEncodingTreeNode *> huffmanEncodingTreeNodeList;
00070
00071 FreeMemory();
00072
00073 for ( counter = 0; counter < 256; counter++ )
00074 {
00075 node = RakNet::OP_NEW<HuffmanEncodingTreeNode>( __FILE__, __LINE__ );
00076 node->left = 0;
00077 node->right = 0;
00078 node->value = (unsigned char) counter;
00079 node->weight = frequencyTable[ counter ];
00080
00081 if ( node->weight == 0 )
00082 node->weight = 1;
00083
00084 leafList[ counter ] = node;
00085
00086 InsertNodeIntoSortedList( node, &huffmanEncodingTreeNodeList );
00087 }
00088
00089
00090
00091
00092 #ifdef _MSC_VER
00093 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
00094 #endif
00095 while ( 1 )
00096 {
00097 huffmanEncodingTreeNodeList.Beginning();
00098 HuffmanEncodingTreeNode *lesser, *greater;
00099 lesser = huffmanEncodingTreeNodeList.Pop();
00100 greater = huffmanEncodingTreeNodeList.Pop();
00101 node = RakNet::OP_NEW<HuffmanEncodingTreeNode>( __FILE__, __LINE__ );
00102 node->left = lesser;
00103 node->right = greater;
00104 node->weight = lesser->weight + greater->weight;
00105 lesser->parent = node;
00106 greater->parent = node;
00107
00108 if ( huffmanEncodingTreeNodeList.Size() == 0 )
00109 {
00110
00111 root = node;
00112 root->parent = 0;
00113 break;
00114 }
00115
00116
00117 InsertNodeIntoSortedList( node, &huffmanEncodingTreeNodeList );
00118 }
00119
00120 bool tempPath[ 256 ];
00121 unsigned short tempPathLength;
00122 HuffmanEncodingTreeNode *currentNode;
00123 RakNet::BitStream bitStream;
00124
00125
00126
00127
00128 for ( counter = 0; counter < 256; counter++ )
00129 {
00130
00131 tempPathLength = 0;
00132
00133
00134 currentNode = leafList[ counter ];
00135
00136 do
00137 {
00138 if ( currentNode->parent->left == currentNode )
00139 tempPath[ tempPathLength++ ] = false;
00140 else
00141 tempPath[ tempPathLength++ ] = true;
00142
00143 currentNode = currentNode->parent;
00144 }
00145
00146 while ( currentNode != root );
00147
00148
00149 while ( tempPathLength-- > 0 )
00150 {
00151 if ( tempPath[ tempPathLength ] )
00152 bitStream.Write1();
00153 else
00154 bitStream.Write0();
00155 }
00156
00157
00158 encodingTable[ counter ].bitLength = ( unsigned char ) bitStream.CopyData( &encodingTable[ counter ].encoding );
00159
00160
00161 bitStream.Reset();
00162 }
00163 }
00164
00165
00166 void HuffmanEncodingTree::EncodeArray( unsigned char *input, size_t sizeInBytes, RakNet::BitStream * output )
00167 {
00168 unsigned counter;
00169
00170
00171 for ( counter = 0; counter < sizeInBytes; counter++ )
00172 {
00173 output->WriteBits( encodingTable[ input[ counter ] ].encoding, encodingTable[ input[ counter ] ].bitLength, false );
00174 }
00175
00176
00177 if ( output->GetNumberOfBitsUsed() % 8 != 0 )
00178 {
00179
00180 unsigned char remainingBits = (unsigned char) ( 8 - ( output->GetNumberOfBitsUsed() % 8 ) );
00181
00182 for ( counter = 0; counter < 256; counter++ )
00183 if ( encodingTable[ counter ].bitLength > remainingBits )
00184 {
00185 output->WriteBits( encodingTable[ counter ].encoding, remainingBits, false );
00186 break;
00187 }
00188
00189 #ifdef _DEBUG
00190 RakAssert( counter != 256 );
00191
00192 #endif
00193
00194 }
00195 }
00196
00197 unsigned HuffmanEncodingTree::DecodeArray( RakNet::BitStream * input, BitSize_t sizeInBits, size_t maxCharsToWrite, unsigned char *output )
00198 {
00199 HuffmanEncodingTreeNode * currentNode;
00200
00201 unsigned outputWriteIndex;
00202 outputWriteIndex = 0;
00203 currentNode = root;
00204
00205
00206
00207 for ( unsigned counter = 0; counter < sizeInBits; counter++ )
00208 {
00209 if ( input->ReadBit() == false )
00210 currentNode = currentNode->left;
00211 else
00212 currentNode = currentNode->right;
00213
00214 if ( currentNode->left == 0 && currentNode->right == 0 )
00215 {
00216
00217 if ( outputWriteIndex < maxCharsToWrite )
00218 output[ outputWriteIndex ] = currentNode->value;
00219
00220 outputWriteIndex++;
00221
00222 currentNode = root;
00223 }
00224 }
00225
00226 return outputWriteIndex;
00227 }
00228
00229
00230 void HuffmanEncodingTree::DecodeArray( unsigned char *input, BitSize_t sizeInBits, RakNet::BitStream * output )
00231 {
00232 HuffmanEncodingTreeNode * currentNode;
00233
00234 if ( sizeInBits <= 0 )
00235 return ;
00236
00237 RakNet::BitStream bitStream( input, BITS_TO_BYTES(sizeInBits), false );
00238
00239 currentNode = root;
00240
00241
00242 for ( unsigned counter = 0; counter < sizeInBits; counter++ )
00243 {
00244 if ( bitStream.ReadBit() == false )
00245 currentNode = currentNode->left;
00246 else
00247 currentNode = currentNode->right;
00248
00249 if ( currentNode->left == 0 && currentNode->right == 0 )
00250 {
00251 output->WriteBits( &( currentNode->value ), sizeof( char ) * 8, true );
00252 currentNode = root;
00253 }
00254 }
00255 }
00256
00257
00258 void HuffmanEncodingTree::InsertNodeIntoSortedList( HuffmanEncodingTreeNode * node, DataStructures::LinkedList<HuffmanEncodingTreeNode *> *huffmanEncodingTreeNodeList ) const
00259 {
00260 if ( huffmanEncodingTreeNodeList->Size() == 0 )
00261 {
00262 huffmanEncodingTreeNodeList->Insert( node );
00263 return ;
00264 }
00265
00266 huffmanEncodingTreeNodeList->Beginning();
00267
00268 unsigned counter = 0;
00269 #ifdef _MSC_VER
00270 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
00271 #endif
00272 while ( 1 )
00273 {
00274 if ( huffmanEncodingTreeNodeList->Peek()->weight < node->weight )
00275 ++( *huffmanEncodingTreeNodeList );
00276 else
00277 {
00278 huffmanEncodingTreeNodeList->Insert( node );
00279 break;
00280 }
00281
00282
00283 if ( ++counter == huffmanEncodingTreeNodeList->Size() )
00284 {
00285 huffmanEncodingTreeNodeList->End();
00286
00287 huffmanEncodingTreeNodeList->Add( node )
00288
00289 ;
00290 break;
00291 }
00292 }
00293 }
00294
00295 #ifdef _MSC_VER
00296 #pragma warning( pop )
00297 #endif