RakString.cpp 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. #include "RakString.h"
  11. #include "RakAssert.h"
  12. #include "RakMemoryOverride.h"
  13. #include "BitStream.h"
  14. #include <stdarg.h>
  15. #include <string.h>
  16. #include "LinuxStrings.h"
  17. #include "StringCompressor.h"
  18. #include "SimpleMutex.h"
  19. #include <stdlib.h>
  20. #include "Itoa.h"
  21. using namespace RakNet;
  22. //DataStructures::MemoryPool<RakString::SharedString> RakString::pool;
  23. RakString::SharedString RakString::emptyString={0,0,0,(char*) "",(char*) ""};
  24. //RakString::SharedString *RakString::sharedStringFreeList=0;
  25. //unsigned int RakString::sharedStringFreeListAllocationCount=0;
  26. DataStructures::List<RakString::SharedString*> RakString::freeList;
  27. class RakStringCleanup
  28. {
  29. public:
  30. ~RakStringCleanup()
  31. {
  32. RakNet::RakString::FreeMemoryNoMutex();
  33. }
  34. };
  35. static RakStringCleanup cleanup;
  36. SimpleMutex& GetPoolMutex(void)
  37. {
  38. static SimpleMutex poolMutex;
  39. return poolMutex;
  40. }
  41. int RakNet::RakString::RakStringComp( RakString const &key, RakString const &data )
  42. {
  43. return key.StrCmp(data);
  44. }
  45. RakString::RakString()
  46. {
  47. sharedString=&emptyString;
  48. }
  49. RakString::RakString( RakString::SharedString *_sharedString )
  50. {
  51. sharedString=_sharedString;
  52. }
  53. RakString::RakString(char input)
  54. {
  55. char str[2];
  56. str[0]=input;
  57. str[1]=0;
  58. Assign(str);
  59. }
  60. RakString::RakString(unsigned char input)
  61. {
  62. char str[2];
  63. str[0]=(char) input;
  64. str[1]=0;
  65. Assign(str);
  66. }
  67. RakString::RakString(const unsigned char *format, ...){
  68. va_list ap;
  69. va_start(ap, format);
  70. Assign((const char*) format,ap);
  71. }
  72. RakString::RakString(const char *format, ...){
  73. va_list ap;
  74. va_start(ap, format);
  75. Assign(format,ap);
  76. }
  77. RakString::RakString( const RakString & rhs)
  78. {
  79. if (rhs.sharedString==&emptyString)
  80. {
  81. sharedString=&emptyString;
  82. return;
  83. }
  84. rhs.sharedString->refCountMutex->Lock();
  85. if (rhs.sharedString->refCount==0)
  86. {
  87. sharedString=&emptyString;
  88. }
  89. else
  90. {
  91. rhs.sharedString->refCount++;
  92. sharedString=rhs.sharedString;
  93. }
  94. rhs.sharedString->refCountMutex->Unlock();
  95. }
  96. RakString::~RakString()
  97. {
  98. Free();
  99. }
  100. RakString& RakString::operator = ( const RakString& rhs )
  101. {
  102. Free();
  103. if (rhs.sharedString==&emptyString)
  104. return *this;
  105. rhs.sharedString->refCountMutex->Lock();
  106. if (rhs.sharedString->refCount==0)
  107. {
  108. sharedString=&emptyString;
  109. }
  110. else
  111. {
  112. sharedString=rhs.sharedString;
  113. sharedString->refCount++;
  114. }
  115. rhs.sharedString->refCountMutex->Unlock();
  116. return *this;
  117. }
  118. RakString& RakString::operator = ( const char *str )
  119. {
  120. Free();
  121. Assign(str);
  122. return *this;
  123. }
  124. RakString& RakString::operator = ( char *str )
  125. {
  126. return operator = ((const char*)str);
  127. }
  128. RakString& RakString::operator = ( const unsigned char *str )
  129. {
  130. return operator = ((const char*)str);
  131. }
  132. RakString& RakString::operator = ( char unsigned *str )
  133. {
  134. return operator = ((const char*)str);
  135. }
  136. RakString& RakString::operator = ( const char c )
  137. {
  138. char buff[2];
  139. buff[0]=c;
  140. buff[1]=0;
  141. return operator = ((const char*)buff);
  142. }
  143. void RakString::Realloc(SharedString *sharedString, size_t bytes)
  144. {
  145. if (bytes<=sharedString->bytesUsed)
  146. return;
  147. RakAssert(bytes>0);
  148. size_t oldBytes = sharedString->bytesUsed;
  149. size_t newBytes;
  150. const size_t smallStringSize = 128-sizeof(unsigned int)-sizeof(size_t)-sizeof(char*)*2;
  151. newBytes = GetSizeToAllocate(bytes);
  152. if (oldBytes <=(size_t) smallStringSize && newBytes > (size_t) smallStringSize)
  153. {
  154. sharedString->bigString=(char*) rakMalloc_Ex(newBytes, _FILE_AND_LINE_);
  155. strcpy(sharedString->bigString, sharedString->smallString);
  156. sharedString->c_str=sharedString->bigString;
  157. }
  158. else if (oldBytes > smallStringSize)
  159. {
  160. sharedString->bigString=(char*) rakRealloc_Ex(sharedString->bigString,newBytes, _FILE_AND_LINE_);
  161. sharedString->c_str=sharedString->bigString;
  162. }
  163. sharedString->bytesUsed=newBytes;
  164. }
  165. RakString& RakString::operator +=( const RakString& rhs)
  166. {
  167. if (rhs.IsEmpty())
  168. return *this;
  169. if (IsEmpty())
  170. {
  171. return operator=(rhs);
  172. }
  173. else
  174. {
  175. Clone();
  176. size_t strLen=rhs.GetLength()+GetLength()+1;
  177. Realloc(sharedString, strLen+GetLength());
  178. strcat(sharedString->c_str,rhs.C_String());
  179. }
  180. return *this;
  181. }
  182. RakString& RakString::operator +=( const char *str )
  183. {
  184. if (str==0 || str[0]==0)
  185. return *this;
  186. if (IsEmpty())
  187. {
  188. Assign(str);
  189. }
  190. else
  191. {
  192. Clone();
  193. size_t strLen=strlen(str)+GetLength()+1;
  194. Realloc(sharedString, strLen);
  195. strcat(sharedString->c_str,str);
  196. }
  197. return *this;
  198. }
  199. RakString& RakString::operator +=( char *str )
  200. {
  201. return operator += ((const char*)str);
  202. }
  203. RakString& RakString::operator +=( const unsigned char *str )
  204. {
  205. return operator += ((const char*)str);
  206. }
  207. RakString& RakString::operator +=( unsigned char *str )
  208. {
  209. return operator += ((const char*)str);
  210. }
  211. RakString& RakString::operator +=( const char c )
  212. {
  213. char buff[2];
  214. buff[0]=c;
  215. buff[1]=0;
  216. return operator += ((const char*)buff);
  217. }
  218. unsigned char RakString::operator[] ( const unsigned int position ) const
  219. {
  220. RakAssert(position<GetLength());
  221. return sharedString->c_str[position];
  222. }
  223. bool RakString::operator==(const RakString &rhs) const
  224. {
  225. return strcmp(sharedString->c_str,rhs.sharedString->c_str)==0;
  226. }
  227. bool RakString::operator==(const char *str) const
  228. {
  229. return strcmp(sharedString->c_str,str)==0;
  230. }
  231. bool RakString::operator==(char *str) const
  232. {
  233. return strcmp(sharedString->c_str,str)==0;
  234. }
  235. bool RakString::operator < ( const RakString& right ) const
  236. {
  237. return strcmp(sharedString->c_str,right.C_String()) < 0;
  238. }
  239. bool RakString::operator <= ( const RakString& right ) const
  240. {
  241. return strcmp(sharedString->c_str,right.C_String()) <= 0;
  242. }
  243. bool RakString::operator > ( const RakString& right ) const
  244. {
  245. return strcmp(sharedString->c_str,right.C_String()) > 0;
  246. }
  247. bool RakString::operator >= ( const RakString& right ) const
  248. {
  249. return strcmp(sharedString->c_str,right.C_String()) >= 0;
  250. }
  251. bool RakString::operator!=(const RakString &rhs) const
  252. {
  253. return strcmp(sharedString->c_str,rhs.sharedString->c_str)!=0;
  254. }
  255. bool RakString::operator!=(const char *str) const
  256. {
  257. return strcmp(sharedString->c_str,str)!=0;
  258. }
  259. bool RakString::operator!=(char *str) const
  260. {
  261. return strcmp(sharedString->c_str,str)!=0;
  262. }
  263. const RakNet::RakString operator+(const RakNet::RakString &lhs, const RakNet::RakString &rhs)
  264. {
  265. if (lhs.IsEmpty() && rhs.IsEmpty())
  266. {
  267. return RakString(&RakString::emptyString);
  268. }
  269. if (lhs.IsEmpty())
  270. {
  271. rhs.sharedString->refCountMutex->Lock();
  272. if (rhs.sharedString->refCount==0)
  273. {
  274. rhs.sharedString->refCountMutex->Unlock();
  275. lhs.sharedString->refCountMutex->Lock();
  276. lhs.sharedString->refCount++;
  277. lhs.sharedString->refCountMutex->Unlock();
  278. return RakString(lhs.sharedString);
  279. }
  280. else
  281. {
  282. rhs.sharedString->refCount++;
  283. rhs.sharedString->refCountMutex->Unlock();
  284. return RakString(rhs.sharedString);
  285. }
  286. // rhs.sharedString->refCountMutex->Unlock();
  287. }
  288. if (rhs.IsEmpty())
  289. {
  290. lhs.sharedString->refCountMutex->Lock();
  291. lhs.sharedString->refCount++;
  292. lhs.sharedString->refCountMutex->Unlock();
  293. return RakString(lhs.sharedString);
  294. }
  295. size_t len1 = lhs.GetLength();
  296. size_t len2 = rhs.GetLength();
  297. size_t allocatedBytes = len1 + len2 + 1;
  298. allocatedBytes = RakString::GetSizeToAllocate(allocatedBytes);
  299. RakString::SharedString *sharedString;
  300. RakString::LockMutex();
  301. // sharedString = RakString::pool.Allocate( _FILE_AND_LINE_ );
  302. if (RakString::freeList.Size()==0)
  303. {
  304. //RakString::sharedStringFreeList=(RakString::SharedString*) rakRealloc_Ex(RakString::sharedStringFreeList,(RakString::sharedStringFreeListAllocationCount+1024)*sizeof(RakString::SharedString), _FILE_AND_LINE_);
  305. unsigned i;
  306. for (i=0; i < 128; i++)
  307. {
  308. // RakString::freeList.Insert(RakString::sharedStringFreeList+i+RakString::sharedStringFreeListAllocationCount);
  309. RakString::SharedString *ss;
  310. ss = (RakString::SharedString*) rakMalloc_Ex(sizeof(RakString::SharedString), _FILE_AND_LINE_);
  311. ss->refCountMutex=RakNet::OP_NEW<SimpleMutex>(_FILE_AND_LINE_);
  312. RakString::freeList.Insert(ss, _FILE_AND_LINE_);
  313. }
  314. //RakString::sharedStringFreeListAllocationCount+=1024;
  315. }
  316. sharedString = RakString::freeList[RakString::freeList.Size()-1];
  317. RakString::freeList.RemoveAtIndex(RakString::freeList.Size()-1);
  318. RakString::UnlockMutex();
  319. const int smallStringSize = 128-sizeof(unsigned int)-sizeof(size_t)-sizeof(char*)*2;
  320. sharedString->bytesUsed=allocatedBytes;
  321. sharedString->refCount=1;
  322. if (allocatedBytes <= (size_t) smallStringSize)
  323. {
  324. sharedString->c_str=sharedString->smallString;
  325. }
  326. else
  327. {
  328. sharedString->bigString=(char*)rakMalloc_Ex(sharedString->bytesUsed, _FILE_AND_LINE_);
  329. sharedString->c_str=sharedString->bigString;
  330. }
  331. strcpy(sharedString->c_str, lhs);
  332. strcat(sharedString->c_str, rhs);
  333. return RakString(sharedString);
  334. }
  335. const char * RakString::ToLower(void)
  336. {
  337. Clone();
  338. size_t strLen = strlen(sharedString->c_str);
  339. unsigned i;
  340. for (i=0; i < strLen; i++)
  341. sharedString->c_str[i]=ToLower(sharedString->c_str[i]);
  342. return sharedString->c_str;
  343. }
  344. const char * RakString::ToUpper(void)
  345. {
  346. Clone();
  347. size_t strLen = strlen(sharedString->c_str);
  348. unsigned i;
  349. for (i=0; i < strLen; i++)
  350. sharedString->c_str[i]=ToUpper(sharedString->c_str[i]);
  351. return sharedString->c_str;
  352. }
  353. void RakString::Set(const char *format, ...)
  354. {
  355. va_list ap;
  356. va_start(ap, format);
  357. Clear();
  358. Assign(format,ap);
  359. }
  360. bool RakString::IsEmpty(void) const
  361. {
  362. return sharedString==&emptyString;
  363. }
  364. size_t RakString::GetLength(void) const
  365. {
  366. return strlen(sharedString->c_str);
  367. }
  368. // http://porg.es/blog/counting-characters-in-utf-8-strings-is-faster
  369. int porges_strlen2(char *s)
  370. {
  371. int i = 0;
  372. int iBefore = 0;
  373. int count = 0;
  374. while (s[i] > 0)
  375. ascii: i++;
  376. count += i-iBefore;
  377. while (s[i])
  378. {
  379. if (s[i] > 0)
  380. {
  381. iBefore = i;
  382. goto ascii;
  383. }
  384. else
  385. switch (0xF0 & s[i])
  386. {
  387. case 0xE0: i += 3; break;
  388. case 0xF0: i += 4; break;
  389. default: i += 2; break;
  390. }
  391. ++count;
  392. }
  393. return count;
  394. }
  395. size_t RakString::GetLengthUTF8(void) const
  396. {
  397. return porges_strlen2(sharedString->c_str);
  398. }
  399. void RakString::Replace(unsigned index, unsigned count, unsigned char c)
  400. {
  401. RakAssert(index+count < GetLength());
  402. Clone();
  403. unsigned countIndex=0;
  404. while (countIndex<count)
  405. {
  406. sharedString->c_str[index]=c;
  407. index++;
  408. countIndex++;
  409. }
  410. }
  411. void RakString::SetChar( unsigned index, unsigned char c )
  412. {
  413. RakAssert(index < GetLength());
  414. Clone();
  415. sharedString->c_str[index]=c;
  416. }
  417. void RakString::SetChar( unsigned index, RakNet::RakString s )
  418. {
  419. RakAssert(index < GetLength());
  420. Clone();
  421. RakNet::RakString firstHalf = SubStr(0, index);
  422. RakNet::RakString secondHalf = SubStr(index+1, (unsigned int)-1);
  423. *this = firstHalf;
  424. *this += s;
  425. *this += secondHalf;
  426. }
  427. #ifdef _WIN32
  428. WCHAR * RakString::ToWideChar(void)
  429. {
  430. //
  431. // Special case of NULL or empty input string
  432. //
  433. if ( (sharedString->c_str == NULL) || (*sharedString->c_str == '\0') )
  434. {
  435. // Return empty string
  436. return L"";
  437. }
  438. //
  439. // Get size of destination UTF-16 buffer, in WCHAR's
  440. //
  441. int cchUTF16 = ::MultiByteToWideChar(
  442. CP_UTF8, // convert from UTF-8
  443. 0, // Flags
  444. sharedString->c_str, // source UTF-8 string
  445. GetLength()+1, // total length of source UTF-8 string,
  446. // in CHAR's (= bytes), including end-of-string \0
  447. NULL, // unused - no conversion done in this step
  448. 0 // request size of destination buffer, in WCHAR's
  449. );
  450. if ( cchUTF16 == 0 )
  451. {
  452. RakAssert("RakString::ToWideChar exception from cchUTF16==0" && 0);
  453. return 0;
  454. }
  455. //
  456. // Allocate destination buffer to store UTF-16 string
  457. //
  458. WCHAR * pszUTF16 = RakNet::OP_NEW_ARRAY<WCHAR>(cchUTF16,__FILE__,__LINE__);
  459. //
  460. // Do the conversion from UTF-8 to UTF-16
  461. //
  462. int result = ::MultiByteToWideChar(
  463. CP_UTF8, // convert from UTF-8
  464. 0, // Buffer
  465. sharedString->c_str, // source UTF-8 string
  466. GetLength()+1, // total length of source UTF-8 string,
  467. // in CHAR's (= bytes), including end-of-string \0
  468. pszUTF16, // destination buffer
  469. cchUTF16 // size of destination buffer, in WCHAR's
  470. );
  471. if ( result == 0 )
  472. {
  473. RakAssert("RakString::ToWideChar exception from MultiByteToWideChar" && 0);
  474. return 0;
  475. }
  476. return pszUTF16;
  477. }
  478. void RakString::DeallocWideChar(WCHAR * w)
  479. {
  480. RakNet::OP_DELETE_ARRAY(w,__FILE__,__LINE__);
  481. }
  482. void RakString::FromWideChar(const wchar_t *source)
  483. {
  484. Clear();
  485. int bufSize = wcslen(source)*4;
  486. Allocate(bufSize);
  487. WideCharToMultiByte ( CP_ACP, // ANSI code page
  488. WC_COMPOSITECHECK, // Check for accented characters
  489. source, // Source Unicode string
  490. -1, // -1 means string is zero-terminated
  491. sharedString->c_str, // Destination char string
  492. bufSize, // Size of buffer
  493. NULL, // No default character
  494. NULL ); // Don't care about this flag
  495. }
  496. RakNet::RakString RakString::FromWideChar_S(const wchar_t *source)
  497. {
  498. RakNet::RakString rs;
  499. rs.FromWideChar(source);
  500. return rs;
  501. }
  502. #endif
  503. size_t RakString::Find(const char *stringToFind,size_t pos)
  504. {
  505. size_t len=GetLength();
  506. if (pos>=len || stringToFind==0 || stringToFind[0]==0)
  507. {
  508. return (size_t) -1;
  509. }
  510. size_t matchLen= strlen(stringToFind);
  511. size_t matchPos=0;
  512. size_t iStart=0;
  513. for (size_t i=pos;i<len;i++)
  514. {
  515. if (stringToFind[matchPos]==sharedString->c_str[i])
  516. {
  517. if(matchPos==0)
  518. {
  519. iStart=i;
  520. }
  521. matchPos++;
  522. }
  523. else
  524. {
  525. matchPos=0;
  526. }
  527. if (matchPos>=matchLen)
  528. {
  529. return iStart;
  530. }
  531. }
  532. return (size_t) -1;
  533. }
  534. void RakString::TruncateUTF8(unsigned int length)
  535. {
  536. int i = 0;
  537. unsigned int count = 0;
  538. while (sharedString->c_str[i]!=0)
  539. {
  540. if (count==length)
  541. {
  542. sharedString->c_str[i]=0;
  543. return;
  544. }
  545. else if (sharedString->c_str[i]>0)
  546. {
  547. i++;
  548. }
  549. else
  550. {
  551. switch (0xF0 & sharedString->c_str[i])
  552. {
  553. case 0xE0: i += 3; break;
  554. case 0xF0: i += 4; break;
  555. default: i += 2; break;
  556. }
  557. }
  558. count++;
  559. }
  560. }
  561. void RakString::Truncate(unsigned int length)
  562. {
  563. if (length < GetLength())
  564. {
  565. SetChar(length, 0);
  566. }
  567. }
  568. RakString RakString::SubStr(unsigned int index, unsigned int count) const
  569. {
  570. size_t length = GetLength();
  571. if (index >= length || count==0)
  572. return RakString();
  573. RakString copy;
  574. size_t numBytes = length-index;
  575. if (count < numBytes)
  576. numBytes=count;
  577. copy.Allocate(numBytes+1);
  578. size_t i;
  579. for (i=0; i < numBytes; i++)
  580. copy.sharedString->c_str[i]=sharedString->c_str[index+i];
  581. copy.sharedString->c_str[i]=0;
  582. return copy;
  583. }
  584. void RakString::Erase(unsigned int index, unsigned int count)
  585. {
  586. size_t len = GetLength();
  587. RakAssert(index+count <= len);
  588. Clone();
  589. unsigned i;
  590. for (i=index; i < len-count; i++)
  591. {
  592. sharedString->c_str[i]=sharedString->c_str[i+count];
  593. }
  594. sharedString->c_str[i]=0;
  595. }
  596. void RakString::TerminateAtLastCharacter(char c)
  597. {
  598. int i, len=(int) GetLength();
  599. for (i=len-1; i >= 0; i--)
  600. {
  601. if (sharedString->c_str[i]==c)
  602. {
  603. Clone();
  604. sharedString->c_str[i]=0;
  605. return;
  606. }
  607. }
  608. }
  609. void RakString::StartAfterLastCharacter(char c)
  610. {
  611. int i, len=(int) GetLength();
  612. for (i=len-1; i >= 0; i--)
  613. {
  614. if (sharedString->c_str[i]==c)
  615. {
  616. ++i;
  617. if (i < len)
  618. {
  619. *this = SubStr(i,GetLength()-i);
  620. }
  621. return;
  622. }
  623. }
  624. }
  625. void RakString::TerminateAtFirstCharacter(char c)
  626. {
  627. unsigned int i, len=(unsigned int) GetLength();
  628. for (i=0; i < len; i++)
  629. {
  630. if (sharedString->c_str[i]==c)
  631. {
  632. if (i > 0)
  633. {
  634. Clone();
  635. sharedString->c_str[i]=0;
  636. }
  637. }
  638. }
  639. }
  640. void RakString::StartAfterFirstCharacter(char c)
  641. {
  642. unsigned int i, len=(unsigned int) GetLength();
  643. for (i=0; i < len; i++)
  644. {
  645. if (sharedString->c_str[i]==c)
  646. {
  647. ++i;
  648. if (i < len)
  649. {
  650. *this = SubStr(i,GetLength()-i);
  651. }
  652. return;
  653. }
  654. }
  655. }
  656. int RakString::GetCharacterCount(char c)
  657. {
  658. int count=0;
  659. unsigned int i, len=(unsigned int) GetLength();
  660. for (i=0; i < len; i++)
  661. {
  662. if (sharedString->c_str[i]==c)
  663. {
  664. ++count;
  665. }
  666. }
  667. return count;
  668. }
  669. void RakString::RemoveCharacter(char c)
  670. {
  671. if (c==0)
  672. return;
  673. unsigned int readIndex, writeIndex=0;
  674. for (readIndex=0; sharedString->c_str[readIndex]; readIndex++)
  675. {
  676. if (sharedString->c_str[readIndex]!=c)
  677. sharedString->c_str[writeIndex++]=sharedString->c_str[readIndex];
  678. else
  679. Clone();
  680. }
  681. sharedString->c_str[writeIndex]=0;
  682. if (writeIndex==0)
  683. Clear();
  684. }
  685. int RakString::StrCmp(const RakString &rhs) const
  686. {
  687. return strcmp(sharedString->c_str, rhs.C_String());
  688. }
  689. int RakString::StrNCmp(const RakString &rhs, size_t num) const
  690. {
  691. return strncmp(sharedString->c_str, rhs.C_String(), num);
  692. }
  693. int RakString::StrICmp(const RakString &rhs) const
  694. {
  695. return _stricmp(sharedString->c_str, rhs.C_String());
  696. }
  697. void RakString::Printf(void)
  698. {
  699. RAKNET_DEBUG_PRINTF("%s", sharedString->c_str);
  700. }
  701. void RakString::FPrintf(FILE *fp)
  702. {
  703. fprintf(fp,"%s", sharedString->c_str);
  704. }
  705. bool RakString::IPAddressMatch(const char *IP)
  706. {
  707. unsigned characterIndex;
  708. if ( IP == 0 || IP[ 0 ] == 0 || strlen( IP ) > 15 )
  709. return false;
  710. characterIndex = 0;
  711. #ifdef _MSC_VER
  712. #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
  713. #endif
  714. while ( true )
  715. {
  716. if (sharedString->c_str[ characterIndex ] == IP[ characterIndex ] )
  717. {
  718. // Equal characters
  719. if ( IP[ characterIndex ] == 0 )
  720. {
  721. // End of the string and the strings match
  722. return true;
  723. }
  724. characterIndex++;
  725. }
  726. else
  727. {
  728. if ( sharedString->c_str[ characterIndex ] == 0 || IP[ characterIndex ] == 0 )
  729. {
  730. // End of one of the strings
  731. break;
  732. }
  733. // Characters do not match
  734. if ( sharedString->c_str[ characterIndex ] == '*' )
  735. {
  736. // Domain is banned.
  737. return true;
  738. }
  739. // Characters do not match and it is not a *
  740. break;
  741. }
  742. }
  743. // No match found.
  744. return false;
  745. }
  746. bool RakString::ContainsNonprintableExceptSpaces(void) const
  747. {
  748. size_t strLen = strlen(sharedString->c_str);
  749. unsigned i;
  750. for (i=0; i < strLen; i++)
  751. {
  752. if (sharedString->c_str[i] < ' ' || sharedString->c_str[i] >126)
  753. return true;
  754. }
  755. return false;
  756. }
  757. bool RakString::IsEmailAddress(void) const
  758. {
  759. if (IsEmpty())
  760. return false;
  761. size_t strLen = strlen(sharedString->c_str);
  762. if (strLen < 6) // a@b.de
  763. return false;
  764. if (sharedString->c_str[strLen-4]!='.' && sharedString->c_str[strLen-3]!='.') // .com, .net., .org, .de
  765. return false;
  766. unsigned i;
  767. // Has non-printable?
  768. for (i=0; i < strLen; i++)
  769. {
  770. if (sharedString->c_str[i] <= ' ' || sharedString->c_str[i] >126)
  771. return false;
  772. }
  773. int atCount=0;
  774. for (i=0; i < strLen; i++)
  775. {
  776. if (sharedString->c_str[i]=='@')
  777. {
  778. atCount++;
  779. }
  780. }
  781. if (atCount!=1)
  782. return false;
  783. int dotCount=0;
  784. for (i=0; i < strLen; i++)
  785. {
  786. if (sharedString->c_str[i]=='.')
  787. {
  788. dotCount++;
  789. }
  790. }
  791. if (dotCount==0)
  792. return false;
  793. // There's more I could check, but this is good enough
  794. return true;
  795. }
  796. RakNet::RakString& RakString::URLEncode(void)
  797. {
  798. RakString result;
  799. size_t strLen = strlen(sharedString->c_str);
  800. result.Allocate(strLen*3);
  801. char *output=result.sharedString->c_str;
  802. unsigned int outputIndex=0;
  803. unsigned i;
  804. unsigned char c;
  805. for (i=0; i < strLen; i++)
  806. {
  807. c=sharedString->c_str[i];
  808. if (
  809. (c<=47) ||
  810. (c>=58 && c<=64) ||
  811. (c>=91 && c<=96) ||
  812. (c>=123)
  813. )
  814. {
  815. char buff[3];
  816. Itoa(c, buff, 16);
  817. output[outputIndex++]='%';
  818. output[outputIndex++]=buff[0];
  819. output[outputIndex++]=buff[1];
  820. }
  821. else
  822. {
  823. output[outputIndex++]=c;
  824. }
  825. }
  826. output[outputIndex]=0;
  827. *this = result;
  828. return *this;
  829. }
  830. RakNet::RakString& RakString::URLDecode(void)
  831. {
  832. RakString result;
  833. size_t strLen = strlen(sharedString->c_str);
  834. result.Allocate(strLen);
  835. char *output=result.sharedString->c_str;
  836. unsigned int outputIndex=0;
  837. char c;
  838. char hexDigits[2];
  839. char hexValues[2];
  840. unsigned int i;
  841. for (i=0; i < strLen; i++)
  842. {
  843. c=sharedString->c_str[i];
  844. if (c=='%')
  845. {
  846. hexDigits[0]=sharedString->c_str[++i];
  847. hexDigits[1]=sharedString->c_str[++i];
  848. if (hexDigits[0]==' ')
  849. hexValues[0]=0;
  850. if (hexDigits[0]>='A' && hexDigits[0]<='F')
  851. hexValues[0]=hexDigits[0]-'A'+10;
  852. if (hexDigits[0]>='a' && hexDigits[0]<='f')
  853. hexValues[0]=hexDigits[0]-'a'+10;
  854. else
  855. hexValues[0]=hexDigits[0]-'0';
  856. if (hexDigits[1]>='A' && hexDigits[1]<='F')
  857. hexValues[1]=hexDigits[1]-'A'+10;
  858. if (hexDigits[1]>='a' && hexDigits[1]<='f')
  859. hexValues[1]=hexDigits[1]-'a'+10;
  860. else
  861. hexValues[1]=hexDigits[1]-'0';
  862. output[outputIndex++]=hexValues[0]*16+hexValues[1];
  863. }
  864. else
  865. {
  866. output[outputIndex++]=c;
  867. }
  868. }
  869. output[outputIndex]=0;
  870. *this = result;
  871. return *this;
  872. }
  873. void RakString::SplitURI(RakNet::RakString &header, RakNet::RakString &domain, RakNet::RakString &path)
  874. {
  875. header.Clear();
  876. domain.Clear();
  877. path.Clear();
  878. size_t strLen = strlen(sharedString->c_str);
  879. char c;
  880. unsigned int i=0;
  881. if (strncmp(sharedString->c_str, "http://", 7)==0)
  882. i+=(unsigned int) strlen("http://");
  883. else if (strncmp(sharedString->c_str, "https://", 8)==0)
  884. i+=(unsigned int) strlen("https://");
  885. if (strncmp(sharedString->c_str, "www.", 4)==0)
  886. i+=(unsigned int) strlen("www.");
  887. if (i!=0)
  888. {
  889. header.Allocate(i+1);
  890. strncpy(header.sharedString->c_str, sharedString->c_str, i);
  891. header.sharedString->c_str[i]=0;
  892. }
  893. domain.Allocate(strLen-i+1);
  894. char *domainOutput=domain.sharedString->c_str;
  895. unsigned int outputIndex=0;
  896. for (; i < strLen; i++)
  897. {
  898. c=sharedString->c_str[i];
  899. if (c=='/')
  900. {
  901. break;
  902. }
  903. else
  904. {
  905. domainOutput[outputIndex++]=sharedString->c_str[i];
  906. }
  907. }
  908. domainOutput[outputIndex]=0;
  909. path.Allocate(strLen-header.GetLength()-outputIndex+1);
  910. outputIndex=0;
  911. char *pathOutput=path.sharedString->c_str;
  912. for (; i < strLen; i++)
  913. {
  914. pathOutput[outputIndex++]=sharedString->c_str[i];
  915. }
  916. pathOutput[outputIndex]=0;
  917. }
  918. RakNet::RakString& RakString::SQLEscape(void)
  919. {
  920. int strLen=(int)GetLength();
  921. int escapedCharacterCount=0;
  922. int index;
  923. for (index=0; index < strLen; index++)
  924. {
  925. if (sharedString->c_str[index]=='\'' ||
  926. sharedString->c_str[index]=='"' ||
  927. sharedString->c_str[index]=='\\')
  928. escapedCharacterCount++;
  929. }
  930. if (escapedCharacterCount==0)
  931. return *this;
  932. Clone();
  933. Realloc(sharedString, strLen+escapedCharacterCount);
  934. int writeIndex, readIndex;
  935. writeIndex = strLen+escapedCharacterCount;
  936. readIndex=strLen;
  937. while (readIndex>=0)
  938. {
  939. if (sharedString->c_str[readIndex]=='\'' ||
  940. sharedString->c_str[readIndex]=='"' ||
  941. sharedString->c_str[readIndex]=='\\')
  942. {
  943. sharedString->c_str[writeIndex--]=sharedString->c_str[readIndex--];
  944. sharedString->c_str[writeIndex--]='\\';
  945. }
  946. else
  947. {
  948. sharedString->c_str[writeIndex--]=sharedString->c_str[readIndex--];
  949. }
  950. }
  951. return *this;
  952. }
  953. RakNet::RakString RakString::FormatForPUTOrPost(const char* type, const char* uri, const char* contentType, const char* body, const char* extraHeaders)
  954. {
  955. RakString out;
  956. RakString host;
  957. RakString remotePath;
  958. RakNet::RakString header;
  959. RakString uriRs;
  960. uriRs = uri;
  961. uriRs.SplitURI(header, host, remotePath);
  962. if (host.IsEmpty() || remotePath.IsEmpty())
  963. return out;
  964. // RakString bodyEncoded = body;
  965. // bodyEncoded.URLEncode();
  966. if (extraHeaders!=0 && extraHeaders[0])
  967. {
  968. out.Set("%s %s HTTP/1.1\r\n"
  969. "%s\r\n"
  970. "Host: %s\r\n"
  971. "Content-Type: %s\r\n"
  972. "Content-Length: %u\r\n"
  973. "\r\n"
  974. "%s",
  975. type,
  976. remotePath.C_String(),
  977. extraHeaders,
  978. host.C_String(),
  979. contentType,
  980. //bodyEncoded.GetLength(),
  981. //bodyEncoded.C_String());
  982. strlen(body),
  983. body);
  984. }
  985. else
  986. {
  987. out.Set("%s %s HTTP/1.1\r\n"
  988. "Host: %s\r\n"
  989. "Content-Type: %s\r\n"
  990. "Content-Length: %u\r\n"
  991. "\r\n"
  992. "%s",
  993. type,
  994. remotePath.C_String(),
  995. host.C_String(),
  996. contentType,
  997. //bodyEncoded.GetLength(),
  998. //bodyEncoded.C_String());
  999. strlen(body),
  1000. body);
  1001. }
  1002. return out;
  1003. }
  1004. RakString RakString::FormatForPOST(const char* uri, const char* contentType, const char* body, const char* extraHeaders)
  1005. {
  1006. return FormatForPUTOrPost("POST", uri, contentType, body, extraHeaders);
  1007. }
  1008. RakString RakString::FormatForPUT(const char* uri, const char* contentType, const char* body, const char* extraHeaders)
  1009. {
  1010. return FormatForPUTOrPost("PUT", uri, contentType, body, extraHeaders);
  1011. }
  1012. RakString RakString::FormatForGET(const char* uri, const char* extraHeaders)
  1013. {
  1014. RakString out;
  1015. RakString host;
  1016. RakString remotePath;
  1017. RakNet::RakString header;
  1018. RakNet::RakString uriRs;
  1019. uriRs = uri;
  1020. uriRs.SplitURI(header, host, remotePath);
  1021. if (host.IsEmpty() || remotePath.IsEmpty())
  1022. return out;
  1023. if (extraHeaders && extraHeaders[0])
  1024. {
  1025. out.Set("GET %s HTTP/1.1\r\n"
  1026. "%s\r\n"
  1027. "Host: %s\r\n"
  1028. "\r\n",
  1029. remotePath.C_String(),
  1030. extraHeaders,
  1031. host.C_String());
  1032. }
  1033. else
  1034. {
  1035. out.Set("GET %s HTTP/1.1\r\n"
  1036. "Host: %s\r\n"
  1037. "\r\n",
  1038. remotePath.C_String(),
  1039. host.C_String());
  1040. }
  1041. return out;
  1042. }
  1043. RakString RakString::FormatForDELETE(const char* uri, const char* extraHeaders)
  1044. {
  1045. RakString out;
  1046. RakString host;
  1047. RakString remotePath;
  1048. RakNet::RakString header;
  1049. RakNet::RakString uriRs;
  1050. uriRs = uri;
  1051. uriRs.SplitURI(header, host, remotePath);
  1052. if (host.IsEmpty() || remotePath.IsEmpty())
  1053. return out;
  1054. if (extraHeaders && extraHeaders[0])
  1055. {
  1056. out.Set("DELETE %s HTTP/1.1\r\n"
  1057. "%s\r\n"
  1058. "Content-Length: 0\r\n"
  1059. "Host: %s\r\n"
  1060. "Connection: close\r\n"
  1061. "\r\n",
  1062. remotePath.C_String(),
  1063. extraHeaders,
  1064. host.C_String());
  1065. }
  1066. else
  1067. {
  1068. out.Set("DELETE %s HTTP/1.1\r\n"
  1069. "Content-Length: 0\r\n"
  1070. "Host: %s\r\n"
  1071. "Connection: close\r\n"
  1072. "\r\n",
  1073. remotePath.C_String(),
  1074. host.C_String());
  1075. }
  1076. return out;
  1077. }
  1078. RakNet::RakString& RakString::MakeFilePath(void)
  1079. {
  1080. if (IsEmpty())
  1081. return *this;
  1082. RakNet::RakString fixedString = *this;
  1083. fixedString.Clone();
  1084. for (int i=0; fixedString.sharedString->c_str[i]; i++)
  1085. {
  1086. #ifdef _WIN32
  1087. if (fixedString.sharedString->c_str[i]=='/')
  1088. fixedString.sharedString->c_str[i]='\\';
  1089. #else
  1090. if (fixedString.sharedString->c_str[i]=='\\')
  1091. fixedString.sharedString->c_str[i]='/';
  1092. #endif
  1093. }
  1094. #ifdef _WIN32
  1095. if (fixedString.sharedString->c_str[strlen(fixedString.sharedString->c_str)-1]!='\\')
  1096. {
  1097. fixedString+='\\';
  1098. }
  1099. #else
  1100. if (fixedString.sharedString->c_str[strlen(fixedString.sharedString->c_str)-1]!='/')
  1101. {
  1102. fixedString+='/';
  1103. }
  1104. #endif
  1105. if (fixedString!=*this)
  1106. *this = fixedString;
  1107. return *this;
  1108. }
  1109. void RakString::FreeMemory(void)
  1110. {
  1111. LockMutex();
  1112. FreeMemoryNoMutex();
  1113. UnlockMutex();
  1114. }
  1115. void RakString::FreeMemoryNoMutex(void)
  1116. {
  1117. for (unsigned int i=0; i < freeList.Size(); i++)
  1118. {
  1119. RakNet::OP_DELETE(freeList[i]->refCountMutex,_FILE_AND_LINE_);
  1120. rakFree_Ex(freeList[i], _FILE_AND_LINE_ );
  1121. }
  1122. freeList.Clear(false, _FILE_AND_LINE_);
  1123. }
  1124. void RakString::Serialize(BitStream *bs) const
  1125. {
  1126. Serialize(sharedString->c_str, bs);
  1127. }
  1128. void RakString::Serialize(const char *str, BitStream *bs)
  1129. {
  1130. unsigned short l = (unsigned short) strlen(str);
  1131. bs->Write(l);
  1132. bs->WriteAlignedBytes((const unsigned char*) str, (const unsigned int) l);
  1133. }
  1134. void RakString::SerializeCompressed(BitStream *bs, uint8_t languageId, bool writeLanguageId) const
  1135. {
  1136. SerializeCompressed(C_String(), bs, languageId, writeLanguageId);
  1137. }
  1138. void RakString::SerializeCompressed(const char *str, BitStream *bs, uint8_t languageId, bool writeLanguageId)
  1139. {
  1140. if (writeLanguageId)
  1141. bs->WriteCompressed(languageId);
  1142. StringCompressor::Instance()->EncodeString(str,0xFFFF,bs,languageId);
  1143. }
  1144. bool RakString::Deserialize(BitStream *bs)
  1145. {
  1146. Clear();
  1147. bool b;
  1148. unsigned short l;
  1149. b=bs->Read(l);
  1150. if (l>0)
  1151. {
  1152. Allocate(((unsigned int) l)+1);
  1153. b=bs->ReadAlignedBytes((unsigned char*) sharedString->c_str, l);
  1154. if (b)
  1155. sharedString->c_str[l]=0;
  1156. else
  1157. Clear();
  1158. }
  1159. else
  1160. bs->AlignReadToByteBoundary();
  1161. return b;
  1162. }
  1163. bool RakString::Deserialize(char *str, BitStream *bs)
  1164. {
  1165. bool b;
  1166. unsigned short l;
  1167. b=bs->Read(l);
  1168. if (b && l>0)
  1169. b=bs->ReadAlignedBytes((unsigned char*) str, l);
  1170. if (b==false)
  1171. str[0]=0;
  1172. str[l]=0;
  1173. return b;
  1174. }
  1175. bool RakString::DeserializeCompressed(BitStream *bs, bool readLanguageId)
  1176. {
  1177. uint8_t languageId;
  1178. if (readLanguageId)
  1179. bs->ReadCompressed(languageId);
  1180. else
  1181. languageId=0;
  1182. return StringCompressor::Instance()->DecodeString(this,0xFFFF,bs,languageId);
  1183. }
  1184. bool RakString::DeserializeCompressed(char *str, BitStream *bs, bool readLanguageId)
  1185. {
  1186. uint8_t languageId;
  1187. if (readLanguageId)
  1188. bs->ReadCompressed(languageId);
  1189. else
  1190. languageId=0;
  1191. return StringCompressor::Instance()->DecodeString(str,0xFFFF,bs,languageId);
  1192. }
  1193. const char *RakString::ToString(int64_t i)
  1194. {
  1195. static int index=0;
  1196. static char buff[64][64];
  1197. #if defined(_WIN32)
  1198. sprintf(buff[index], "%I64d", i);
  1199. #else
  1200. sprintf(buff[index], "%lld", (long long unsigned int) i);
  1201. #endif
  1202. int lastIndex=index;
  1203. if (++index==64)
  1204. index=0;
  1205. return buff[lastIndex];
  1206. }
  1207. const char *RakString::ToString(uint64_t i)
  1208. {
  1209. static int index=0;
  1210. static char buff[64][64];
  1211. #if defined(_WIN32)
  1212. sprintf(buff[index], "%I64u", i);
  1213. #else
  1214. sprintf(buff[index], "%llu", (long long unsigned int) i);
  1215. #endif
  1216. int lastIndex=index;
  1217. if (++index==64)
  1218. index=0;
  1219. return buff[lastIndex];
  1220. }
  1221. void RakString::Clear(void)
  1222. {
  1223. Free();
  1224. }
  1225. void RakString::Allocate(size_t len)
  1226. {
  1227. RakString::LockMutex();
  1228. // sharedString = RakString::pool.Allocate( _FILE_AND_LINE_ );
  1229. if (RakString::freeList.Size()==0)
  1230. {
  1231. //RakString::sharedStringFreeList=(RakString::SharedString*) rakRealloc_Ex(RakString::sharedStringFreeList,(RakString::sharedStringFreeListAllocationCount+1024)*sizeof(RakString::SharedString), _FILE_AND_LINE_);
  1232. unsigned i;
  1233. for (i=0; i < 128; i++)
  1234. {
  1235. // RakString::freeList.Insert(RakString::sharedStringFreeList+i+RakString::sharedStringFreeListAllocationCount);
  1236. // RakString::freeList.Insert((RakString::SharedString*)rakMalloc_Ex(sizeof(RakString::SharedString), _FILE_AND_LINE_), _FILE_AND_LINE_);
  1237. RakString::SharedString *ss;
  1238. ss = (RakString::SharedString*) rakMalloc_Ex(sizeof(RakString::SharedString), _FILE_AND_LINE_);
  1239. ss->refCountMutex=RakNet::OP_NEW<SimpleMutex>(_FILE_AND_LINE_);
  1240. RakString::freeList.Insert(ss, _FILE_AND_LINE_);
  1241. }
  1242. //RakString::sharedStringFreeListAllocationCount+=1024;
  1243. }
  1244. sharedString = RakString::freeList[RakString::freeList.Size()-1];
  1245. RakString::freeList.RemoveAtIndex(RakString::freeList.Size()-1);
  1246. RakString::UnlockMutex();
  1247. const size_t smallStringSize = 128-sizeof(unsigned int)-sizeof(size_t)-sizeof(char*)*2;
  1248. sharedString->refCount=1;
  1249. if (len <= smallStringSize)
  1250. {
  1251. sharedString->bytesUsed=smallStringSize;
  1252. sharedString->c_str=sharedString->smallString;
  1253. }
  1254. else
  1255. {
  1256. sharedString->bytesUsed=len<<1;
  1257. sharedString->bigString=(char*)rakMalloc_Ex(sharedString->bytesUsed, _FILE_AND_LINE_);
  1258. sharedString->c_str=sharedString->bigString;
  1259. }
  1260. }
  1261. void RakString::Assign(const char *str)
  1262. {
  1263. if (str==0 || str[0]==0)
  1264. {
  1265. sharedString=&emptyString;
  1266. return;
  1267. }
  1268. size_t len = strlen(str)+1;
  1269. Allocate(len);
  1270. memcpy(sharedString->c_str, str, len);
  1271. }
  1272. void RakString::Assign(const char *str, va_list ap)
  1273. {
  1274. if (str==0 || str[0]==0)
  1275. {
  1276. sharedString=&emptyString;
  1277. return;
  1278. }
  1279. char stackBuff[512];
  1280. if (_vsnprintf(stackBuff, 512, str, ap)!=-1
  1281. #ifndef _WIN32
  1282. // Here Windows will return -1 if the string is too long; Linux just truncates the string.
  1283. && strlen(str) <511
  1284. #endif
  1285. )
  1286. {
  1287. Assign(stackBuff);
  1288. return;
  1289. }
  1290. char *buff=0, *newBuff;
  1291. size_t buffSize=8096;
  1292. while (1)
  1293. {
  1294. newBuff = (char*) rakRealloc_Ex(buff, buffSize,__FILE__,__LINE__);
  1295. if (newBuff==0)
  1296. {
  1297. notifyOutOfMemory(_FILE_AND_LINE_);
  1298. if (buff!=0)
  1299. {
  1300. Assign(buff);
  1301. rakFree_Ex(buff,__FILE__,__LINE__);
  1302. }
  1303. else
  1304. {
  1305. Assign(stackBuff);
  1306. }
  1307. return;
  1308. }
  1309. buff=newBuff;
  1310. if (_vsnprintf(buff, buffSize, str, ap)!=-1)
  1311. {
  1312. Assign(buff);
  1313. rakFree_Ex(buff,__FILE__,__LINE__);
  1314. return;
  1315. }
  1316. buffSize*=2;
  1317. }
  1318. }
  1319. RakNet::RakString RakString::Assign(const char *str,size_t pos, size_t n )
  1320. {
  1321. size_t incomingLen=strlen(str);
  1322. Clone();
  1323. if (str==0 || str[0]==0||pos>=incomingLen)
  1324. {
  1325. sharedString=&emptyString;
  1326. return (*this);
  1327. }
  1328. if (pos+n>=incomingLen)
  1329. {
  1330. n=incomingLen-pos;
  1331. }
  1332. const char * tmpStr=&(str[pos]);
  1333. size_t len = n+1;
  1334. Allocate(len);
  1335. memcpy(sharedString->c_str, tmpStr, len);
  1336. sharedString->c_str[n]=0;
  1337. return (*this);
  1338. }
  1339. RakNet::RakString RakString::NonVariadic(const char *str)
  1340. {
  1341. RakNet::RakString rs;
  1342. rs=str;
  1343. return rs;
  1344. }
  1345. unsigned long RakString::ToInteger(const char *str)
  1346. {
  1347. unsigned long hash = 0;
  1348. int c;
  1349. while ((c = *str++))
  1350. hash = c + (hash << 6) + (hash << 16) - hash;
  1351. return hash;
  1352. }
  1353. unsigned long RakString::ToInteger(const RakString &rs)
  1354. {
  1355. return RakString::ToInteger(rs.C_String());
  1356. }
  1357. int RakString::ReadIntFromSubstring(const char *str, size_t pos, size_t n)
  1358. {
  1359. char tmp[32];
  1360. if (n >= 32)
  1361. return 0;
  1362. for (size_t i=0; i < n; i++)
  1363. tmp[i]=str[i+pos];
  1364. return atoi(tmp);
  1365. }
  1366. void RakString::AppendBytes(const char *bytes, unsigned int count)
  1367. {
  1368. if (IsEmpty())
  1369. {
  1370. Allocate(count);
  1371. memcpy(sharedString->c_str, bytes, count+1);
  1372. sharedString->c_str[count]=0;
  1373. }
  1374. else
  1375. {
  1376. Clone();
  1377. unsigned int length=(unsigned int) GetLength();
  1378. Realloc(sharedString, count+length+1);
  1379. memcpy(sharedString->c_str+length, bytes, count);
  1380. sharedString->c_str[length+count]=0;
  1381. }
  1382. }
  1383. void RakString::Clone(void)
  1384. {
  1385. RakAssert(sharedString!=&emptyString);
  1386. if (sharedString==&emptyString)
  1387. {
  1388. return;
  1389. }
  1390. // Empty or solo then no point to cloning
  1391. sharedString->refCountMutex->Lock();
  1392. if (sharedString->refCount==1)
  1393. {
  1394. sharedString->refCountMutex->Unlock();
  1395. return;
  1396. }
  1397. sharedString->refCount--;
  1398. sharedString->refCountMutex->Unlock();
  1399. Assign(sharedString->c_str);
  1400. }
  1401. void RakString::Free(void)
  1402. {
  1403. if (sharedString==&emptyString)
  1404. return;
  1405. sharedString->refCountMutex->Lock();
  1406. sharedString->refCount--;
  1407. if (sharedString->refCount==0)
  1408. {
  1409. sharedString->refCountMutex->Unlock();
  1410. const size_t smallStringSize = 128-sizeof(unsigned int)-sizeof(size_t)-sizeof(char*)*2;
  1411. if (sharedString->bytesUsed>smallStringSize)
  1412. rakFree_Ex(sharedString->bigString, _FILE_AND_LINE_ );
  1413. /*
  1414. poolMutex->Lock();
  1415. pool.Release(sharedString);
  1416. poolMutex->Unlock();
  1417. */
  1418. RakString::LockMutex();
  1419. RakString::freeList.Insert(sharedString, _FILE_AND_LINE_);
  1420. RakString::UnlockMutex();
  1421. sharedString=&emptyString;
  1422. }
  1423. else
  1424. {
  1425. sharedString->refCountMutex->Unlock();
  1426. }
  1427. sharedString=&emptyString;
  1428. }
  1429. unsigned char RakString::ToLower(unsigned char c)
  1430. {
  1431. if (c >= 'A' && c <= 'Z')
  1432. return c-'A'+'a';
  1433. return c;
  1434. }
  1435. unsigned char RakString::ToUpper(unsigned char c)
  1436. {
  1437. if (c >= 'a' && c <= 'z')
  1438. return c-'a'+'A';
  1439. return c;
  1440. }
  1441. void RakString::LockMutex(void)
  1442. {
  1443. GetPoolMutex().Lock();
  1444. }
  1445. void RakString::UnlockMutex(void)
  1446. {
  1447. GetPoolMutex().Unlock();
  1448. }
  1449. /*
  1450. #include "RakString.h"
  1451. #include <string>
  1452. #include "GetTime.h"
  1453. using namespace RakNet;
  1454. int main(void)
  1455. {
  1456. RakString s3("Hello world");
  1457. RakString s5=s3;
  1458. RakString s1;
  1459. RakString s2('a');
  1460. RakString s4("%i %f", 5, 6.0);
  1461. RakString s6=s3;
  1462. RakString s7=s6;
  1463. RakString s8=s6;
  1464. RakString s9;
  1465. s9=s9;
  1466. RakString s10(s3);
  1467. RakString s11=s10 + s4 + s9 + s2;
  1468. s11+=RakString("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
  1469. RakString s12("Test");
  1470. s12+=s11;
  1471. bool b1 = s12==s12;
  1472. s11=s5;
  1473. s12.ToUpper();
  1474. s12.ToLower();
  1475. RakString s13;
  1476. bool b3 = s13.IsEmpty();
  1477. s13.Set("blah %s", s12.C_String());
  1478. bool b4 = s13.IsEmpty();
  1479. size_t i1=s13.GetLength();
  1480. s3.Clear(_FILE_AND_LINE_);
  1481. s4.Clear(_FILE_AND_LINE_);
  1482. s5.Clear(_FILE_AND_LINE_);
  1483. s5.Clear(_FILE_AND_LINE_);
  1484. s6.Printf();
  1485. s7.Printf();
  1486. RAKNET_DEBUG_PRINTF("\n");
  1487. static const int repeatCount=750;
  1488. DataStructures::List<RakString> rakStringList;
  1489. DataStructures::List<std::string> stdStringList;
  1490. DataStructures::List<char*> referenceStringList;
  1491. char *c;
  1492. unsigned i;
  1493. RakNet::TimeMS beforeReferenceList, beforeRakString, beforeStdString, afterStdString;
  1494. unsigned loop;
  1495. for (loop=0; loop<2; loop++)
  1496. {
  1497. beforeReferenceList=RakNet::GetTimeMS();
  1498. for (i=0; i < repeatCount; i++)
  1499. {
  1500. c = RakNet::OP_NEW_ARRAY<char >(56,_FILE_AND_LINE_ );
  1501. strcpy(c, "Aalsdkj alsdjf laksdjf ;lasdfj ;lasjfd");
  1502. referenceStringList.Insert(c);
  1503. }
  1504. beforeRakString=RakNet::GetTimeMS();
  1505. for (i=0; i < repeatCount; i++)
  1506. rakStringList.Insert("Aalsdkj alsdjf laksdjf ;lasdfj ;lasjfd");
  1507. beforeStdString=RakNet::GetTimeMS();
  1508. for (i=0; i < repeatCount; i++)
  1509. stdStringList.Insert("Aalsdkj alsdjf laksdjf ;lasdfj ;lasjfd");
  1510. afterStdString=RakNet::GetTimeMS();
  1511. RAKNET_DEBUG_PRINTF("Insertion 1 Ref=%i Rak=%i, Std=%i\n", beforeRakString-beforeReferenceList, beforeStdString-beforeRakString, afterStdString-beforeStdString);
  1512. beforeReferenceList=RakNet::GetTimeMS();
  1513. for (i=0; i < repeatCount; i++)
  1514. {
  1515. RakNet::OP_DELETE_ARRAY(referenceStringList[0], _FILE_AND_LINE_);
  1516. referenceStringList.RemoveAtIndex(0);
  1517. }
  1518. beforeRakString=RakNet::GetTimeMS();
  1519. for (i=0; i < repeatCount; i++)
  1520. rakStringList.RemoveAtIndex(0);
  1521. beforeStdString=RakNet::GetTimeMS();
  1522. for (i=0; i < repeatCount; i++)
  1523. stdStringList.RemoveAtIndex(0);
  1524. afterStdString=RakNet::GetTimeMS();
  1525. RAKNET_DEBUG_PRINTF("RemoveHead Ref=%i Rak=%i, Std=%i\n", beforeRakString-beforeReferenceList, beforeStdString-beforeRakString, afterStdString-beforeStdString);
  1526. beforeReferenceList=RakNet::GetTimeMS();
  1527. for (i=0; i < repeatCount; i++)
  1528. {
  1529. c = RakNet::OP_NEW_ARRAY<char >(56, _FILE_AND_LINE_ );
  1530. strcpy(c, "Aalsdkj alsdjf laksdjf ;lasdfj ;lasjfd");
  1531. referenceStringList.Insert(0);
  1532. }
  1533. beforeRakString=RakNet::GetTimeMS();
  1534. for (i=0; i < repeatCount; i++)
  1535. rakStringList.Insert("Aalsdkj alsdjf laksdjf ;lasdfj ;lasjfd");
  1536. beforeStdString=RakNet::GetTimeMS();
  1537. for (i=0; i < repeatCount; i++)
  1538. stdStringList.Insert("Aalsdkj alsdjf laksdjf ;lasdfj ;lasjfd");
  1539. afterStdString=RakNet::GetTimeMS();
  1540. RAKNET_DEBUG_PRINTF("Insertion 2 Ref=%i Rak=%i, Std=%i\n", beforeRakString-beforeReferenceList, beforeStdString-beforeRakString, afterStdString-beforeStdString);
  1541. beforeReferenceList=RakNet::GetTimeMS();
  1542. for (i=0; i < repeatCount; i++)
  1543. {
  1544. RakNet::OP_DELETE_ARRAY(referenceStringList[referenceStringList.Size()-1], _FILE_AND_LINE_);
  1545. referenceStringList.RemoveAtIndex(referenceStringList.Size()-1);
  1546. }
  1547. beforeRakString=RakNet::GetTimeMS();
  1548. for (i=0; i < repeatCount; i++)
  1549. rakStringList.RemoveAtIndex(rakStringList.Size()-1);
  1550. beforeStdString=RakNet::GetTimeMS();
  1551. for (i=0; i < repeatCount; i++)
  1552. stdStringList.RemoveAtIndex(stdStringList.Size()-1);
  1553. afterStdString=RakNet::GetTimeMS();
  1554. RAKNET_DEBUG_PRINTF("RemoveTail Ref=%i Rak=%i, Std=%i\n", beforeRakString-beforeReferenceList, beforeStdString-beforeRakString, afterStdString-beforeStdString);
  1555. }
  1556. printf("Done.");
  1557. char str[128];
  1558. Gets(str, sizeof(str));
  1559. return 1;
  1560. }
  1561. */
粤ICP备19079148号