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