1 // Common/MyString.cpp
2 
3 #include "StdAfx.h"
4 
5 #ifdef _WIN32
6 #include <windows.h>
7 #include <wchar.h>
8 #else
9 #include <ctype.h>
10 #endif
11 
12 #if !defined(_UNICODE) || !defined(USE_UNICODE_FSTRING)
13 #include "StringConvert.h"
14 #endif
15 
16 #include "MyString.h"
17 
18 #define MY_STRING_NEW(_T_, _size_) new _T_[_size_]
19 // #define MY_STRING_NEW(_T_, _size_) ((_T_ *)my_new((size_t)(_size_) * sizeof(_T_)))
20 
21 /*
22 inline const char* MyStringGetNextCharPointer(const char *p) throw()
23 {
24   #if defined(_WIN32) && !defined(UNDER_CE)
25   return CharNextA(p);
26   #else
27   return p + 1;
28   #endif
29 }
30 */
31 
FindCharPosInString(const char * s,char c)32 int FindCharPosInString(const char *s, char c) throw()
33 {
34   for (const char *p = s;; p++)
35   {
36     if (*p == c)
37       return (int)(p - s);
38     if (*p == 0)
39       return -1;
40     // MyStringGetNextCharPointer(p);
41   }
42 }
43 
FindCharPosInString(const wchar_t * s,wchar_t c)44 int FindCharPosInString(const wchar_t *s, wchar_t c) throw()
45 {
46   for (const wchar_t *p = s;; p++)
47   {
48     if (*p == c)
49       return (int)(p - s);
50     if (*p == 0)
51       return -1;
52   }
53 }
54 
55 /*
56 void MyStringUpper_Ascii(wchar_t *s)
57 {
58   for (;;)
59   {
60     wchar_t c = *s;
61     if (c == 0)
62       return;
63     *s++ = MyCharUpper_Ascii(c);
64   }
65 }
66 */
67 
MyStringLower_Ascii(wchar_t * s)68 void MyStringLower_Ascii(wchar_t *s) throw()
69 {
70   for (;;)
71   {
72     wchar_t c = *s;
73     if (c == 0)
74       return;
75     *s++ = MyCharLower_Ascii(c);
76   }
77 }
78 
79 #ifdef _WIN32
80 
81 #ifdef _UNICODE
82 
83 // wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }
84 // wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }
85 // for WinCE - FString - char
86 // const char *MyStringGetPrevCharPointer(const char * /* base */, const char *p) { return p - 1; }
87 
88 #else
89 
90 // const char * MyStringGetPrevCharPointer(const char *base, const char *p) throw() { return CharPrevA(base, p); }
91 // char * MyStringUpper(char *s) { return CharUpperA(s); }
92 // char * MyStringLower(char *s) { return CharLowerA(s); }
93 
MyCharUpper_WIN(wchar_t c)94 wchar_t MyCharUpper_WIN(wchar_t c) throw()
95 {
96   wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c);
97   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
98     return (wchar_t)(unsigned)(UINT_PTR)res;
99   const int kBufSize = 4;
100   char s[kBufSize + 1];
101   int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0);
102   if (numChars == 0 || numChars > kBufSize)
103     return c;
104   s[numChars] = 0;
105   ::CharUpperA(s);
106   ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
107   return c;
108 }
109 
110 /*
111 wchar_t MyCharLower_WIN(wchar_t c)
112 {
113   wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c);
114   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
115     return (wchar_t)(unsigned)(UINT_PTR)res;
116   const int kBufSize = 4;
117   char s[kBufSize + 1];
118   int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0);
119   if (numChars == 0 || numChars > kBufSize)
120     return c;
121   s[numChars] = 0;
122   ::CharLowerA(s);
123   ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
124   return c;
125 }
126 */
127 
128 /*
129 wchar_t * MyStringUpper(wchar_t *s)
130 {
131   if (s == 0)
132     return 0;
133   wchar_t *res = CharUpperW(s);
134   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
135     return res;
136   AString a = UnicodeStringToMultiByte(s);
137   a.MakeUpper();
138   MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
139   return s;
140 }
141 */
142 
143 /*
144 wchar_t * MyStringLower(wchar_t *s)
145 {
146   if (s == 0)
147     return 0;
148   wchar_t *res = CharLowerW(s);
149   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
150     return res;
151   AString a = UnicodeStringToMultiByte(s);
152   a.MakeLower();
153   MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
154   return s;
155 }
156 */
157 
158 #endif
159 
160 #endif
161 
IsString1PrefixedByString2(const char * s1,const char * s2)162 bool IsString1PrefixedByString2(const char *s1, const char *s2) throw()
163 {
164   for (;;)
165   {
166     unsigned char c2 = (unsigned char)*s2++; if (c2 == 0) return true;
167     unsigned char c1 = (unsigned char)*s1++; if (c1 != c2) return false;
168   }
169 }
170 
StringsAreEqualNoCase(const wchar_t * s1,const wchar_t * s2)171 bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw()
172 {
173   for (;;)
174   {
175     wchar_t c1 = *s1++;
176     wchar_t c2 = *s2++;
177     if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false;
178     if (c1 == 0) return true;
179   }
180 }
181 
182 // ---------- ASCII ----------
183 
IsPrefixedBy_Ascii_NoCase(const char * s) const184 bool AString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw()
185 {
186   const char *s1 = _chars;
187   for (;;)
188   {
189     char c2 = *s++;
190     if (c2 == 0)
191       return true;
192     char c1 = *s1++;
193     if (MyCharLower_Ascii(c1) !=
194         MyCharLower_Ascii(c2))
195       return false;
196   }
197 }
198 
IsPrefixedBy_Ascii_NoCase(const char * s) const199 bool UString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw()
200 {
201   const wchar_t *s1 = _chars;
202   for (;;)
203   {
204     char c2 = *s++;
205     if (c2 == 0)
206       return true;
207     wchar_t c1 = *s1++;
208     if (MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))
209       return false;
210   }
211 }
212 
StringsAreEqual_Ascii(const wchar_t * u,const char * a)213 bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw()
214 {
215   for (;;)
216   {
217     unsigned char c = *a;
218     if (c != *u)
219       return false;
220     if (c == 0)
221       return true;
222     a++;
223     u++;
224   }
225 }
226 
StringsAreEqualNoCase_Ascii(const char * s1,const char * s2)227 bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw()
228 {
229   for (;;)
230   {
231     char c1 = *s1++;
232     char c2 = *s2++;
233     if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
234       return false;
235     if (c1 == 0)
236       return true;
237   }
238 }
239 
StringsAreEqualNoCase_Ascii(const wchar_t * s1,const wchar_t * s2)240 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw()
241 {
242   for (;;)
243   {
244     wchar_t c1 = *s1++;
245     wchar_t c2 = *s2++;
246     if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
247       return false;
248     if (c1 == 0)
249       return true;
250   }
251 }
252 
StringsAreEqualNoCase_Ascii(const wchar_t * s1,const char * s2)253 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw()
254 {
255   for (;;)
256   {
257     wchar_t c1 = *s1++;
258     char c2 = *s2++;
259     if (c1 != (unsigned char)c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)))
260       return false;
261     if (c1 == 0)
262       return true;
263   }
264 }
265 
IsString1PrefixedByString2(const wchar_t * s1,const wchar_t * s2)266 bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw()
267 {
268   for (;;)
269   {
270     wchar_t c2 = *s2++; if (c2 == 0) return true;
271     wchar_t c1 = *s1++; if (c1 != c2) return false;
272   }
273 }
274 
275 // NTFS order: uses upper case
MyStringCompareNoCase(const wchar_t * s1,const wchar_t * s2)276 int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw()
277 {
278   for (;;)
279   {
280     wchar_t c1 = *s1++;
281     wchar_t c2 = *s2++;
282     if (c1 != c2)
283     {
284       wchar_t u1 = MyCharUpper(c1);
285       wchar_t u2 = MyCharUpper(c2);
286       if (u1 < u2) return -1;
287       if (u1 > u2) return 1;
288     }
289     if (c1 == 0) return 0;
290   }
291 }
292 
MyStringCompareNoCase_N(const wchar_t * s1,const wchar_t * s2,unsigned num)293 int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw()
294 {
295   for (; num != 0; num--)
296   {
297     wchar_t c1 = *s1++;
298     wchar_t c2 = *s2++;
299     if (c1 != c2)
300     {
301       wchar_t u1 = MyCharUpper(c1);
302       wchar_t u2 = MyCharUpper(c2);
303       if (u1 < u2) return -1;
304       if (u1 > u2) return 1;
305     }
306     if (c1 == 0) return 0;
307   }
308   return 0;
309 }
310 
311 
312 // ---------- AString ----------
313 
InsertSpace(unsigned & index,unsigned size)314 void AString::InsertSpace(unsigned &index, unsigned size)
315 {
316   Grow(size);
317   MoveItems(index + size, index);
318 }
319 
ReAlloc(unsigned newLimit)320 void AString::ReAlloc(unsigned newLimit)
321 {
322   if (newLimit < _len || newLimit >= 0x20000000) throw 20130220;
323   // MY_STRING_REALLOC(_chars, char, newLimit + 1, _len + 1);
324   char *newBuf = MY_STRING_NEW(char, newLimit + 1);
325   memcpy(newBuf, _chars, (size_t)(_len + 1)); \
326   MY_STRING_DELETE(_chars);
327   _chars = newBuf;
328 
329   _limit = newLimit;
330 }
331 
SetStartLen(unsigned len)332 void AString::SetStartLen(unsigned len)
333 {
334   _chars = 0;
335   _chars = MY_STRING_NEW(char, len + 1);
336   _len = len;
337   _limit = len;
338 }
339 
Grow_1()340 void AString::Grow_1()
341 {
342   unsigned next = _len;
343   next += next / 2;
344   next += 16;
345   next &= ~(unsigned)15;
346   ReAlloc(next - 1);
347 }
348 
Grow(unsigned n)349 void AString::Grow(unsigned n)
350 {
351   unsigned freeSize = _limit - _len;
352   if (n <= freeSize)
353     return;
354 
355   unsigned next = _len + n;
356   next += next / 2;
357   next += 16;
358   next &= ~(unsigned)15;
359   ReAlloc(next - 1);
360 }
361 
362 /*
363 AString::AString(unsigned num, const char *s)
364 {
365   unsigned len = MyStringLen(s);
366   if (num > len)
367     num = len;
368   SetStartLen(num);
369   memcpy(_chars, s, num);
370   _chars[num] = 0;
371 }
372 */
373 
AString(unsigned num,const AString & s)374 AString::AString(unsigned num, const AString &s)
375 {
376   if (num > s._len)
377     num = s._len;
378   SetStartLen(num);
379   memcpy(_chars, s._chars, num);
380   _chars[num] = 0;
381 }
382 
AString(const AString & s,char c)383 AString::AString(const AString &s, char c)
384 {
385   SetStartLen(s.Len() + 1);
386   char *chars = _chars;
387   unsigned len = s.Len();
388   memcpy(chars, s, len);
389   chars[len] = c;
390   chars[len + 1] = 0;
391 }
392 
AString(const char * s1,unsigned num1,const char * s2,unsigned num2)393 AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2)
394 {
395   SetStartLen(num1 + num2);
396   char *chars = _chars;
397   memcpy(chars, s1, num1);
398   memcpy(chars + num1, s2, num2 + 1);
399 }
400 
operator +(const AString & s1,const AString & s2)401 AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); }
operator +(const AString & s1,const char * s2)402 AString operator+(const AString &s1, const char    *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); }
operator +(const char * s1,const AString & s2)403 AString operator+(const char    *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); }
404 
AString()405 AString::AString()
406 {
407   _chars = 0;
408   _chars = MY_STRING_NEW(char, 4);
409   _len = 0;
410   _limit = 4 - 1;
411   _chars[0] = 0;
412 }
413 
AString(char c)414 AString::AString(char c)
415 {
416   SetStartLen(1);
417   _chars[0] = c;
418   _chars[1] = 0;
419 }
420 
AString(const char * s)421 AString::AString(const char *s)
422 {
423   SetStartLen(MyStringLen(s));
424   MyStringCopy(_chars, s);
425 }
426 
AString(const AString & s)427 AString::AString(const AString &s)
428 {
429   SetStartLen(s._len);
430   MyStringCopy(_chars, s._chars);
431 }
432 
operator =(char c)433 AString &AString::operator=(char c)
434 {
435   if (1 > _limit)
436   {
437     char *newBuf = MY_STRING_NEW(char, 1 + 1);
438     MY_STRING_DELETE(_chars);
439     _chars = newBuf;
440     _limit = 1;
441   }
442   _len = 1;
443   _chars[0] = c;
444   _chars[1] = 0;
445   return *this;
446 }
447 
operator =(const char * s)448 AString &AString::operator=(const char *s)
449 {
450   unsigned len = MyStringLen(s);
451   if (len > _limit)
452   {
453     char *newBuf = MY_STRING_NEW(char, len + 1);
454     MY_STRING_DELETE(_chars);
455     _chars = newBuf;
456     _limit = len;
457   }
458   _len = len;
459   MyStringCopy(_chars, s);
460   return *this;
461 }
462 
operator =(const AString & s)463 AString &AString::operator=(const AString &s)
464 {
465   if (&s == this)
466     return *this;
467   unsigned len = s._len;
468   if (len > _limit)
469   {
470     char *newBuf = MY_STRING_NEW(char, len + 1);
471     MY_STRING_DELETE(_chars);
472     _chars = newBuf;
473     _limit = len;
474   }
475   _len = len;
476   MyStringCopy(_chars, s._chars);
477   return *this;
478 }
479 
operator +=(const char * s)480 AString &AString::operator+=(const char *s)
481 {
482   unsigned len = MyStringLen(s);
483   Grow(len);
484   MyStringCopy(_chars + _len, s);
485   _len += len;
486   return *this;
487 }
488 
operator +=(const AString & s)489 AString &AString::operator+=(const AString &s)
490 {
491   Grow(s._len);
492   MyStringCopy(_chars + _len, s._chars);
493   _len += s._len;
494   return *this;
495 }
496 
SetFrom(const char * s,unsigned len)497 void AString::SetFrom(const char *s, unsigned len) // no check
498 {
499   if (len > _limit)
500   {
501     char *newBuf = MY_STRING_NEW(char, len + 1);
502     MY_STRING_DELETE(_chars);
503     _chars = newBuf;
504     _limit = len;
505   }
506   memcpy(_chars, s, len);
507   _chars[len] = 0;
508   _len = len;
509 }
510 
Find(const AString & s,unsigned startIndex) const511 int AString::Find(const AString &s, unsigned startIndex) const throw()
512 {
513   if (s.IsEmpty())
514     return startIndex;
515   for (; startIndex < _len; startIndex++)
516   {
517     unsigned j;
518     for (j = 0; j < s._len && startIndex + j < _len; j++)
519       if (_chars[startIndex + j] != s._chars[j])
520         break;
521     if (j == s._len)
522       return (int)startIndex;
523   }
524   return -1;
525 }
526 
ReverseFind(char c) const527 int AString::ReverseFind(char c) const throw()
528 {
529   if (_len == 0)
530     return -1;
531   const char *p = _chars + _len - 1;
532   for (;;)
533   {
534     if (*p == c)
535       return (int)(p - _chars);
536     if (p == _chars)
537       return -1;
538     p--; // p = GetPrevCharPointer(_chars, p);
539   }
540 }
541 
TrimLeft()542 void AString::TrimLeft() throw()
543 {
544   const char *p = _chars;
545   for (;; p++)
546   {
547     char c = *p;
548     if (c != ' ' && c != '\n' && c != '\t')
549       break;
550   }
551   unsigned pos = (unsigned)(p - _chars);
552   if (pos != 0)
553   {
554     MoveItems(0, pos);
555     _len -= pos;
556   }
557 }
558 
TrimRight()559 void AString::TrimRight() throw()
560 {
561   const char *p = _chars;
562   int i;
563   for (i = _len - 1; i >= 0; i--)
564   {
565     char c = p[i];
566     if (c != ' ' && c != '\n' && c != '\t')
567       break;
568   }
569   i++;
570   if ((unsigned)i != _len)
571   {
572     _chars[i] = 0;
573     _len = i;
574   }
575 }
576 
InsertAtFront(char c)577 void AString::InsertAtFront(char c)
578 {
579   if (_limit == _len)
580     Grow_1();
581   MoveItems(1, 0);
582   _chars[0] = c;
583   _len++;
584 }
585 
586 /*
587 void AString::Insert(unsigned index, char c)
588 {
589   InsertSpace(index, 1);
590   _chars[index] = c;
591   _len++;
592 }
593 */
594 
Insert(unsigned index,const char * s)595 void AString::Insert(unsigned index, const char *s)
596 {
597   unsigned num = MyStringLen(s);
598   if (num != 0)
599   {
600     InsertSpace(index, num);
601     memcpy(_chars + index, s, num);
602     _len += num;
603   }
604 }
605 
Insert(unsigned index,const AString & s)606 void AString::Insert(unsigned index, const AString &s)
607 {
608   unsigned num = s.Len();
609   if (num != 0)
610   {
611     InsertSpace(index, num);
612     memcpy(_chars + index, s, num);
613     _len += num;
614   }
615 }
616 
RemoveChar(char ch)617 void AString::RemoveChar(char ch) throw()
618 {
619   int pos = Find(ch);
620   if (pos < 0)
621     return;
622   const char *src = _chars;
623   char *dest = _chars + pos;
624   pos++;
625   unsigned len = _len;
626   for (; (unsigned)pos < len; pos++)
627   {
628     char c = src[(unsigned)pos];
629     if (c != ch)
630       *dest++ = c;
631   }
632   *dest = 0;
633   _len = (unsigned)(dest - _chars);
634 }
635 
636 // !!!!!!!!!!!!!!! test it if newChar = '\0'
Replace(char oldChar,char newChar)637 void AString::Replace(char oldChar, char newChar) throw()
638 {
639   if (oldChar == newChar)
640     return; // 0;
641   // unsigned number = 0;
642   int pos = 0;
643   while ((unsigned)pos < _len)
644   {
645     pos = Find(oldChar, pos);
646     if (pos < 0)
647       break;
648     _chars[pos] = newChar;
649     pos++;
650     // number++;
651   }
652   return; //  number;
653 }
654 
Replace(const AString & oldString,const AString & newString)655 void AString::Replace(const AString &oldString, const AString &newString)
656 {
657   if (oldString.IsEmpty())
658     return; // 0;
659   if (oldString == newString)
660     return; // 0;
661   unsigned oldLen = oldString.Len();
662   unsigned newLen = newString.Len();
663   // unsigned number = 0;
664   int pos = 0;
665   while ((unsigned)pos < _len)
666   {
667     pos = Find(oldString, pos);
668     if (pos < 0)
669       break;
670     Delete(pos, oldLen);
671     Insert(pos, newString);
672     pos += newLen;
673     // number++;
674   }
675   // return number;
676 }
677 
Delete(unsigned index)678 void AString::Delete(unsigned index) throw()
679 {
680   MoveItems(index, index + 1);
681   _len--;
682 }
683 
Delete(unsigned index,unsigned count)684 void AString::Delete(unsigned index, unsigned count) throw()
685 {
686   if (index + count > _len)
687     count = _len - index;
688   if (count > 0)
689   {
690     MoveItems(index, index + count);
691     _len -= count;
692   }
693 }
694 
DeleteFrontal(unsigned num)695 void AString::DeleteFrontal(unsigned num) throw()
696 {
697   if (num != 0)
698   {
699     MoveItems(0, num);
700     _len -= num;
701   }
702 }
703 
704 /*
705 AString operator+(const AString &s1, const AString &s2)
706 {
707   AString result(s1);
708   result += s2;
709   return result;
710 }
711 
712 AString operator+(const AString &s, const char *chars)
713 {
714   AString result(s);
715   result += chars;
716   return result;
717 }
718 
719 AString operator+(const char *chars, const AString &s)
720 {
721   AString result(chars);
722   result += s;
723   return result;
724 }
725 
726 AString operator+(const AString &s, char c)
727 {
728   AString result(s);
729   result += c;
730   return result;
731 }
732 */
733 
734 /*
735 AString operator+(char c, const AString &s)
736 {
737   AString result(c);
738   result += s;
739   return result;
740 }
741 */
742 
743 
744 
745 
746 // ---------- UString ----------
747 
InsertSpace(unsigned index,unsigned size)748 void UString::InsertSpace(unsigned index, unsigned size)
749 {
750   Grow(size);
751   MoveItems(index + size, index);
752 }
753 
ReAlloc(unsigned newLimit)754 void UString::ReAlloc(unsigned newLimit)
755 {
756   if (newLimit < _len || newLimit >= 0x20000000) throw 20130221;
757   // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, _len + 1);
758   wchar_t *newBuf = MY_STRING_NEW(wchar_t, newLimit + 1);
759   wmemcpy(newBuf, _chars, _len + 1);
760   MY_STRING_DELETE(_chars);
761   _chars = newBuf;
762 
763   _limit = newLimit;
764 }
765 
SetStartLen(unsigned len)766 void UString::SetStartLen(unsigned len)
767 {
768   _chars = 0;
769   _chars = MY_STRING_NEW(wchar_t, len + 1);
770   _len = len;
771   _limit = len;
772 }
773 
Grow_1()774 void UString::Grow_1()
775 {
776   unsigned next = _len;
777   next += next / 2;
778   next += 16;
779   next &= ~(unsigned)15;
780   ReAlloc(next - 1);
781 }
782 
Grow(unsigned n)783 void UString::Grow(unsigned n)
784 {
785   unsigned freeSize = _limit - _len;
786   if (n <= freeSize)
787     return;
788 
789   unsigned next = _len + n;
790   next += next / 2;
791   next += 16;
792   next &= ~(unsigned)15;
793   ReAlloc(next - 1);
794 }
795 
796 
UString(unsigned num,const wchar_t * s)797 UString::UString(unsigned num, const wchar_t *s)
798 {
799   unsigned len = MyStringLen(s);
800   if (num > len)
801     num = len;
802   SetStartLen(num);
803   wmemcpy(_chars, s, num);
804   _chars[num] = 0;
805 }
806 
807 
UString(unsigned num,const UString & s)808 UString::UString(unsigned num, const UString &s)
809 {
810   if (num > s._len)
811     num = s._len;
812   SetStartLen(num);
813   wmemcpy(_chars, s._chars, num);
814   _chars[num] = 0;
815 }
816 
UString(const UString & s,wchar_t c)817 UString::UString(const UString &s, wchar_t c)
818 {
819   SetStartLen(s.Len() + 1);
820   wchar_t *chars = _chars;
821   unsigned len = s.Len();
822   wmemcpy(chars, s, len);
823   chars[len] = c;
824   chars[len + 1] = 0;
825 }
826 
UString(const wchar_t * s1,unsigned num1,const wchar_t * s2,unsigned num2)827 UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2)
828 {
829   SetStartLen(num1 + num2);
830   wchar_t *chars = _chars;
831   wmemcpy(chars, s1, num1);
832   wmemcpy(chars + num1, s2, num2 + 1);
833 }
834 
operator +(const UString & s1,const UString & s2)835 UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); }
operator +(const UString & s1,const wchar_t * s2)836 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)837 UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); }
838 
UString()839 UString::UString()
840 {
841   _chars = 0;
842   _chars = MY_STRING_NEW(wchar_t, 4);
843   _len = 0;
844   _limit = 4 - 1;
845   _chars[0] = 0;
846 }
847 
UString(wchar_t c)848 UString::UString(wchar_t c)
849 {
850   SetStartLen(1);
851   _chars[0] = c;
852   _chars[1] = 0;
853 }
854 
UString(const wchar_t * s)855 UString::UString(const wchar_t *s)
856 {
857   SetStartLen(MyStringLen(s));
858   MyStringCopy(_chars, s);
859 }
860 
UString(const UString & s)861 UString::UString(const UString &s)
862 {
863   SetStartLen(s._len);
864   MyStringCopy(_chars, s._chars);
865 }
866 
operator =(wchar_t c)867 UString &UString::operator=(wchar_t c)
868 {
869   if (1 > _limit)
870   {
871     wchar_t *newBuf = MY_STRING_NEW(wchar_t, 1 + 1);
872     MY_STRING_DELETE(_chars);
873     _chars = newBuf;
874     _limit = 1;
875   }
876   _len = 1;
877   _chars[0] = c;
878   _chars[1] = 0;
879   return *this;
880 }
881 
operator =(const wchar_t * s)882 UString &UString::operator=(const wchar_t *s)
883 {
884   unsigned len = MyStringLen(s);
885   if (len > _limit)
886   {
887     wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
888     MY_STRING_DELETE(_chars);
889     _chars = newBuf;
890     _limit = len;
891   }
892   _len = len;
893   MyStringCopy(_chars, s);
894   return *this;
895 }
896 
operator =(const UString & s)897 UString &UString::operator=(const UString &s)
898 {
899   if (&s == this)
900     return *this;
901   unsigned len = s._len;
902   if (len > _limit)
903   {
904     wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
905     MY_STRING_DELETE(_chars);
906     _chars = newBuf;
907     _limit = len;
908   }
909   _len = len;
910   MyStringCopy(_chars, s._chars);
911   return *this;
912 }
913 
operator +=(const wchar_t * s)914 UString &UString::operator+=(const wchar_t *s)
915 {
916   unsigned len = MyStringLen(s);
917   Grow(len);
918   MyStringCopy(_chars + _len, s);
919   _len += len;
920   return *this;
921 }
922 
operator +=(const UString & s)923 UString &UString::operator+=(const UString &s)
924 {
925   Grow(s._len);
926   MyStringCopy(_chars + _len, s._chars);
927   _len += s._len;
928   return *this;
929 }
930 
SetFrom(const wchar_t * s,unsigned len)931 void UString::SetFrom(const wchar_t *s, unsigned len) // no check
932 {
933   if (len > _limit)
934   {
935     wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
936     MY_STRING_DELETE(_chars);
937     _chars = newBuf;
938     _limit = len;
939   }
940   wmemcpy(_chars, s, len);
941   _chars[len] = 0;
942   _len = len;
943 }
944 
SetFromAscii(const char * s)945 void UString::SetFromAscii(const char *s)
946 {
947   unsigned len = MyStringLen(s);
948   if (len > _limit)
949   {
950     wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
951     MY_STRING_DELETE(_chars);
952     _chars = newBuf;
953     _limit = len;
954   }
955   wchar_t *chars = _chars;
956   for (unsigned i = 0; i < len; i++)
957     chars[i] = s[i];
958   chars[len] = 0;
959   _len = len;
960 }
961 
AddAsciiStr(const char * s)962 void UString::AddAsciiStr(const char *s)
963 {
964   unsigned len = MyStringLen(s);
965   Grow(len);
966   wchar_t *chars = _chars + _len;
967   for (unsigned i = 0; i < len; i++)
968     chars[i] = s[i];
969   chars[len] = 0;
970   _len += len;
971 }
972 
973 
974 
Find(const UString & s,unsigned startIndex) const975 int UString::Find(const UString &s, unsigned startIndex) const throw()
976 {
977   if (s.IsEmpty())
978     return startIndex;
979   for (; startIndex < _len; startIndex++)
980   {
981     unsigned j;
982     for (j = 0; j < s._len && startIndex + j < _len; j++)
983       if (_chars[startIndex + j] != s._chars[j])
984         break;
985     if (j == s._len)
986       return (int)startIndex;
987   }
988   return -1;
989 }
990 
ReverseFind(wchar_t c) const991 int UString::ReverseFind(wchar_t c) const throw()
992 {
993   if (_len == 0)
994     return -1;
995   const wchar_t *p = _chars + _len - 1;
996   for (;;)
997   {
998     if (*p == c)
999       return (int)(p - _chars);
1000     if (p == _chars)
1001       return -1;
1002     p--;
1003   }
1004 }
1005 
TrimLeft()1006 void UString::TrimLeft() throw()
1007 {
1008   const wchar_t *p = _chars;
1009   for (;; p++)
1010   {
1011     wchar_t c = *p;
1012     if (c != ' ' && c != '\n' && c != '\t')
1013       break;
1014   }
1015   unsigned pos = (unsigned)(p - _chars);
1016   if (pos != 0)
1017   {
1018     MoveItems(0, pos);
1019     _len -= pos;
1020   }
1021 }
1022 
TrimRight()1023 void UString::TrimRight() throw()
1024 {
1025   const wchar_t *p = _chars;
1026   int i;
1027   for (i = _len - 1; i >= 0; i--)
1028   {
1029     wchar_t c = p[i];
1030     if (c != ' ' && c != '\n' && c != '\t')
1031       break;
1032   }
1033   i++;
1034   if ((unsigned)i != _len)
1035   {
1036     _chars[i] = 0;
1037     _len = i;
1038   }
1039 }
1040 
InsertAtFront(wchar_t c)1041 void UString::InsertAtFront(wchar_t c)
1042 {
1043   if (_limit == _len)
1044     Grow_1();
1045   MoveItems(1, 0);
1046   _chars[0] = c;
1047   _len++;
1048 }
1049 
1050 /*
1051 void UString::Insert(unsigned index, wchar_t c)
1052 {
1053   InsertSpace(index, 1);
1054   _chars[index] = c;
1055   _len++;
1056 }
1057 */
1058 
Insert(unsigned index,const wchar_t * s)1059 void UString::Insert(unsigned index, const wchar_t *s)
1060 {
1061   unsigned num = MyStringLen(s);
1062   if (num != 0)
1063   {
1064     InsertSpace(index, num);
1065     wmemcpy(_chars + index, s, num);
1066     _len += num;
1067   }
1068 }
1069 
Insert(unsigned index,const UString & s)1070 void UString::Insert(unsigned index, const UString &s)
1071 {
1072   unsigned num = s.Len();
1073   if (num != 0)
1074   {
1075     InsertSpace(index, num);
1076     wmemcpy(_chars + index, s, num);
1077     _len += num;
1078   }
1079 }
1080 
RemoveChar(wchar_t ch)1081 void UString::RemoveChar(wchar_t ch) throw()
1082 {
1083   int pos = Find(ch);
1084   if (pos < 0)
1085     return;
1086   const wchar_t *src = _chars;
1087   wchar_t *dest = _chars + pos;
1088   pos++;
1089   unsigned len = _len;
1090   for (; (unsigned)pos < len; pos++)
1091   {
1092     wchar_t c = src[(unsigned)pos];
1093     if (c != ch)
1094       *dest++ = c;
1095   }
1096   *dest = 0;
1097   _len = (unsigned)(dest - _chars);
1098 }
1099 
1100 // !!!!!!!!!!!!!!! test it if newChar = '\0'
Replace(wchar_t oldChar,wchar_t newChar)1101 void UString::Replace(wchar_t oldChar, wchar_t newChar) throw()
1102 {
1103   if (oldChar == newChar)
1104     return; // 0;
1105   // unsigned number = 0;
1106   int pos = 0;
1107   while ((unsigned)pos < _len)
1108   {
1109     pos = Find(oldChar, pos);
1110     if (pos < 0)
1111       break;
1112     _chars[pos] = newChar;
1113     pos++;
1114     // number++;
1115   }
1116   return; //  number;
1117 }
1118 
Replace(const UString & oldString,const UString & newString)1119 void UString::Replace(const UString &oldString, const UString &newString)
1120 {
1121   if (oldString.IsEmpty())
1122     return; // 0;
1123   if (oldString == newString)
1124     return; // 0;
1125   unsigned oldLen = oldString.Len();
1126   unsigned newLen = newString.Len();
1127   // unsigned number = 0;
1128   int pos = 0;
1129   while ((unsigned)pos < _len)
1130   {
1131     pos = Find(oldString, pos);
1132     if (pos < 0)
1133       break;
1134     Delete(pos, oldLen);
1135     Insert(pos, newString);
1136     pos += newLen;
1137     // number++;
1138   }
1139   // return number;
1140 }
1141 
Delete(unsigned index)1142 void UString::Delete(unsigned index) throw()
1143 {
1144   MoveItems(index, index + 1);
1145   _len--;
1146 }
1147 
Delete(unsigned index,unsigned count)1148 void UString::Delete(unsigned index, unsigned count) throw()
1149 {
1150   if (index + count > _len)
1151     count = _len - index;
1152   if (count > 0)
1153   {
1154     MoveItems(index, index + count);
1155     _len -= count;
1156   }
1157 }
1158 
DeleteFrontal(unsigned num)1159 void UString::DeleteFrontal(unsigned num) throw()
1160 {
1161   if (num != 0)
1162   {
1163     MoveItems(0, num);
1164     _len -= num;
1165   }
1166 }
1167 
1168 
1169 // ----------------------------------------
1170 
1171 /*
1172 int MyStringCompareNoCase(const char *s1, const char *s2)
1173 {
1174   return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));
1175 }
1176 */
1177 
GetCurrentCodePage()1178 static inline UINT GetCurrentCodePage()
1179 {
1180   #if defined(UNDER_CE) || !defined(_WIN32)
1181   return CP_ACP;
1182   #else
1183   return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP;
1184   #endif
1185 }
1186 
1187 #ifdef USE_UNICODE_FSTRING
1188 
1189 #ifndef _UNICODE
1190 
fs2fas(CFSTR s)1191 AString fs2fas(CFSTR s)
1192 {
1193   return UnicodeStringToMultiByte(s, GetCurrentCodePage());
1194 }
1195 
fas2fs(const AString & s)1196 FString fas2fs(const AString &s)
1197 {
1198   return MultiByteToUnicodeString(s, GetCurrentCodePage());
1199 }
1200 
1201 #endif
1202 
1203 #else
1204 
fs2us(const FString & s)1205 UString fs2us(const FString &s)
1206 {
1207   return MultiByteToUnicodeString((AString)s, GetCurrentCodePage());
1208 }
1209 
us2fs(const wchar_t * s)1210 FString us2fs(const wchar_t *s)
1211 {
1212   return UnicodeStringToMultiByte(s, GetCurrentCodePage());
1213 }
1214 
1215 #endif
1216