00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "CATString.h"
00015 #include <stdlib.h>
00016
00017
00018 CATString::CATString()
00019 {
00020 Init();
00021 }
00022
00023 CATString::CATString(const char* str)
00024 {
00025 Init();
00026 *this = str;
00027 }
00028
00029 CATString::CATString(const CATString& str)
00030 {
00031 if (&str == this)
00032 return;
00033 Init();
00034 *this = str;
00035 }
00036
00037 CATString::CATString(const CATWChar* str)
00038 {
00039 Init();
00040 *this = str;
00041 }
00042
00043 void CATString::SetCodePage(CATUInt32 codePage)
00044 {
00045 fCodePage = codePage;
00046 }
00047
00048
00049 CATString::~CATString()
00050 {
00051 delete [] fBuffer;
00052 delete [] fUnicodeBuffer;
00053 }
00054
00055
00056 bool CATString::Create(CATUInt32 length)
00057 {
00058 Destroy();
00059
00060 if (!AllocBuffer(length))
00061 {
00062 return false;
00063 }
00064
00065 return true;
00066 }
00067
00068 CATUInt32 CATString::Length()
00069 {
00070
00071 if (!fLenDirty)
00072 {
00073 return fStrLen;
00074 }
00075
00076 fStrLen = this->LengthCalc();
00077 fLenDirty = false;
00078
00079 return fStrLen;
00080 }
00081
00082 CATUInt32 CATString::LengthCalc() const
00083 {
00084 CATASSERT( (fAsciiLocked == false) || (fUnicodeLocked == false), "Either ascii or unicode should be unlocked...");
00085
00086 if (this->fAsciiLocked)
00087 {
00088 if (fBuffer == 0)
00089 return 0;
00090
00091 return (CATUInt32)strlen(fBuffer);
00092 }
00093
00094 if (fUnicodeBuffer == 0)
00095 return 0;
00096
00097 return (CATUInt32)wcslen(fUnicodeBuffer);
00098 }
00099
00100
00101 char* CATString::GetAsciiBuffer(CATUInt32 minlength)
00102 {
00103 CATASSERT(fUnicodeLocked == false, "Can't get an ascii buffer while the unicode buffer is locked");
00104
00105 CATUInt32 bufSize = CATMax(minlength, this->Length());
00106
00107 if (bufSize == 0)
00108 bufSize = 1;
00109
00110 if (bufSize > fBufferLength)
00111 {
00112 this->ExpandBuffer(bufSize+1);
00113 }
00114
00115
00116 this->AsciiFromUnicode();
00117
00118 this->fBufferSizeLocked = true;
00119 this->fAsciiLocked = true;
00120
00121 return fBuffer;
00122 }
00123
00124 CATWChar* CATString::GetUnicodeBuffer(CATUInt32 minlength)
00125 {
00126 CATASSERT(fAsciiLocked == false, "Can't get a unicode buffer while the ascii buffer is locked");
00127
00128 CATUInt32 bufSize = CATMax(minlength, this->Length());
00129
00130 if (bufSize > fBufferLength)
00131 {
00132 this->ExpandBuffer(bufSize+1);
00133 }
00134
00135 this->fBufferSizeLocked = true;
00136 this->fUnicodeLocked = true;
00137
00138 return fUnicodeBuffer;
00139 }
00140
00141
00142 void CATString::ReleaseBuffer()
00143 {
00144
00145 this->fBufferSizeLocked = false;
00146 this->fUnicodeLocked = false;
00147
00148 if (fAsciiLocked)
00149 {
00150 this->fAsciiLocked = false;
00151 this->UnicodeFromAscii();
00152 }
00153
00154 fLenDirty = true;
00155 }
00156
00157 CATInt32 CATString::Compare(const CATString& str, CATUInt32 cmpLen, CATUInt32 offset) const
00158 {
00159
00160 if (&str == this)
00161 return 0;
00162
00163 CATInt32 retVal = 0;
00164
00165 CATASSERT((fAsciiLocked == false) && (str.fAsciiLocked == false),
00166 "Not supporting locked ascii strings for compares currently");
00167
00168 CATASSERT((offset == 0) || (offset < this->LengthCalc()),"offset beyond length of string." );
00169
00170
00171
00172 if (fUnicodeBuffer == 0)
00173 {
00174 return -1;
00175 }
00176
00177 if (str.fUnicodeBuffer == 0)
00178 {
00179 return 1;
00180 }
00181
00182
00183 if (this->IsEmpty() && str.IsEmpty())
00184 {
00185 return 0;
00186 }
00187
00188
00189 if (offset >= this->LengthCalc())
00190 {
00191 return -1;
00192 }
00193
00194 CATUInt32 i = 0;
00195
00196
00197
00198 while ((fUnicodeBuffer[i+offset] != 0) && (str.fUnicodeBuffer[i] != 0) && (retVal == 0) && ((cmpLen == 0) || (i < cmpLen)))
00199 {
00200 if (fUnicodeBuffer[i+offset] == str.fUnicodeBuffer[i])
00201 {
00202 i++;
00203 }
00204 else
00205 {
00206 if (fUnicodeBuffer[i+offset] < str.fUnicodeBuffer[i])
00207 {
00208 retVal = -1;
00209 }
00210 else
00211 {
00212 retVal = 1;
00213 }
00214 }
00215 }
00216
00217
00218 if ((retVal == 0) && ((cmpLen == 0) || (i < cmpLen)))
00219 {
00220 if (fUnicodeBuffer[i+offset] != 0)
00221 {
00222 retVal = 1;
00223 }
00224 else if (str.fUnicodeBuffer[i] != 0)
00225 {
00226 retVal = -1;
00227 }
00228 }
00229
00230 return retVal;
00231 }
00232
00233
00234
00235
00236
00237
00238
00239 CATInt32 CATString::CompareNoCase(const CATString& str,CATUInt32 cmpLen, CATUInt32 offset) const
00240 {
00241
00242 if (&str == this)
00243 return 0;
00244
00245 CATInt32 retVal = 0;
00246
00247 CATASSERT((fAsciiLocked == false) && (str.fAsciiLocked == false),
00248 "Not supporting locked or dirty ascii strings for compares currently");
00249
00250 CATASSERT((offset == 0) || (offset < this->LengthCalc()),"offset beyond length of string." );
00251
00252
00253
00254 if (fUnicodeBuffer == 0)
00255 {
00256 return -1;
00257 }
00258
00259 if (str.fUnicodeBuffer == 0)
00260 {
00261 return 1;
00262 }
00263
00264
00265 if (offset >= this->LengthCalc())
00266 {
00267 return -1;
00268 }
00269
00270 CATUInt32 i = 0;
00271
00272
00273
00274 while ((fUnicodeBuffer[i+offset] != 0) && (str.fUnicodeBuffer[i] != 0) && (retVal == 0) && ((cmpLen == 0) || (i < cmpLen)))
00275 {
00276 CATWChar c1, c2;
00277 c1 = fUnicodeBuffer[i+offset];
00278 c2 = str.fUnicodeBuffer[i];
00279
00280
00281 if ((c1 >= (CATWChar)'A') && (c1 <= (CATWChar)'Z'))
00282 {
00283 c1 ^= 0x0020;
00284 }
00285
00286 if ((c2 >= (CATWChar)'A') && (c2 <= (CATWChar)'Z'))
00287 {
00288 c2 ^= 0x0020;
00289 }
00290
00291 if (c1 == c2)
00292 {
00293 i++;
00294 }
00295 else
00296 {
00297 if (c1 < c2)
00298 {
00299 retVal = -1;
00300 }
00301 else
00302 {
00303 retVal = 1;
00304 }
00305 }
00306 }
00307
00308
00309 if ((retVal == 0) && ((cmpLen == 0) || (i < cmpLen)))
00310 {
00311 if (fUnicodeBuffer[i+offset] != 0)
00312 {
00313 retVal = 1;
00314 }
00315 else if (str.fUnicodeBuffer[i] != 0)
00316 {
00317 retVal = -1;
00318 }
00319 }
00320
00321 return retVal;
00322 }
00323
00324
00325
00326
00327
00328
00329 bool CATString::Find(const CATString& str, CATUInt32& offset) const
00330 {
00331 CATASSERT((fAsciiLocked == false) && (str.fAsciiLocked == false),
00332 "Not supporting locked or dirty strings for searches currently");
00333
00334 bool found = false;
00335
00336 CATUInt32 i = 0;
00337 CATUInt32 j = 0;
00338
00339 CATUInt32 len;
00340 CATUInt32 patlen;
00341
00342 if (this->fLenDirty)
00343 {
00344 len = this->LengthCalc();
00345 }
00346 else
00347 {
00348 len = this->fStrLen;
00349 }
00350
00351 if (str.fLenDirty)
00352 {
00353 patlen = str.LengthCalc();
00354 }
00355 else
00356 {
00357 patlen = str.fStrLen;
00358 }
00359
00360
00361 len -= offset;
00362
00363
00364 CATWChar* data = this->fUnicodeBuffer + offset;
00365 CATWChar* pattern = str.fUnicodeBuffer;
00366
00367 if (len > patlen)
00368 {
00369 while (i <= len - patlen)
00370 {
00371 if (data[i+j] == pattern[j])
00372 {
00373 j++;
00374 }
00375 else
00376 {
00377 j = 0;
00378 i++;
00379 }
00380
00381 if (j == patlen)
00382 {
00383 found = true;
00384 break;
00385 }
00386 }
00387 }
00388
00389 if (found)
00390 {
00391 offset += i;
00392 }
00393
00394 return found;
00395 }
00396
00397
00398 bool CATString::Find(CATWChar theChar, CATUInt32& offset) const
00399 {
00400 CATASSERT((fAsciiLocked == false),
00401 "Not supporting locked or dirty strings for searches currently");
00402
00403 bool found = false;
00404
00405 CATUInt32 i = 0;
00406 CATUInt32 len = this->LengthCalc();
00407 len -= offset;
00408
00409 while ( (i < len) && (!found))
00410 {
00411 if (this->fUnicodeBuffer[i+offset] == theChar)
00412 {
00413 found = true;
00414 }
00415 else
00416 {
00417 i++;
00418 }
00419 }
00420
00421 if (found)
00422 {
00423 offset += i;
00424 }
00425
00426 return found;
00427 }
00428
00429
00430
00431 bool CATString::ReverseFind(const CATString& str, CATUInt32& offset) const
00432 {
00433 CATASSERT((fAsciiLocked == false) && (str.fAsciiLocked == false),
00434 "Not supporting locked or dirty strings for searches currently");
00435
00436 bool found = false;
00437
00438 CATUInt32 i = 0;
00439 CATUInt32 j = 0;
00440
00441 CATUInt32 len;
00442 CATUInt32 patlen;
00443 CATUInt32 locoffset = offset;
00444
00445 if (this->fLenDirty)
00446 {
00447 len = this->LengthCalc();
00448 }
00449 else
00450 {
00451 len = this->fStrLen;
00452 }
00453
00454 if (str.fLenDirty)
00455 {
00456 patlen = str.LengthCalc();
00457 }
00458 else
00459 {
00460 patlen = str.fStrLen;
00461 }
00462
00463 if (locoffset == -1)
00464 {
00465 locoffset = len - patlen;
00466 }
00467
00468
00469 i = locoffset;
00470 if (i + patlen > len)
00471 {
00472 i = len - patlen;
00473 }
00474
00475
00476 CATWChar* data = this->fUnicodeBuffer;
00477 CATWChar* pattern = str.fUnicodeBuffer;
00478
00479 if (len > patlen)
00480 {
00481 for ( ; ; )
00482 {
00483 if (data[i+j] == pattern[j])
00484 {
00485 j++;
00486 }
00487 else
00488 {
00489 j = 0;
00490
00491 if (i == 0)
00492 break;
00493
00494 i--;
00495 }
00496
00497 if (j == patlen)
00498 {
00499 found = true;
00500 break;
00501 }
00502 }
00503 }
00504
00505 if (found)
00506 {
00507 offset = i;
00508 }
00509
00510 return found;
00511 }
00512
00513
00514 bool CATString::ReverseFind(CATWChar theChar, CATUInt32& offset) const
00515 {
00516 CATASSERT((fAsciiLocked == false),
00517 "Not supporting locked or dirty strings for searches currently");
00518
00519 bool found = false;
00520
00521 CATUInt32 i = 0;
00522 CATUInt32 len = this->GetLength(fUnicodeBuffer);
00523
00524
00525 CATUInt32 locoffset = offset;
00526 if (locoffset == -1)
00527 {
00528 locoffset = len - 1;
00529 }
00530
00531 i = locoffset;
00532
00533 while (!found)
00534 {
00535 if (this->fUnicodeBuffer[i] == theChar)
00536 {
00537 found = true;
00538 }
00539 else
00540 {
00541 if (i == 0)
00542 {
00543
00544 break;
00545 }
00546 i--;
00547 }
00548 }
00549
00550 if (found)
00551 {
00552 offset = i;
00553 }
00554
00555 return found;
00556 }
00557
00558
00559
00560 CATString CATString::Left(CATUInt32 maxlength) const
00561 {
00562 CATString newString;
00563
00564 CATUInt32 newLen = CATMin(maxlength,this->LengthCalc());
00565 newString.Create( newLen + 1);
00566 this->CopyBuffer(newString.fUnicodeBuffer, this->fUnicodeBuffer, newLen);
00567
00568 newString.fLenDirty = true;
00569 return newString;
00570 }
00571
00572
00573
00574
00575 CATString CATString::Right(CATUInt32 start) const
00576 {
00577 CATString newString;
00578
00579 if (start >= this->LengthCalc())
00580 {
00581 return newString;
00582 }
00583
00584 CATUInt32 length = this->LengthCalc() - start;
00585 newString.Create(length+1);
00586 this->CopyBuffer(newString.fUnicodeBuffer, this->fUnicodeBuffer + start, length);
00587
00588 newString.fLenDirty = true;
00589 return newString;
00590 }
00591
00592 CATString CATString::FromRight(CATUInt32 length) const
00593 {
00594 return Right(LengthCalc() - length);
00595 }
00596
00597
00598 CATString CATString::Sub(CATUInt32 start, CATUInt32 length) const
00599 {
00600 CATString newString;
00601
00602 CATUInt32 actualLength;
00603
00604 if (start >= this->LengthCalc())
00605 {
00606 return newString;
00607 }
00608
00609 actualLength = CATMin(length, this->LengthCalc() - start);
00610 newString.Create(length);
00611 CopyBuffer(newString.fUnicodeBuffer, this->fUnicodeBuffer + start, length);
00612
00613 newString.fLenDirty = true;
00614
00615 return newString;
00616 }
00617
00618
00619
00620 CATString::CATString(CATUInt32 val)
00621 {
00622 Init();
00623 *this = val;
00624 }
00625
00626 CATString::CATString(CATInt32 val)
00627 {
00628 Init();
00629 *this = val;
00630 }
00631
00632 CATString::CATString(CATFloat32 val)
00633 {
00634 Init();
00635 *this = val;
00636 }
00637
00638
00639 CATString::CATString(CATFloat64 val)
00640 {
00641 Init();
00642 *this = val;
00643 }
00644
00645
00646 CATString::CATString(bool val)
00647 {
00648 Init();
00649 *this = val;
00650 }
00651
00652
00653 CATString::CATString(char val)
00654 {
00655 Init();
00656 *this = val;
00657 }
00658
00659
00660 CATString::CATString(CATWChar val)
00661 {
00662 Init();
00663 *this = val;
00664 }
00665 CATString::CATString(const GUID& guid)
00666 {
00667 Init();
00668 *this = guid;
00669 }
00670
00671 CATString::CATString(const GUID* guid)
00672 {
00673 Init();
00674 *this = guid;
00675 }
00676
00677
00678 CATString& CATString::operator=(CATFloat32 val)
00679 {
00680 CATWChar tmpBuf[256];
00681 swprintf(tmpBuf,256,L"%.5f",val);
00682
00683 int lastByte = (int)(wcslen(tmpBuf) - 1);
00684 while ((lastByte > 0) && (tmpBuf[lastByte] == '0') && (tmpBuf[lastByte - 1] != '.'))
00685 {
00686 tmpBuf[lastByte] = 0;
00687 lastByte--;
00688 }
00689
00690 *this = tmpBuf;
00691 return *this;
00692 }
00693
00694
00695 CATString& CATString::operator=(CATFloat64 val)
00696 {
00697 CATWChar tmpBuf[512];
00698 swprintf(tmpBuf,512,L"%.5f",val);
00699
00700 int lastByte = (int)(wcslen(tmpBuf) - 1);
00701 while ((lastByte > 0) && (tmpBuf[lastByte] == '0') && (tmpBuf[lastByte - 1] != '.'))
00702 {
00703 tmpBuf[lastByte] = 0;
00704 lastByte--;
00705 }
00706
00707 *this = tmpBuf;
00708 return *this;
00709 }
00710
00711 CATString& CATString::operator=(const GUID& guid)
00712 {
00713 CATWChar tmpBuf[512];
00714 swprintf(tmpBuf,512,L"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
00715 guid.Data1, guid.Data2,guid.Data3,
00716 guid.Data4[0],
00717 guid.Data4[1],
00718 guid.Data4[2],
00719 guid.Data4[3],
00720 guid.Data4[4],
00721 guid.Data4[5],
00722 guid.Data4[6],
00723 guid.Data4[7]
00724 );
00725 *this = tmpBuf;
00726 return *this;
00727 }
00728
00729 CATString& CATString::operator=(const GUID* guid)
00730 {
00731 *this = (*guid);
00732 return *this;
00733 }
00734
00735
00736 CATString& CATString::operator=(CATUInt32 val)
00737 {
00738 CATWChar tmpBuf[32];
00739 swprintf(tmpBuf,32,L"%u",val);
00740 *this = tmpBuf;
00741 return *this;
00742 }
00743
00744
00745 CATString& CATString::operator=(bool val)
00746 {
00747
00748 if (val)
00749 {
00750 *this = (const CATWChar*)L"True";
00751 }
00752 else
00753 {
00754 *this = (const CATWChar*)L"False";
00755 }
00756
00757 return *this;
00758 }
00759
00760
00761 CATString& CATString::operator=(char val)
00762 {
00763 char tmpBuf[2];
00764 tmpBuf[0] = val;
00765 tmpBuf[1] = 0;
00766 *this = tmpBuf;
00767 return *this;
00768 }
00769
00770
00771 CATString& CATString::operator=(CATWChar val)
00772 {
00773 CATWChar tmpBuf[2];
00774 tmpBuf[0] = val;
00775 tmpBuf[1] = 0;
00776 *this = tmpBuf;
00777 return *this;
00778 }
00779
00780
00781 CATString& CATString::operator=(CATInt32 val)
00782 {
00783 this->ExpandBuffer(33);
00784 swprintf(fUnicodeBuffer,33,L"%d",val);
00785 this->fLenDirty = true;
00786 return *this;
00787 }
00788
00789
00790 CATString::operator CATInt32() const
00791 {
00792 if (fUnicodeBuffer == 0)
00793 return 0;
00794
00795 if ((fUnicodeBuffer[0] == '0') && (fUnicodeBuffer[1] == 'x'))
00796 {
00797 return (CATInt32)this->FromHex();
00798 }
00799
00800 CATWChar* endPtr = 0;
00801 return wcstol(fUnicodeBuffer,&endPtr,10);
00802 }
00803
00804 CATString::operator CATInt64() const
00805 {
00806 CATWChar* endPtr = 0;
00807
00808 if (fUnicodeBuffer == 0)
00809 return 0;
00810
00811 if ((fUnicodeBuffer[0] == '0') && (fUnicodeBuffer[1] == 'x'))
00812 {
00813 return (CATInt64)_wcstoui64(fUnicodeBuffer,&endPtr,16);
00814 }
00815
00816 return (CATInt64)_wcstoui64(fUnicodeBuffer,&endPtr,10);
00817 }
00818
00819 CATString::operator bool() const
00820 {
00821 if (fUnicodeBuffer == 0)
00822 return false;
00823
00824 CATWChar firstChar = this->GetWChar(0);
00825
00826
00827 switch (firstChar)
00828 {
00829
00830 case 'T':
00831 case 't':
00832 case 'y':
00833 case 'Y':
00834 return true;
00835 case 'F':
00836 case 'f':
00837 case 'n':
00838 case 'N':
00839 return false;
00840 }
00841
00842
00843 if ((CATInt32)*this)
00844 {
00845 return true;
00846 }
00847
00848 return false;
00849 }
00850
00851
00852 CATString::operator CATFloat32() const
00853 {
00854 if (fUnicodeBuffer == 0)
00855 return 0;
00856
00857 return (CATFloat32)_wtof(fUnicodeBuffer);
00858 }
00859
00860
00861 CATString::operator CATFloat64() const
00862 {
00863 if (fUnicodeBuffer == 0)
00864 return 0;
00865
00866 return _wtof(fUnicodeBuffer);
00867 }
00868
00869
00870 CATString::operator CATUInt32() const
00871 {
00872 if (fUnicodeBuffer == 0)
00873 return 0;
00874
00875 if ((fUnicodeBuffer[0] == '0') && (fUnicodeBuffer[1] == 'x'))
00876 {
00877 return this->FromHex();
00878 }
00879
00880 CATWChar* endPtr = 0;
00881 return wcstoul(fUnicodeBuffer,&endPtr,10);
00882 }
00883
00884
00885
00886 CATString& CATString::operator=(const CATString& str)
00887 {
00888 if (&str == this)
00889 return *this;
00890
00891 if (str.IsEmpty())
00892 {
00893 *this = "";
00894 return *this;
00895 }
00896
00897 CATASSERT((str.fUnicodeLocked != true) && (str.fAsciiLocked != true), "Can't copy locked strings right now");
00898 Destroy();
00899
00900 CATUInt32 newlen = str.LengthCalc();
00901
00902 this->Create(newlen+1);
00903 this->CopyBuffer(this->fUnicodeBuffer,str.fUnicodeBuffer,newlen);
00904
00905 fLenDirty = true;
00906
00907 return *this;
00908 }
00909
00910
00911 CATString& CATString::operator=(const CATWChar* unistr)
00912 {
00913 Destroy();
00914 if (unistr == 0)
00915 return *this;
00916
00917 CATUInt32 newlen = (CATUInt32)(wcslen(unistr));
00918 this->AllocBuffer(newlen+1);
00919
00920 if (fUnicodeBuffer == 0)
00921 {
00922 CATASSERT(fUnicodeBuffer != 0,"Make sure we could allocate it");
00923 throw;
00924 }
00925
00926 this->CopyBuffer(this->fUnicodeBuffer,unistr,newlen);
00927
00928 fLenDirty = true;
00929 return *this;
00930 }
00931
00932
00933 CATString& CATString::operator=(const char* asciistr)
00934 {
00935 Destroy();
00936 this->ImportAscii(asciistr);
00937 return *this;
00938 }
00939
00940
00941 CATString::operator const char *() const
00942 {
00943 CATASSERT(fUnicodeLocked != true,"Getting pointer to ascii while unicode is locked - dangerous.");
00944 this->AsciiFromUnicode();
00945 return fBuffer;
00946 }
00947
00948
00949 CATString::operator const CATWChar*() const
00950 {
00951 CATASSERT(fAsciiLocked != true,"Getting pointer to unicode while ascii is locked - dangerous.");
00952 return fUnicodeBuffer;
00953 }
00954
00955
00956
00957 CATString& CATString::operator+=(const CATString& str)
00958 {
00959 CATASSERT(this->fBufferSizeLocked != true, "Performing operations that modify the string length after locking buffer with GetBuffer() is dangerous. Use ReleaseBuffer first!");
00960
00961 if (this == &str)
00962 {
00963 CATString temp = str + str;
00964 *this = temp;
00965 return *this;
00966 }
00967
00968
00969 CATUInt32 newLength = Length();
00970
00971
00972
00973 if (str.fLenDirty)
00974 {
00975 newLength += str.LengthCalc() + 1;
00976 }
00977 else
00978 {
00979 newLength += str.fStrLen + 1;
00980 }
00981
00982 if (fUnicodeBuffer == 0)
00983 {
00984 this->AllocBuffer(newLength);
00985 }
00986 else
00987 {
00988 this->ExpandBuffer(newLength);
00989 }
00990
00991 CopyBuffer(this->fUnicodeBuffer + this->Length(),str.fUnicodeBuffer,newLength);
00992
00993 fStrLen = newLength-1;
00994 fLenDirty = false;
00995 return *this;
00996 }
00997
00998
00999
01000
01001 bool CATString::AsciiFromUnicode() const
01002 {
01003
01004 CATUInt32 asciiLen = 0;
01005 if (fCodePage == CP_UTF8)
01006 {
01007 asciiLen = WideCharToMultiByte( fCodePage,0,fUnicodeBuffer, -1,
01008 0, 0, 0, 0);
01009 }
01010 else
01011 {
01012 asciiLen = WideCharToMultiByte( fCodePage,WC_COMPOSITECHECK | WC_DISCARDNS,fUnicodeBuffer, -1,
01013 0, 0, 0, 0);
01014 }
01015
01016 if (fBuffer)
01017 delete [] fBuffer;
01018
01019
01020 fBuffer = new char[CATMax(asciiLen+1,fBufferLength)];
01021
01022 memset(fBuffer,0,CATMax(asciiLen+1,fBufferLength));
01023
01024
01025 if (fCodePage == CP_UTF8)
01026 {
01027 WideCharToMultiByte( fCodePage,0,fUnicodeBuffer, -1,
01028 fBuffer, asciiLen, 0, 0);
01029 }
01030 else
01031 {
01032 WideCharToMultiByte( fCodePage,WC_COMPOSITECHECK | WC_DISCARDNS,fUnicodeBuffer, -1,
01033 fBuffer, asciiLen, 0, 0);
01034 }
01035
01036
01037 return true;
01038 }
01039
01040 bool CATString::UnicodeFromAscii()
01041 {
01042 if (fBuffer == 0)
01043 {
01044 if (fUnicodeBuffer)
01045 delete [] fUnicodeBuffer;
01046 fBufferLength = 0;
01047 fStrLen = 0;
01048 fLenDirty = 0;
01049 return true;
01050 }
01051
01052
01053 CATUInt32 uniLen = 0;
01054 uniLen = MultiByteToWideChar( fCodePage,
01055 MB_PRECOMPOSED,
01056 fBuffer,
01057 -1,
01058 0,
01059 0);
01060
01061
01062 if (fUnicodeBuffer)
01063 delete [] fUnicodeBuffer;
01064
01065
01066 fBufferLength = CATMax(uniLen+1,fBufferLength);
01067 fUnicodeBuffer = new CATWChar[fBufferLength];
01068 memset(fUnicodeBuffer,0,fBufferLength * sizeof(CATWChar));
01069
01070
01071 ::MultiByteToWideChar( fCodePage,
01072 MB_PRECOMPOSED,
01073 fBuffer,
01074 -1,
01075 fUnicodeBuffer,
01076 uniLen);
01077 this->fLenDirty = true;
01078 return true;
01079 }
01080
01081 bool CATString::ImportAscii(const char* ascii)
01082 {
01083 if (ascii == 0)
01084 {
01085 if (fUnicodeBuffer)
01086 delete [] fUnicodeBuffer;
01087 fBufferLength = 0;
01088 fStrLen = 0;
01089 fLenDirty = 0;
01090 return true;
01091 }
01092
01093 if (fBuffer)
01094 {
01095 delete [] fBuffer;
01096 fBuffer = 0;
01097 }
01098
01099
01100 CATUInt32 uniLen = 0;
01101 uniLen = MultiByteToWideChar( fCodePage,
01102 MB_PRECOMPOSED,
01103 ascii,
01104 -1,
01105 0,
01106 0);
01107
01108
01109 if (fUnicodeBuffer)
01110 delete [] fUnicodeBuffer;
01111
01112
01113 fBufferLength = CATMax(uniLen+1,fBufferLength);
01114 fUnicodeBuffer = new CATWChar[fBufferLength];
01115 memset(fUnicodeBuffer,0,fBufferLength * sizeof(CATWChar));
01116
01117
01118 ::MultiByteToWideChar( fCodePage,
01119 MB_PRECOMPOSED,
01120 ascii,
01121 -1,
01122 fUnicodeBuffer,
01123 uniLen);
01124 this->fLenDirty = true;
01125 return true;
01126 }
01127
01128
01129
01130
01131 bool CATString::AllocBuffer(CATUInt32 minLength)
01132 {
01133
01134
01135 CATASSERT(!fBufferSizeLocked,"Buffer size shouldn't be locked here...");
01136
01137 if ((fBufferSizeLocked == true) || (fUnicodeBuffer != 0) )
01138 {
01139 return false;
01140 }
01141
01142 if (fBuffer)
01143 {
01144 delete [] fBuffer;
01145 fBuffer = 0;
01146 }
01147
01148 CATUInt32 realLength = 0;
01149
01150
01151
01152 if (minLength < 32)
01153 {
01154 realLength = 32;
01155 }
01156 else if (minLength < 64)
01157 {
01158 realLength = 64;
01159 }
01160 else if (minLength < 128)
01161 {
01162 realLength = 128;
01163 }
01164 else if (minLength < 256)
01165 {
01166 realLength = 256;
01167 }
01168 else if (minLength < 1024)
01169 {
01170 realLength = 1024;
01171 }
01172 else
01173 {
01174
01175 realLength = minLength + 1;
01176 }
01177
01178 fUnicodeBuffer = new CATWChar[realLength];
01179 memset(fUnicodeBuffer,0,realLength*sizeof(CATWChar));
01180 CATASSERT(fUnicodeBuffer != 0, "Got a null string buffer when we tried to allocate it.");
01181 if (fUnicodeBuffer == 0)
01182 {
01183 fBufferLength = 0;
01184 return false;
01185 }
01186
01187 fBufferLength = realLength;
01188
01189 return true;
01190 }
01191
01192
01193 bool CATString::ExpandBuffer(CATUInt32 minLength)
01194 {
01195
01196
01197
01198 CATASSERT(this->fBufferSizeLocked != true,"Always use ReleaseBuffer() before performing operations that could change the string size!!!");
01199
01200 if (fBufferSizeLocked)
01201 {
01202 return false;
01203 }
01204
01205 if (this->fUnicodeBuffer == 0)
01206 {
01207 return this->AllocBuffer(minLength);
01208 }
01209
01210
01211 CATUInt32 realLength = this->Length() + 1;
01212
01213 if (minLength >= realLength)
01214 {
01215 realLength = minLength + 1;
01216 }
01217
01218
01219
01220 if (realLength <= fBufferLength)
01221 {
01222 return true;
01223 }
01224
01225
01226
01227 if (realLength < 16)
01228 {
01229 realLength = 16;
01230 }
01231 else if (realLength < 32)
01232 {
01233 realLength = 32;
01234 }
01235 else if (realLength < 64)
01236 {
01237 realLength = 64;
01238 }
01239 else if (realLength < 128)
01240 {
01241 realLength = 128;
01242 }
01243 else if (realLength < 256)
01244 {
01245 realLength = 256;
01246 }
01247 else if (realLength < 1024)
01248 {
01249 realLength = 1024;
01250 }
01251 else if (realLength < 1024*10)
01252 {
01253
01254
01255 realLength = realLength + 1024;
01256 }
01257 else
01258 {
01259 realLength = realLength + 1024*10;
01260 }
01261
01262 CATWChar *tmpBuf = fUnicodeBuffer;
01263
01264
01265 if (fBuffer != 0)
01266 {
01267 delete [] fBuffer;
01268 fBuffer = 0;
01269 }
01270
01271
01272 fUnicodeBuffer = new CATWChar[realLength];
01273 CATASSERT(fUnicodeBuffer != 0, "Got a null buffer when reallocating a string");
01274 if (!fUnicodeBuffer)
01275 {
01276 return false;
01277 }
01278 memset(fUnicodeBuffer,0,realLength*sizeof(CATWChar));
01279 fBufferLength = realLength;
01280
01281
01282 CopyIn(tmpBuf);
01283
01284
01285 delete [] tmpBuf;
01286
01287 fStrLen = (CATUInt32)(wcslen(fUnicodeBuffer));
01288 fLenDirty = false;
01289 return true;
01290 }
01291
01292
01293 void CATString::CopyIn(const CATWChar* str)
01294 {
01295 if (str == 0)
01296 {
01297 if (fUnicodeBuffer)
01298 {
01299 fUnicodeBuffer[0] = 0;
01300 }
01301 return;
01302 }
01303
01304 CATUInt32 i = 0;
01305
01306 while ((str[i] != 0) && (i < fBufferLength - 1))
01307 {
01308 fUnicodeBuffer[i] = str[i];
01309 i++;
01310 }
01311
01312 fUnicodeBuffer[i] = 0;
01313
01314
01315 fLenDirty = true;
01316 }
01317
01318
01319
01320 bool CATString::IsEmpty() const
01321 {
01322
01323 if (this->fAsciiLocked)
01324 {
01325 if ((this->fBuffer == 0) || (this->fBuffer[0] == 0))
01326 {
01327 return true;
01328 }
01329
01330 return false;
01331 }
01332
01333 if ((this->fUnicodeBuffer == 0) || (fUnicodeBuffer[0] == 0))
01334 {
01335 return true;
01336 }
01337
01338 return false;
01339 }
01340
01341
01342 CATString& CATString::AppendHex(CATUInt32 hexValue, bool addX)
01343 {
01344
01345 if (addX)
01346 *this << L"0x";
01347
01348 for (CATUInt32 i = 0; i < 8; i++)
01349 {
01350 CATUInt32 shift = ((7 - i)*4);
01351 char nibble = (char)( ((hexValue & (0xf << shift)) >> shift) );
01352 if (nibble >= 0x0a)
01353 {
01354 nibble += 'A' - 0x0a;
01355 }
01356 else
01357 {
01358 nibble += '0';
01359 }
01360
01361 *this << nibble;
01362 }
01363 return *this;
01364 }
01365
01366
01367 CATString& CATString::AppendHexByte(CATUInt8 hexValue, bool addX)
01368 {
01369 if (addX)
01370 {
01371 *this << L"0x";
01372 }
01373 char nibble = (char)((hexValue & 0xf0) >> 4);
01374 if (nibble >= 0x0a)
01375 {
01376 nibble += 'A' - 0x0a;
01377 }
01378 else
01379 {
01380 nibble += '0';
01381 }
01382
01383 *this << nibble;
01384
01385 nibble = (char)(hexValue & 0xf);
01386 if (nibble >= 0x0a)
01387 {
01388 nibble += 'A' - 0x0a;
01389 }
01390 else
01391 {
01392 nibble += '0';
01393 }
01394
01395 *this << nibble;
01396
01397 return *this;
01398 }
01399
01400
01401 CATString& CATString::operator<<(const CATString& str)
01402 {
01403
01404 *this += str;
01405 return *this;
01406 }
01407
01408
01409 CATString& CATString::operator<<(const char* str)
01410 {
01411 *this += str;
01412 return *this;
01413 }
01414
01415
01416
01417 CATString& CATString::operator<<(const CATWChar* str)
01418 {
01419 *this += str;
01420 return *this;
01421 }
01422
01423
01424
01425 CATString& CATString::operator<<(char strChar)
01426 {
01427 char tmpBuf[2];
01428 tmpBuf[1] = 0;
01429 tmpBuf[0] = strChar;
01430 *this += tmpBuf;
01431 return *this;
01432 }
01433
01434
01435 CATString& CATString::operator<<(CATWChar strChar)
01436 {
01437 CATWChar tmpBuf[2];
01438 tmpBuf[1] = 0;
01439 tmpBuf[0] = strChar;
01440 *this += tmpBuf;
01441 return *this;
01442 }
01443
01444
01445 CATString& CATString::operator<<(CATUInt32 val)
01446 {
01447 CATWChar tmpBuf[32];
01448 swprintf(tmpBuf,32,L"%u",val);
01449 *this += tmpBuf;
01450 return *this;
01451 }
01452
01453
01454 CATString& CATString::operator<<(CATInt32 val)
01455 {
01456 CATWChar tmpBuf[32];
01457 swprintf(tmpBuf,32,L"%d",val);
01458 *this += tmpBuf;
01459 return *this;
01460 }
01461
01462
01463 CATString& CATString::operator<<(CATFloat32 val)
01464 {
01465 CATWChar tmpBuf[256];
01466 swprintf(tmpBuf,256,L"%.5f",val);
01467
01468 CATInt32 lastByte = (CATInt32)(wcslen(tmpBuf) - 1);
01469 while ((lastByte > 0) && (tmpBuf[lastByte] == '0') && (tmpBuf[lastByte - 1] != '.'))
01470 {
01471 tmpBuf[lastByte] = 0;
01472 lastByte--;
01473 }
01474
01475 *this += tmpBuf;
01476 return *this;
01477 }
01478
01479
01480 CATString& CATString::operator<<(CATFloat64 val)
01481 {
01482 CATWChar tmpBuf[512];
01483 swprintf(tmpBuf,512,L"%.5f",val);
01484
01485 CATInt32 lastByte = (CATInt32)(wcslen(tmpBuf) - 1);
01486 while ((lastByte > 0) && (tmpBuf[lastByte] == '0') && (tmpBuf[lastByte - 1] != '.'))
01487 {
01488 tmpBuf[lastByte] = 0;
01489 lastByte--;
01490 }
01491
01492 *this += tmpBuf;
01493 return *this;
01494 }
01495
01496 CATString& CATString::operator<<(const GUID& guid)
01497 {
01498 CATWChar tmpBuf[512];
01499 swprintf(tmpBuf,512,L"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
01500 guid.Data1, guid.Data2,guid.Data3,
01501 guid.Data4[0],
01502 guid.Data4[1],
01503 guid.Data4[2],
01504 guid.Data4[3],
01505 guid.Data4[4],
01506 guid.Data4[5],
01507 guid.Data4[6],
01508 guid.Data4[7]
01509 );
01510 *this += tmpBuf;
01511 return *this;
01512 }
01513
01514 CATString& CATString::operator<<(const GUID* guid)
01515 {
01516 *this << *guid;
01517 return *this;
01518 }
01519
01520 CATWChar CATString::GetWChar(CATUInt32 offset) const
01521 {
01522 CATASSERT( (!fUnicodeLocked) && (!fAsciiLocked), "Unlock the string before playing with it.");
01523 CATASSERT( offset < fBufferLength, "Offset is invalid.");
01524
01525 if (offset >= fBufferLength)
01526 {
01527 return 0;
01528 }
01529
01530 if (offset > GetLength(fUnicodeBuffer))
01531 {
01532 return 0;
01533 }
01534
01535
01536 return fUnicodeBuffer[offset];
01537 }
01538
01539
01540 bool CATString::SetWChar(CATUInt32 offset, CATWChar theChar)
01541 {
01542 CATASSERT( (!fUnicodeLocked) && (!fAsciiLocked), "Unlock the string before playing with it.");
01543 if (fUnicodeLocked || fAsciiLocked)
01544 {
01545 return false;
01546 }
01547
01548 CATASSERT( offset < fBufferLength, "Offset is invalid.");
01549 if (offset >= fBufferLength)
01550 {
01551 return false;
01552 }
01553
01554 fUnicodeBuffer[offset] = theChar;
01555
01556 return true;
01557 }
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587 bool CATString::PullNextToken(CATString& token, const CATString& splitTokens)
01588 {
01589 CATASSERT((fAsciiLocked == false),
01590 "Not supporting locked or dirty strings for searches currently");
01591 this->Trim();
01592
01593 for (CATUInt32 i=0; i<this->fStrLen; i++)
01594 {
01595 for (CATUInt32 tIndex = 0; tIndex < splitTokens.LengthCalc(); tIndex++)
01596 {
01597 if (fUnicodeBuffer[i] == splitTokens.GetWChar(tIndex))
01598 {
01599
01600 token = this->Left(i);
01601 *this = this->Right(i+1);
01602 token.Trim();
01603 this->Trim();
01604 return true;
01605 }
01606 }
01607 }
01608
01609
01610 token = *this;
01611 token.Trim();
01612 *this = L"";
01613 return false;
01614 }
01615
01616
01617 void CATString::Pad(CATUInt32 length, CATWChar theChar)
01618 {
01619 CATUInt32 curLen = this->Length();
01620
01621 if (curLen >= length)
01622 return;
01623
01624 CATWChar* buffer = this->GetUnicodeBuffer(length+1);
01625 for (CATUInt32 i = curLen; i < length; i++)
01626 {
01627 buffer[i] = theChar;
01628 }
01629 buffer[length] = 0;
01630 this->ReleaseBuffer();
01631 }
01632
01633
01634 void CATString::Trim()
01635 {
01636 CATASSERT( (!fUnicodeLocked) && (!fAsciiLocked), "Unlock the string before playing with it.");
01637 CATUInt32 start = 0;
01638 CATUInt32 end = this->Length();
01639
01640
01641 bool done = false;
01642 while ( (!done) && (start <= end))
01643 {
01644 switch (fUnicodeBuffer[start])
01645 {
01646 case 0x0a:
01647 case 0x0d:
01648 case 0x20:
01649 case 0x00:
01650 case 0x09:
01651 start++;
01652 break;
01653 default:
01654 done = true;
01655 }
01656 }
01657
01658 done = false;
01659 while ( (!done) && (end >= start))
01660 {
01661 switch (fUnicodeBuffer[end])
01662 {
01663 case 0x0a:
01664 case 0x0d:
01665 case 0x20:
01666 case 0x00:
01667 case 0x09:
01668 end--;
01669 break;
01670 default:
01671 done = true;
01672 }
01673 }
01674
01675
01676 if ( end < start)
01677 {
01678 *this = L"";
01679 return;
01680 }
01681
01682
01683 *this = this->Sub(start, (end - start) + 1);
01684 }
01685
01686
01687
01688 CATUInt32 CATString::FromHex() const
01689 {
01690 CATUInt32 resultVal = 0;
01691 CATUInt32 start = 0;
01692
01693 CATUInt32 length = this->LengthCalc();
01694 if ( (length > 2) &&
01695 (this->GetWChar(0) == '0') &&
01696 ((this->GetWChar(1) | (char)0x20) == 'x'))
01697 {
01698 start = 2;
01699 }
01700
01701
01702 for (CATUInt32 i = start; i < length; i++)
01703 {
01704 resultVal = resultVal << 4;
01705 CATUInt8 curChar = (CATUInt8)this->GetWChar(i);
01706
01707 if ((curChar >= 'A') && (curChar <= 'F'))
01708 {
01709 resultVal |= ((curChar - 'A') + (CATUInt8)0x0a);
01710 }
01711 else if ((curChar >= 'a') && (curChar <= 'f'))
01712 {
01713 resultVal |= ((curChar - 'a') + (CATUInt8)0x0a);
01714 }
01715 else if ((curChar >= '0') && (curChar <= '9'))
01716 {
01717 resultVal |= (curChar - '0');
01718 }
01719 else
01720 {
01721 CATASSERT(false,"Invalid hex number.");
01722 return 0;
01723 }
01724 }
01725
01726 return resultVal;
01727 }
01728
01729
01730
01731 void CATString::ToUpper()
01732 {
01733 CATUInt32 length = this->Length();
01734 CATWChar* buffer = this->GetUnicodeBuffer();
01735 for (CATUInt32 i = 0; i < length; i++)
01736 {
01737 if ((buffer[i] >= 'a') && (buffer[i] <= 'z'))
01738 {
01739 buffer[i] &= ~((CATWChar)0x20);
01740 }
01741 }
01742 ReleaseBuffer();
01743 }
01744
01745
01746
01747 void CATString::ToLower()
01748 {
01749 CATUInt32 length = this->Length();
01750 CATWChar* buffer = this->GetUnicodeBuffer();
01751 for (CATUInt32 i = 0; i < length; i++)
01752 {
01753 if ((buffer[i] >= 'A') && (buffer[i] <= 'Z'))
01754 {
01755 buffer[i] |= (CATWChar)0x20;
01756 }
01757 }
01758 ReleaseBuffer();
01759 }
01760
01761
01762 const CATString& CATString::Format(const CATWChar* formatSpecs, ...)
01763 {
01764 va_list fmtArgs;
01765 va_start(fmtArgs, formatSpecs);
01766
01767 CATString testString;
01768 int testLen = 1024;
01769 CATWChar* testBuf = testString.GetUnicodeBuffer(testLen);
01770
01771
01772
01773
01774 int length = _vsnwprintf(testBuf,testLen - 1, formatSpecs,fmtArgs);
01775
01776 testString.ReleaseBuffer();
01777
01778 while (length == -1)
01779 {
01780 testLen *= 2;
01781 testBuf = testString.GetUnicodeBuffer(testLen);
01782 length = _vsnwprintf(testBuf,testLen - 1,formatSpecs,fmtArgs);
01783 testString.ReleaseBuffer();
01784 }
01785
01786 va_end(fmtArgs);
01787
01788 *this = testString;
01789 return *this;
01790 }
01791
01792
01793 const CATString& CATString::Format(const char* formatSpecs, ...)
01794 {
01795 va_list fmtArgs;
01796 va_start(fmtArgs, formatSpecs);
01797
01798 CATString testString;
01799 int testLen = 1024;
01800 char* testBuf = testString.GetAsciiBuffer(testLen);
01801
01802
01803
01804
01805 int length = vsnprintf(testBuf,testLen - 1,formatSpecs, fmtArgs);
01806
01807 testString.ReleaseBuffer();
01808
01809 while (length == -1)
01810 {
01811 testLen *= 2;
01812 testBuf = testString.GetAsciiBuffer(testLen + 1);
01813 length = vsnprintf(testBuf,testLen - 1,formatSpecs, fmtArgs );
01814 testString.ReleaseBuffer();
01815 }
01816
01817 va_end(fmtArgs);
01818
01819 *this = testString;
01820 return *this;
01821 }
01822
01823 const CATString& CATString::FormatArgs(const CATWChar* formatSpecs, va_list fmtArgs)
01824 {
01825 CATString testString;
01826 int testLen = 1024;
01827 CATWChar* testBuf = testString.GetUnicodeBuffer(testLen);
01828
01829
01830
01831
01832
01833 int length = _vsnwprintf(testBuf,testLen - 1, formatSpecs,fmtArgs);
01834 testString.ReleaseBuffer();
01835
01836 while (length == -1)
01837 {
01838 testLen *= 2;
01839 testBuf = testString.GetUnicodeBuffer(testLen);
01840 length = _vsnwprintf(testBuf,testLen - 1,formatSpecs,fmtArgs);
01841 testString.ReleaseBuffer();
01842 }
01843
01844 *this = testString;
01845 return *this;
01846 }
01847
01848
01849 const CATString& CATString::FormatArgs(const char* formatSpecs, va_list fmtArgs)
01850 {
01851 CATString testString;
01852 int testLen = 1024;
01853 char* testBuf = testString.GetAsciiBuffer(testLen);
01854
01855
01856
01857
01858 int length = vsnprintf(testBuf,testLen - 1,formatSpecs, fmtArgs);
01859
01860 testString.ReleaseBuffer();
01861
01862 while (length == -1)
01863 {
01864 testLen *= 2;
01865 testBuf = testString.GetAsciiBuffer(testLen);
01866 length = vsnprintf(testBuf,testLen,formatSpecs, fmtArgs );
01867 testString.ReleaseBuffer();
01868 }
01869
01870 *this = testString;
01871 return *this;
01872 }
01873
01874 CATUInt32 CATString::GetLength(const char* asciistr) const
01875 {
01876 return (CATUInt32)strlen(asciistr);
01877 }
01878
01879 CATUInt32 CATString::GetLength(const CATWChar* unistr) const
01880 {
01881 return (CATUInt32)wcslen(unistr);
01882 }
01883
01884 void CATString::CopyBuffer(char* str1, const char* str2, CATUInt32 length)
01885 {
01886 if (str1 == 0 || str2 == 0)
01887 {
01888 return;
01889 }
01890
01891 CATUInt32 i = 0;
01892 while ((str2[i] != 0) && (i < length))
01893 {
01894 str1[i] = str2[i];
01895 i++;
01896 }
01897
01898 str1[i] = 0;
01899 }
01900
01901
01902
01903 void CATString::CopyBuffer(CATWChar* str1, const CATWChar* str2, CATUInt32 length)
01904 {
01905 if (str1 == 0 || str2 == 0)
01906 {
01907 return;
01908 }
01909
01910 CATUInt32 i = 0;
01911 while ((str2[i] != 0) && (i < length))
01912 {
01913 str1[i] = str2[i];
01914 i++;
01915 }
01916
01917 str1[i] = 0;
01918 }
01919
01920 CATString CATString::Escape() const
01921 {
01922 CATString retString;
01923 CATUInt32 length = LengthCalc();
01924 CATUInt32 i;
01925
01926 for (i = 0; i < length; i++)
01927 {
01928 CATWChar curChar = GetWChar(i);
01929 switch (curChar)
01930 {
01931 case 0x0a:
01932 retString << "
";
01933 break;
01934 case 0x0d:
01935 retString << "
";
01936 break;
01937 case 0x09:
01938 retString << "	";
01939 break;
01940 case '-':
01941 if (i < length - 1)
01942 {
01943 if (GetWChar(i+1) == '-')
01944 {
01945 retString << "-";
01946 }
01947 else
01948 {
01949 retString << curChar;
01950 }
01951 }
01952 break;
01953 case '&':
01954 retString << "&";
01955 break;
01956 case '<':
01957 retString << "<";
01958 break;
01959 case '>':
01960 retString << ">";
01961 break;
01962 case '\"':
01963 retString << """;
01964 break;
01965 case '\'':
01966 retString << "'";
01967 break;
01968 default:
01969 retString << curChar;
01970 break;
01971 }
01972 }
01973
01974
01975 retString.SetCodePage(CP_UTF8);
01976 return retString;
01977 }
01978
01979
01980 bool CATString::GetGUID(GUID& guid) const
01981 {
01982 CATASSERT( (fAsciiLocked == false) || (fUnicodeLocked == false), "Either ascii or unicode should be unlocked...");
01983
01984 int numEntries = 0;
01985 GUID tmpGuid;
01986
01987 if (this->LengthCalc() < 35)
01988 return false;
01989
01990 int data0, data1,data2,data3,data4,data5,data6,data7;
01991
01992 if (this->fAsciiLocked)
01993 {
01994 if (fBuffer == 0)
01995 return 0;
01996
01997 numEntries = sscanf(fBuffer, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
01998 &tmpGuid.Data1,
01999 &tmpGuid.Data2,
02000 &tmpGuid.Data3,
02001 &data0,
02002 &data1,
02003 &data2,
02004 &data3,
02005 &data4,
02006 &data5,
02007 &data6,
02008 &data7);
02009
02010 if (numEntries != 11)
02011 {
02012 numEntries = sscanf(fBuffer, "%08X-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X",
02013 &tmpGuid.Data1,
02014 &tmpGuid.Data2,
02015 &tmpGuid.Data3,
02016 &data0,
02017 &data1,
02018 &data2,
02019 &data3,
02020 &data4,
02021 &data5,
02022 &data6,
02023 &data7);
02024 }
02025
02026 }
02027 else
02028 {
02029 if (fUnicodeBuffer == 0)
02030 return 0;
02031
02032 numEntries = swscanf(fUnicodeBuffer, L"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
02033 &tmpGuid.Data1,
02034 &tmpGuid.Data2,
02035 &tmpGuid.Data3,
02036 &data0,
02037 &data1,
02038 &data2,
02039 &data3,
02040 &data4,
02041 &data5,
02042 &data6,
02043 &data7);
02044
02045 if (numEntries != 11)
02046 {
02047 numEntries = swscanf(fUnicodeBuffer, L"%08X-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X",
02048 &tmpGuid.Data1,
02049 &tmpGuid.Data2,
02050 &tmpGuid.Data3,
02051 &data0,
02052 &data1,
02053 &data2,
02054 &data3,
02055 &data4,
02056 &data5,
02057 &data6,
02058 &data7);
02059 }
02060 }
02061
02062 if (numEntries == 11)
02063 {
02064 tmpGuid.Data4[0] = (BYTE)data0;
02065 tmpGuid.Data4[1] = (BYTE)data1;
02066 tmpGuid.Data4[2] = (BYTE)data2;
02067 tmpGuid.Data4[3] = (BYTE)data3;
02068 tmpGuid.Data4[4] = (BYTE)data4;
02069 tmpGuid.Data4[5] = (BYTE)data5;
02070 tmpGuid.Data4[6] = (BYTE)data6;
02071 tmpGuid.Data4[7] = (BYTE)data7;
02072
02073 guid = tmpGuid;
02074 return true;
02075 }
02076
02077 return false;
02078 }
02079
02080 bool CATString::SplitPath(CATString* drive, CATString* path, CATString* filename, CATString* ext) const
02081 {
02082 if (drive) *drive = L"";
02083 if (path) *path = L"";
02084 if (filename) *filename = L"";
02085 if (ext) *ext = L"";
02086
02087 CATUInt32 curPos = 0;
02088 CATUInt32 filePos = (CATUInt32)-1;
02089 CATUInt32 length = LengthCalc();
02090
02091 if (length == 0)
02092 return false;
02093
02094 if (length >= 2)
02095 {
02096 if (GetWChar(1) == CAT_DRIVESEPERATOR)
02097 {
02098 if (drive)
02099 (*drive) << GetWChar(0) << GetWChar(1);
02100
02101 curPos = 2;
02102 }
02103 }
02104
02105 CATUInt32 lastPath = (CATUInt32)-1;
02106 ReverseFind(CAT_PATHSEPERATOR,lastPath);
02107 CATUInt32 lastPath2 = (CATUInt32)-1;
02108 ReverseFind(CAT_OPTPATHSEPERATOR,lastPath2);
02109
02110 if (lastPath != (CATUInt32)-1)
02111 filePos = lastPath;
02112 if (lastPath2 != (CATUInt32)-1)
02113 {
02114 if (lastPath == -1)
02115 filePos = lastPath2;
02116 else if (lastPath2 > lastPath)
02117 filePos = lastPath2;
02118 }
02119
02120 if (filePos != -1)
02121 {
02122 if (path)
02123 (*path) = Sub(curPos,(filePos-curPos)+1);
02124
02125 curPos = filePos + 1;
02126 }
02127
02128 while (curPos < length)
02129 {
02130 if (GetWChar(curPos) != CAT_EXTSEPERATOR)
02131 {
02132 if (filename)
02133 (*filename) << GetWChar(curPos);
02134 }
02135 else
02136 {
02137 break;
02138 }
02139 curPos++;
02140 }
02141
02142 if ((curPos < length) && (GetWChar(curPos) == CAT_EXTSEPERATOR))
02143 {
02144 while (curPos < length)
02145 {
02146 if (ext)
02147 (*ext) << GetWChar(curPos);
02148 curPos++;
02149 }
02150 }
02151
02152
02153 if (path)
02154 {
02155 CATUInt32 pathLen = path->LengthCalc();
02156 for (CATUInt32 i = 0; i < pathLen; i++)
02157 {
02158 if ( path->GetWChar(i) == CAT_OPTPATHSEPERATOR)
02159 {
02160 path->SetWChar(i,CAT_PATHSEPERATOR);
02161 }
02162 }
02163 }
02164
02165
02166 return true;
02167 }
02168
02169 CATString CATString::GetDriveDirectory() const
02170 {
02171 CATString drive,directory;
02172 CATString path;
02173 if (this->SplitPath(&drive,&directory,0,0))
02174 {
02175 path << drive << directory;
02176 }
02177 return path;
02178 }
02179
02180 CATString CATString::GetFilenameExt() const
02181 {
02182 CATString filename,ext;
02183 CATString fullfile;
02184 if (this->SplitPath(0,0,&filename,&ext))
02185 {
02186 fullfile << filename << ext;
02187 }
02188 return fullfile;
02189 }
02190
02191 CATString CATString::GetFilenameNoExt() const
02192 {
02193 CATString filename;
02194 this->SplitPath(0,0,&filename,0);
02195 return filename;
02196 }
02197
02198
02199 CATString CATString::EncodeURL() const
02200 {
02201 CATString retString;
02202 CATUInt32 length = LengthCalc();
02203 CATUInt32 i;
02204
02205 for (i = 0; i < length; i++)
02206 {
02207 CATWChar curChar = GetWChar(i);
02208 if ((curChar >= 0x7f) || (curChar <= 0x20))
02209 {
02210
02211 retString << L"%";
02212 retString.AppendHexByte((CATUInt8)curChar,false);
02213 }
02214 else
02215 {
02216 switch (curChar)
02217 {
02218 case 0x22: case 0x23:
02219 case 0x24: case 0x25:
02220 case 0x26: case 0x2B:
02221 case 0x2C: case 0x2F:
02222 case 0x3A: case 0x3B:
02223 case 0x3C: case 0x3D:
02224 case 0x3E: case 0x3F:
02225 case 0x40: case 0x5B:
02226 case 0x5C: case 0x5D:
02227 case 0x5E: case 0x60:
02228 case 0x7B: case 0x7C:
02229 case 0x7D: case 0x7E:
02230 retString << L"%";
02231 retString.AppendHexByte((CATUInt8)curChar,false);
02232 break;
02233 default:
02234 retString << curChar;
02235 break;
02236 }
02237 }
02238 }
02239 return retString;
02240 }
02241
02242
02243 CATString CATString::DecodeURL() const
02244 {
02245 CATString retString;
02246 CATUInt32 length = LengthCalc();
02247 CATUInt32 i;
02248
02249 for (i = 0; i < length; i++)
02250 {
02251 CATWChar curChar = GetWChar(i);
02252 if (curChar == '%')
02253 {
02254 if (i < (length-2))
02255 {
02256 CATString hexByte;
02257 hexByte << GetWChar(i+1) << GetWChar(i+2);
02258 retString << (char)hexByte.FromHex();
02259 }
02260 i+=2;
02261 }
02262 else
02263 {
02264 retString << curChar;
02265 }
02266 }
02267 return retString;
02268 }
02269