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