Home | History | Annotate | Download | only in Common
      1 // Common/String.h
      2 
      3 #ifndef __COMMON_STRING_H
      4 #define __COMMON_STRING_H
      5 
      6 #include <string.h>
      7 
      8 #ifndef _WIN32
      9 #include <wctype.h>
     10 #include <wchar.h>
     11 #endif
     12 
     13 #include "MyWindows.h"
     14 #include "MyTypes.h"
     15 #include "MyVector.h"
     16 
     17 #ifdef _WIN32
     18 #define IS_PATH_SEPAR(c) ((c) == '\\' || (c) == '/')
     19 #else
     20 #define IS_PATH_SEPAR(c) ((c) == CHAR_PATH_SEPARATOR)
     21 #endif
     22 
     23 inline bool IsPathSepar(char    c) { return IS_PATH_SEPAR(c); }
     24 inline bool IsPathSepar(wchar_t c) { return IS_PATH_SEPAR(c); }
     25 
     26 inline unsigned MyStringLen(const char *s)
     27 {
     28   unsigned i;
     29   for (i = 0; s[i] != 0; i++);
     30   return i;
     31 }
     32 
     33 inline void MyStringCopy(char *dest, const char *src)
     34 {
     35   while ((*dest++ = *src++) != 0);
     36 }
     37 
     38 inline char *MyStpCpy(char *dest, const char *src)
     39 {
     40   for (;;)
     41   {
     42     char c = *src;
     43     *dest = c;
     44     if (c == 0)
     45       return dest;
     46     src++;
     47     dest++;
     48   }
     49 }
     50 
     51 inline unsigned MyStringLen(const wchar_t *s)
     52 {
     53   unsigned i;
     54   for (i = 0; s[i] != 0; i++);
     55   return i;
     56 }
     57 
     58 inline void MyStringCopy(wchar_t *dest, const wchar_t *src)
     59 {
     60   while ((*dest++ = *src++) != 0);
     61 }
     62 
     63 /*
     64 inline wchar_t *MyWcpCpy(wchar_t *dest, const wchar_t *src)
     65 {
     66   for (;;)
     67   {
     68     wchar_t c = *src;
     69     *dest = c;
     70     if (c == 0)
     71       return dest;
     72     src++;
     73     dest++;
     74   }
     75 }
     76 */
     77 
     78 int FindCharPosInString(const char *s, char c) throw();
     79 int FindCharPosInString(const wchar_t *s, wchar_t c) throw();
     80 
     81 #ifdef _WIN32
     82   #ifndef _UNICODE
     83     #define STRING_UNICODE_THROW
     84   #endif
     85 #endif
     86 
     87 #ifndef STRING_UNICODE_THROW
     88   #define STRING_UNICODE_THROW throw()
     89 #endif
     90 
     91 /*
     92 inline char MyCharUpper_Ascii(char c)
     93 {
     94   if (c >= 'a' && c <= 'z')
     95     return (char)(c - 0x20);
     96   return c;
     97 }
     98 inline wchar_t MyCharUpper_Ascii(wchar_t c)
     99 {
    100   if (c >= 'a' && c <= 'z')
    101     return (wchar_t)(c - 0x20);
    102   return c;
    103 }
    104 */
    105 
    106 inline char MyCharLower_Ascii(char c)
    107 {
    108   if (c >= 'A' && c <= 'Z')
    109     return (char)((unsigned char)c + 0x20);
    110   return c;
    111 }
    112 
    113 inline wchar_t MyCharLower_Ascii(wchar_t c)
    114 {
    115   if (c >= 'A' && c <= 'Z')
    116     return (wchar_t)(c + 0x20);
    117   return c;
    118 }
    119 
    120 wchar_t MyCharUpper_WIN(wchar_t c) throw();
    121 
    122 inline wchar_t MyCharUpper(wchar_t c) throw()
    123 {
    124   if (c < 'a') return c;
    125   if (c <= 'z') return (wchar_t)(c - 0x20);
    126   if (c <= 0x7F) return c;
    127   #ifdef _WIN32
    128     #ifdef _UNICODE
    129       return (wchar_t)(unsigned)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c);
    130     #else
    131       return (wchar_t)MyCharUpper_WIN(c);
    132     #endif
    133   #else
    134     return (wchar_t)towupper(c);
    135   #endif
    136 }
    137 
    138 /*
    139 wchar_t MyCharLower_WIN(wchar_t c) throw();
    140 
    141 inline wchar_t MyCharLower(wchar_t c) throw()
    142 {
    143   if (c < 'A') return c;
    144   if (c <= 'Z') return (wchar_t)(c + 0x20);
    145   if (c <= 0x7F) return c;
    146   #ifdef _WIN32
    147     #ifdef _UNICODE
    148       return (wchar_t)(unsigned)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c);
    149     #else
    150       return (wchar_t)MyCharLower_WIN(c);
    151     #endif
    152   #else
    153     return (wchar_t)tolower(c);
    154   #endif
    155 }
    156 */
    157 
    158 // char *MyStringUpper(char *s) throw();
    159 // char *MyStringLower(char *s) throw();
    160 
    161 // void MyStringUpper_Ascii(wchar_t *s) throw();
    162 void MyStringLower_Ascii(char *s) throw();
    163 void MyStringLower_Ascii(wchar_t *s) throw();
    164 // wchar_t *MyStringUpper(wchar_t *s) STRING_UNICODE_THROW;
    165 // wchar_t *MyStringLower(wchar_t *s) STRING_UNICODE_THROW;
    166 
    167 bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw();
    168 
    169 bool IsString1PrefixedByString2(const char *s1, const char *s2) throw();
    170 bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw();
    171 bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw();
    172 
    173 int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw();
    174 // int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw();
    175 
    176 // ---------- ASCII ----------
    177 // char values in ASCII strings must be less then 128
    178 bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw();
    179 bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw();
    180 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw();
    181 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw();
    182 
    183 #define MY_STRING_DELETE(_p_) delete []_p_;
    184 // #define MY_STRING_DELETE(_p_) my_delete(_p_);
    185 
    186 class AString
    187 {
    188   char *_chars;
    189   unsigned _len;
    190   unsigned _limit;
    191 
    192   void MoveItems(unsigned dest, unsigned src)
    193   {
    194     memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(char));
    195   }
    196 
    197   void InsertSpace(unsigned &index, unsigned size);
    198 
    199   void ReAlloc(unsigned newLimit);
    200   void ReAlloc2(unsigned newLimit);
    201   void SetStartLen(unsigned len);
    202   void Grow_1();
    203   void Grow(unsigned n);
    204 
    205   // AString(unsigned num, const char *s);
    206   AString(unsigned num, const AString &s);
    207   AString(const AString &s, char c); // it's for String + char
    208   AString(const char *s1, unsigned num1, const char *s2, unsigned num2);
    209 
    210   friend AString operator+(const AString &s, char c) { return AString(s, c); } ;
    211   // friend AString operator+(char c, const AString &s); // is not supported
    212 
    213   friend AString operator+(const AString &s1, const AString &s2);
    214   friend AString operator+(const AString &s1, const char    *s2);
    215   friend AString operator+(const char    *s1, const AString &s2);
    216 
    217   // ---------- forbidden functions ----------
    218   AString &operator+=(wchar_t c);
    219   AString &operator=(wchar_t c);
    220   AString(wchar_t c);
    221   void Find(wchar_t c) const;
    222   void Find(wchar_t c, unsigned startIndex) const;
    223   void ReverseFind(wchar_t c) const;
    224   void InsertAtFront(wchar_t c);
    225   void RemoveChar(wchar_t ch);
    226   void Replace(wchar_t oldChar, wchar_t newChar);
    227 
    228 public:
    229   AString();
    230   AString(char c);
    231   AString(const char *s);
    232   AString(const AString &s);
    233   ~AString() { MY_STRING_DELETE(_chars); }
    234 
    235   unsigned Len() const { return _len; }
    236   bool IsEmpty() const { return _len == 0; }
    237   void Empty() { _len = 0; _chars[0] = 0; }
    238 
    239   operator const char *() const { return _chars; }
    240   const char *Ptr() const { return _chars; }
    241   const char *Ptr(unsigned pos) const { return _chars + pos; }
    242   const char *RightPtr(unsigned num) const { return _chars + _len - num; }
    243   char Back() const { return _chars[_len - 1]; }
    244 
    245   void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; }
    246 
    247   /* GetBuf(minLen): provides the buffer that can store
    248      at least (minLen) characters and additional null terminator.
    249      9.35: GetBuf doesn't preserve old characters and terminator */
    250   char *GetBuf(unsigned minLen)
    251   {
    252     if (minLen > _limit)
    253       ReAlloc2(minLen);
    254     return _chars;
    255   }
    256   char *GetBuf_SetEnd(unsigned minLen)
    257   {
    258     if (minLen > _limit)
    259       ReAlloc2(minLen);
    260     char *chars = _chars;
    261     chars[minLen] = 0;
    262     _len = minLen;
    263     return chars;
    264   }
    265 
    266   void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
    267   void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
    268   void ReleaseBuf_CalcLen(unsigned maxLen)
    269   {
    270     char *chars = _chars;
    271     chars[maxLen] = 0;
    272     _len = MyStringLen(chars);
    273   }
    274 
    275   AString &operator=(char c);
    276   AString &operator=(const char *s);
    277   AString &operator=(const AString &s);
    278   void SetFromWStr_if_Ascii(const wchar_t *s);
    279   // void SetFromBstr_if_Ascii(BSTR s);
    280 
    281   AString &operator+=(char c)
    282   {
    283     if (_limit == _len)
    284       Grow_1();
    285     unsigned len = _len;
    286     char *chars = _chars;
    287     chars[len++] = c;
    288     chars[len] = 0;
    289     _len = len;
    290     return *this;
    291   }
    292 
    293   void Add_Space();
    294   void Add_Space_if_NotEmpty();
    295   void Add_LF();
    296   void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); }
    297 
    298   AString &operator+=(const char *s);
    299   AString &operator+=(const AString &s);
    300   void AddAscii(const char *s) { operator+=(s); }
    301 
    302   void SetFrom(const char *s, unsigned len); // no check
    303   void SetFrom_CalcLen(const char *s, unsigned len);
    304   // void SetFromAscii(const char *s) { operator+=(s); }
    305 
    306   AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); }
    307   AString Left(unsigned count) const { return AString(count, *this); }
    308 
    309   // void MakeUpper() { MyStringUpper(_chars); }
    310   // void MakeLower() { MyStringLower(_chars); }
    311   void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
    312 
    313 
    314   bool IsEqualTo(const char *s) const { return strcmp(_chars, s) == 0; }
    315   bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }
    316   // int Compare(const char *s) const { return MyStringCompare(_chars, s); }
    317   // int Compare(const AString &s) const { return MyStringCompare(_chars, s._chars); }
    318   // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); }
    319   // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); }
    320   bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); }
    321   bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
    322 
    323   bool IsAscii() const
    324   {
    325     unsigned len = Len();
    326     const char *s = _chars;
    327     for (unsigned i = 0; i < len; i++)
    328       if ((unsigned char)s[i] >= 0x80)
    329         return false;
    330     return true;
    331   }
    332   int Find(char c) const { return FindCharPosInString(_chars, c); }
    333   int Find(char c, unsigned startIndex) const
    334   {
    335     int pos = FindCharPosInString(_chars + startIndex, c);
    336     return pos < 0 ? -1 : (int)startIndex + pos;
    337   }
    338 
    339   int ReverseFind(char c) const throw();
    340   int ReverseFind_Dot() const throw() { return ReverseFind('.'); }
    341   int ReverseFind_PathSepar() const throw();
    342 
    343   int Find(const char *s) const { return Find(s, 0); }
    344   int Find(const char *s, unsigned startIndex) const throw();
    345 
    346   void TrimLeft() throw();
    347   void TrimRight() throw();
    348   void Trim()
    349   {
    350     TrimRight();
    351     TrimLeft();
    352   }
    353 
    354   void InsertAtFront(char c);
    355   // void Insert(unsigned index, char c);
    356   void Insert(unsigned index, const char *s);
    357   void Insert(unsigned index, const AString &s);
    358 
    359   void RemoveChar(char ch) throw();
    360 
    361   void Replace(char oldChar, char newChar) throw();
    362   void Replace(const AString &oldString, const AString &newString);
    363 
    364   void Delete(unsigned index) throw();
    365   void Delete(unsigned index, unsigned count) throw();
    366   void DeleteFrontal(unsigned num) throw();
    367   void DeleteBack() { _chars[--_len] = 0; }
    368   void DeleteFrom(unsigned index)
    369   {
    370     if (index < _len)
    371     {
    372       _len = index;
    373       _chars[index] = 0;
    374     }
    375   }
    376 };
    377 
    378 bool operator<(const AString &s1, const AString &s2);
    379 bool operator>(const AString &s1, const AString &s2);
    380 
    381 /*
    382 bool operator==(const AString &s1, const AString &s2);
    383 bool operator==(const AString &s1, const char    *s2);
    384 bool operator==(const char    *s1, const AString &s2);
    385 
    386 bool operator!=(const AString &s1, const AString &s2);
    387 bool operator!=(const AString &s1, const char    *s2);
    388 bool operator!=(const char    *s1, const AString &s2);
    389 */
    390 
    391 inline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; }
    392 inline bool operator==(const AString &s1, const char    *s2) { return strcmp(s1, s2) == 0; }
    393 inline bool operator==(const char    *s1, const AString &s2) { return strcmp(s1, s2) == 0; }
    394 
    395 inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; }
    396 inline bool operator!=(const AString &s1, const char    *s2) { return strcmp(s1, s2) != 0; }
    397 inline bool operator!=(const char    *s1, const AString &s2) { return strcmp(s1, s2) != 0; }
    398 
    399 // ---------- forbidden functions ----------
    400 
    401 void operator==(char c1, const AString &s2);
    402 void operator==(const AString &s1, char c2);
    403 
    404 void operator+(char c, const AString &s); // this function can be OK, but we don't use it
    405 
    406 void operator+(const AString &s, int c);
    407 void operator+(const AString &s, unsigned c);
    408 void operator+(int c, const AString &s);
    409 void operator+(unsigned c, const AString &s);
    410 void operator-(const AString &s, int c);
    411 void operator-(const AString &s, unsigned c);
    412 
    413 
    414 class UString
    415 {
    416   wchar_t *_chars;
    417   unsigned _len;
    418   unsigned _limit;
    419 
    420   void MoveItems(unsigned dest, unsigned src)
    421   {
    422     memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(wchar_t));
    423   }
    424 
    425   void InsertSpace(unsigned index, unsigned size);
    426 
    427   void ReAlloc(unsigned newLimit);
    428   void ReAlloc2(unsigned newLimit);
    429   void SetStartLen(unsigned len);
    430   void Grow_1();
    431   void Grow(unsigned n);
    432 
    433   UString(unsigned num, const wchar_t *s); // for Mid
    434   UString(unsigned num, const UString &s); // for Left
    435   UString(const UString &s, wchar_t c); // it's for String + char
    436   UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2);
    437 
    438   friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); } ;
    439   // friend UString operator+(wchar_t c, const UString &s); // is not supported
    440 
    441   friend UString operator+(const UString &s1, const UString &s2);
    442   friend UString operator+(const UString &s1, const wchar_t *s2);
    443   friend UString operator+(const wchar_t *s1, const UString &s2);
    444 
    445   // ---------- forbidden functions ----------
    446 
    447   UString &operator+=(char c);
    448   UString &operator+=(unsigned char c);
    449   UString &operator=(char c);
    450   UString &operator=(unsigned char c);
    451   UString(char c);
    452   UString(unsigned char c);
    453   void Find(char c) const;
    454   void Find(unsigned char c) const;
    455   void Find(char c, unsigned startIndex) const;
    456   void Find(unsigned char c, unsigned startIndex) const;
    457   void ReverseFind(char c) const;
    458   void ReverseFind(unsigned char c) const;
    459   void InsertAtFront(char c);
    460   void InsertAtFront(unsigned char c);
    461   void RemoveChar(char ch);
    462   void RemoveChar(unsigned char ch);
    463   void Replace(char oldChar, char newChar);
    464   void Replace(unsigned char oldChar, unsigned char newChar);
    465 
    466 public:
    467   UString();
    468   UString(wchar_t c);
    469   UString(const wchar_t *s);
    470   UString(const UString &s);
    471   ~UString() { MY_STRING_DELETE(_chars); }
    472 
    473   unsigned Len() const { return _len; }
    474   bool IsEmpty() const { return _len == 0; }
    475   void Empty() { _len = 0; _chars[0] = 0; }
    476 
    477   operator const wchar_t *() const { return _chars; }
    478   const wchar_t *Ptr() const { return _chars; }
    479   const wchar_t *Ptr(unsigned pos) const { return _chars + pos; }
    480   const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; }
    481   wchar_t Back() const { return _chars[_len - 1]; }
    482 
    483   void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; }
    484 
    485   wchar_t *GetBuf(unsigned minLen)
    486   {
    487     if (minLen > _limit)
    488       ReAlloc2(minLen);
    489     return _chars;
    490   }
    491   wchar_t *GetBuf_SetEnd(unsigned minLen)
    492   {
    493     if (minLen > _limit)
    494       ReAlloc2(minLen);
    495     wchar_t *chars = _chars;
    496     chars[minLen] = 0;
    497     _len = minLen;
    498     return chars;
    499   }
    500 
    501   void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
    502   void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
    503   void ReleaseBuf_CalcLen(unsigned maxLen)
    504   {
    505     wchar_t *chars = _chars;
    506     chars[maxLen] = 0;
    507     _len = MyStringLen(chars);
    508   }
    509 
    510   UString &operator=(wchar_t c);
    511   UString &operator=(const wchar_t *s);
    512   UString &operator=(const UString &s);
    513   void SetFromBstr(BSTR s);
    514 
    515   UString &operator+=(wchar_t c)
    516   {
    517     if (_limit == _len)
    518       Grow_1();
    519     unsigned len = _len;
    520     wchar_t *chars = _chars;
    521     chars[len++] = c;
    522     chars[len] = 0;
    523     _len = len;
    524     return *this;
    525   }
    526 
    527   void Add_Space();
    528   void Add_Space_if_NotEmpty();
    529   void Add_LF();
    530   void Add_PathSepar() { operator+=(WCHAR_PATH_SEPARATOR); }
    531 
    532   UString &operator+=(const wchar_t *s);
    533   UString &operator+=(const UString &s);
    534 
    535   void SetFrom(const wchar_t *s, unsigned len); // no check
    536 
    537   void SetFromAscii(const char *s);
    538   void AddAscii(const char *s);
    539 
    540   UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); }
    541   UString Left(unsigned count) const { return UString(count, *this); }
    542 
    543   // void MakeUpper() { MyStringUpper(_chars); }
    544   // void MakeUpper() { MyStringUpper_Ascii(_chars); }
    545   // void MakeUpper_Ascii() { MyStringUpper_Ascii(_chars); }
    546   void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
    547 
    548   bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); }
    549   bool IsEqualTo_NoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); }
    550   bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }
    551   int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }
    552   // int Compare(const UString &s) const { return MyStringCompare(_chars, s._chars); }
    553   // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); }
    554   // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); }
    555   bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); }
    556   bool IsPrefixedBy_NoCase(const wchar_t *s) const { return IsString1PrefixedByString2_NoCase(_chars, s); }
    557   bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
    558 
    559   bool IsAscii() const
    560   {
    561     unsigned len = Len();
    562     const wchar_t *s = _chars;
    563     for (unsigned i = 0; i < len; i++)
    564       if (s[i] >= 0x80)
    565         return false;
    566     return true;
    567   }
    568   int Find(wchar_t c) const { return FindCharPosInString(_chars, c); }
    569   int Find(wchar_t c, unsigned startIndex) const
    570   {
    571     int pos = FindCharPosInString(_chars + startIndex, c);
    572     return pos < 0 ? -1 : (int)startIndex + pos;
    573   }
    574 
    575   int ReverseFind(wchar_t c) const throw();
    576   int ReverseFind_Dot() const throw() { return ReverseFind(L'.'); }
    577   int ReverseFind_PathSepar() const throw();
    578 
    579   int Find(const wchar_t *s) const { return Find(s, 0); }
    580   int Find(const wchar_t *s, unsigned startIndex) const throw();
    581 
    582   void TrimLeft() throw();
    583   void TrimRight() throw();
    584   void Trim()
    585   {
    586     TrimRight();
    587     TrimLeft();
    588   }
    589 
    590   void InsertAtFront(wchar_t c);
    591   // void Insert(unsigned index, wchar_t c);
    592   void Insert(unsigned index, const wchar_t *s);
    593   void Insert(unsigned index, const UString &s);
    594 
    595   void RemoveChar(wchar_t ch) throw();
    596 
    597   void Replace(wchar_t oldChar, wchar_t newChar) throw();
    598   void Replace(const UString &oldString, const UString &newString);
    599 
    600   void Delete(unsigned index) throw();
    601   void Delete(unsigned index, unsigned count) throw();
    602   void DeleteFrontal(unsigned num) throw();
    603   void DeleteBack() { _chars[--_len] = 0; }
    604   void DeleteFrom(unsigned index)
    605   {
    606     if (index < _len)
    607     {
    608       _len = index;
    609       _chars[index] = 0;
    610     }
    611   }
    612 };
    613 
    614 bool operator<(const UString &s1, const UString &s2);
    615 bool operator>(const UString &s1, const UString &s2);
    616 
    617 inline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; }
    618 inline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; }
    619 inline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; }
    620 
    621 inline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; }
    622 inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; }
    623 inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; }
    624 
    625 
    626 // ---------- forbidden functions ----------
    627 
    628 void operator==(wchar_t c1, const UString &s2);
    629 void operator==(const UString &s1, wchar_t c2);
    630 
    631 void operator+(wchar_t c, const UString &s); // this function can be OK, but we don't use it
    632 
    633 void operator+(const UString &s, char c);
    634 void operator+(const UString &s, unsigned char c);
    635 void operator+(char c, const UString &s);
    636 void operator+(unsigned char c, const UString &s);
    637 void operator-(const UString &s1, wchar_t c);
    638 
    639 #ifdef _WIN32
    640 // can we forbid these functions, if wchar_t is 32-bit ?
    641 void operator+(const UString &s, int c);
    642 void operator+(const UString &s, unsigned c);
    643 void operator+(int c, const UString &s);
    644 void operator+(unsigned c, const UString &s);
    645 void operator-(const UString &s1, int c);
    646 void operator-(const UString &s1, unsigned c);
    647 #endif
    648 
    649 
    650 
    651 
    652 
    653 
    654 
    655 class UString2
    656 {
    657   wchar_t *_chars;
    658   unsigned _len;
    659 
    660   void ReAlloc2(unsigned newLimit);
    661   void SetStartLen(unsigned len);
    662 
    663   // ---------- forbidden functions ----------
    664 
    665   UString2 &operator=(char c);
    666   UString2 &operator=(unsigned char c);
    667   UString2 &operator=(wchar_t c);
    668   UString2(char c);
    669   UString2(unsigned char c);
    670 
    671 public:
    672   UString2(): _chars(NULL), _len(0) {}
    673   // UString2(wchar_t c);
    674   UString2(const wchar_t *s);
    675   UString2(const UString2 &s);
    676   ~UString2() { if (_chars) MY_STRING_DELETE(_chars); }
    677 
    678   unsigned Len() const { return _len; }
    679   bool IsEmpty() const { return _len == 0; }
    680   // void Empty() { _len = 0; _chars[0] = 0; }
    681 
    682   // operator const wchar_t *() const { return _chars; }
    683   const wchar_t *GetRawPtr() const { return _chars; }
    684 
    685   wchar_t *GetBuf(unsigned minLen)
    686   {
    687     if (!_chars || minLen > _len)
    688       ReAlloc2(minLen);
    689     return _chars;
    690   }
    691   void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
    692 
    693   UString2 &operator=(const wchar_t *s);
    694   UString2 &operator=(const UString2 &s);
    695   void SetFromAscii(const char *s);
    696 };
    697 
    698 bool operator==(const UString2 &s1, const UString2 &s2);
    699 bool operator==(const UString2 &s1, const wchar_t *s2);
    700 bool operator==(const wchar_t *s1, const UString2 &s2);
    701 
    702 inline bool operator!=(const UString2 &s1, const UString2 &s2) { return !(s1 == s2); }
    703 inline bool operator!=(const UString2 &s1, const wchar_t *s2) { return !(s1 == s2); }
    704 inline bool operator!=(const wchar_t *s1, const UString2 &s2) { return !(s1 == s2); }
    705 
    706 
    707 // ---------- forbidden functions ----------
    708 
    709 void operator==(wchar_t c1, const UString2 &s2);
    710 void operator==(const UString2 &s1, wchar_t c2);
    711 bool operator<(const UString2 &s1, const UString2 &s2);
    712 bool operator>(const UString2 &s1, const UString2 &s2);
    713 
    714 void operator+(const UString2 &s1, const UString2 &s2);
    715 void operator+(const UString2 &s1, const wchar_t *s2);
    716 void operator+(const wchar_t *s1, const UString2 &s2);
    717 void operator+(wchar_t c, const UString2 &s);
    718 void operator+(const UString2 &s, wchar_t c);
    719 void operator+(const UString2 &s, char c);
    720 void operator+(const UString2 &s, unsigned char c);
    721 void operator+(char c, const UString2 &s);
    722 void operator+(unsigned char c, const UString2 &s);
    723 void operator-(const UString2 &s1, wchar_t c);
    724 
    725 
    726 
    727 
    728 
    729 
    730 typedef CObjectVector<AString> AStringVector;
    731 typedef CObjectVector<UString> UStringVector;
    732 
    733 #ifdef _UNICODE
    734   typedef UString CSysString;
    735 #else
    736   typedef AString CSysString;
    737 #endif
    738 
    739 typedef CObjectVector<CSysString> CSysStringVector;
    740 
    741 
    742 // ---------- FString ----------
    743 
    744 #ifdef _WIN32
    745   #define USE_UNICODE_FSTRING
    746 #endif
    747 
    748 #ifdef USE_UNICODE_FSTRING
    749 
    750   #define __FTEXT(quote) L##quote
    751 
    752   typedef wchar_t FChar;
    753   typedef UString FString;
    754 
    755   #define fs2us(_x_) (_x_)
    756   #define us2fs(_x_) (_x_)
    757   FString fas2fs(const AString &s);
    758   AString fs2fas(const FChar *s);
    759 
    760 #else
    761 
    762   #define __FTEXT(quote) quote
    763 
    764   typedef char FChar;
    765   typedef AString FString;
    766 
    767   UString fs2us(const FString &s);
    768   FString us2fs(const wchar_t *s);
    769   #define fas2fs(_x_) (_x_)
    770   #define fs2fas(_x_) (_x_)
    771 
    772 #endif
    773 
    774 #define FTEXT(quote) __FTEXT(quote)
    775 
    776 #define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR)
    777 #define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR)
    778 #define FCHAR_ANY_MASK FTEXT('*')
    779 #define FSTRING_ANY_MASK FTEXT("*")
    780 typedef const FChar *CFSTR;
    781 
    782 typedef CObjectVector<FString> FStringVector;
    783 
    784 #endif
    785