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 char * u,const char * a)240 bool StringsAreEqual_Ascii(const char *u, const char *a) throw()
241 {
242   for (;;)
243   {
244     char c = *a;
245     if (c != *u)
246       return false;
247     if (c == 0)
248       return true;
249     a++;
250     u++;
251   }
252 }
253 
StringsAreEqual_Ascii(const wchar_t * u,const char * a)254 bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw()
255 {
256   for (;;)
257   {
258     unsigned char c = (unsigned char)*a;
259     if (c != *u)
260       return false;
261     if (c == 0)
262       return true;
263     a++;
264     u++;
265   }
266 }
267 
StringsAreEqualNoCase_Ascii(const char * s1,const char * s2)268 bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw()
269 {
270   for (;;)
271   {
272     char c1 = *s1++;
273     char c2 = *s2++;
274     if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
275       return false;
276     if (c1 == 0)
277       return true;
278   }
279 }
280 
StringsAreEqualNoCase_Ascii(const wchar_t * s1,const wchar_t * s2)281 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw()
282 {
283   for (;;)
284   {
285     wchar_t c1 = *s1++;
286     wchar_t c2 = *s2++;
287     if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
288       return false;
289     if (c1 == 0)
290       return true;
291   }
292 }
293 
StringsAreEqualNoCase_Ascii(const wchar_t * s1,const char * s2)294 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw()
295 {
296   for (;;)
297   {
298     wchar_t c1 = *s1++;
299     char c2 = *s2++;
300     if (c1 != (unsigned char)c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)))
301       return false;
302     if (c1 == 0)
303       return true;
304   }
305 }
306 
IsString1PrefixedByString2(const wchar_t * s1,const wchar_t * s2)307 bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw()
308 {
309   for (;;)
310   {
311     wchar_t c2 = *s2++; if (c2 == 0) return true;
312     wchar_t c1 = *s1++; if (c1 != c2) return false;
313   }
314 }
315 
IsString1PrefixedByString2(const wchar_t * s1,const char * s2)316 bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw()
317 {
318   for (;;)
319   {
320     unsigned char c2 = (unsigned char)(*s2++); if (c2 == 0) return true;
321     wchar_t c1 = *s1++; if (c1 != c2) return false;
322   }
323 }
324 
IsString1PrefixedByString2_NoCase_Ascii(const char * s1,const char * s2)325 bool IsString1PrefixedByString2_NoCase_Ascii(const char *s1, const char *s2) throw()
326 {
327   for (;;)
328   {
329     char c2 = *s2++; if (c2 == 0) return true;
330     char c1 = *s1++;
331     if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
332       return false;
333   }
334 }
335 
IsString1PrefixedByString2_NoCase_Ascii(const wchar_t * s1,const char * s2)336 bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *s1, const char *s2) throw()
337 {
338   for (;;)
339   {
340     char c2 = *s2++; if (c2 == 0) return true;
341     wchar_t c1 = *s1++;
342     if (c1 != (unsigned char)c2 && MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))
343       return false;
344   }
345 }
346 
IsString1PrefixedByString2_NoCase(const wchar_t * s1,const wchar_t * s2)347 bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw()
348 {
349   for (;;)
350   {
351     wchar_t c2 = *s2++; if (c2 == 0) return true;
352     wchar_t c1 = *s1++;
353     if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2))
354       return false;
355   }
356 }
357 
358 // NTFS order: uses upper case
MyStringCompareNoCase(const wchar_t * s1,const wchar_t * s2)359 int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw()
360 {
361   for (;;)
362   {
363     wchar_t c1 = *s1++;
364     wchar_t c2 = *s2++;
365     if (c1 != c2)
366     {
367       wchar_t u1 = MyCharUpper(c1);
368       wchar_t u2 = MyCharUpper(c2);
369       if (u1 < u2) return -1;
370       if (u1 > u2) return 1;
371     }
372     if (c1 == 0) return 0;
373   }
374 }
375 
376 /*
377 int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num)
378 {
379   for (; num != 0; num--)
380   {
381     wchar_t c1 = *s1++;
382     wchar_t c2 = *s2++;
383     if (c1 != c2)
384     {
385       wchar_t u1 = MyCharUpper(c1);
386       wchar_t u2 = MyCharUpper(c2);
387       if (u1 < u2) return -1;
388       if (u1 > u2) return 1;
389     }
390     if (c1 == 0) return 0;
391   }
392   return 0;
393 }
394 */
395 
396 // ---------- AString ----------
397 
InsertSpace(unsigned & index,unsigned size)398 void AString::InsertSpace(unsigned &index, unsigned size)
399 {
400   Grow(size);
401   MoveItems(index + size, index);
402 }
403 
404 #define k_Alloc_Len_Limit 0x40000000
405 
ReAlloc(unsigned newLimit)406 void AString::ReAlloc(unsigned newLimit)
407 {
408   if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130220;
409   // MY_STRING_REALLOC(_chars, char, newLimit + 1, _len + 1);
410   char *newBuf = MY_STRING_NEW_char(newLimit + 1);
411   memcpy(newBuf, _chars, (size_t)(_len + 1));
412   MY_STRING_DELETE(_chars);
413   _chars = newBuf;
414   _limit = newLimit;
415 }
416 
ReAlloc2(unsigned newLimit)417 void AString::ReAlloc2(unsigned newLimit)
418 {
419   if (newLimit >= k_Alloc_Len_Limit) throw 20130220;
420   // MY_STRING_REALLOC(_chars, char, newLimit + 1, 0);
421   char *newBuf = MY_STRING_NEW_char(newLimit + 1);
422   newBuf[0] = 0;
423   MY_STRING_DELETE(_chars);
424   _chars = newBuf;
425   _limit = newLimit;
426 }
427 
SetStartLen(unsigned len)428 void AString::SetStartLen(unsigned len)
429 {
430   _chars = 0;
431   _chars = MY_STRING_NEW_char(len + 1);
432   _len = len;
433   _limit = len;
434 }
435 
Grow_1()436 void AString::Grow_1()
437 {
438   unsigned next = _len;
439   next += next / 2;
440   next += 16;
441   next &= ~(unsigned)15;
442   ReAlloc(next - 1);
443 }
444 
Grow(unsigned n)445 void AString::Grow(unsigned n)
446 {
447   unsigned freeSize = _limit - _len;
448   if (n <= freeSize)
449     return;
450 
451   unsigned next = _len + n;
452   next += next / 2;
453   next += 16;
454   next &= ~(unsigned)15;
455   ReAlloc(next - 1);
456 }
457 
AString(unsigned num,const char * s)458 AString::AString(unsigned num, const char *s)
459 {
460   unsigned len = MyStringLen(s);
461   if (num > len)
462     num = len;
463   SetStartLen(num);
464   memcpy(_chars, s, num);
465   _chars[num] = 0;
466 }
467 
AString(unsigned num,const AString & s)468 AString::AString(unsigned num, const AString &s)
469 {
470   if (num > s._len)
471     num = s._len;
472   SetStartLen(num);
473   memcpy(_chars, s._chars, num);
474   _chars[num] = 0;
475 }
476 
AString(const AString & s,char c)477 AString::AString(const AString &s, char c)
478 {
479   SetStartLen(s.Len() + 1);
480   char *chars = _chars;
481   unsigned len = s.Len();
482   memcpy(chars, s, len);
483   chars[len] = c;
484   chars[(size_t)len + 1] = 0;
485 }
486 
AString(const char * s1,unsigned num1,const char * s2,unsigned num2)487 AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2)
488 {
489   SetStartLen(num1 + num2);
490   char *chars = _chars;
491   memcpy(chars, s1, num1);
492   memcpy(chars + num1, s2, num2 + 1);
493 }
494 
operator +(const AString & s1,const AString & s2)495 AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); }
operator +(const AString & s1,const char * s2)496 AString operator+(const AString &s1, const char    *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); }
operator +(const char * s1,const AString & s2)497 AString operator+(const char    *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); }
498 
499 static const unsigned kStartStringCapacity = 4;
500 
AString()501 AString::AString()
502 {
503   _chars = 0;
504   _chars = MY_STRING_NEW_char(kStartStringCapacity);
505   _len = 0;
506   _limit = kStartStringCapacity - 1;
507   _chars[0] = 0;
508 }
509 
AString(char c)510 AString::AString(char c)
511 {
512   SetStartLen(1);
513   char *chars = _chars;
514   chars[0] = c;
515   chars[1] = 0;
516 }
517 
AString(const char * s)518 AString::AString(const char *s)
519 {
520   SetStartLen(MyStringLen(s));
521   MyStringCopy(_chars, s);
522 }
523 
AString(const AString & s)524 AString::AString(const AString &s)
525 {
526   SetStartLen(s._len);
527   MyStringCopy(_chars, s._chars);
528 }
529 
operator =(char c)530 AString &AString::operator=(char c)
531 {
532   if (1 > _limit)
533   {
534     char *newBuf = MY_STRING_NEW_char(1 + 1);
535     MY_STRING_DELETE(_chars);
536     _chars = newBuf;
537     _limit = 1;
538   }
539   _len = 1;
540   char *chars = _chars;
541   chars[0] = c;
542   chars[1] = 0;
543   return *this;
544 }
545 
operator =(const char * s)546 AString &AString::operator=(const char *s)
547 {
548   unsigned len = MyStringLen(s);
549   if (len > _limit)
550   {
551     char *newBuf = MY_STRING_NEW_char(len + 1);
552     MY_STRING_DELETE(_chars);
553     _chars = newBuf;
554     _limit = len;
555   }
556   _len = len;
557   MyStringCopy(_chars, s);
558   return *this;
559 }
560 
operator =(const AString & s)561 AString &AString::operator=(const AString &s)
562 {
563   if (&s == this)
564     return *this;
565   unsigned len = s._len;
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   MyStringCopy(_chars, s._chars);
575   return *this;
576 }
577 
SetFromWStr_if_Ascii(const wchar_t * s)578 void AString::SetFromWStr_if_Ascii(const wchar_t *s)
579 {
580   unsigned len = 0;
581   {
582     for (;; len++)
583     {
584       wchar_t c = s[len];
585       if (c == 0)
586         break;
587       if (c >= 0x80)
588         return;
589     }
590   }
591   if (len > _limit)
592   {
593     char *newBuf = MY_STRING_NEW_char(len + 1);
594     MY_STRING_DELETE(_chars);
595     _chars = newBuf;
596     _limit = len;
597   }
598   _len = len;
599   char *dest = _chars;
600   unsigned i;
601   for (i = 0; i < len; i++)
602     dest[i] = (char)s[i];
603   dest[i] = 0;
604 }
605 
606 /*
607 void AString::SetFromBstr_if_Ascii(BSTR s)
608 {
609   unsigned len = ::SysStringLen(s);
610   {
611     for (unsigned i = 0; i < len; i++)
612       if (s[i] <= 0 || s[i] >= 0x80)
613         return;
614   }
615   if (len > _limit)
616   {
617     char *newBuf = MY_STRING_NEW_char(len + 1);
618     MY_STRING_DELETE(_chars);
619     _chars = newBuf;
620     _limit = len;
621   }
622   _len = len;
623   char *dest = _chars;
624   unsigned i;
625   for (i = 0; i < len; i++)
626     dest[i] = (char)s[i];
627   dest[i] = 0;
628 }
629 */
630 
Add_Space()631 void AString::Add_Space() { operator+=(' '); }
Add_Space_if_NotEmpty()632 void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
Add_LF()633 void AString::Add_LF() { operator+=('\n'); }
634 
operator +=(const char * s)635 AString &AString::operator+=(const char *s)
636 {
637   unsigned len = MyStringLen(s);
638   Grow(len);
639   MyStringCopy(_chars + _len, s);
640   _len += len;
641   return *this;
642 }
643 
Add_OptSpaced(const char * s)644 void AString::Add_OptSpaced(const char *s)
645 {
646   Add_Space_if_NotEmpty();
647   (*this) += s;
648 }
649 
operator +=(const AString & s)650 AString &AString::operator+=(const AString &s)
651 {
652   Grow(s._len);
653   MyStringCopy(_chars + _len, s._chars);
654   _len += s._len;
655   return *this;
656 }
657 
Add_UInt32(UInt32 v)658 void AString::Add_UInt32(UInt32 v)
659 {
660   Grow(10);
661   _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars);
662 }
663 
Add_UInt64(UInt64 v)664 void UString::Add_UInt64(UInt64 v)
665 {
666   Grow(20);
667   _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars);
668 }
669 
SetFrom(const char * s,unsigned len)670 void AString::SetFrom(const char *s, unsigned len) // no check
671 {
672   if (len > _limit)
673   {
674     char *newBuf = MY_STRING_NEW_char(len + 1);
675     MY_STRING_DELETE(_chars);
676     _chars = newBuf;
677     _limit = len;
678   }
679   if (len != 0)
680     memcpy(_chars, s, len);
681   _chars[len] = 0;
682   _len = len;
683 }
684 
SetFrom_CalcLen(const char * s,unsigned len)685 void AString::SetFrom_CalcLen(const char *s, unsigned len) // no check
686 {
687   unsigned i;
688   for (i = 0; i < len; i++)
689     if (s[i] == 0)
690       break;
691   SetFrom(s, i);
692 }
693 
Find(const char * s,unsigned startIndex) const694 int AString::Find(const char *s, unsigned startIndex) const throw()
695 {
696   const char *fs = strstr(_chars + startIndex, s);
697   if (!fs)
698     return -1;
699   return (int)(fs - _chars);
700 
701   /*
702   if (s[0] == 0)
703     return startIndex;
704   unsigned len = MyStringLen(s);
705   const char *p = _chars + startIndex;
706   for (;; p++)
707   {
708     const char c = *p;
709     if (c != s[0])
710     {
711       if (c == 0)
712         return -1;
713       continue;
714     }
715     unsigned i;
716     for (i = 1; i < len; i++)
717       if (p[i] != s[i])
718         break;
719     if (i == len)
720       return (int)(p - _chars);
721   }
722   */
723 }
724 
ReverseFind(char c) const725 int AString::ReverseFind(char c) const throw()
726 {
727   if (_len == 0)
728     return -1;
729   const char *p = _chars + _len - 1;
730   for (;;)
731   {
732     if (*p == c)
733       return (int)(p - _chars);
734     if (p == _chars)
735       return -1;
736     p--; // p = GetPrevCharPointer(_chars, p);
737   }
738 }
739 
ReverseFind_PathSepar() const740 int AString::ReverseFind_PathSepar() const throw()
741 {
742   if (_len == 0)
743     return -1;
744   const char *p = _chars + _len - 1;
745   for (;;)
746   {
747     char c = *p;
748     if (IS_PATH_SEPAR(c))
749       return (int)(p - _chars);
750     if (p == _chars)
751       return -1;
752     p--;
753   }
754 }
755 
TrimLeft()756 void AString::TrimLeft() throw()
757 {
758   const char *p = _chars;
759   for (;; p++)
760   {
761     char c = *p;
762     if (c != ' ' && c != '\n' && c != '\t')
763       break;
764   }
765   unsigned pos = (unsigned)(p - _chars);
766   if (pos != 0)
767   {
768     MoveItems(0, pos);
769     _len -= pos;
770   }
771 }
772 
TrimRight()773 void AString::TrimRight() throw()
774 {
775   const char *p = _chars;
776   unsigned i;
777   for (i = _len; i != 0; i--)
778   {
779     char c = p[(size_t)i - 1];
780     if (c != ' ' && c != '\n' && c != '\t')
781       break;
782   }
783   if (i != _len)
784   {
785     _chars[i] = 0;
786     _len = i;
787   }
788 }
789 
InsertAtFront(char c)790 void AString::InsertAtFront(char c)
791 {
792   if (_limit == _len)
793     Grow_1();
794   MoveItems(1, 0);
795   _chars[0] = c;
796   _len++;
797 }
798 
799 /*
800 void AString::Insert(unsigned index, char c)
801 {
802   InsertSpace(index, 1);
803   _chars[index] = c;
804   _len++;
805 }
806 */
807 
Insert(unsigned index,const char * s)808 void AString::Insert(unsigned index, const char *s)
809 {
810   unsigned num = MyStringLen(s);
811   if (num != 0)
812   {
813     InsertSpace(index, num);
814     memcpy(_chars + index, s, num);
815     _len += num;
816   }
817 }
818 
Insert(unsigned index,const AString & s)819 void AString::Insert(unsigned index, const AString &s)
820 {
821   unsigned num = s.Len();
822   if (num != 0)
823   {
824     InsertSpace(index, num);
825     memcpy(_chars + index, s, num);
826     _len += num;
827   }
828 }
829 
RemoveChar(char ch)830 void AString::RemoveChar(char ch) throw()
831 {
832   char *src = _chars;
833 
834   for (;;)
835   {
836     char c = *src++;
837     if (c == 0)
838       return;
839     if (c == ch)
840       break;
841   }
842 
843   char *dest = src - 1;
844 
845   for (;;)
846   {
847     char c = *src++;
848     if (c == 0)
849       break;
850     if (c != ch)
851       *dest++ = c;
852   }
853 
854   *dest = 0;
855   _len = (unsigned)(dest - _chars);
856 }
857 
858 // !!!!!!!!!!!!!!! test it if newChar = '\0'
Replace(char oldChar,char newChar)859 void AString::Replace(char oldChar, char newChar) throw()
860 {
861   if (oldChar == newChar)
862     return; // 0;
863   // unsigned number = 0;
864   int pos = 0;
865   char *chars = _chars;
866   while ((unsigned)pos < _len)
867   {
868     pos = Find(oldChar, (unsigned)pos);
869     if (pos < 0)
870       break;
871     chars[(unsigned)pos] = newChar;
872     pos++;
873     // number++;
874   }
875   return; //  number;
876 }
877 
Replace(const AString & oldString,const AString & newString)878 void AString::Replace(const AString &oldString, const AString &newString)
879 {
880   if (oldString.IsEmpty())
881     return; // 0;
882   if (oldString == newString)
883     return; // 0;
884   unsigned oldLen = oldString.Len();
885   unsigned newLen = newString.Len();
886   // unsigned number = 0;
887   int pos = 0;
888   while ((unsigned)pos < _len)
889   {
890     pos = Find(oldString, (unsigned)pos);
891     if (pos < 0)
892       break;
893     Delete((unsigned)pos, oldLen);
894     Insert((unsigned)pos, newString);
895     pos += newLen;
896     // number++;
897   }
898   // return number;
899 }
900 
Delete(unsigned index)901 void AString::Delete(unsigned index) throw()
902 {
903   MoveItems(index, index + 1);
904   _len--;
905 }
906 
Delete(unsigned index,unsigned count)907 void AString::Delete(unsigned index, unsigned count) throw()
908 {
909   if (index + count > _len)
910     count = _len - index;
911   if (count > 0)
912   {
913     MoveItems(index, index + count);
914     _len -= count;
915   }
916 }
917 
DeleteFrontal(unsigned num)918 void AString::DeleteFrontal(unsigned num) throw()
919 {
920   if (num != 0)
921   {
922     MoveItems(0, num);
923     _len -= num;
924   }
925 }
926 
927 /*
928 AString operator+(const AString &s1, const AString &s2)
929 {
930   AString result(s1);
931   result += s2;
932   return result;
933 }
934 
935 AString operator+(const AString &s, const char *chars)
936 {
937   AString result(s);
938   result += chars;
939   return result;
940 }
941 
942 AString operator+(const char *chars, const AString &s)
943 {
944   AString result(chars);
945   result += s;
946   return result;
947 }
948 
949 AString operator+(const AString &s, char c)
950 {
951   AString result(s);
952   result += c;
953   return result;
954 }
955 */
956 
957 /*
958 AString operator+(char c, const AString &s)
959 {
960   AString result(c);
961   result += s;
962   return result;
963 }
964 */
965 
966 
967 
968 
969 // ---------- UString ----------
970 
InsertSpace(unsigned index,unsigned size)971 void UString::InsertSpace(unsigned index, unsigned size)
972 {
973   Grow(size);
974   MoveItems(index + size, index);
975 }
976 
ReAlloc(unsigned newLimit)977 void UString::ReAlloc(unsigned newLimit)
978 {
979   if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130221;
980   // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, _len + 1);
981   wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1);
982   wmemcpy(newBuf, _chars, _len + 1);
983   MY_STRING_DELETE(_chars);
984   _chars = newBuf;
985   _limit = newLimit;
986 }
987 
ReAlloc2(unsigned newLimit)988 void UString::ReAlloc2(unsigned newLimit)
989 {
990   if (newLimit >= k_Alloc_Len_Limit) throw 20130221;
991   // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
992   wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1);
993   newBuf[0] = 0;
994   MY_STRING_DELETE(_chars);
995   _chars = newBuf;
996   _limit = newLimit;
997 }
998 
SetStartLen(unsigned len)999 void UString::SetStartLen(unsigned len)
1000 {
1001   _chars = 0;
1002   _chars = MY_STRING_NEW_wchar_t(len + 1);
1003   _len = len;
1004   _limit = len;
1005 }
1006 
Grow_1()1007 void UString::Grow_1()
1008 {
1009   unsigned next = _len;
1010   next += next / 2;
1011   next += 16;
1012   next &= ~(unsigned)15;
1013   ReAlloc(next - 1);
1014 }
1015 
Grow(unsigned n)1016 void UString::Grow(unsigned n)
1017 {
1018   unsigned freeSize = _limit - _len;
1019   if (n <= freeSize)
1020     return;
1021 
1022   unsigned next = _len + n;
1023   next += next / 2;
1024   next += 16;
1025   next &= ~(unsigned)15;
1026   ReAlloc(next - 1);
1027 }
1028 
1029 
UString(unsigned num,const wchar_t * s)1030 UString::UString(unsigned num, const wchar_t *s)
1031 {
1032   unsigned len = MyStringLen(s);
1033   if (num > len)
1034     num = len;
1035   SetStartLen(num);
1036   wmemcpy(_chars, s, num);
1037   _chars[num] = 0;
1038 }
1039 
1040 
UString(unsigned num,const UString & s)1041 UString::UString(unsigned num, const UString &s)
1042 {
1043   if (num > s._len)
1044     num = s._len;
1045   SetStartLen(num);
1046   wmemcpy(_chars, s._chars, num);
1047   _chars[num] = 0;
1048 }
1049 
UString(const UString & s,wchar_t c)1050 UString::UString(const UString &s, wchar_t c)
1051 {
1052   SetStartLen(s.Len() + 1);
1053   wchar_t *chars = _chars;
1054   unsigned len = s.Len();
1055   wmemcpy(chars, s, len);
1056   chars[len] = c;
1057   chars[(size_t)len + 1] = 0;
1058 }
1059 
UString(const wchar_t * s1,unsigned num1,const wchar_t * s2,unsigned num2)1060 UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2)
1061 {
1062   SetStartLen(num1 + num2);
1063   wchar_t *chars = _chars;
1064   wmemcpy(chars, s1, num1);
1065   wmemcpy(chars + num1, s2, num2 + 1);
1066 }
1067 
operator +(const UString & s1,const UString & s2)1068 UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); }
operator +(const UString & s1,const wchar_t * s2)1069 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)1070 UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); }
1071 
UString()1072 UString::UString()
1073 {
1074   _chars = 0;
1075   _chars = MY_STRING_NEW_wchar_t(kStartStringCapacity);
1076   _len = 0;
1077   _limit = kStartStringCapacity - 1;
1078   _chars[0] = 0;
1079 }
1080 
UString(wchar_t c)1081 UString::UString(wchar_t c)
1082 {
1083   SetStartLen(1);
1084   wchar_t *chars = _chars;
1085   chars[0] = c;
1086   chars[1] = 0;
1087 }
1088 
UString(char c)1089 UString::UString(char c)
1090 {
1091   SetStartLen(1);
1092   wchar_t *chars = _chars;
1093   chars[0] = (unsigned char)c;
1094   chars[1] = 0;
1095 }
1096 
UString(const wchar_t * s)1097 UString::UString(const wchar_t *s)
1098 {
1099   const unsigned len = MyStringLen(s);
1100   SetStartLen(len);
1101   wmemcpy(_chars, s, len + 1);
1102 }
1103 
UString(const char * s)1104 UString::UString(const char *s)
1105 {
1106   const unsigned len = MyStringLen(s);
1107   SetStartLen(len);
1108   wchar_t *chars = _chars;
1109   for (unsigned i = 0; i < len; i++)
1110     chars[i] = (unsigned char)s[i];
1111   chars[len] = 0;
1112 }
1113 
UString(const AString & s)1114 UString::UString(const AString &s)
1115 {
1116   const unsigned len = s.Len();
1117   SetStartLen(len);
1118   wchar_t *chars = _chars;
1119   const char *s2 = s.Ptr();
1120   for (unsigned i = 0; i < len; i++)
1121     chars[i] = (unsigned char)s2[i];
1122   chars[len] = 0;
1123 }
1124 
UString(const UString & s)1125 UString::UString(const UString &s)
1126 {
1127   SetStartLen(s._len);
1128   wmemcpy(_chars, s._chars, s._len + 1);
1129 }
1130 
operator =(wchar_t c)1131 UString &UString::operator=(wchar_t c)
1132 {
1133   if (1 > _limit)
1134   {
1135     wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);
1136     MY_STRING_DELETE(_chars);
1137     _chars = newBuf;
1138     _limit = 1;
1139   }
1140   _len = 1;
1141   wchar_t *chars = _chars;
1142   chars[0] = c;
1143   chars[1] = 0;
1144   return *this;
1145 }
1146 
operator =(const wchar_t * s)1147 UString &UString::operator=(const wchar_t *s)
1148 {
1149   unsigned len = MyStringLen(s);
1150   if (len > _limit)
1151   {
1152     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1153     MY_STRING_DELETE(_chars);
1154     _chars = newBuf;
1155     _limit = len;
1156   }
1157   _len = len;
1158   wmemcpy(_chars, s, len + 1);
1159   return *this;
1160 }
1161 
operator =(const UString & s)1162 UString &UString::operator=(const UString &s)
1163 {
1164   if (&s == this)
1165     return *this;
1166   unsigned len = s._len;
1167   if (len > _limit)
1168   {
1169     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1170     MY_STRING_DELETE(_chars);
1171     _chars = newBuf;
1172     _limit = len;
1173   }
1174   _len = len;
1175   wmemcpy(_chars, s._chars, len + 1);
1176   return *this;
1177 }
1178 
SetFrom(const wchar_t * s,unsigned len)1179 void UString::SetFrom(const wchar_t *s, unsigned len) // no check
1180 {
1181   if (len > _limit)
1182   {
1183     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1184     MY_STRING_DELETE(_chars);
1185     _chars = newBuf;
1186     _limit = len;
1187   }
1188   if (len != 0)
1189     wmemcpy(_chars, s, len);
1190   _chars[len] = 0;
1191   _len = len;
1192 }
1193 
SetFromBstr(LPCOLESTR s)1194 void UString::SetFromBstr(LPCOLESTR s)
1195 {
1196   unsigned len = ::SysStringLen((BSTR)(void *)(s));
1197 
1198   /*
1199   #if WCHAR_MAX > 0xffff
1200   size_t num_wchars = 0;
1201   for (size_t i = 0; i < len;)
1202   {
1203     wchar_t c = s[i++];
1204     if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
1205     {
1206       wchar_t c2 = s[i];
1207       if (c2 >= 0xdc00 && c2 < 0x10000)
1208       {
1209         c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
1210         i++;
1211       }
1212     }
1213     num_wchars++;
1214   }
1215   len = num_wchars;
1216   #endif
1217   */
1218 
1219   if (len > _limit)
1220   {
1221     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1222     MY_STRING_DELETE(_chars);
1223     _chars = newBuf;
1224     _limit = len;
1225   }
1226   _len = len;
1227 
1228   /*
1229   #if WCHAR_MAX > 0xffff
1230 
1231   wchar_t *chars = _chars;
1232   for (size_t i = 0; i <= len; i++)
1233   {
1234     wchar_t c = *s++;
1235     if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
1236     {
1237       wchar_t c2 = *s;
1238       if (c2 >= 0xdc00 && c2 < 0x10000)
1239       {
1240         s++;
1241         c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
1242       }
1243     }
1244     chars[i] = c;
1245   }
1246 
1247   #else
1248   */
1249 
1250   // if (s)
1251     wmemcpy(_chars, s, len + 1);
1252 
1253   // #endif
1254 }
1255 
operator =(const char * s)1256 UString &UString::operator=(const char *s)
1257 {
1258   unsigned len = MyStringLen(s);
1259   if (len > _limit)
1260   {
1261     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1262     MY_STRING_DELETE(_chars);
1263     _chars = newBuf;
1264     _limit = len;
1265   }
1266   wchar_t *chars = _chars;
1267   for (unsigned i = 0; i < len; i++)
1268     chars[i] = (unsigned char)s[i];
1269   chars[len] = 0;
1270   _len = len;
1271   return *this;
1272 }
1273 
Add_Space()1274 void UString::Add_Space() { operator+=(L' '); }
Add_Space_if_NotEmpty()1275 void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
1276 
Add_LF()1277 void UString::Add_LF()
1278 {
1279   if (_limit == _len)
1280     Grow_1();
1281   unsigned len = _len;
1282   wchar_t *chars = _chars;
1283   chars[len++] = L'\n';
1284   chars[len] = 0;
1285   _len = len;
1286 }
1287 
operator +=(const wchar_t * s)1288 UString &UString::operator+=(const wchar_t *s)
1289 {
1290   unsigned len = MyStringLen(s);
1291   Grow(len);
1292   wmemcpy(_chars + _len, s, len + 1);
1293   _len += len;
1294   return *this;
1295 }
1296 
operator +=(const UString & s)1297 UString &UString::operator+=(const UString &s)
1298 {
1299   Grow(s._len);
1300   wmemcpy(_chars + _len, s._chars, s._len + 1);
1301   _len += s._len;
1302   return *this;
1303 }
1304 
operator +=(const char * s)1305 UString &UString::operator+=(const char *s)
1306 {
1307   unsigned len = MyStringLen(s);
1308   Grow(len);
1309   wchar_t *chars = _chars + _len;
1310   for (unsigned i = 0; i < len; i++)
1311     chars[i] = (unsigned char)s[i];
1312   chars[len] = 0;
1313   _len += len;
1314   return *this;
1315 }
1316 
1317 
Add_UInt32(UInt32 v)1318 void UString::Add_UInt32(UInt32 v)
1319 {
1320   Grow(10);
1321   _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars);
1322 }
1323 
Add_UInt64(UInt64 v)1324 void AString::Add_UInt64(UInt64 v)
1325 {
1326   Grow(20);
1327   _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars);
1328 }
1329 
1330 
Find(const wchar_t * s,unsigned startIndex) const1331 int UString::Find(const wchar_t *s, unsigned startIndex) const throw()
1332 {
1333   const wchar_t *fs = wcsstr(_chars + startIndex, s);
1334   if (!fs)
1335     return -1;
1336   return (int)(fs - _chars);
1337 
1338   /*
1339   if (s[0] == 0)
1340     return startIndex;
1341   unsigned len = MyStringLen(s);
1342   const wchar_t *p = _chars + startIndex;
1343   for (;; p++)
1344   {
1345     const wchar_t c = *p;
1346     if (c != s[0])
1347     {
1348       if (c == 0)
1349         return -1;
1350       continue;
1351     }
1352     unsigned i;
1353     for (i = 1; i < len; i++)
1354       if (p[i] != s[i])
1355         break;
1356     if (i == len)
1357       return (int)(p - _chars);
1358   }
1359   */
1360 }
1361 
ReverseFind(wchar_t c) const1362 int UString::ReverseFind(wchar_t c) const throw()
1363 {
1364   if (_len == 0)
1365     return -1;
1366   const wchar_t *p = _chars + _len - 1;
1367   for (;;)
1368   {
1369     if (*p == c)
1370       return (int)(p - _chars);
1371     if (p == _chars)
1372       return -1;
1373     p--;
1374   }
1375 }
1376 
ReverseFind_PathSepar() const1377 int UString::ReverseFind_PathSepar() const throw()
1378 {
1379   if (_len == 0)
1380     return -1;
1381   const wchar_t *p = _chars + _len - 1;
1382   for (;;)
1383   {
1384     wchar_t c = *p;
1385     if (IS_PATH_SEPAR(c))
1386       return (int)(p - _chars);
1387     if (p == _chars)
1388       return -1;
1389     p--;
1390   }
1391 }
1392 
TrimLeft()1393 void UString::TrimLeft() throw()
1394 {
1395   const wchar_t *p = _chars;
1396   for (;; p++)
1397   {
1398     wchar_t c = *p;
1399     if (c != ' ' && c != '\n' && c != '\t')
1400       break;
1401   }
1402   unsigned pos = (unsigned)(p - _chars);
1403   if (pos != 0)
1404   {
1405     MoveItems(0, pos);
1406     _len -= pos;
1407   }
1408 }
1409 
TrimRight()1410 void UString::TrimRight() throw()
1411 {
1412   const wchar_t *p = _chars;
1413   unsigned i;
1414   for (i = _len; i != 0; i--)
1415   {
1416     wchar_t c = p[(size_t)i - 1];
1417     if (c != ' ' && c != '\n' && c != '\t')
1418       break;
1419   }
1420   if (i != _len)
1421   {
1422     _chars[i] = 0;
1423     _len = i;
1424   }
1425 }
1426 
InsertAtFront(wchar_t c)1427 void UString::InsertAtFront(wchar_t c)
1428 {
1429   if (_limit == _len)
1430     Grow_1();
1431   MoveItems(1, 0);
1432   _chars[0] = c;
1433   _len++;
1434 }
1435 
1436 /*
1437 void UString::Insert_wchar_t(unsigned index, wchar_t c)
1438 {
1439   InsertSpace(index, 1);
1440   _chars[index] = c;
1441   _len++;
1442 }
1443 */
1444 
Insert(unsigned index,const wchar_t * s)1445 void UString::Insert(unsigned index, const wchar_t *s)
1446 {
1447   unsigned num = MyStringLen(s);
1448   if (num != 0)
1449   {
1450     InsertSpace(index, num);
1451     wmemcpy(_chars + index, s, num);
1452     _len += num;
1453   }
1454 }
1455 
Insert(unsigned index,const UString & s)1456 void UString::Insert(unsigned index, const UString &s)
1457 {
1458   unsigned num = s.Len();
1459   if (num != 0)
1460   {
1461     InsertSpace(index, num);
1462     wmemcpy(_chars + index, s, num);
1463     _len += num;
1464   }
1465 }
1466 
RemoveChar(wchar_t ch)1467 void UString::RemoveChar(wchar_t ch) throw()
1468 {
1469   wchar_t *src = _chars;
1470 
1471   for (;;)
1472   {
1473     wchar_t c = *src++;
1474     if (c == 0)
1475       return;
1476     if (c == ch)
1477       break;
1478   }
1479 
1480   wchar_t *dest = src - 1;
1481 
1482   for (;;)
1483   {
1484     wchar_t c = *src++;
1485     if (c == 0)
1486       break;
1487     if (c != ch)
1488       *dest++ = c;
1489   }
1490 
1491   *dest = 0;
1492   _len = (unsigned)(dest - _chars);
1493 }
1494 
1495 // !!!!!!!!!!!!!!! test it if newChar = '\0'
Replace(wchar_t oldChar,wchar_t newChar)1496 void UString::Replace(wchar_t oldChar, wchar_t newChar) throw()
1497 {
1498   if (oldChar == newChar)
1499     return; // 0;
1500   // unsigned number = 0;
1501   int pos = 0;
1502   wchar_t *chars = _chars;
1503   while ((unsigned)pos < _len)
1504   {
1505     pos = Find(oldChar, (unsigned)pos);
1506     if (pos < 0)
1507       break;
1508     chars[(unsigned)pos] = newChar;
1509     pos++;
1510     // number++;
1511   }
1512   return; //  number;
1513 }
1514 
Replace(const UString & oldString,const UString & newString)1515 void UString::Replace(const UString &oldString, const UString &newString)
1516 {
1517   if (oldString.IsEmpty())
1518     return; // 0;
1519   if (oldString == newString)
1520     return; // 0;
1521   unsigned oldLen = oldString.Len();
1522   unsigned newLen = newString.Len();
1523   // unsigned number = 0;
1524   int pos = 0;
1525   while ((unsigned)pos < _len)
1526   {
1527     pos = Find(oldString, (unsigned)pos);
1528     if (pos < 0)
1529       break;
1530     Delete((unsigned)pos, oldLen);
1531     Insert((unsigned)pos, newString);
1532     pos += newLen;
1533     // number++;
1534   }
1535   // return number;
1536 }
1537 
Delete(unsigned index)1538 void UString::Delete(unsigned index) throw()
1539 {
1540   MoveItems(index, index + 1);
1541   _len--;
1542 }
1543 
Delete(unsigned index,unsigned count)1544 void UString::Delete(unsigned index, unsigned count) throw()
1545 {
1546   if (index + count > _len)
1547     count = _len - index;
1548   if (count > 0)
1549   {
1550     MoveItems(index, index + count);
1551     _len -= count;
1552   }
1553 }
1554 
DeleteFrontal(unsigned num)1555 void UString::DeleteFrontal(unsigned num) throw()
1556 {
1557   if (num != 0)
1558   {
1559     MoveItems(0, num);
1560     _len -= num;
1561   }
1562 }
1563 
1564 
1565 // ---------- UString2 ----------
1566 
ReAlloc2(unsigned newLimit)1567 void UString2::ReAlloc2(unsigned newLimit)
1568 {
1569   if (newLimit >= k_Alloc_Len_Limit) throw 20130221;
1570   // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
1571   _chars = MY_STRING_NEW_wchar_t(newLimit + 1);
1572 }
1573 
SetStartLen(unsigned len)1574 void UString2::SetStartLen(unsigned len)
1575 {
1576   _chars = 0;
1577   _chars = MY_STRING_NEW_wchar_t(len + 1);
1578   _len = len;
1579 }
1580 
1581 
1582 /*
1583 UString2::UString2(wchar_t c)
1584 {
1585   SetStartLen(1);
1586   wchar_t *chars = _chars;
1587   chars[0] = c;
1588   chars[1] = 0;
1589 }
1590 */
1591 
UString2(const wchar_t * s)1592 UString2::UString2(const wchar_t *s)
1593 {
1594   unsigned len = MyStringLen(s);
1595   SetStartLen(len);
1596   wmemcpy(_chars, s, len + 1);
1597 }
1598 
UString2(const UString2 & s)1599 UString2::UString2(const UString2 &s): _chars(NULL), _len(0)
1600 {
1601   if (s._chars)
1602   {
1603     SetStartLen(s._len);
1604     wmemcpy(_chars, s._chars, s._len + 1);
1605   }
1606 }
1607 
1608 /*
1609 UString2 &UString2::operator=(wchar_t c)
1610 {
1611   if (1 > _len)
1612   {
1613     wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);
1614     if (_chars)
1615       MY_STRING_DELETE(_chars);
1616     _chars = newBuf;
1617   }
1618   _len = 1;
1619   wchar_t *chars = _chars;
1620   chars[0] = c;
1621   chars[1] = 0;
1622   return *this;
1623 }
1624 */
1625 
operator =(const wchar_t * s)1626 UString2 &UString2::operator=(const wchar_t *s)
1627 {
1628   unsigned len = MyStringLen(s);
1629   if (len > _len)
1630   {
1631     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1632     if (_chars)
1633       MY_STRING_DELETE(_chars);
1634     _chars = newBuf;
1635   }
1636   _len = len;
1637   MyStringCopy(_chars, s);
1638   return *this;
1639 }
1640 
SetFromAscii(const char * s)1641 void UString2::SetFromAscii(const char *s)
1642 {
1643   unsigned len = MyStringLen(s);
1644   if (len > _len)
1645   {
1646     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1647     if (_chars)
1648       MY_STRING_DELETE(_chars);
1649     _chars = newBuf;
1650   }
1651   wchar_t *chars = _chars;
1652   for (unsigned i = 0; i < len; i++)
1653     chars[i] = (unsigned char)s[i];
1654   chars[len] = 0;
1655   _len = len;
1656 }
1657 
operator =(const UString2 & s)1658 UString2 &UString2::operator=(const UString2 &s)
1659 {
1660   if (&s == this)
1661     return *this;
1662   unsigned len = s._len;
1663   if (len > _len)
1664   {
1665     wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1666     if (_chars)
1667       MY_STRING_DELETE(_chars);
1668     _chars = newBuf;
1669   }
1670   _len = len;
1671   MyStringCopy(_chars, s._chars);
1672   return *this;
1673 }
1674 
operator ==(const UString2 & s1,const UString2 & s2)1675 bool operator==(const UString2 &s1, const UString2 &s2)
1676 {
1677   return s1.Len() == s2.Len() && (s1.IsEmpty() || wcscmp(s1.GetRawPtr(), s2.GetRawPtr()) == 0);
1678 }
1679 
operator ==(const UString2 & s1,const wchar_t * s2)1680 bool operator==(const UString2 &s1, const wchar_t *s2)
1681 {
1682   if (s1.IsEmpty())
1683     return (*s2 == 0);
1684   return wcscmp(s1.GetRawPtr(), s2) == 0;
1685 }
1686 
operator ==(const wchar_t * s1,const UString2 & s2)1687 bool operator==(const wchar_t *s1, const UString2 &s2)
1688 {
1689   if (s2.IsEmpty())
1690     return (*s1 == 0);
1691   return wcscmp(s1, s2.GetRawPtr()) == 0;
1692 }
1693 
1694 
1695 
1696 // ----------------------------------------
1697 
1698 /*
1699 int MyStringCompareNoCase(const char *s1, const char *s2)
1700 {
1701   return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));
1702 }
1703 */
1704 
1705 #if !defined(USE_UNICODE_FSTRING) || !defined(_UNICODE)
1706 
GetCurrentCodePage()1707 static inline UINT GetCurrentCodePage()
1708 {
1709   #if defined(UNDER_CE) || !defined(_WIN32)
1710   return CP_ACP;
1711   #else
1712   return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP;
1713   #endif
1714 }
1715 
1716 #endif
1717 
1718 #ifdef USE_UNICODE_FSTRING
1719 
1720 #ifndef _UNICODE
1721 
fs2fas(CFSTR s)1722 AString fs2fas(CFSTR s)
1723 {
1724   return UnicodeStringToMultiByte(s, GetCurrentCodePage());
1725 }
1726 
fas2fs(const char * s)1727 FString fas2fs(const char *s)
1728 {
1729   return MultiByteToUnicodeString(s, GetCurrentCodePage());
1730 }
1731 
fas2fs(const AString & s)1732 FString fas2fs(const AString &s)
1733 {
1734   return MultiByteToUnicodeString(s, GetCurrentCodePage());
1735 }
1736 
1737 #endif //  _UNICODE
1738 
1739 #else // USE_UNICODE_FSTRING
1740 
fs2us(const FChar * s)1741 UString fs2us(const FChar *s)
1742 {
1743   return MultiByteToUnicodeString(s, GetCurrentCodePage());
1744 }
1745 
fs2us(const FString & s)1746 UString fs2us(const FString &s)
1747 {
1748   return MultiByteToUnicodeString(s, GetCurrentCodePage());
1749 }
1750 
us2fs(const wchar_t * s)1751 FString us2fs(const wchar_t *s)
1752 {
1753   return UnicodeStringToMultiByte(s, GetCurrentCodePage());
1754 }
1755 
1756 #endif // USE_UNICODE_FSTRING
1757