• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

RakString.cpp

Go to the documentation of this file.
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 //DataStructures::MemoryPool<RakString::SharedString> RakString::pool;
00014 unsigned int RakString::nPos=(unsigned int) -1;
00015 RakString::SharedString RakString::emptyString={0,0,0,"",""};
00016 //RakString::SharedString *RakString::sharedStringFreeList=0;
00017 //unsigned int RakString::sharedStringFreeListAllocationCount=0;
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                 // rhs.sharedString->refCountMutex->Unlock();
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         // sharedString = RakString::pool.Allocate( __FILE__, __LINE__ );
00289         if (RakString::freeList.Size()==0)
00290         {
00291                 //RakString::sharedStringFreeList=(RakString::SharedString*) rakRealloc_Ex(RakString::sharedStringFreeList,(RakString::sharedStringFreeListAllocationCount+1024)*sizeof(RakString::SharedString), __FILE__, __LINE__);
00292                 unsigned i;
00293                 for (i=0; i < 128; i++)
00294                 {
00295                 //      RakString::freeList.Insert(RakString::sharedStringFreeList+i+RakString::sharedStringFreeListAllocationCount);
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                 //RakString::sharedStringFreeListAllocationCount+=1024;
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                         // Equal characters
00535                         if ( IP[ characterIndex ] == 0 )
00536                         {
00537                                 // End of the string and the strings match
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                                 // End of one of the strings
00550                                 break;
00551                         }
00552 
00553                         // Characters do not match
00554                         if ( sharedString->c_str[ characterIndex ] == '*' )
00555                         {
00556                                 // Domain is banned.
00557                                 return true;
00558                         }
00559 
00560                         // Characters do not match and it is not a *
00561                         break;
00562                 }
00563         }
00564 
00565 
00566         // No match found.
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) // a@b.com
00586                 return false;
00587         if (sharedString->c_str[strLen-4]!='.') // .com, .net., .org
00588                 return false;
00589         unsigned i;
00590         // Has non-printable?
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         // There's more I could check, but this is good enough
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         // sharedString = RakString::pool.Allocate( __FILE__, __LINE__ );
00889         if (RakString::freeList.Size()==0)
00890         {
00891                 //RakString::sharedStringFreeList=(RakString::SharedString*) rakRealloc_Ex(RakString::sharedStringFreeList,(RakString::sharedStringFreeListAllocationCount+1024)*sizeof(RakString::SharedString), __FILE__, __LINE__);
00892                 unsigned i;
00893                 for (i=0; i < 128; i++)
00894                 {
00895                         //      RakString::freeList.Insert(RakString::sharedStringFreeList+i+RakString::sharedStringFreeListAllocationCount);
00896         //              RakString::freeList.Insert((RakString::SharedString*)rakMalloc_Ex(sizeof(RakString::SharedString), __FILE__, __LINE__), __FILE__, __LINE__);
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                 //RakString::sharedStringFreeListAllocationCount+=1024;
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         // Empty or solo then no point to cloning
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                 poolMutex->Lock();
01060                 pool.Release(sharedString);
01061                 poolMutex->Unlock();
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 #include "RakString.h"
01099 #include <string>
01100 #include "GetTime.h"
01101 
01102 using namespace RakNet;
01103 
01104 int main(void)
01105 {
01106         RakString s3("Hello world");
01107         RakString s5=s3;
01108 
01109         RakString s1;
01110         RakString s2('a');
01111 
01112         RakString s4("%i %f", 5, 6.0);
01113 
01114         RakString s6=s3;
01115         RakString s7=s6;
01116         RakString s8=s6;
01117         RakString s9;
01118         s9=s9;
01119         RakString s10(s3);
01120         RakString s11=s10 + s4 + s9 + s2;
01121         s11+=RakString("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
01122         RakString s12("Test");
01123         s12+=s11;
01124         bool b1 = s12==s12;
01125         s11=s5;
01126         s12.ToUpper();
01127         s12.ToLower();
01128         RakString s13;
01129         bool b3 = s13.IsEmpty();
01130         s13.Set("blah %s", s12.C_String());
01131         bool b4 = s13.IsEmpty();
01132         size_t i1=s13.GetLength();
01133         s3.Clear(__FILE__, __LINE__);
01134         s4.Clear(__FILE__, __LINE__);
01135         s5.Clear(__FILE__, __LINE__);
01136         s5.Clear(__FILE__, __LINE__);
01137         s6.Printf();
01138         s7.Printf();
01139         RAKNET_DEBUG_PRINTF("\n");
01140 
01141         static const int repeatCount=750;
01142         DataStructures::List<RakString> rakStringList;
01143         DataStructures::List<std::string> stdStringList;
01144         DataStructures::List<char*> referenceStringList;
01145         char *c;
01146         unsigned i;
01147         RakNetTime beforeReferenceList, beforeRakString, beforeStdString, afterStdString;
01148 
01149         unsigned loop;
01150         for (loop=0; loop<2; loop++)
01151         {
01152                 beforeReferenceList=RakNet::GetTime();
01153                 for (i=0; i < repeatCount; i++)
01154                 {
01155                         c = RakNet::OP_NEW_ARRAY<char >(56,__FILE__, __LINE__ );
01156                         strcpy(c, "Aalsdkj alsdjf laksdjf ;lasdfj ;lasjfd");
01157                         referenceStringList.Insert(c);
01158                 }
01159                 beforeRakString=RakNet::GetTime();
01160                 for (i=0; i < repeatCount; i++)
01161                         rakStringList.Insert("Aalsdkj alsdjf laksdjf ;lasdfj ;lasjfd");
01162                 beforeStdString=RakNet::GetTime();
01163 
01164                 for (i=0; i < repeatCount; i++)
01165                         stdStringList.Insert("Aalsdkj alsdjf laksdjf ;lasdfj ;lasjfd");
01166                 afterStdString=RakNet::GetTime();
01167                 RAKNET_DEBUG_PRINTF("Insertion 1 Ref=%i Rak=%i, Std=%i\n", beforeRakString-beforeReferenceList, beforeStdString-beforeRakString, afterStdString-beforeStdString);
01168 
01169                 beforeReferenceList=RakNet::GetTime();
01170                 for (i=0; i < repeatCount; i++)
01171                 {
01172                         RakNet::OP_DELETE_ARRAY(referenceStringList[0], __FILE__, __LINE__);
01173                         referenceStringList.RemoveAtIndex(0);
01174                 }
01175                 beforeRakString=RakNet::GetTime();
01176                 for (i=0; i < repeatCount; i++)
01177                         rakStringList.RemoveAtIndex(0);
01178                 beforeStdString=RakNet::GetTime();
01179                 for (i=0; i < repeatCount; i++)
01180                         stdStringList.RemoveAtIndex(0);
01181                 afterStdString=RakNet::GetTime();
01182                 RAKNET_DEBUG_PRINTF("RemoveHead Ref=%i Rak=%i, Std=%i\n", beforeRakString-beforeReferenceList, beforeStdString-beforeRakString, afterStdString-beforeStdString);
01183 
01184                 beforeReferenceList=RakNet::GetTime();
01185                 for (i=0; i < repeatCount; i++)
01186                 {
01187                         c = RakNet::OP_NEW_ARRAY<char >(56, __FILE__, __LINE__ );
01188                         strcpy(c, "Aalsdkj alsdjf laksdjf ;lasdfj ;lasjfd");
01189                         referenceStringList.Insert(0);
01190                 }
01191                 beforeRakString=RakNet::GetTime();
01192                 for (i=0; i < repeatCount; i++)
01193                         rakStringList.Insert("Aalsdkj alsdjf laksdjf ;lasdfj ;lasjfd");
01194                 beforeStdString=RakNet::GetTime();
01195                 for (i=0; i < repeatCount; i++)
01196                         stdStringList.Insert("Aalsdkj alsdjf laksdjf ;lasdfj ;lasjfd");
01197                 afterStdString=RakNet::GetTime();
01198                 RAKNET_DEBUG_PRINTF("Insertion 2 Ref=%i Rak=%i, Std=%i\n", beforeRakString-beforeReferenceList, beforeStdString-beforeRakString, afterStdString-beforeStdString);
01199 
01200                 beforeReferenceList=RakNet::GetTime();
01201                 for (i=0; i < repeatCount; i++)
01202                 {
01203                         RakNet::OP_DELETE_ARRAY(referenceStringList[referenceStringList.Size()-1], __FILE__, __LINE__);
01204                         referenceStringList.RemoveAtIndex(referenceStringList.Size()-1);
01205                 }
01206                 beforeRakString=RakNet::GetTime();
01207                 for (i=0; i < repeatCount; i++)
01208                         rakStringList.RemoveAtIndex(rakStringList.Size()-1);
01209                 beforeStdString=RakNet::GetTime();
01210                 for (i=0; i < repeatCount; i++)
01211                         stdStringList.RemoveAtIndex(stdStringList.Size()-1);
01212                 afterStdString=RakNet::GetTime();
01213                 RAKNET_DEBUG_PRINTF("RemoveTail Ref=%i Rak=%i, Std=%i\n", beforeRakString-beforeReferenceList, beforeStdString-beforeRakString, afterStdString-beforeStdString);
01214 
01215         }
01216 
01217         printf("Done.");
01218         char str[128];
01219         gets(str);
01220         return 1;
01221 }
01222 */

Generated on Thu Sep 30 2010 01:27:26 for RakNet by  doxygen 1.7.1