SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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