Home | History | Annotate | Download | only in Common
      1 // Common/MyString.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #ifdef _WIN32
      6 #include <wchar.h>
      7 #else
      8 #include <ctype.h>
      9 #endif
     10 
     11 #include "IntToString.h"
     12 
     13 #if !defined(_UNICODE) || !defined(USE_UNICODE_FSTRING)
     14 #include "StringConvert.h"
     15 #endif
     16 
     17 #include "MyString.h"
     18 
     19 #define MY_STRING_NEW(_T_, _size_) new _T_[_size_]
     20 // #define MY_STRING_NEW(_T_, _size_) ((_T_ *)my_new((size_t)(_size_) * sizeof(_T_)))
     21 
     22 /*
     23 inline const char* MyStringGetNextCharPointer(const char *p) throw()
     24 {
     25   #if defined(_WIN32) && !defined(UNDER_CE)
     26   return CharNextA(p);
     27   #else
     28   return p + 1;
     29   #endif
     30 }
     31 */
     32 
     33 #define MY_STRING_NEW_char(_size_) MY_STRING_NEW(char, _size_)
     34 #define MY_STRING_NEW_wchar_t(_size_) MY_STRING_NEW(wchar_t, _size_)
     35 
     36 
     37 int FindCharPosInString(const char *s, char c) throw()
     38 {
     39   for (const char *p = s;; p++)
     40   {
     41     if (*p == c)
     42       return (int)(p - s);
     43     if (*p == 0)
     44       return -1;
     45     // MyStringGetNextCharPointer(p);
     46   }
     47 }
     48 
     49 int FindCharPosInString(const wchar_t *s, wchar_t c) throw()
     50 {
     51   for (const wchar_t *p = s;; p++)
     52   {
     53     if (*p == c)
     54       return (int)(p - s);
     55     if (*p == 0)
     56       return -1;
     57   }
     58 }
     59 
     60 /*
     61 void MyStringUpper_Ascii(char *s) throw()
     62 {
     63   for (;;)
     64   {
     65     char c = *s;
     66     if (c == 0)
     67       return;
     68     *s++ = MyCharUpper_Ascii(c);
     69   }
     70 }
     71 
     72 void MyStringUpper_Ascii(wchar_t *s) throw()
     73 {
     74   for (;;)
     75   {
     76     wchar_t c = *s;
     77     if (c == 0)
     78       return;
     79     *s++ = MyCharUpper_Ascii(c);
     80   }
     81 }
     82 */
     83 
     84 void MyStringLower_Ascii(char *s) throw()
     85 {
     86   for (;;)
     87   {
     88     char c = *s;
     89     if (c == 0)
     90       return;
     91     *s++ = MyCharLower_Ascii(c);
     92   }
     93 }
     94 
     95 void MyStringLower_Ascii(wchar_t *s) throw()
     96 {
     97   for (;;)
     98   {
     99     wchar_t c = *s;
    100     if (c == 0)
    101       return;
    102     *s++ = MyCharLower_Ascii(c);
    103   }
    104 }
    105 
    106 #ifdef _WIN32
    107 
    108 #ifdef _UNICODE
    109 
    110 // wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }
    111 // wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }
    112 // for WinCE - FString - char
    113 // const char *MyStringGetPrevCharPointer(const char * /* base */, const char *p) { return p - 1; }
    114 
    115 #else
    116 
    117 // const char * MyStringGetPrevCharPointer(const char *base, const char *p) throw() { return CharPrevA(base, p); }
    118 // char * MyStringUpper(char *s) { return CharUpperA(s); }
    119 // char * MyStringLower(char *s) { return CharLowerA(s); }
    120 
    121 wchar_t MyCharUpper_WIN(wchar_t c) throw()
    122 {
    123   wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c);
    124   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
    125     return (wchar_t)(unsigned)(UINT_PTR)res;
    126   const int kBufSize = 4;
    127   char s[kBufSize + 1];
    128   int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0);
    129   if (numChars == 0 || numChars > kBufSize)
    130     return c;
    131   s[numChars] = 0;
    132   ::CharUpperA(s);
    133   ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
    134   return c;
    135 }
    136 
    137 /*
    138 wchar_t MyCharLower_WIN(wchar_t c)
    139 {
    140   wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c);
    141   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
    142     return (wchar_t)(unsigned)(UINT_PTR)res;
    143   const int kBufSize = 4;
    144   char s[kBufSize + 1];
    145   int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0);
    146   if (numChars == 0 || numChars > kBufSize)
    147     return c;
    148   s[numChars] = 0;
    149   ::CharLowerA(s);
    150   ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
    151   return c;
    152 }
    153 */
    154 
    155 /*
    156 wchar_t * MyStringUpper(wchar_t *s)
    157 {
    158   if (s == 0)
    159     return 0;
    160   wchar_t *res = CharUpperW(s);
    161   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
    162     return res;
    163   AString a = UnicodeStringToMultiByte(s);
    164   a.MakeUpper();
    165   MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
    166   return s;
    167 }
    168 */
    169 
    170 /*
    171 wchar_t * MyStringLower(wchar_t *s)
    172 {
    173   if (s == 0)
    174     return 0;
    175   wchar_t *res = CharLowerW(s);
    176   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
    177     return res;
    178   AString a = UnicodeStringToMultiByte(s);
    179   a.MakeLower();
    180   MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
    181   return s;
    182 }
    183 */
    184 
    185 #endif
    186 
    187 #endif
    188 
    189 bool IsString1PrefixedByString2(const char *s1, const char *s2) throw()
    190 {
    191   for (;;)
    192   {
    193     unsigned char c2 = (unsigned char)*s2++; if (c2 == 0) return true;
    194     unsigned char c1 = (unsigned char)*s1++; if (c1 != c2) return false;
    195   }
    196 }
    197 
    198 bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw()
    199 {
    200   for (;;)
    201   {
    202     wchar_t c1 = *s1++;
    203     wchar_t c2 = *s2++;
    204     if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false;
    205     if (c1 == 0) return true;
    206   }
    207 }
    208 
    209 // ---------- ASCII ----------
    210 
    211 bool AString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw()
    212 {
    213   const char *s1 = _chars;
    214   for (;;)
    215   {
    216     char c2 = *s++;
    217     if (c2 == 0)
    218       return true;
    219     char c1 = *s1++;
    220     if (MyCharLower_Ascii(c1) !=
    221         MyCharLower_Ascii(c2))
    222       return false;
    223   }
    224 }
    225 
    226 bool UString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw()
    227 {
    228   const wchar_t *s1 = _chars;
    229   for (;;)
    230   {
    231     char c2 = *s++;
    232     if (c2 == 0)
    233       return true;
    234     wchar_t c1 = *s1++;
    235     if (MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))
    236       return false;
    237   }
    238 }
    239 
    240 bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw()
    241 {
    242   for (;;)
    243   {
    244     unsigned char c = *a;
    245     if (c != *u)
    246       return false;
    247     if (c == 0)
    248       return true;
    249     a++;
    250     u++;
    251   }
    252 }
    253 
    254 bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw()
    255 {
    256   for (;;)
    257   {
    258     char c1 = *s1++;
    259     char c2 = *s2++;
    260     if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
    261       return false;
    262     if (c1 == 0)
    263       return true;
    264   }
    265 }
    266 
    267 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw()
    268 {
    269   for (;;)
    270   {
    271     wchar_t c1 = *s1++;
    272     wchar_t c2 = *s2++;
    273     if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
    274       return false;
    275     if (c1 == 0)
    276       return true;
    277   }
    278 }
    279 
    280 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw()
    281 {
    282   for (;;)
    283   {
    284     wchar_t c1 = *s1++;
    285     char c2 = *s2++;
    286     if (c1 != (unsigned char)c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)))
    287       return false;
    288     if (c1 == 0)
    289       return true;
    290   }
    291 }
    292 
    293 bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw()
    294 {
    295   for (;;)
    296   {
    297     wchar_t c2 = *s2++; if (c2 == 0) return true;
    298     wchar_t c1 = *s1++; if (c1 != c2) return false;
    299   }
    300 }
    301 
    302 bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw()
    303 {
    304   for (;;)
    305   {
    306     unsigned char c2 = (unsigned char)(*s2++); if (c2 == 0) return true;
    307     wchar_t c1 = *s1++; if (c1 != c2) return false;
    308   }
    309 }
    310 
    311 bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *s1, const char *s2) throw()
    312 {
    313   for (;;)
    314   {
    315     char c2 = *s2++; if (c2 == 0) return true;
    316     wchar_t c1 = *s1++;
    317     if (c1 != (unsigned char)c2 && MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))
    318       return false;
    319   }
    320 }
    321 
    322 bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw()
    323 {
    324   for (;;)
    325   {
    326     wchar_t c2 = *s2++; if (c2 == 0) return true;
    327     wchar_t c1 = *s1++;
    328     if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2))
    329       return false;
    330   }
    331 }
    332 
    333 // NTFS order: uses upper case
    334 int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw()
    335 {
    336   for (;;)
    337   {
    338     wchar_t c1 = *s1++;
    339     wchar_t c2 = *s2++;
    340     if (c1 != c2)
    341     {
    342       wchar_t u1 = MyCharUpper(c1);
    343       wchar_t u2 = MyCharUpper(c2);
    344       if (u1 < u2) return -1;
    345       if (u1 > u2) return 1;
    346     }
    347     if (c1 == 0) return 0;
    348   }
    349 }
    350 
    351 /*
    352 int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num)
    353 {
    354   for (; num != 0; num--)
    355   {
    356     wchar_t c1 = *s1++;
    357     wchar_t c2 = *s2++;
    358     if (c1 != c2)
    359     {
    360       wchar_t u1 = MyCharUpper(c1);
    361       wchar_t u2 = MyCharUpper(c2);
    362       if (u1 < u2) return -1;
    363       if (u1 > u2) return 1;
    364     }
    365     if (c1 == 0) return 0;
    366   }
    367   return 0;
    368 }
    369 */
    370 
    371 // ---------- AString ----------
    372 
    373 void AString::InsertSpace(unsigned &index, unsigned size)
    374 {
    375   Grow(size);
    376   MoveItems(index + size, index);
    377 }
    378 
    379 #define k_Alloc_Len_Limit 0x40000000
    380 
    381 void AString::ReAlloc(unsigned newLimit)
    382 {
    383   if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130220;
    384   // MY_STRING_REALLOC(_chars, char, newLimit + 1, _len + 1);
    385   char *newBuf = MY_STRING_NEW_char(newLimit + 1);
    386   memcpy(newBuf, _chars, (size_t)(_len + 1));
    387   MY_STRING_DELETE(_chars);
    388   _chars = newBuf;
    389   _limit = newLimit;
    390 }
    391 
    392 void AString::ReAlloc2(unsigned newLimit)
    393 {
    394   if (newLimit >= k_Alloc_Len_Limit) throw 20130220;
    395   // MY_STRING_REALLOC(_chars, char, newLimit + 1, 0);
    396   char *newBuf = MY_STRING_NEW_char(newLimit + 1);
    397   newBuf[0] = 0;
    398   MY_STRING_DELETE(_chars);
    399   _chars = newBuf;
    400   _limit = newLimit;
    401 }
    402 
    403 void AString::SetStartLen(unsigned len)
    404 {
    405   _chars = 0;
    406   _chars = MY_STRING_NEW_char(len + 1);
    407   _len = len;
    408   _limit = len;
    409 }
    410 
    411 void AString::Grow_1()
    412 {
    413   unsigned next = _len;
    414   next += next / 2;
    415   next += 16;
    416   next &= ~(unsigned)15;
    417   ReAlloc(next - 1);
    418 }
    419 
    420 void AString::Grow(unsigned n)
    421 {
    422   unsigned freeSize = _limit - _len;
    423   if (n <= freeSize)
    424     return;
    425 
    426   unsigned next = _len + n;
    427   next += next / 2;
    428   next += 16;
    429   next &= ~(unsigned)15;
    430   ReAlloc(next - 1);
    431 }
    432 
    433 AString::AString(unsigned num, const char *s)
    434 {
    435   unsigned len = MyStringLen(s);
    436   if (num > len)
    437     num = len;
    438   SetStartLen(num);
    439   memcpy(_chars, s, num);
    440   _chars[num] = 0;
    441 }
    442 
    443 AString::AString(unsigned num, const AString &s)
    444 {
    445   if (num > s._len)
    446     num = s._len;
    447   SetStartLen(num);
    448   memcpy(_chars, s._chars, num);
    449   _chars[num] = 0;
    450 }
    451 
    452 AString::AString(const AString &s, char c)
    453 {
    454   SetStartLen(s.Len() + 1);
    455   char *chars = _chars;
    456   unsigned len = s.Len();
    457   memcpy(chars, s, len);
    458   chars[len] = c;
    459   chars[(size_t)len + 1] = 0;
    460 }
    461 
    462 AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2)
    463 {
    464   SetStartLen(num1 + num2);
    465   char *chars = _chars;
    466   memcpy(chars, s1, num1);
    467   memcpy(chars + num1, s2, num2 + 1);
    468 }
    469 
    470 AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); }
    471 AString operator+(const AString &s1, const char    *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); }
    472 AString operator+(const char    *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); }
    473 
    474 static const unsigned kStartStringCapacity = 4;
    475 
    476 AString::AString()
    477 {
    478   _chars = 0;
    479   _chars = MY_STRING_NEW_char(kStartStringCapacity);
    480   _len = 0;
    481   _limit = kStartStringCapacity - 1;
    482   _chars[0] = 0;
    483 }
    484 
    485 AString::AString(char c)
    486 {
    487   SetStartLen(1);
    488   char *chars = _chars;
    489   chars[0] = c;
    490   chars[1] = 0;
    491 }
    492 
    493 AString::AString(const char *s)
    494 {
    495   SetStartLen(MyStringLen(s));
    496   MyStringCopy(_chars, s);
    497 }
    498 
    499 AString::AString(const AString &s)
    500 {
    501   SetStartLen(s._len);
    502   MyStringCopy(_chars, s._chars);
    503 }
    504 
    505 AString &AString::operator=(char c)
    506 {
    507   if (1 > _limit)
    508   {
    509     char *newBuf = MY_STRING_NEW_char(1 + 1);
    510     MY_STRING_DELETE(_chars);
    511     _chars = newBuf;
    512     _limit = 1;
    513   }
    514   _len = 1;
    515   char *chars = _chars;
    516   chars[0] = c;
    517   chars[1] = 0;
    518   return *this;
    519 }
    520 
    521 AString &AString::operator=(const char *s)
    522 {
    523   unsigned len = MyStringLen(s);
    524   if (len > _limit)
    525   {
    526     char *newBuf = MY_STRING_NEW_char(len + 1);
    527     MY_STRING_DELETE(_chars);
    528     _chars = newBuf;
    529     _limit = len;
    530   }
    531   _len = len;
    532   MyStringCopy(_chars, s);
    533   return *this;
    534 }
    535 
    536 AString &AString::operator=(const AString &s)
    537 {
    538   if (&s == this)
    539     return *this;
    540   unsigned len = s._len;
    541   if (len > _limit)
    542   {
    543     char *newBuf = MY_STRING_NEW_char(len + 1);
    544     MY_STRING_DELETE(_chars);
    545     _chars = newBuf;
    546     _limit = len;
    547   }
    548   _len = len;
    549   MyStringCopy(_chars, s._chars);
    550   return *this;
    551 }
    552 
    553 void AString::SetFromWStr_if_Ascii(const wchar_t *s)
    554 {
    555   unsigned len = 0;
    556   {
    557     for (;; len++)
    558     {
    559       wchar_t c = s[len];
    560       if (c == 0)
    561         break;
    562       if (c >= 0x80)
    563         return;
    564     }
    565   }
    566   if (len > _limit)
    567   {
    568     char *newBuf = MY_STRING_NEW_char(len + 1);
    569     MY_STRING_DELETE(_chars);
    570     _chars = newBuf;
    571     _limit = len;
    572   }
    573   _len = len;
    574   char *dest = _chars;
    575   unsigned i;
    576   for (i = 0; i < len; i++)
    577     dest[i] = (char)s[i];
    578   dest[i] = 0;
    579 }
    580 
    581 /*
    582 void AString::SetFromBstr_if_Ascii(BSTR s)
    583 {
    584   unsigned len = ::SysStringLen(s);
    585   {
    586     for (unsigned i = 0; i < len; i++)
    587       if (s[i] <= 0 || s[i] >= 0x80)
    588         return;
    589   }
    590   if (len > _limit)
    591   {
    592     char *newBuf = MY_STRING_NEW_char(len + 1);
    593     MY_STRING_DELETE(_chars);
    594     _chars = newBuf;
    595     _limit = len;
    596   }
    597   _len = len;
    598   char *dest = _chars;
    599   unsigned i;
    600   for (i = 0; i < len; i++)
    601     dest[i] = (char)s[i];
    602   dest[i] = 0;
    603 }
    604 */
    605 
    606 void AString::Add_Space() { operator+=(' '); }
    607 void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
    608 void AString::Add_LF() { operator+=('\n'); }
    609 
    610 AString &AString::operator+=(const char *s)
    611 {
    612   unsigned len = MyStringLen(s);
    613   Grow(len);
    614   MyStringCopy(_chars + _len, s);
    615   _len += len;
    616   return *this;
    617 }
    618 
    619 void AString::Add_OptSpaced(const char *s)
    620 {
    621   Add_Space_if_NotEmpty();
    622   (*this) += s;
    623 }
    624 
    625 AString &AString::operator+=(const AString &s)
    626 {
    627   Grow(s._len);
    628   MyStringCopy(_chars + _len, s._chars);
    629   _len += s._len;
    630   return *this;
    631 }
    632 
    633 void AString::Add_UInt32(UInt32 v)
    634 {
    635   char sz[16];
    636   ConvertUInt32ToString(v, sz);
    637   (*this) += sz;
    638 }
    639 
    640 void AString::SetFrom(const char *s, unsigned len) // no check
    641 {
    642   if (len > _limit)
    643   {
    644     char *newBuf = MY_STRING_NEW_char(len + 1);
    645     MY_STRING_DELETE(_chars);
    646     _chars = newBuf;
    647     _limit = len;
    648   }
    649   if (len != 0)
    650     memcpy(_chars, s, len);
    651   _chars[len] = 0;
    652   _len = len;
    653 }
    654 
    655 void AString::SetFrom_CalcLen(const char *s, unsigned len) // no check
    656 {
    657   unsigned i;
    658   for (i = 0; i < len; i++)
    659     if (s[i] == 0)
    660       break;
    661   SetFrom(s, i);
    662 }
    663 
    664 int AString::Find(const char *s, unsigned startIndex) const throw()
    665 {
    666   const char *fs = strstr(_chars + startIndex, s);
    667   if (!fs)
    668     return -1;
    669   return (int)(fs - _chars);
    670 
    671   /*
    672   if (s[0] == 0)
    673     return startIndex;
    674   unsigned len = MyStringLen(s);
    675   const char *p = _chars + startIndex;
    676   for (;; p++)
    677   {
    678     const char c = *p;
    679     if (c != s[0])
    680     {
    681       if (c == 0)
    682         return -1;
    683       continue;
    684     }
    685     unsigned i;
    686     for (i = 1; i < len; i++)
    687       if (p[i] != s[i])
    688         break;
    689     if (i == len)
    690       return (int)(p - _chars);
    691   }
    692   */
    693 }
    694 
    695 int AString::ReverseFind(char c) const throw()
    696 {
    697   if (_len == 0)
    698     return -1;
    699   const char *p = _chars + _len - 1;
    700   for (;;)
    701   {
    702     if (*p == c)
    703       return (int)(p - _chars);
    704     if (p == _chars)
    705       return -1;
    706     p--; // p = GetPrevCharPointer(_chars, p);
    707   }
    708 }
    709 
    710 int AString::ReverseFind_PathSepar() const throw()
    711 {
    712   if (_len == 0)
    713     return -1;
    714   const char *p = _chars + _len - 1;
    715   for (;;)
    716   {
    717     char c = *p;
    718     if (IS_PATH_SEPAR(c))
    719       return (int)(p - _chars);
    720     if (p == _chars)
    721       return -1;
    722     p--;
    723   }
    724 }
    725 
    726 void AString::TrimLeft() throw()
    727 {
    728   const char *p = _chars;
    729   for (;; p++)
    730   {
    731     char c = *p;
    732     if (c != ' ' && c != '\n' && c != '\t')
    733       break;
    734   }
    735   unsigned pos = (unsigned)(p - _chars);
    736   if (pos != 0)
    737   {
    738     MoveItems(0, pos);
    739     _len -= pos;
    740   }
    741 }
    742 
    743 void AString::TrimRight() throw()
    744 {
    745   const char *p = _chars;
    746   unsigned i;
    747   for (i = _len; i != 0; i--)
    748   {
    749     char c = p[(size_t)i - 1];
    750     if (c != ' ' && c != '\n' && c != '\t')
    751       break;
    752   }
    753   if (i != _len)
    754   {
    755     _chars[i] = 0;
    756     _len = i;
    757   }
    758 }
    759 
    760 void AString::InsertAtFront(char c)
    761 {
    762   if (_limit == _len)
    763     Grow_1();
    764   MoveItems(1, 0);
    765   _chars[0] = c;
    766   _len++;
    767 }
    768 
    769 /*
    770 void AString::Insert(unsigned index, char c)
    771 {
    772   InsertSpace(index, 1);
    773   _chars[index] = c;
    774   _len++;
    775 }
    776 */
    777 
    778 void AString::Insert(unsigned index, const char *s)
    779 {
    780   unsigned num = MyStringLen(s);
    781   if (num != 0)
    782   {
    783     InsertSpace(index, num);
    784     memcpy(_chars + index, s, num);
    785     _len += num;
    786   }
    787 }
    788 
    789 void AString::Insert(unsigned index, const AString &s)
    790 {
    791   unsigned num = s.Len();
    792   if (num != 0)
    793   {
    794     InsertSpace(index, num);
    795     memcpy(_chars + index, s, num);
    796     _len += num;
    797   }
    798 }
    799 
    800 void AString::RemoveChar(char ch) throw()
    801 {
    802   char *src = _chars;
    803 
    804   for (;;)
    805   {
    806     char c = *src++;
    807     if (c == 0)
    808       return;
    809     if (c == ch)
    810       break;
    811   }
    812 
    813   char *dest = src - 1;
    814 
    815   for (;;)
    816   {
    817     char c = *src++;
    818     if (c == 0)
    819       break;
    820     if (c != ch)
    821       *dest++ = c;
    822   }
    823 
    824   *dest = 0;
    825   _len = (unsigned)(dest - _chars);
    826 }
    827 
    828 // !!!!!!!!!!!!!!! test it if newChar = '\0'
    829 void AString::Replace(char oldChar, char newChar) throw()
    830 {
    831   if (oldChar == newChar)
    832     return; // 0;
    833   // unsigned number = 0;
    834   int pos = 0;
    835   char *chars = _chars;
    836   while ((unsigned)pos < _len)
    837   {
    838     pos = Find(oldChar, pos);
    839     if (pos < 0)
    840       break;
    841     chars[(unsigned)pos] = newChar;
    842     pos++;
    843     // number++;
    844   }
    845   return; //  number;
    846 }
    847 
    848 void AString::Replace(const AString &oldString, const AString &newString)
    849 {
    850   if (oldString.IsEmpty())
    851     return; // 0;
    852   if (oldString == newString)
    853     return; // 0;
    854   unsigned oldLen = oldString.Len();
    855   unsigned newLen = newString.Len();
    856   // unsigned number = 0;
    857   int pos = 0;
    858   while ((unsigned)pos < _len)
    859   {
    860     pos = Find(oldString, pos);
    861     if (pos < 0)
    862       break;
    863     Delete(pos, oldLen);
    864     Insert(pos, newString);
    865     pos += newLen;
    866     // number++;
    867   }
    868   // return number;
    869 }
    870 
    871 void AString::Delete(unsigned index) throw()
    872 {
    873   MoveItems(index, index + 1);
    874   _len--;
    875 }
    876 
    877 void AString::Delete(unsigned index, unsigned count) throw()
    878 {
    879   if (index + count > _len)
    880     count = _len - index;
    881   if (count > 0)
    882   {
    883     MoveItems(index, index + count);
    884     _len -= count;
    885   }
    886 }
    887 
    888 void AString::DeleteFrontal(unsigned num) throw()
    889 {
    890   if (num != 0)
    891   {
    892     MoveItems(0, num);
    893     _len -= num;
    894   }
    895 }
    896 
    897 /*
    898 AString operator+(const AString &s1, const AString &s2)
    899 {
    900   AString result(s1);
    901   result += s2;
    902   return result;
    903 }
    904 
    905 AString operator+(const AString &s, const char *chars)
    906 {
    907   AString result(s);
    908   result += chars;
    909   return result;
    910 }
    911 
    912 AString operator+(const char *chars, const AString &s)
    913 {
    914   AString result(chars);
    915   result += s;
    916   return result;
    917 }
    918 
    919 AString operator+(const AString &s, char c)
    920 {
    921   AString result(s);
    922   result += c;
    923   return result;
    924 }
    925 */
    926 
    927 /*
    928 AString operator+(char c, const AString &s)
    929 {
    930   AString result(c);
    931   result += s;
    932   return result;
    933 }
    934 */
    935 
    936 
    937 
    938 
    939 // ---------- UString ----------
    940 
    941 void UString::InsertSpace(unsigned index, unsigned size)
    942 {
    943   Grow(size);
    944   MoveItems(index + size, index);
    945 }
    946 
    947 void UString::ReAlloc(unsigned newLimit)
    948 {
    949   if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130221;
    950   // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, _len + 1);
    951   wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1);
    952   wmemcpy(newBuf, _chars, _len + 1);
    953   MY_STRING_DELETE(_chars);
    954   _chars = newBuf;
    955   _limit = newLimit;
    956 }
    957 
    958 void UString::ReAlloc2(unsigned newLimit)
    959 {
    960   if (newLimit >= k_Alloc_Len_Limit) throw 20130221;
    961   // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
    962   wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1);
    963   newBuf[0] = 0;
    964   MY_STRING_DELETE(_chars);
    965   _chars = newBuf;
    966   _limit = newLimit;
    967 }
    968 
    969 void UString::SetStartLen(unsigned len)
    970 {
    971   _chars = 0;
    972   _chars = MY_STRING_NEW_wchar_t(len + 1);
    973   _len = len;
    974   _limit = len;
    975 }
    976 
    977 void UString::Grow_1()
    978 {
    979   unsigned next = _len;
    980   next += next / 2;
    981   next += 16;
    982   next &= ~(unsigned)15;
    983   ReAlloc(next - 1);
    984 }
    985 
    986 void UString::Grow(unsigned n)
    987 {
    988   unsigned freeSize = _limit - _len;
    989   if (n <= freeSize)
    990     return;
    991 
    992   unsigned next = _len + n;
    993   next += next / 2;
    994   next += 16;
    995   next &= ~(unsigned)15;
    996   ReAlloc(next - 1);
    997 }
    998 
    999 
   1000 UString::UString(unsigned num, const wchar_t *s)
   1001 {
   1002   unsigned len = MyStringLen(s);
   1003   if (num > len)
   1004     num = len;
   1005   SetStartLen(num);
   1006   wmemcpy(_chars, s, num);
   1007   _chars[num] = 0;
   1008 }
   1009 
   1010 
   1011 UString::UString(unsigned num, const UString &s)
   1012 {
   1013   if (num > s._len)
   1014     num = s._len;
   1015   SetStartLen(num);
   1016   wmemcpy(_chars, s._chars, num);
   1017   _chars[num] = 0;
   1018 }
   1019 
   1020 UString::UString(const UString &s, wchar_t c)
   1021 {
   1022   SetStartLen(s.Len() + 1);
   1023   wchar_t *chars = _chars;
   1024   unsigned len = s.Len();
   1025   wmemcpy(chars, s, len);
   1026   chars[len] = c;
   1027   chars[(size_t)len + 1] = 0;
   1028 }
   1029 
   1030 UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2)
   1031 {
   1032   SetStartLen(num1 + num2);
   1033   wchar_t *chars = _chars;
   1034   wmemcpy(chars, s1, num1);
   1035   wmemcpy(chars + num1, s2, num2 + 1);
   1036 }
   1037 
   1038 UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); }
   1039 UString operator+(const UString &s1, const wchar_t *s2) { return UString(s1, s1.Len(), s2, MyStringLen(s2)); }
   1040 UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); }
   1041 
   1042 UString::UString()
   1043 {
   1044   _chars = 0;
   1045   _chars = MY_STRING_NEW_wchar_t(kStartStringCapacity);
   1046   _len = 0;
   1047   _limit = kStartStringCapacity - 1;
   1048   _chars[0] = 0;
   1049 }
   1050 
   1051 UString::UString(wchar_t c)
   1052 {
   1053   SetStartLen(1);
   1054   wchar_t *chars = _chars;
   1055   chars[0] = c;
   1056   chars[1] = 0;
   1057 }
   1058 
   1059 UString::UString(char c)
   1060 {
   1061   SetStartLen(1);
   1062   wchar_t *chars = _chars;
   1063   chars[0] = (unsigned char)c;
   1064   chars[1] = 0;
   1065 }
   1066 
   1067 UString::UString(const wchar_t *s)
   1068 {
   1069   unsigned len = MyStringLen(s);
   1070   SetStartLen(len);
   1071   wmemcpy(_chars, s, len + 1);
   1072 }
   1073 
   1074 UString::UString(const char *s)
   1075 {
   1076   unsigned len = MyStringLen(s);
   1077   SetStartLen(len);
   1078   wchar_t *chars = _chars;
   1079   for (unsigned i = 0; i < len; i++)
   1080     chars[i] = (unsigned char)s[i];
   1081   chars[len] = 0;
   1082 }
   1083 
   1084 UString::UString(const UString &s)
   1085 {
   1086   SetStartLen(s._len);
   1087   wmemcpy(_chars, s._chars, s._len + 1);
   1088 }
   1089 
   1090 UString &UString::operator=(wchar_t c)
   1091 {
   1092   if (1 > _limit)
   1093   {
   1094     wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);
   1095     MY_STRING_DELETE(_chars);
   1096     _chars = newBuf;
   1097     _limit = 1;
   1098   }
   1099   _len = 1;
   1100   wchar_t *chars = _chars;
   1101   chars[0] = c;
   1102   chars[1] = 0;
   1103   return *this;
   1104 }
   1105 
   1106 UString &UString::operator=(const wchar_t *s)
   1107 {
   1108   unsigned len = MyStringLen(s);
   1109   if (len > _limit)
   1110   {
   1111     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
   1112     MY_STRING_DELETE(_chars);
   1113     _chars = newBuf;
   1114     _limit = len;
   1115   }
   1116   _len = len;
   1117   wmemcpy(_chars, s, len + 1);
   1118   return *this;
   1119 }
   1120 
   1121 UString &UString::operator=(const UString &s)
   1122 {
   1123   if (&s == this)
   1124     return *this;
   1125   unsigned len = s._len;
   1126   if (len > _limit)
   1127   {
   1128     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
   1129     MY_STRING_DELETE(_chars);
   1130     _chars = newBuf;
   1131     _limit = len;
   1132   }
   1133   _len = len;
   1134   wmemcpy(_chars, s._chars, len + 1);
   1135   return *this;
   1136 }
   1137 
   1138 void UString::SetFrom(const wchar_t *s, unsigned len) // no check
   1139 {
   1140   if (len > _limit)
   1141   {
   1142     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
   1143     MY_STRING_DELETE(_chars);
   1144     _chars = newBuf;
   1145     _limit = len;
   1146   }
   1147   if (len != 0)
   1148     wmemcpy(_chars, s, len);
   1149   _chars[len] = 0;
   1150   _len = len;
   1151 }
   1152 
   1153 void UString::SetFromBstr(BSTR s)
   1154 {
   1155   unsigned len = ::SysStringLen(s);
   1156   if (len > _limit)
   1157   {
   1158     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
   1159     MY_STRING_DELETE(_chars);
   1160     _chars = newBuf;
   1161     _limit = len;
   1162   }
   1163   _len = len;
   1164   // if (s)
   1165     wmemcpy(_chars, s, len + 1);
   1166 }
   1167 
   1168 UString &UString::operator=(const char *s)
   1169 {
   1170   unsigned len = MyStringLen(s);
   1171   if (len > _limit)
   1172   {
   1173     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
   1174     MY_STRING_DELETE(_chars);
   1175     _chars = newBuf;
   1176     _limit = len;
   1177   }
   1178   wchar_t *chars = _chars;
   1179   for (unsigned i = 0; i < len; i++)
   1180     chars[i] = (unsigned char)s[i];
   1181   chars[len] = 0;
   1182   _len = len;
   1183   return *this;
   1184 }
   1185 
   1186 void UString::Add_Space() { operator+=(L' '); }
   1187 void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
   1188 
   1189 void UString::Add_LF()
   1190 {
   1191   if (_limit == _len)
   1192     Grow_1();
   1193   unsigned len = _len;
   1194   wchar_t *chars = _chars;
   1195   chars[len++] = L'\n';
   1196   chars[len] = 0;
   1197   _len = len;
   1198 }
   1199 
   1200 UString &UString::operator+=(const wchar_t *s)
   1201 {
   1202   unsigned len = MyStringLen(s);
   1203   Grow(len);
   1204   wmemcpy(_chars + _len, s, len + 1);
   1205   _len += len;
   1206   return *this;
   1207 }
   1208 
   1209 UString &UString::operator+=(const UString &s)
   1210 {
   1211   Grow(s._len);
   1212   wmemcpy(_chars + _len, s._chars, s._len + 1);
   1213   _len += s._len;
   1214   return *this;
   1215 }
   1216 
   1217 UString &UString::operator+=(const char *s)
   1218 {
   1219   unsigned len = MyStringLen(s);
   1220   Grow(len);
   1221   wchar_t *chars = _chars + _len;
   1222   for (unsigned i = 0; i < len; i++)
   1223     chars[i] = (unsigned char)s[i];
   1224   chars[len] = 0;
   1225   _len += len;
   1226   return *this;
   1227 }
   1228 
   1229 
   1230 void UString::Add_UInt32(UInt32 v)
   1231 {
   1232   char sz[16];
   1233   ConvertUInt32ToString(v, sz);
   1234   (*this) += sz;
   1235 }
   1236 
   1237 
   1238 int UString::Find(const wchar_t *s, unsigned startIndex) const throw()
   1239 {
   1240   const wchar_t *fs = wcsstr(_chars + startIndex, s);
   1241   if (!fs)
   1242     return -1;
   1243   return (int)(fs - _chars);
   1244 
   1245   /*
   1246   if (s[0] == 0)
   1247     return startIndex;
   1248   unsigned len = MyStringLen(s);
   1249   const wchar_t *p = _chars + startIndex;
   1250   for (;; p++)
   1251   {
   1252     const wchar_t c = *p;
   1253     if (c != s[0])
   1254     {
   1255       if (c == 0)
   1256         return -1;
   1257       continue;
   1258     }
   1259     unsigned i;
   1260     for (i = 1; i < len; i++)
   1261       if (p[i] != s[i])
   1262         break;
   1263     if (i == len)
   1264       return (int)(p - _chars);
   1265   }
   1266   */
   1267 }
   1268 
   1269 int UString::ReverseFind(wchar_t c) const throw()
   1270 {
   1271   if (_len == 0)
   1272     return -1;
   1273   const wchar_t *p = _chars + _len - 1;
   1274   for (;;)
   1275   {
   1276     if (*p == c)
   1277       return (int)(p - _chars);
   1278     if (p == _chars)
   1279       return -1;
   1280     p--;
   1281   }
   1282 }
   1283 
   1284 int UString::ReverseFind_PathSepar() const throw()
   1285 {
   1286   if (_len == 0)
   1287     return -1;
   1288   const wchar_t *p = _chars + _len - 1;
   1289   for (;;)
   1290   {
   1291     wchar_t c = *p;
   1292     if (IS_PATH_SEPAR(c))
   1293       return (int)(p - _chars);
   1294     if (p == _chars)
   1295       return -1;
   1296     p--;
   1297   }
   1298 }
   1299 
   1300 void UString::TrimLeft() throw()
   1301 {
   1302   const wchar_t *p = _chars;
   1303   for (;; p++)
   1304   {
   1305     wchar_t c = *p;
   1306     if (c != ' ' && c != '\n' && c != '\t')
   1307       break;
   1308   }
   1309   unsigned pos = (unsigned)(p - _chars);
   1310   if (pos != 0)
   1311   {
   1312     MoveItems(0, pos);
   1313     _len -= pos;
   1314   }
   1315 }
   1316 
   1317 void UString::TrimRight() throw()
   1318 {
   1319   const wchar_t *p = _chars;
   1320   unsigned i;
   1321   for (i = _len; i != 0; i--)
   1322   {
   1323     wchar_t c = p[(size_t)i - 1];
   1324     if (c != ' ' && c != '\n' && c != '\t')
   1325       break;
   1326   }
   1327   if (i != _len)
   1328   {
   1329     _chars[i] = 0;
   1330     _len = i;
   1331   }
   1332 }
   1333 
   1334 void UString::InsertAtFront(wchar_t c)
   1335 {
   1336   if (_limit == _len)
   1337     Grow_1();
   1338   MoveItems(1, 0);
   1339   _chars[0] = c;
   1340   _len++;
   1341 }
   1342 
   1343 /*
   1344 void UString::Insert(unsigned index, wchar_t c)
   1345 {
   1346   InsertSpace(index, 1);
   1347   _chars[index] = c;
   1348   _len++;
   1349 }
   1350 */
   1351 
   1352 void UString::Insert(unsigned index, const wchar_t *s)
   1353 {
   1354   unsigned num = MyStringLen(s);
   1355   if (num != 0)
   1356   {
   1357     InsertSpace(index, num);
   1358     wmemcpy(_chars + index, s, num);
   1359     _len += num;
   1360   }
   1361 }
   1362 
   1363 void UString::Insert(unsigned index, const UString &s)
   1364 {
   1365   unsigned num = s.Len();
   1366   if (num != 0)
   1367   {
   1368     InsertSpace(index, num);
   1369     wmemcpy(_chars + index, s, num);
   1370     _len += num;
   1371   }
   1372 }
   1373 
   1374 void UString::RemoveChar(wchar_t ch) throw()
   1375 {
   1376   wchar_t *src = _chars;
   1377 
   1378   for (;;)
   1379   {
   1380     wchar_t c = *src++;
   1381     if (c == 0)
   1382       return;
   1383     if (c == ch)
   1384       break;
   1385   }
   1386 
   1387   wchar_t *dest = src - 1;
   1388 
   1389   for (;;)
   1390   {
   1391     wchar_t c = *src++;
   1392     if (c == 0)
   1393       break;
   1394     if (c != ch)
   1395       *dest++ = c;
   1396   }
   1397 
   1398   *dest = 0;
   1399   _len = (unsigned)(dest - _chars);
   1400 }
   1401 
   1402 // !!!!!!!!!!!!!!! test it if newChar = '\0'
   1403 void UString::Replace(wchar_t oldChar, wchar_t newChar) throw()
   1404 {
   1405   if (oldChar == newChar)
   1406     return; // 0;
   1407   // unsigned number = 0;
   1408   int pos = 0;
   1409   wchar_t *chars = _chars;
   1410   while ((unsigned)pos < _len)
   1411   {
   1412     pos = Find(oldChar, pos);
   1413     if (pos < 0)
   1414       break;
   1415     chars[(unsigned)pos] = newChar;
   1416     pos++;
   1417     // number++;
   1418   }
   1419   return; //  number;
   1420 }
   1421 
   1422 void UString::Replace(const UString &oldString, const UString &newString)
   1423 {
   1424   if (oldString.IsEmpty())
   1425     return; // 0;
   1426   if (oldString == newString)
   1427     return; // 0;
   1428   unsigned oldLen = oldString.Len();
   1429   unsigned newLen = newString.Len();
   1430   // unsigned number = 0;
   1431   int pos = 0;
   1432   while ((unsigned)pos < _len)
   1433   {
   1434     pos = Find(oldString, pos);
   1435     if (pos < 0)
   1436       break;
   1437     Delete(pos, oldLen);
   1438     Insert(pos, newString);
   1439     pos += newLen;
   1440     // number++;
   1441   }
   1442   // return number;
   1443 }
   1444 
   1445 void UString::Delete(unsigned index) throw()
   1446 {
   1447   MoveItems(index, index + 1);
   1448   _len--;
   1449 }
   1450 
   1451 void UString::Delete(unsigned index, unsigned count) throw()
   1452 {
   1453   if (index + count > _len)
   1454     count = _len - index;
   1455   if (count > 0)
   1456   {
   1457     MoveItems(index, index + count);
   1458     _len -= count;
   1459   }
   1460 }
   1461 
   1462 void UString::DeleteFrontal(unsigned num) throw()
   1463 {
   1464   if (num != 0)
   1465   {
   1466     MoveItems(0, num);
   1467     _len -= num;
   1468   }
   1469 }
   1470 
   1471 
   1472 // ---------- UString2 ----------
   1473 
   1474 void UString2::ReAlloc2(unsigned newLimit)
   1475 {
   1476   if (newLimit >= k_Alloc_Len_Limit) throw 20130221;
   1477   // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
   1478   _chars = MY_STRING_NEW_wchar_t(newLimit + 1);
   1479 }
   1480 
   1481 void UString2::SetStartLen(unsigned len)
   1482 {
   1483   _chars = 0;
   1484   _chars = MY_STRING_NEW_wchar_t(len + 1);
   1485   _len = len;
   1486 }
   1487 
   1488 
   1489 /*
   1490 UString2::UString2(wchar_t c)
   1491 {
   1492   SetStartLen(1);
   1493   wchar_t *chars = _chars;
   1494   chars[0] = c;
   1495   chars[1] = 0;
   1496 }
   1497 */
   1498 
   1499 UString2::UString2(const wchar_t *s)
   1500 {
   1501   unsigned len = MyStringLen(s);
   1502   SetStartLen(len);
   1503   wmemcpy(_chars, s, len + 1);
   1504 }
   1505 
   1506 UString2::UString2(const UString2 &s): _chars(NULL), _len(0)
   1507 {
   1508   if (s._chars)
   1509   {
   1510     SetStartLen(s._len);
   1511     wmemcpy(_chars, s._chars, s._len + 1);
   1512   }
   1513 }
   1514 
   1515 /*
   1516 UString2 &UString2::operator=(wchar_t c)
   1517 {
   1518   if (1 > _len)
   1519   {
   1520     wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);
   1521     if (_chars)
   1522       MY_STRING_DELETE(_chars);
   1523     _chars = newBuf;
   1524   }
   1525   _len = 1;
   1526   wchar_t *chars = _chars;
   1527   chars[0] = c;
   1528   chars[1] = 0;
   1529   return *this;
   1530 }
   1531 */
   1532 
   1533 UString2 &UString2::operator=(const wchar_t *s)
   1534 {
   1535   unsigned len = MyStringLen(s);
   1536   if (len > _len)
   1537   {
   1538     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
   1539     if (_chars)
   1540       MY_STRING_DELETE(_chars);
   1541     _chars = newBuf;
   1542   }
   1543   _len = len;
   1544   MyStringCopy(_chars, s);
   1545   return *this;
   1546 }
   1547 
   1548 void UString2::SetFromAscii(const char *s)
   1549 {
   1550   unsigned len = MyStringLen(s);
   1551   if (len > _len)
   1552   {
   1553     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
   1554     if (_chars)
   1555       MY_STRING_DELETE(_chars);
   1556     _chars = newBuf;
   1557   }
   1558   wchar_t *chars = _chars;
   1559   for (unsigned i = 0; i < len; i++)
   1560     chars[i] = (unsigned char)s[i];
   1561   chars[len] = 0;
   1562   _len = len;
   1563 }
   1564 
   1565 UString2 &UString2::operator=(const UString2 &s)
   1566 {
   1567   if (&s == this)
   1568     return *this;
   1569   unsigned len = s._len;
   1570   if (len > _len)
   1571   {
   1572     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
   1573     if (_chars)
   1574       MY_STRING_DELETE(_chars);
   1575     _chars = newBuf;
   1576   }
   1577   _len = len;
   1578   MyStringCopy(_chars, s._chars);
   1579   return *this;
   1580 }
   1581 
   1582 bool operator==(const UString2 &s1, const UString2 &s2)
   1583 {
   1584   return s1.Len() == s2.Len() && (s1.IsEmpty() || wcscmp(s1.GetRawPtr(), s2.GetRawPtr()) == 0);
   1585 }
   1586 
   1587 bool operator==(const UString2 &s1, const wchar_t *s2)
   1588 {
   1589   if (s1.IsEmpty())
   1590     return (*s2 == 0);
   1591   return wcscmp(s1.GetRawPtr(), s2) == 0;
   1592 }
   1593 
   1594 bool operator==(const wchar_t *s1, const UString2 &s2)
   1595 {
   1596   if (s2.IsEmpty())
   1597     return (*s1 == 0);
   1598   return wcscmp(s1, s2.GetRawPtr()) == 0;
   1599 }
   1600 
   1601 
   1602 
   1603 // ----------------------------------------
   1604 
   1605 /*
   1606 int MyStringCompareNoCase(const char *s1, const char *s2)
   1607 {
   1608   return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));
   1609 }
   1610 */
   1611 
   1612 static inline UINT GetCurrentCodePage()
   1613 {
   1614   #if defined(UNDER_CE) || !defined(_WIN32)
   1615   return CP_ACP;
   1616   #else
   1617   return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP;
   1618   #endif
   1619 }
   1620 
   1621 #ifdef USE_UNICODE_FSTRING
   1622 
   1623 #ifndef _UNICODE
   1624 
   1625 AString fs2fas(CFSTR s)
   1626 {
   1627   return UnicodeStringToMultiByte(s, GetCurrentCodePage());
   1628 }
   1629 
   1630 FString fas2fs(const char *s)
   1631 {
   1632   return MultiByteToUnicodeString(s, GetCurrentCodePage());
   1633 }
   1634 
   1635 FString fas2fs(const AString &s)
   1636 {
   1637   return MultiByteToUnicodeString(s, GetCurrentCodePage());
   1638 }
   1639 
   1640 #endif
   1641 
   1642 #else
   1643 
   1644 UString fs2us(const FChar *s)
   1645 {
   1646   return MultiByteToUnicodeString(s, GetCurrentCodePage());
   1647 }
   1648 
   1649 UString fs2us(const FString &s)
   1650 {
   1651   return MultiByteToUnicodeString(s, GetCurrentCodePage());
   1652 }
   1653 
   1654 FString us2fs(const wchar_t *s)
   1655 {
   1656   return UnicodeStringToMultiByte(s, GetCurrentCodePage());
   1657 }
   1658 
   1659 #endif
   1660