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