00001
00002
00003
00004
00005
00006
00007
00008 #include "StringCompressor.h"
00009 #include "DS_HuffmanEncodingTree.h"
00010 #include "BitStream.h"
00011 #include "RakString.h"
00012 #include "RakAssert.h"
00013 #include <string.h>
00014 #if !defined(_PS3) && !defined(__PS3__) && !defined(SN_TARGET_PS3)
00015 #include <memory.h>
00016 #endif
00017 #if defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3)
00018
00019 #endif
00020
00021 using namespace RakNet;
00022
00023 StringCompressor* StringCompressor::instance=0;
00024 int StringCompressor::referenceCount=0;
00025
00026 void StringCompressor::AddReference(void)
00027 {
00028 if (++referenceCount==1)
00029 {
00030 instance = RakNet::OP_NEW<StringCompressor>( __FILE__, __LINE__ );
00031 }
00032 }
00033 void StringCompressor::RemoveReference(void)
00034 {
00035 RakAssert(referenceCount > 0);
00036
00037 if (referenceCount > 0)
00038 {
00039 if (--referenceCount==0)
00040 {
00041 RakNet::OP_DELETE(instance, __FILE__, __LINE__);
00042 instance=0;
00043 }
00044 }
00045 }
00046
00047 StringCompressor* StringCompressor::Instance(void)
00048 {
00049 return instance;
00050 }
00051
00052 unsigned int englishCharacterFrequencies[ 256 ] =
00053 {
00054 0,
00055 0,
00056 0,
00057 0,
00058 0,
00059 0,
00060 0,
00061 0,
00062 0,
00063 0,
00064 722,
00065 0,
00066 0,
00067 2,
00068 0,
00069 0,
00070 0,
00071 0,
00072 0,
00073 0,
00074 0,
00075 0,
00076 0,
00077 0,
00078 0,
00079 0,
00080 0,
00081 0,
00082 0,
00083 0,
00084 0,
00085 0,
00086 11084,
00087 58,
00088 63,
00089 1,
00090 0,
00091 31,
00092 0,
00093 317,
00094 64,
00095 64,
00096 44,
00097 0,
00098 695,
00099 62,
00100 980,
00101 266,
00102 69,
00103 67,
00104 56,
00105 7,
00106 73,
00107 3,
00108 14,
00109 2,
00110 69,
00111 1,
00112 167,
00113 9,
00114 1,
00115 2,
00116 25,
00117 94,
00118 0,
00119 195,
00120 139,
00121 34,
00122 96,
00123 48,
00124 103,
00125 56,
00126 125,
00127 653,
00128 21,
00129 5,
00130 23,
00131 64,
00132 85,
00133 44,
00134 34,
00135 7,
00136 92,
00137 76,
00138 147,
00139 12,
00140 14,
00141 57,
00142 15,
00143 39,
00144 15,
00145 1,
00146 1,
00147 1,
00148 2,
00149 3,
00150 0,
00151 3611,
00152 845,
00153 1077,
00154 1884,
00155 5870,
00156 841,
00157 1057,
00158 2501,
00159 3212,
00160 164,
00161 531,
00162 2019,
00163 1330,
00164 3056,
00165 4037,
00166 848,
00167 47,
00168 2586,
00169 2919,
00170 4771,
00171 1707,
00172 535,
00173 1106,
00174 152,
00175 1243,
00176 100,
00177 0,
00178 2,
00179 0,
00180 10,
00181 0,
00182 0,
00183 0,
00184 0,
00185 0,
00186 0,
00187 0,
00188 0,
00189 0,
00190 0,
00191 0,
00192 0,
00193 0,
00194 0,
00195 0,
00196 0,
00197 0,
00198 0,
00199 0,
00200 0,
00201 0,
00202 0,
00203 0,
00204 0,
00205 0,
00206 0,
00207 0,
00208 0,
00209 0,
00210 0,
00211 0,
00212 0,
00213 0,
00214 0,
00215 0,
00216 0,
00217 0,
00218 0,
00219 0,
00220 0,
00221 0,
00222 0,
00223 0,
00224 0,
00225 0,
00226 0,
00227 0,
00228 0,
00229 0,
00230 0,
00231 0,
00232 0,
00233 0,
00234 0,
00235 0,
00236 0,
00237 0,
00238 0,
00239 0,
00240 0,
00241 0,
00242 0,
00243 0,
00244 0,
00245 0,
00246 0,
00247 0,
00248 0,
00249 0,
00250 0,
00251 0,
00252 0,
00253 0,
00254 0,
00255 0,
00256 0,
00257 0,
00258 0,
00259 0,
00260 0,
00261 0,
00262 0,
00263 0,
00264 0,
00265 0,
00266 0,
00267 0,
00268 0,
00269 0,
00270 0,
00271 0,
00272 0,
00273 0,
00274 0,
00275 0,
00276 0,
00277 0,
00278 0,
00279 0,
00280 0,
00281 0,
00282 0,
00283 0,
00284 0,
00285 0,
00286 0,
00287 0,
00288 0,
00289 0,
00290 0,
00291 0,
00292 0,
00293 0,
00294 0,
00295 0,
00296 0,
00297 0,
00298 0,
00299 0,
00300 0,
00301 0,
00302 0,
00303 0,
00304 0,
00305 0,
00306 0,
00307 0,
00308 0,
00309 0
00310 };
00311
00312 StringCompressor::StringCompressor()
00313 {
00314 DataStructures::Map<int, HuffmanEncodingTree *>::IMPLEMENT_DEFAULT_COMPARISON();
00315
00316
00317 HuffmanEncodingTree *huffmanEncodingTree = RakNet::OP_NEW<HuffmanEncodingTree>( __FILE__, __LINE__ );
00318 huffmanEncodingTree->GenerateFromFrequencyTable( englishCharacterFrequencies );
00319
00320 huffmanEncodingTrees.Set(0, huffmanEncodingTree);
00321 }
00322 void StringCompressor::GenerateTreeFromStrings( unsigned char *input, unsigned inputLength, int languageID )
00323 {
00324 HuffmanEncodingTree *huffmanEncodingTree;
00325 if (huffmanEncodingTrees.Has(languageID))
00326 {
00327 huffmanEncodingTree = huffmanEncodingTrees.Get(languageID);
00328 RakNet::OP_DELETE(huffmanEncodingTree, __FILE__, __LINE__);
00329 }
00330
00331 unsigned index;
00332 unsigned int frequencyTable[ 256 ];
00333
00334 if ( inputLength == 0 )
00335 return ;
00336
00337
00338 memset( frequencyTable, 0, sizeof( frequencyTable ) );
00339
00340
00341 for ( index = 0; index < inputLength; index++ )
00342 frequencyTable[ input[ index ] ] ++;
00343
00344
00345 huffmanEncodingTree = RakNet::OP_NEW<HuffmanEncodingTree>( __FILE__, __LINE__ );
00346 huffmanEncodingTree->GenerateFromFrequencyTable( frequencyTable );
00347 huffmanEncodingTrees.Set(languageID, huffmanEncodingTree);
00348 }
00349
00350 StringCompressor::~StringCompressor()
00351 {
00352 for (unsigned i=0; i < huffmanEncodingTrees.Size(); i++)
00353 RakNet::OP_DELETE(huffmanEncodingTrees[i], __FILE__, __LINE__);
00354 }
00355
00356 void StringCompressor::EncodeString( const char *input, int maxCharsToWrite, RakNet::BitStream *output, int languageID )
00357 {
00358 HuffmanEncodingTree *huffmanEncodingTree;
00359 if (huffmanEncodingTrees.Has(languageID)==false)
00360 return;
00361 huffmanEncodingTree=huffmanEncodingTrees.Get(languageID);
00362
00363 if ( input == 0 )
00364 {
00365 output->WriteCompressed( (unsigned int) 0 );
00366 return ;
00367 }
00368
00369 RakNet::BitStream encodedBitStream;
00370
00371 unsigned int stringBitLength;
00372
00373 int charsToWrite;
00374
00375 if ( maxCharsToWrite<=0 || ( int ) strlen( input ) < maxCharsToWrite )
00376 charsToWrite = ( int ) strlen( input );
00377 else
00378 charsToWrite = maxCharsToWrite - 1;
00379
00380 huffmanEncodingTree->EncodeArray( ( unsigned char* ) input, charsToWrite, &encodedBitStream );
00381
00382 stringBitLength = (unsigned int) encodedBitStream.GetNumberOfBitsUsed();
00383
00384 output->WriteCompressed( stringBitLength );
00385
00386 output->WriteBits( encodedBitStream.GetData(), stringBitLength );
00387 }
00388
00389 bool StringCompressor::DecodeString( char *output, int maxCharsToWrite, RakNet::BitStream *input, int languageID )
00390 {
00391 HuffmanEncodingTree *huffmanEncodingTree;
00392 if (huffmanEncodingTrees.Has(languageID)==false)
00393 return false;
00394 if (maxCharsToWrite<=0)
00395 return false;
00396 huffmanEncodingTree=huffmanEncodingTrees.Get(languageID);
00397
00398 unsigned int stringBitLength;
00399 int bytesInStream;
00400
00401 output[ 0 ] = 0;
00402
00403 if ( input->ReadCompressed( stringBitLength ) == false )
00404 return false;
00405
00406 if ( (unsigned) input->GetNumberOfUnreadBits() < stringBitLength )
00407 return false;
00408
00409 bytesInStream = huffmanEncodingTree->DecodeArray( input, stringBitLength, maxCharsToWrite, ( unsigned char* ) output );
00410
00411 if ( bytesInStream < maxCharsToWrite )
00412 output[ bytesInStream ] = 0;
00413 else
00414 output[ maxCharsToWrite - 1 ] = 0;
00415
00416 return true;
00417 }
00418 #ifdef _CSTRING_COMPRESSOR
00419 void StringCompressor::EncodeString( const CString &input, int maxCharsToWrite, RakNet::BitStream *output )
00420 {
00421 LPTSTR p = input;
00422 EncodeString(p, maxCharsToWrite*sizeof(TCHAR), output, languageID);
00423 }
00424 bool StringCompressor::DecodeString( CString &output, int maxCharsToWrite, RakNet::BitStream *input, int languageID )
00425 {
00426 LPSTR p = output.GetBuffer(maxCharsToWrite*sizeof(TCHAR));
00427 DecodeString(p,maxCharsToWrite*sizeof(TCHAR), input, languageID);
00428 output.ReleaseBuffer(0)
00429
00430 }
00431 #endif
00432 #ifdef _STD_STRING_COMPRESSOR
00433 void StringCompressor::EncodeString( const std::string &input, int maxCharsToWrite, RakNet::BitStream *output, int languageID )
00434 {
00435 EncodeString(input.c_str(), maxCharsToWrite, output, languageID);
00436 }
00437 bool StringCompressor::DecodeString( std::string *output, int maxCharsToWrite, RakNet::BitStream *input, int languageID )
00438 {
00439 if (maxCharsToWrite <= 0)
00440 {
00441 output->clear();
00442 return true;
00443 }
00444
00445 char *destinationBlock;
00446 bool out;
00447
00448 #if !defined(_XBOX) && !defined(_X360)
00449 if (maxCharsToWrite < MAX_ALLOCA_STACK_ALLOCATION)
00450 {
00451 destinationBlock = (char*) alloca(maxCharsToWrite);
00452 out=DecodeString(destinationBlock, maxCharsToWrite, input, languageID);
00453 *output=destinationBlock;
00454 }
00455 else
00456 #endif
00457 {
00458 destinationBlock = (char*) rakMalloc_Ex( maxCharsToWrite, __FILE__, __LINE__ );
00459 out=DecodeString(destinationBlock, maxCharsToWrite, input, languageID);
00460 *output=destinationBlock;
00461 rakFree_Ex(destinationBlock, __FILE__, __LINE__ );
00462 }
00463
00464 return out;
00465 }
00466 #endif
00467 void StringCompressor::EncodeString( const RakString *input, int maxCharsToWrite, RakNet::BitStream *output, int languageID )
00468 {
00469 EncodeString(input->C_String(), maxCharsToWrite, output, languageID);
00470 }
00471 bool StringCompressor::DecodeString( RakString *output, int maxCharsToWrite, RakNet::BitStream *input, int languageID )
00472 {
00473 if (maxCharsToWrite <= 0)
00474 {
00475 output->Clear();
00476 return true;
00477 }
00478
00479 char *destinationBlock;
00480 bool out;
00481
00482 #if !defined(_XBOX) && !defined(_X360)
00483 if (maxCharsToWrite < MAX_ALLOCA_STACK_ALLOCATION)
00484 {
00485 destinationBlock = (char*) alloca(maxCharsToWrite);
00486 out=DecodeString(destinationBlock, maxCharsToWrite, input, languageID);
00487 *output=destinationBlock;
00488 }
00489 else
00490 #endif
00491 {
00492 destinationBlock = (char*) rakMalloc_Ex( maxCharsToWrite, __FILE__, __LINE__ );
00493 out=DecodeString(destinationBlock, maxCharsToWrite, input, languageID);
00494 *output=destinationBlock;
00495 rakFree_Ex(destinationBlock, __FILE__, __LINE__ );
00496 }
00497
00498 return out;
00499 }