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