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