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