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 
FindCharPosInString(const char * s,char c)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 
FindCharPosInString(const wchar_t * s,wchar_t c)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 
MyStringLower_Ascii(char * s)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 
MyStringLower_Ascii(wchar_t * s)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 
MyCharUpper_WIN(wchar_t c)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 
IsString1PrefixedByString2(const char * s1,const char * s2)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 
StringsAreEqualNoCase(const wchar_t * s1,const wchar_t * s2)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 
IsPrefixedBy_Ascii_NoCase(const char * s) const211 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 
IsPrefixedBy_Ascii_NoCase(const char * s) const226 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 
StringsAreEqual_Ascii(const wchar_t * u,const char * a)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 
StringsAreEqualNoCase_Ascii(const char * s1,const char * s2)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 
StringsAreEqualNoCase_Ascii(const wchar_t * s1,const wchar_t * s2)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 
StringsAreEqualNoCase_Ascii(const wchar_t * s1,const char * s2)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 
IsString1PrefixedByString2(const wchar_t * s1,const wchar_t * s2)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 
IsString1PrefixedByString2(const wchar_t * s1,const char * s2)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 
IsString1PrefixedByString2_NoCase_Ascii(const wchar_t * s1,const char * s2)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 
IsString1PrefixedByString2_NoCase(const wchar_t * s1,const wchar_t * s2)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
MyStringCompareNoCase(const wchar_t * s1,const wchar_t * s2)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 
InsertSpace(unsigned & index,unsigned size)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 
ReAlloc(unsigned newLimit)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 
ReAlloc2(unsigned newLimit)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 
SetStartLen(unsigned len)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 
Grow_1()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 
Grow(unsigned n)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 
AString(unsigned num,const char * s)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 
AString(unsigned num,const AString & s)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 
AString(const AString & s,char c)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 
AString(const char * s1,unsigned num1,const char * s2,unsigned num2)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 
operator +(const AString & s1,const AString & s2)470 AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); }
operator +(const AString & s1,const char * s2)471 AString operator+(const AString &s1, const char    *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); }
operator +(const char * s1,const AString & 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 
AString()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 
AString(char c)485 AString::AString(char c)
486 {
487   SetStartLen(1);
488   char *chars = _chars;
489   chars[0] = c;
490   chars[1] = 0;
491 }
492 
AString(const char * s)493 AString::AString(const char *s)
494 {
495   SetStartLen(MyStringLen(s));
496   MyStringCopy(_chars, s);
497 }
498 
AString(const AString & s)499 AString::AString(const AString &s)
500 {
501   SetStartLen(s._len);
502   MyStringCopy(_chars, s._chars);
503 }
504 
operator =(char c)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 
operator =(const char * s)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 
operator =(const AString & s)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 
SetFromWStr_if_Ascii(const wchar_t * s)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 
Add_Space()606 void AString::Add_Space() { operator+=(' '); }
Add_Space_if_NotEmpty()607 void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
Add_LF()608 void AString::Add_LF() { operator+=('\n'); }
609 
operator +=(const char * s)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 
Add_OptSpaced(const char * s)619 void AString::Add_OptSpaced(const char *s)
620 {
621   Add_Space_if_NotEmpty();
622   (*this) += s;
623 }
624 
operator +=(const AString & s)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 
Add_UInt32(UInt32 v)633 void AString::Add_UInt32(UInt32 v)
634 {
635   char sz[16];
636   ConvertUInt32ToString(v, sz);
637   (*this) += sz;
638 }
639 
SetFrom(const char * s,unsigned len)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 
SetFrom_CalcLen(const char * s,unsigned len)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 
Find(const char * s,unsigned startIndex) const664 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 
ReverseFind(char c) const695 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 
ReverseFind_PathSepar() const710 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 
TrimLeft()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 
TrimRight()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 
InsertAtFront(char c)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 
Insert(unsigned index,const char * s)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 
Insert(unsigned index,const AString & s)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 
RemoveChar(char ch)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'
Replace(char oldChar,char newChar)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 
Replace(const AString & oldString,const AString & newString)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 
Delete(unsigned index)871 void AString::Delete(unsigned index) throw()
872 {
873   MoveItems(index, index + 1);
874   _len--;
875 }
876 
Delete(unsigned index,unsigned count)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 
DeleteFrontal(unsigned num)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 
InsertSpace(unsigned index,unsigned size)941 void UString::InsertSpace(unsigned index, unsigned size)
942 {
943   Grow(size);
944   MoveItems(index + size, index);
945 }
946 
ReAlloc(unsigned newLimit)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 
ReAlloc2(unsigned newLimit)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 
SetStartLen(unsigned len)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 
Grow_1()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 
Grow(unsigned n)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 
UString(unsigned num,const wchar_t * s)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 
UString(unsigned num,const UString & s)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 
UString(const UString & s,wchar_t c)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 
UString(const wchar_t * s1,unsigned num1,const wchar_t * s2,unsigned num2)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 
operator +(const UString & s1,const UString & s2)1038 UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); }
operator +(const UString & s1,const wchar_t * s2)1039 UString operator+(const UString &s1, const wchar_t *s2) { return UString(s1, s1.Len(), s2, MyStringLen(s2)); }
operator +(const wchar_t * s1,const UString & s2)1040 UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); }
1041 
UString()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 
UString(wchar_t c)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 
UString(char c)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 
UString(const wchar_t * s)1067 UString::UString(const wchar_t *s)
1068 {
1069   unsigned len = MyStringLen(s);
1070   SetStartLen(len);
1071   wmemcpy(_chars, s, len + 1);
1072 }
1073 
UString(const char * s)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 
UString(const UString & s)1084 UString::UString(const UString &s)
1085 {
1086   SetStartLen(s._len);
1087   wmemcpy(_chars, s._chars, s._len + 1);
1088 }
1089 
operator =(wchar_t c)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 
operator =(const wchar_t * s)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 
operator =(const UString & s)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 
SetFrom(const wchar_t * s,unsigned len)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 
SetFromBstr(BSTR s)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 
operator =(const char * s)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 
Add_Space()1186 void UString::Add_Space() { operator+=(L' '); }
Add_Space_if_NotEmpty()1187 void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
1188 
Add_LF()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 
operator +=(const wchar_t * s)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 
operator +=(const UString & s)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 
operator +=(const char * s)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 
Add_UInt32(UInt32 v)1230 void UString::Add_UInt32(UInt32 v)
1231 {
1232   char sz[16];
1233   ConvertUInt32ToString(v, sz);
1234   (*this) += sz;
1235 }
1236 
1237 
Find(const wchar_t * s,unsigned startIndex) const1238 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 
ReverseFind(wchar_t c) const1269 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 
ReverseFind_PathSepar() const1284 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 
TrimLeft()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 
TrimRight()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 
InsertAtFront(wchar_t c)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 
Insert(unsigned index,const wchar_t * s)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 
Insert(unsigned index,const UString & s)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 
RemoveChar(wchar_t ch)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'
Replace(wchar_t oldChar,wchar_t newChar)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 
Replace(const UString & oldString,const UString & newString)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 
Delete(unsigned index)1445 void UString::Delete(unsigned index) throw()
1446 {
1447   MoveItems(index, index + 1);
1448   _len--;
1449 }
1450 
Delete(unsigned index,unsigned count)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 
DeleteFrontal(unsigned num)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 
ReAlloc2(unsigned newLimit)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 
SetStartLen(unsigned len)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 
UString2(const wchar_t * s)1499 UString2::UString2(const wchar_t *s)
1500 {
1501   unsigned len = MyStringLen(s);
1502   SetStartLen(len);
1503   wmemcpy(_chars, s, len + 1);
1504 }
1505 
UString2(const UString2 & s)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 
operator =(const wchar_t * s)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 
SetFromAscii(const char * s)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 
operator =(const UString2 & s)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 
operator ==(const UString2 & s1,const UString2 & s2)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 
operator ==(const UString2 & s1,const wchar_t * s2)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 
operator ==(const wchar_t * s1,const UString2 & s2)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 
GetCurrentCodePage()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 
fs2fas(CFSTR s)1625 AString fs2fas(CFSTR s)
1626 {
1627   return UnicodeStringToMultiByte(s, GetCurrentCodePage());
1628 }
1629 
fas2fs(const char * s)1630 FString fas2fs(const char *s)
1631 {
1632   return MultiByteToUnicodeString(s, GetCurrentCodePage());
1633 }
1634 
fas2fs(const AString & s)1635 FString fas2fs(const AString &s)
1636 {
1637   return MultiByteToUnicodeString(s, GetCurrentCodePage());
1638 }
1639 
1640 #endif
1641 
1642 #else
1643 
fs2us(const FChar * s)1644 UString fs2us(const FChar *s)
1645 {
1646   return MultiByteToUnicodeString(s, GetCurrentCodePage());
1647 }
1648 
fs2us(const FString & s)1649 UString fs2us(const FString &s)
1650 {
1651   return MultiByteToUnicodeString(s, GetCurrentCodePage());
1652 }
1653 
us2fs(const wchar_t * s)1654 FString us2fs(const wchar_t *s)
1655 {
1656   return UnicodeStringToMultiByte(s, GetCurrentCodePage());
1657 }
1658 
1659 #endif
1660