00001 #include "RakString.h"
00002 #include "RakAssert.h"
00003 #include "RakMemoryOverride.h"
00004 #include "BitStream.h"
00005 #include <stdarg.h>
00006 #include <string.h>
00007 #include "LinuxStrings.h"
00008 #include "StringCompressor.h"
00009 #include "SimpleMutex.h"
00010
00011 using namespace RakNet;
00012
00013
00014 unsigned int RakString::nPos=(unsigned int) -1;
00015 RakString::SharedString RakString::emptyString={0,0,0,"",""};
00016
00017
00018 DataStructures::List<RakString::SharedString*> RakString::freeList;
00019
00020 class RakStringCleanup
00021 {
00022 public:
00023 ~RakStringCleanup()
00024 {
00025 RakNet::RakString::FreeMemoryNoMutex();
00026 }
00027 };
00028
00029 static RakStringCleanup cleanup;
00030
00031 SimpleMutex& GetPoolMutex(void)
00032 {
00033 static SimpleMutex poolMutex;
00034 return poolMutex;
00035 }
00036
00037 int RakString::RakStringComp( RakString const &key, RakString const &data )
00038 {
00039 return key.StrCmp(data);
00040 }
00041
00042 RakString::RakString()
00043 {
00044 sharedString=&emptyString;
00045 }
00046 RakString::RakString( RakString::SharedString *_sharedString )
00047 {
00048 sharedString=_sharedString;
00049 }
00050 RakString::RakString(char input)
00051 {
00052 char str[2];
00053 str[0]=input;
00054 str[1]=0;
00055 Assign(str);
00056 }
00057 RakString::RakString(unsigned char input)
00058 {
00059 char str[2];
00060 str[0]=(char) input;
00061 str[1]=0;
00062 Assign(str);
00063 }
00064 RakString::RakString(const unsigned char *format, ...){
00065 va_list ap;
00066 va_start(ap, format);
00067 Assign((const char*) format,ap);
00068 }
00069 RakString::RakString(const char *format, ...){
00070 va_list ap;
00071 va_start(ap, format);
00072 Assign(format,ap);
00073 }
00074 RakString::RakString( const RakString & rhs)
00075 {
00076 if (rhs.sharedString==&emptyString)
00077 {
00078 sharedString=&emptyString;
00079 return;
00080 }
00081
00082 rhs.sharedString->refCountMutex->Lock();
00083 if (rhs.sharedString->refCount==0)
00084 {
00085 sharedString=&emptyString;
00086 }
00087 else
00088 {
00089 rhs.sharedString->refCount++;
00090 sharedString=rhs.sharedString;
00091 }
00092 rhs.sharedString->refCountMutex->Unlock();
00093 }
00094 RakString::~RakString()
00095 {
00096 Free();
00097 }
00098 RakString& RakString::operator = ( const RakString& rhs )
00099 {
00100 Free();
00101 if (rhs.sharedString==&emptyString)
00102 return *this;
00103
00104 rhs.sharedString->refCountMutex->Lock();
00105 if (rhs.sharedString->refCount==0)
00106 {
00107 sharedString=&emptyString;
00108 }
00109 else
00110 {
00111 sharedString=rhs.sharedString;
00112 sharedString->refCount++;
00113 }
00114 rhs.sharedString->refCountMutex->Unlock();
00115 return *this;
00116 }
00117 RakString& RakString::operator = ( const char *str )
00118 {
00119 Free();
00120 Assign(str);
00121 return *this;
00122 }
00123 RakString& RakString::operator = ( char *str )
00124 {
00125 return operator = ((const char*)str);
00126 }
00127 RakString& RakString::operator = ( const char c )
00128 {
00129 char buff[2];
00130 buff[0]=c;
00131 buff[1]=0;
00132 return operator = ((const char*)buff);
00133 }
00134 void RakString::Realloc(SharedString *sharedString, size_t bytes)
00135 {
00136 if (bytes<=sharedString->bytesUsed)
00137 return;
00138 RakAssert(bytes>0);
00139 size_t oldBytes = sharedString->bytesUsed;
00140 size_t newBytes;
00141 const size_t smallStringSize = 128-sizeof(unsigned int)-sizeof(size_t)-sizeof(char*)*2;
00142 newBytes = GetSizeToAllocate(bytes);
00143 if (oldBytes <=(size_t) smallStringSize && newBytes > (size_t) smallStringSize)
00144 {
00145 sharedString->bigString=(char*) rakMalloc_Ex(newBytes, __FILE__, __LINE__);
00146 strcpy(sharedString->bigString, sharedString->smallString);
00147 sharedString->c_str=sharedString->bigString;
00148 }
00149 else if (oldBytes > smallStringSize)
00150 {
00151 sharedString->bigString=(char*) rakRealloc_Ex(sharedString->bigString,newBytes, __FILE__, __LINE__);
00152 sharedString->c_str=sharedString->bigString;
00153 }
00154 sharedString->bytesUsed=newBytes;
00155 }
00156 RakString& RakString::operator +=( const RakString& rhs)
00157 {
00158 if (rhs.IsEmpty())
00159 return *this;
00160
00161 if (IsEmpty())
00162 {
00163 return operator=(rhs);
00164 }
00165 else
00166 {
00167 Clone();
00168 size_t strLen=rhs.GetLength()+GetLength()+1;
00169 Realloc(sharedString, strLen+GetLength());
00170 strcat(sharedString->c_str,rhs.C_String());
00171 }
00172 return *this;
00173 }
00174 RakString& RakString::operator +=( const char *str )
00175 {
00176 if (str==0 || str[0]==0)
00177 return *this;
00178
00179 if (IsEmpty())
00180 {
00181 Assign(str);
00182 }
00183 else
00184 {
00185 Clone();
00186 size_t strLen=strlen(str)+GetLength()+1;
00187 Realloc(sharedString, strLen);
00188 strcat(sharedString->c_str,str);
00189 }
00190 return *this;
00191 }
00192 RakString& RakString::operator +=( char *str )
00193 {
00194 return operator += ((const char*)str);
00195 }
00196 RakString& RakString::operator +=( const char c )
00197 {
00198 char buff[2];
00199 buff[0]=c;
00200 buff[1]=0;
00201 return operator += ((const char*)buff);
00202 }
00203 unsigned char RakString::operator[] ( const unsigned int position ) const
00204 {
00205 RakAssert(position<GetLength());
00206 return sharedString->c_str[position];
00207 }
00208 bool RakString::operator==(const RakString &rhs) const
00209 {
00210 return strcmp(sharedString->c_str,rhs.sharedString->c_str)==0;
00211 }
00212 bool RakString::operator==(const char *str) const
00213 {
00214 return strcmp(sharedString->c_str,str)==0;
00215 }
00216 bool RakString::operator==(char *str) const
00217 {
00218 return strcmp(sharedString->c_str,str)==0;
00219 }
00220 bool RakString::operator < ( const RakString& right ) const
00221 {
00222 return strcmp(sharedString->c_str,right.C_String()) < 0;
00223 }
00224 bool RakString::operator <= ( const RakString& right ) const
00225 {
00226 return strcmp(sharedString->c_str,right.C_String()) <= 0;
00227 }
00228 bool RakString::operator > ( const RakString& right ) const
00229 {
00230 return strcmp(sharedString->c_str,right.C_String()) > 0;
00231 }
00232 bool RakString::operator >= ( const RakString& right ) const
00233 {
00234 return strcmp(sharedString->c_str,right.C_String()) >= 0;
00235 }
00236 bool RakString::operator!=(const RakString &rhs) const
00237 {
00238 return strcmp(sharedString->c_str,rhs.sharedString->c_str)!=0;
00239 }
00240 bool RakString::operator!=(const char *str) const
00241 {
00242 return strcmp(sharedString->c_str,str)!=0;
00243 }
00244 bool RakString::operator!=(char *str) const
00245 {
00246 return strcmp(sharedString->c_str,str)!=0;
00247 }
00248 const RakNet::RakString operator+(const RakNet::RakString &lhs, const RakNet::RakString &rhs)
00249 {
00250 if (lhs.IsEmpty() && rhs.IsEmpty())
00251 {
00252 return RakString(&RakString::emptyString);
00253 }
00254 if (lhs.IsEmpty())
00255 {
00256 rhs.sharedString->refCountMutex->Lock();
00257 if (rhs.sharedString->refCount==0)
00258 {
00259 rhs.sharedString->refCountMutex->Unlock();
00260 lhs.sharedString->refCountMutex->Lock();
00261 lhs.sharedString->refCount++;
00262 lhs.sharedString->refCountMutex->Unlock();
00263 return RakString(lhs.sharedString);
00264 }
00265 else
00266 {
00267 rhs.sharedString->refCount++;
00268 rhs.sharedString->refCountMutex->Unlock();
00269 return RakString(rhs.sharedString);
00270 }
00271
00272 }
00273 if (rhs.IsEmpty())
00274 {
00275 lhs.sharedString->refCountMutex->Lock();
00276 lhs.sharedString->refCount++;
00277 lhs.sharedString->refCountMutex->Unlock();
00278 return RakString(lhs.sharedString);
00279 }
00280
00281 size_t len1 = lhs.GetLength();
00282 size_t len2 = rhs.GetLength();
00283 size_t allocatedBytes = len1 + len2 + 1;
00284 allocatedBytes = RakString::GetSizeToAllocate(allocatedBytes);
00285 RakString::SharedString *sharedString;
00286
00287 RakString::LockMutex();
00288
00289 if (RakString::freeList.Size()==0)
00290 {
00291
00292 unsigned i;
00293 for (i=0; i < 128; i++)
00294 {
00295
00296 RakString::SharedString *ss;
00297 ss = (RakString::SharedString*) rakMalloc_Ex(sizeof(RakString::SharedString), __FILE__, __LINE__);
00298 ss->refCountMutex=RakNet::OP_NEW<SimpleMutex>(__FILE__,__LINE__);
00299 RakString::freeList.Insert(ss, __FILE__, __LINE__);
00300
00301 }
00302
00303 }
00304 sharedString = RakString::freeList[RakString::freeList.Size()-1];
00305 RakString::freeList.RemoveAtIndex(RakString::freeList.Size()-1);
00306 RakString::UnlockMutex();
00307
00308 const int smallStringSize = 128-sizeof(unsigned int)-sizeof(size_t)-sizeof(char*)*2;
00309 sharedString->bytesUsed=allocatedBytes;
00310 sharedString->refCount=1;
00311 if (allocatedBytes <= (size_t) smallStringSize)
00312 {
00313 sharedString->c_str=sharedString->smallString;
00314 }
00315 else
00316 {
00317 sharedString->bigString=(char*)rakMalloc_Ex(sharedString->bytesUsed, __FILE__, __LINE__);
00318 sharedString->c_str=sharedString->bigString;
00319 }
00320
00321 strcpy(sharedString->c_str, lhs);
00322 strcat(sharedString->c_str, rhs);
00323
00324 return RakString(sharedString);
00325 }
00326 const char * RakString::ToLower(void)
00327 {
00328 Clone();
00329
00330 size_t strLen = strlen(sharedString->c_str);
00331 unsigned i;
00332 for (i=0; i < strLen; i++)
00333 sharedString->c_str[i]=ToLower(sharedString->c_str[i]);
00334 return sharedString->c_str;
00335 }
00336 const char * RakString::ToUpper(void)
00337 {
00338 Clone();
00339
00340 size_t strLen = strlen(sharedString->c_str);
00341 unsigned i;
00342 for (i=0; i < strLen; i++)
00343 sharedString->c_str[i]=ToUpper(sharedString->c_str[i]);
00344 return sharedString->c_str;
00345 }
00346 void RakString::Set(const char *format, ...)
00347 {
00348 va_list ap;
00349 va_start(ap, format);
00350 Clear();
00351 Assign(format,ap);
00352 }
00353 bool RakString::IsEmpty(void) const
00354 {
00355 return sharedString==&emptyString;
00356 }
00357 size_t RakString::GetLength(void) const
00358 {
00359 return strlen(sharedString->c_str);
00360 }
00361 void RakString::Replace(unsigned index, unsigned count, unsigned char c)
00362 {
00363 RakAssert(index+count < GetLength());
00364 Clone();
00365 unsigned countIndex=0;
00366 while (countIndex<count)
00367 {
00368 sharedString->c_str[index]=c;
00369 index++;
00370 countIndex++;
00371 }
00372 }
00373 void RakString::SetChar( unsigned index, unsigned char c )
00374 {
00375 RakAssert(index < GetLength());
00376 Clone();
00377 sharedString->c_str[index]=c;
00378 }
00379 void RakString::SetChar( unsigned index, RakNet::RakString s )
00380 {
00381 RakAssert(index < GetLength());
00382 Clone();
00383 RakNet::RakString firstHalf = SubStr(0, index);
00384 RakNet::RakString secondHalf = SubStr(index+1, (unsigned int)-1);
00385 *this = firstHalf;
00386 *this += s;
00387 *this += secondHalf;
00388 }
00389
00390 size_t RakString::Find(const char *stringToFind,size_t pos)
00391 {
00392 size_t len=GetLength();
00393 if (pos>=len || stringToFind==0 || stringToFind[0]==0)
00394 {
00395 return nPos;
00396 }
00397 size_t matchLen= strlen(stringToFind);
00398 size_t matchPos=0;
00399 size_t iStart=0;
00400
00401 for (size_t i=pos;i<len;i++)
00402 {
00403 if (stringToFind[matchPos]==sharedString->c_str[i])
00404 {
00405 if(matchPos==0)
00406 {
00407 iStart=i;
00408 }
00409 matchPos++;
00410 }
00411 else
00412 {
00413 matchPos=0;
00414 }
00415
00416 if (matchPos>=matchLen)
00417 {
00418 return iStart;
00419 }
00420 }
00421
00422 return nPos;
00423 }
00424
00425 void RakString::Truncate(unsigned length)
00426 {
00427 if (length < GetLength())
00428 {
00429 SetChar(length, 0);
00430 }
00431 }
00432 RakString RakString::SubStr(unsigned int index, unsigned int count) const
00433 {
00434 size_t length = GetLength();
00435 if (index >= length || count==0)
00436 return RakString();
00437 RakString copy;
00438 size_t numBytes = length-index;
00439 if (count < numBytes)
00440 numBytes=count;
00441 copy.Allocate(numBytes+1);
00442 size_t i;
00443 for (i=0; i < numBytes; i++)
00444 copy.sharedString->c_str[i]=sharedString->c_str[index+i];
00445 copy.sharedString->c_str[i]=0;
00446 return copy;
00447 }
00448 void RakString::Erase(unsigned int index, unsigned int count)
00449 {
00450 size_t len = GetLength();
00451 RakAssert(index+count <= len);
00452
00453 Clone();
00454 unsigned i;
00455 for (i=index; i < len-count; i++)
00456 {
00457 sharedString->c_str[i]=sharedString->c_str[i+count];
00458 }
00459 sharedString->c_str[i]=0;
00460 }
00461 void RakString::TerminateAtLastCharacter(char c)
00462 {
00463 int i, len=(int) GetLength();
00464 for (i=len-1; i >= 0; i--)
00465 {
00466 if (sharedString->c_str[i]==c)
00467 {
00468 Clone();
00469 sharedString->c_str[i]=0;
00470 return;
00471 }
00472 }
00473 }
00474 void RakString::TerminateAtFirstCharacter(char c)
00475 {
00476 unsigned int i, len=(unsigned int) GetLength();
00477 for (i=0; i < len; i++)
00478 {
00479 if (sharedString->c_str[i]==c)
00480 {
00481 Clone();
00482 sharedString->c_str[i]=0;
00483 return;
00484 }
00485 }
00486 }
00487 void RakString::RemoveCharacter(char c)
00488 {
00489 if (c==0)
00490 return;
00491
00492 unsigned int readIndex, writeIndex=0;
00493 for (readIndex=0; sharedString->c_str[readIndex]; readIndex++)
00494 {
00495 if (sharedString->c_str[readIndex]!=c)
00496 sharedString->c_str[writeIndex++]=sharedString->c_str[readIndex];
00497 else
00498 Clone();
00499 }
00500 sharedString->c_str[writeIndex]=0;
00501 }
00502 int RakString::StrCmp(const RakString &rhs) const
00503 {
00504 return strcmp(sharedString->c_str, rhs);
00505 }
00506 int RakString::StrICmp(const RakString &rhs) const
00507 {
00508 return _stricmp(sharedString->c_str, rhs);
00509 }
00510 void RakString::Printf(void)
00511 {
00512 RAKNET_DEBUG_PRINTF(sharedString->c_str);
00513 }
00514 void RakString::FPrintf(FILE *fp)
00515 {
00516 fprintf(fp,sharedString->c_str);
00517 }
00518 bool RakString::IPAddressMatch(const char *IP)
00519 {
00520 unsigned characterIndex;
00521
00522 if ( IP == 0 || IP[ 0 ] == 0 || strlen( IP ) > 15 )
00523 return false;
00524
00525 characterIndex = 0;
00526
00527 #ifdef _MSC_VER
00528 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
00529 #endif
00530 while ( true )
00531 {
00532 if (sharedString->c_str[ characterIndex ] == IP[ characterIndex ] )
00533 {
00534
00535 if ( IP[ characterIndex ] == 0 )
00536 {
00537
00538
00539 return true;
00540 }
00541
00542 characterIndex++;
00543 }
00544
00545 else
00546 {
00547 if ( sharedString->c_str[ characterIndex ] == 0 || IP[ characterIndex ] == 0 )
00548 {
00549
00550 break;
00551 }
00552
00553
00554 if ( sharedString->c_str[ characterIndex ] == '*' )
00555 {
00556
00557 return true;
00558 }
00559
00560
00561 break;
00562 }
00563 }
00564
00565
00566
00567 return false;
00568 }
00569 bool RakString::ContainsNonprintableExceptSpaces(void) const
00570 {
00571 size_t strLen = strlen(sharedString->c_str);
00572 unsigned i;
00573 for (i=0; i < strLen; i++)
00574 {
00575 if (sharedString->c_str[i] < ' ' || sharedString->c_str[i] >126)
00576 return true;
00577 }
00578 return false;
00579 }
00580 bool RakString::IsEmailAddress(void) const
00581 {
00582 if (IsEmpty())
00583 return false;
00584 size_t strLen = strlen(sharedString->c_str);
00585 if (strLen < 7)
00586 return false;
00587 if (sharedString->c_str[strLen-4]!='.')
00588 return false;
00589 unsigned i;
00590
00591 for (i=0; i < strLen; i++)
00592 {
00593 if (sharedString->c_str[i] <= ' ' || sharedString->c_str[i] >126)
00594 return false;
00595 }
00596 int atCount=0;
00597 for (i=0; i < strLen; i++)
00598 {
00599 if (sharedString->c_str[i]=='@')
00600 {
00601 atCount++;
00602 }
00603 }
00604 if (atCount!=1)
00605 return false;
00606 int dotCount=0;
00607 for (i=0; i < strLen; i++)
00608 {
00609 if (sharedString->c_str[i]=='.')
00610 {
00611 dotCount++;
00612 }
00613 }
00614 if (dotCount==0)
00615 return false;
00616
00617
00618 return true;
00619 }
00620 RakNet::RakString& RakString::URLEncode(void)
00621 {
00622 RakString result;
00623 size_t strLen = strlen(sharedString->c_str);
00624 result.Allocate(strLen*3);
00625 char *output=result.sharedString->c_str;
00626 unsigned int outputIndex=0;
00627 unsigned i;
00628 char c;
00629 for (i=0; i < strLen; i++)
00630 {
00631 c=sharedString->c_str[i];
00632 if (
00633 (c<=47) ||
00634 (c>=58 && c<=64) ||
00635 (c>=91 && c<=96) ||
00636 (c>=123)
00637 )
00638 {
00639 RakNet::RakString tmp("%2X", c);
00640 output[outputIndex++]='%';
00641 output[outputIndex++]=tmp.sharedString->c_str[0];
00642 output[outputIndex++]=tmp.sharedString->c_str[1];
00643 }
00644 else
00645 {
00646 output[outputIndex++]=c;
00647 }
00648 }
00649
00650 output[outputIndex]=0;
00651
00652 *this = result;
00653 return *this;
00654 }
00655 RakNet::RakString& RakString::URLDecode(void)
00656 {
00657 RakString result;
00658 size_t strLen = strlen(sharedString->c_str);
00659 result.Allocate(strLen);
00660 char *output=result.sharedString->c_str;
00661 unsigned int outputIndex=0;
00662 char c;
00663 char hexDigits[2];
00664 char hexValues[2];
00665 unsigned int i;
00666 for (i=0; i < strLen; i++)
00667 {
00668 c=sharedString->c_str[i];
00669 if (c=='%')
00670 {
00671 hexDigits[0]=sharedString->c_str[++i];
00672 hexDigits[1]=sharedString->c_str[++i];
00673 if (hexDigits[0]==' ')
00674 hexValues[0]=0;
00675 else if (hexDigits[0]>='A')
00676 hexValues[0]=hexDigits[0]-'A'+10;
00677 else
00678 hexValues[0]=hexDigits[0]-'0';
00679 if (hexDigits[1]>='A')
00680 hexValues[1]=hexDigits[1]-'A'+10;
00681 else
00682 hexValues[1]=hexDigits[1]-'0';
00683 output[outputIndex++]=hexValues[0]*16+hexValues[1];
00684 }
00685 else
00686 {
00687 output[outputIndex++]=c;
00688 }
00689 }
00690
00691 output[outputIndex]=0;
00692
00693 *this = result;
00694 return *this;
00695 }
00696 RakNet::RakString& RakString::SQLEscape(void)
00697 {
00698 int strLen=(int)GetLength();
00699 int escapedCharacterCount=0;
00700 int index;
00701 for (index=0; index < strLen; index++)
00702 {
00703 if (sharedString->c_str[index]=='\'' ||
00704 sharedString->c_str[index]=='"' ||
00705 sharedString->c_str[index]=='\\')
00706 escapedCharacterCount++;
00707 }
00708 if (escapedCharacterCount==0)
00709 return *this;
00710
00711 Clone();
00712 Realloc(sharedString, strLen+escapedCharacterCount);
00713 int writeIndex, readIndex;
00714 writeIndex = strLen+escapedCharacterCount;
00715 readIndex=strLen;
00716 while (readIndex>=0)
00717 {
00718 if (sharedString->c_str[readIndex]=='\'' ||
00719 sharedString->c_str[readIndex]=='"' ||
00720 sharedString->c_str[readIndex]=='\\')
00721 {
00722 sharedString->c_str[writeIndex--]=sharedString->c_str[readIndex--];
00723 sharedString->c_str[writeIndex--]='\\';
00724 }
00725 else
00726 {
00727 sharedString->c_str[writeIndex--]=sharedString->c_str[readIndex--];
00728 }
00729 }
00730 return *this;
00731 }
00732 RakNet::RakString& RakString::MakeFilePath(void)
00733 {
00734 if (IsEmpty())
00735 return *this;
00736
00737 RakNet::RakString fixedString = *this;
00738 fixedString.Clone();
00739 for (int i=0; fixedString.sharedString->c_str[i]; i++)
00740 {
00741 #ifdef _WIN32
00742 if (fixedString.sharedString->c_str[i]=='/')
00743 fixedString.sharedString->c_str[i]='\\';
00744 #else
00745 if (fixedString.sharedString->c_str[i]=='\\')
00746 fixedString.sharedString->c_str[i]='/';
00747 #endif
00748 }
00749
00750 #ifdef _WIN32
00751 if (fixedString.sharedString->c_str[strlen(fixedString.sharedString->c_str)-1]!='\\')
00752 {
00753 fixedString+='\\';
00754 }
00755 #else
00756 if (fixedString.sharedString->c_str[strlen(fixedString.sharedString->c_str)-1]!='/')
00757 {
00758 fixedString+='/';
00759 }
00760 #endif
00761
00762 if (fixedString!=*this)
00763 *this = fixedString;
00764 return *this;
00765 }
00766 void RakString::FreeMemory(void)
00767 {
00768 LockMutex();
00769 FreeMemoryNoMutex();
00770 UnlockMutex();
00771 }
00772 void RakString::FreeMemoryNoMutex(void)
00773 {
00774 for (unsigned int i=0; i < freeList.Size(); i++)
00775 {
00776 RakNet::OP_DELETE(freeList[i]->refCountMutex,__FILE__,__LINE__);
00777 rakFree_Ex(freeList[i], __FILE__, __LINE__ );
00778 }
00779 freeList.Clear(false, __FILE__, __LINE__);
00780 }
00781 void RakString::Serialize(BitStream *bs) const
00782 {
00783 Serialize(sharedString->c_str, bs);
00784 }
00785 void RakString::Serialize(const char *str, BitStream *bs)
00786 {
00787 unsigned short l = (unsigned short) strlen(str);
00788 bs->Write(l);
00789 bs->WriteAlignedBytes((const unsigned char*) str, (const unsigned int) l);
00790 }
00791 void RakString::SerializeCompressed(BitStream *bs, int languageId, bool writeLanguageId) const
00792 {
00793 SerializeCompressed(C_String(), bs, languageId, writeLanguageId);
00794 }
00795 void RakString::SerializeCompressed(const char *str, BitStream *bs, int languageId, bool writeLanguageId)
00796 {
00797 if (writeLanguageId)
00798 bs->WriteCompressed(languageId);
00799 stringCompressor->EncodeString(str,0xFFFF,bs,languageId);
00800 }
00801 bool RakString::Deserialize(BitStream *bs)
00802 {
00803 Clear();
00804
00805 bool b;
00806 unsigned short l;
00807 b=bs->Read(l);
00808 if (l>0)
00809 {
00810 Allocate(((unsigned int) l)+1);
00811 b=bs->ReadAlignedBytes((unsigned char*) sharedString->c_str, l);
00812 if (b)
00813 sharedString->c_str[l]=0;
00814 else
00815 Clear();
00816 }
00817 else
00818 bs->AlignReadToByteBoundary();
00819 return b;
00820 }
00821 bool RakString::Deserialize(char *str, BitStream *bs)
00822 {
00823 bool b;
00824 unsigned short l;
00825 b=bs->Read(l);
00826 if (b && l>0)
00827 b=bs->ReadAlignedBytes((unsigned char*) str, l);
00828
00829 if (b==false)
00830 str[0]=0;
00831
00832 str[l]=0;
00833 return b;
00834 }
00835 bool RakString::DeserializeCompressed(BitStream *bs, bool readLanguageId)
00836 {
00837 unsigned int languageId;
00838 if (readLanguageId)
00839 bs->ReadCompressed(languageId);
00840 else
00841 languageId=0;
00842 return stringCompressor->DecodeString(this,0xFFFF,bs,languageId);
00843 }
00844 bool RakString::DeserializeCompressed(char *str, BitStream *bs, bool readLanguageId)
00845 {
00846 unsigned int languageId;
00847 if (readLanguageId)
00848 bs->ReadCompressed(languageId);
00849 else
00850 languageId=0;
00851 return stringCompressor->DecodeString(str,0xFFFF,bs,languageId);
00852 }
00853 const char *RakString::ToString(int64_t i)
00854 {
00855 static int index=0;
00856 static char buff[64][64];
00857 #if defined(_WIN32)
00858 sprintf(buff[index], "%I64d", i);
00859 #else
00860 sprintf(buff[index], "%lld", i);
00861 #endif
00862 int lastIndex=index;
00863 if (++index==64)
00864 index=0;
00865 return buff[lastIndex];
00866 }
00867 const char *RakString::ToString(uint64_t i)
00868 {
00869 static int index=0;
00870 static char buff[64][64];
00871 #if defined(_WIN32)
00872 sprintf(buff[index], "%I64u", i);
00873 #else
00874 sprintf(buff[index], "%llu", i);
00875 #endif
00876 int lastIndex=index;
00877 if (++index==64)
00878 index=0;
00879 return buff[lastIndex];
00880 }
00881 void RakString::Clear(void)
00882 {
00883 Free();
00884 }
00885 void RakString::Allocate(size_t len)
00886 {
00887 RakString::LockMutex();
00888
00889 if (RakString::freeList.Size()==0)
00890 {
00891
00892 unsigned i;
00893 for (i=0; i < 128; i++)
00894 {
00895
00896
00897
00898 RakString::SharedString *ss;
00899 ss = (RakString::SharedString*) rakMalloc_Ex(sizeof(RakString::SharedString), __FILE__, __LINE__);
00900 ss->refCountMutex=RakNet::OP_NEW<SimpleMutex>(__FILE__,__LINE__);
00901 RakString::freeList.Insert(ss, __FILE__, __LINE__);
00902 }
00903
00904 }
00905 sharedString = RakString::freeList[RakString::freeList.Size()-1];
00906 RakString::freeList.RemoveAtIndex(RakString::freeList.Size()-1);
00907 RakString::UnlockMutex();
00908
00909 const size_t smallStringSize = 128-sizeof(unsigned int)-sizeof(size_t)-sizeof(char*)*2;
00910 sharedString->refCount=1;
00911 if (len <= smallStringSize)
00912 {
00913 sharedString->bytesUsed=smallStringSize;
00914 sharedString->c_str=sharedString->smallString;
00915 }
00916 else
00917 {
00918 sharedString->bytesUsed=len<<1;
00919 sharedString->bigString=(char*)rakMalloc_Ex(sharedString->bytesUsed, __FILE__, __LINE__);
00920 sharedString->c_str=sharedString->bigString;
00921 }
00922 }
00923 void RakString::Assign(const char *str)
00924 {
00925 if (str==0 || str[0]==0)
00926 {
00927 sharedString=&emptyString;
00928 return;
00929 }
00930
00931 size_t len = strlen(str)+1;
00932 Allocate(len);
00933 memcpy(sharedString->c_str, str, len);
00934 }
00935 void RakString::Assign(const char *str, va_list ap)
00936 {
00937 char stackBuff[512];
00938 if (_vsnprintf(stackBuff, 512, str, ap)!=-1)
00939 {
00940 Assign(stackBuff);
00941 return;
00942 }
00943 char *buff=0, *newBuff;
00944 size_t buffSize=8096;
00945 while (1)
00946 {
00947 newBuff = (char*) rakRealloc_Ex(buff, buffSize,__FILE__,__LINE__);
00948 if (newBuff==0)
00949 {
00950 notifyOutOfMemory(__FILE__, __LINE__);
00951 if (buff!=0)
00952 {
00953 Assign(buff);
00954 rakFree_Ex(buff,__FILE__,__LINE__);
00955 }
00956 else
00957 {
00958 Assign(stackBuff);
00959 }
00960 return;
00961 }
00962 buff=newBuff;
00963 if (_vsnprintf(buff, buffSize, str, ap)!=-1)
00964 {
00965 Assign(buff);
00966 rakFree_Ex(buff,__FILE__,__LINE__);
00967 return;
00968 }
00969 buffSize*=2;
00970 }
00971 }
00972 RakNet::RakString RakString::Assign(const char *str,size_t pos, size_t n )
00973 {
00974 size_t incomingLen=strlen(str);
00975
00976 Clone();
00977
00978 if (str==0 || str[0]==0||pos>=incomingLen)
00979 {
00980 sharedString=&emptyString;
00981 return (*this);
00982 }
00983
00984 if (pos+n>=incomingLen)
00985 {
00986 n=incomingLen-pos;
00987
00988 }
00989 const char * tmpStr=&(str[pos]);
00990
00991 size_t len = n+1;
00992 Allocate(len);
00993 memcpy(sharedString->c_str, tmpStr, len);
00994 sharedString->c_str[n]=0;
00995
00996 return (*this);
00997 }
00998
00999 RakNet::RakString RakString::NonVariadic(const char *str)
01000 {
01001 RakNet::RakString rs;
01002 rs=str;
01003 return rs;
01004 }
01005 unsigned long RakString::ToInteger(const char *str)
01006 {
01007 unsigned long hash = 0;
01008 int c;
01009
01010 while (c = *str++)
01011 hash = c + (hash << 6) + (hash << 16) - hash;
01012
01013 return hash;
01014 }
01015 unsigned long RakString::ToInteger(const RakString &rs)
01016 {
01017 return RakString::ToInteger(rs.C_String());
01018 }
01019 void RakString::AppendBytes(const char *bytes, unsigned int count)
01020 {
01021 Clone();
01022 Realloc(sharedString, count);
01023 unsigned int length=(unsigned int) GetLength();
01024 memcpy(sharedString->c_str+length, bytes, count);
01025 sharedString->c_str[length+count]=0;
01026 }
01027 void RakString::Clone(void)
01028 {
01029 if (sharedString==&emptyString)
01030 {
01031 return;
01032 }
01033
01034
01035 sharedString->refCountMutex->Lock();
01036 if (sharedString->refCount==1)
01037 {
01038 sharedString->refCountMutex->Unlock();
01039 return;
01040 }
01041
01042 sharedString->refCount--;
01043 sharedString->refCountMutex->Unlock();
01044 Assign(sharedString->c_str);
01045 }
01046 void RakString::Free(void)
01047 {
01048 if (sharedString==&emptyString)
01049 return;
01050 sharedString->refCountMutex->Lock();
01051 sharedString->refCount--;
01052 if (sharedString->refCount==0)
01053 {
01054 sharedString->refCountMutex->Unlock();
01055 const size_t smallStringSize = 128-sizeof(unsigned int)-sizeof(size_t)-sizeof(char*)*2;
01056 if (sharedString->bytesUsed>smallStringSize)
01057 rakFree_Ex(sharedString->bigString, __FILE__, __LINE__ );
01058
01059
01060
01061
01062
01063
01064 RakString::LockMutex();
01065 RakString::freeList.Insert(sharedString, __FILE__, __LINE__);
01066 RakString::UnlockMutex();
01067
01068 sharedString=&emptyString;
01069 }
01070 else
01071 {
01072 sharedString->refCountMutex->Unlock();
01073 }
01074 sharedString=&emptyString;
01075 }
01076 unsigned char RakString::ToLower(unsigned char c)
01077 {
01078 if (c >= 'A' && c <= 'Z')
01079 return c-'A'+'a';
01080 return c;
01081 }
01082 unsigned char RakString::ToUpper(unsigned char c)
01083 {
01084 if (c >= 'a' && c <= 'z')
01085 return c-'a'+'A';
01086 return c;
01087 }
01088 void RakString::LockMutex(void)
01089 {
01090 GetPoolMutex().Lock();
01091 }
01092 void RakString::UnlockMutex(void)
01093 {
01094 GetPoolMutex().Unlock();
01095 }
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222