tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MyString.cpp (33232B)


      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