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 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 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 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 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 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 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 184 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 199 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 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 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 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 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 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 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 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 314 void AString::InsertSpace(unsigned &index, unsigned size) 315 { 316 Grow(size); 317 MoveItems(index + size, index); 318 } 319 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 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 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 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 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 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 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 401 AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); } 402 AString operator+(const AString &s1, const char *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); } 403 AString operator+(const char *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); } 404 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 414 AString::AString(char c) 415 { 416 SetStartLen(1); 417 _chars[0] = c; 418 _chars[1] = 0; 419 } 420 421 AString::AString(const char *s) 422 { 423 SetStartLen(MyStringLen(s)); 424 MyStringCopy(_chars, s); 425 } 426 427 AString::AString(const AString &s) 428 { 429 SetStartLen(s._len); 430 MyStringCopy(_chars, s._chars); 431 } 432 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 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 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 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 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 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 511 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 527 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 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 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 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 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 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 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' 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 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 678 void AString::Delete(unsigned index) throw() 679 { 680 MoveItems(index, index + 1); 681 _len--; 682 } 683 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 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 748 void UString::InsertSpace(unsigned index, unsigned size) 749 { 750 Grow(size); 751 MoveItems(index + size, index); 752 } 753 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 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 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 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 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 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 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 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 835 UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); } 836 UString operator+(const UString &s1, const wchar_t *s2) { return UString(s1, s1.Len(), s2, MyStringLen(s2)); } 837 UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); } 838 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 848 UString::UString(wchar_t c) 849 { 850 SetStartLen(1); 851 _chars[0] = c; 852 _chars[1] = 0; 853 } 854 855 UString::UString(const wchar_t *s) 856 { 857 SetStartLen(MyStringLen(s)); 858 MyStringCopy(_chars, s); 859 } 860 861 UString::UString(const UString &s) 862 { 863 SetStartLen(s._len); 864 MyStringCopy(_chars, s._chars); 865 } 866 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 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 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 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 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 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 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 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 975 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 991 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 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 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 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 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 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 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' 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 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 1142 void UString::Delete(unsigned index) throw() 1143 { 1144 MoveItems(index, index + 1); 1145 _len--; 1146 } 1147 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 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 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 1191 AString fs2fas(CFSTR s) 1192 { 1193 return UnicodeStringToMultiByte(s, GetCurrentCodePage()); 1194 } 1195 1196 FString fas2fs(const AString &s) 1197 { 1198 return MultiByteToUnicodeString(s, GetCurrentCodePage()); 1199 } 1200 1201 #endif 1202 1203 #else 1204 1205 UString fs2us(const FString &s) 1206 { 1207 return MultiByteToUnicodeString((AString)s, GetCurrentCodePage()); 1208 } 1209 1210 FString us2fs(const wchar_t *s) 1211 { 1212 return UnicodeStringToMultiByte(s, GetCurrentCodePage()); 1213 } 1214 1215 #endif 1216