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