1 #ifndef __CSTRINGT_H__ 2 #define __CSTRINGT_H__ 3 4 #pragma once 5 #include <atlsimpstr.h> 6 #include <stddef.h> 7 #include <stdio.h> 8 #include <wchar.h> 9 #include <atlmem.h> 10 11 namespace ATL 12 { 13 14 inline UINT WINAPI _AtlGetConversionACP() throw() 15 { 16 #ifdef _CONVERSION_DONT_USE_THREAD_LOCALE 17 return CP_ACP; 18 #else 19 return CP_THREAD_ACP; 20 #endif 21 } 22 23 24 template<typename _CharType = wchar_t> 25 class ChTraitsCRT : public ChTraitsBase<_CharType> 26 { 27 public: 28 29 static int __cdecl GetBaseTypeLength(_In_z_ LPCWSTR pszSource) throw() 30 { 31 if (pszSource == NULL) return -1; 32 return static_cast<int>(wcslen(pszSource)); 33 } 34 35 static int __cdecl GetBaseTypeLength(_In_z_ LPCSTR pszSource) throw() 36 { 37 if (pszSource == NULL) return 0; 38 return ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSource, -1, NULL, 0) - 1; 39 } 40 41 static int __cdecl GetBaseTypeLength( 42 _In_reads_(nLength) LPCWSTR pszSource, 43 _In_ int nLength) throw() 44 { 45 return nLength; 46 } 47 48 static int __cdecl GetBaseTypeLength( 49 _In_reads_(nLength) LPCSTR pszSource, 50 _In_ int nLength) throw() 51 { 52 return ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0); 53 } 54 55 static void __cdecl ConvertToBaseType( 56 _Out_writes_(nDestLength) LPWSTR pszDest, 57 _In_ int nDestLength, 58 _In_ LPCWSTR pszSrc, 59 _In_ int nSrcLength = -1) 60 { 61 if (nSrcLength == -1) 62 nSrcLength = 1 + GetBaseTypeLength(pszSrc); 63 64 wmemcpy(pszDest, pszSrc, nSrcLength); 65 } 66 67 static void __cdecl ConvertToBaseType( 68 _Out_writes_(nDestLength) LPWSTR pszDest, 69 _In_ int nDestLength, 70 _In_ LPCSTR pszSrc, 71 _In_ int nSrcLength = -1) 72 { 73 if (nSrcLength == -1) 74 nSrcLength = 1 + GetBaseTypeLength(pszSrc); 75 76 ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength); 77 } 78 79 static void __cdecl MakeLower( 80 _Out_writes_(nSrcLength) LPWSTR pszSource, 81 _In_ int nSrcLength) 82 { 83 ::CharLowerBuffW(pszSource, nSrcLength); 84 } 85 86 static DWORD GetEnvironmentVariable( 87 _In_z_ LPCWSTR pszVar, 88 _Out_writes_opt_(nBufLength) LPWSTR pszBuf, 89 _In_opt_ int nBufLength) 90 { 91 return ::GetEnvironmentVariableW(pszVar, pszBuf, nBufLength); 92 } 93 94 static void __cdecl MakeUpper( 95 _Out_writes_(nSrcLength) LPWSTR pszSource, 96 _In_ int nSrcLength) 97 { 98 ::CharUpperBuffW(pszSource, nSrcLength); 99 } 100 101 static LPWSTR __cdecl FindString( 102 _In_z_ LPCWSTR pszSource, 103 _In_z_ LPCWSTR pszSub) 104 { 105 return ::wcsstr(pszSource, pszSub); 106 } 107 108 static LPWSTR __cdecl FindChar( 109 _In_z_ LPCWSTR pszSource, 110 _In_ WCHAR ch) 111 { 112 return ::wcschr(pszSource, ch); 113 } 114 115 static LPWSTR __cdecl FindCharReverse( 116 _In_z_ LPCWSTR pszSource, 117 _In_ WCHAR ch) 118 { 119 return ::wcsrchr(pszSource, ch); 120 } 121 122 static LPWSTR __cdecl FindOneOf( 123 _In_z_ LPCWSTR pszSource, 124 _In_z_ LPCWSTR pszCharSet) 125 { 126 return ::wcspbrk(pszSource, pszCharSet); 127 } 128 129 static int __cdecl Compare( 130 _In_z_ LPCWSTR psz1, 131 _In_z_ LPCWSTR psz2) 132 { 133 return ::wcscmp(psz1, psz2); 134 } 135 136 static int __cdecl CompareNoCase( 137 _In_z_ LPCWSTR psz1, 138 _In_z_ LPCWSTR psz2) 139 { 140 return ::_wcsicmp(psz1, psz2); 141 } 142 143 static int __cdecl FormatV( 144 _In_opt_z_ LPWSTR pszDest, 145 _In_z_ LPCWSTR pszFormat, 146 _In_ va_list args) 147 { 148 if (pszDest == NULL) 149 return ::_vscwprintf(pszFormat, args); 150 return ::vswprintf(pszDest, pszFormat, args); 151 } 152 153 static BSTR __cdecl AllocSysString( 154 _In_z_ LPCWSTR pszSource, 155 _In_ int nLength) 156 { 157 return ::SysAllocStringLen(pszSource, nLength); 158 } 159 }; 160 161 162 // Template specialization 163 164 template<> 165 class ChTraitsCRT<char> : public ChTraitsBase<char> 166 { 167 public: 168 169 static int __cdecl GetBaseTypeLength(_In_z_ LPCWSTR pszSource) throw() 170 { 171 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, -1, NULL, 0, NULL, NULL) - 1; 172 } 173 174 static int __cdecl GetBaseTypeLength(_In_z_ LPCSTR pszSource) throw() 175 { 176 if (pszSource == NULL) return 0; 177 return static_cast<int>(strlen(pszSource)); 178 } 179 180 static int __cdecl GetBaseTypeLength( 181 _In_reads_(nLength) LPCWSTR pszSource, 182 _In_ int nLength) throw() 183 { 184 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0, NULL, NULL); 185 } 186 187 static int __cdecl GetBaseTypeLength( 188 _In_reads_(nLength) LPCSTR pszSource, 189 _In_ int nLength) throw() 190 { 191 return nLength; 192 } 193 194 static void __cdecl ConvertToBaseType( 195 _Out_writes_(nDestLength) LPSTR pszDest, 196 _In_ int nDestLength, 197 _In_ LPCWSTR pszSrc, 198 _In_ int nSrcLength = -1) 199 { 200 if (nSrcLength == -1) 201 nSrcLength = 1 + GetBaseTypeLength(pszSrc); 202 203 ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL); 204 } 205 206 static void __cdecl ConvertToBaseType( 207 _Out_writes_(nDestLength) LPSTR pszDest, 208 _In_ int nDestLength, 209 _In_ LPCSTR pszSrc, 210 _In_ int nSrcLength = -1) 211 { 212 if (nSrcLength == -1) 213 nSrcLength = 1 + GetBaseTypeLength(pszSrc); 214 215 memcpy(pszDest, pszSrc, nSrcLength); 216 } 217 218 static void __cdecl MakeLower( 219 _Out_writes_(nSrcLength) LPSTR pszSource, 220 _In_ int nSrcLength) 221 { 222 ::CharLowerBuffA(pszSource, nSrcLength); 223 } 224 225 static DWORD GetEnvironmentVariable( 226 _In_z_ LPCSTR pszVar, 227 _Out_writes_opt_(nBufLength) LPSTR pszBuf, 228 _In_opt_ int nBufLength) 229 { 230 return ::GetEnvironmentVariableA(pszVar, pszBuf, nBufLength); 231 } 232 233 static void __cdecl MakeUpper( 234 _Out_writes_(nSrcLength) LPSTR pszSource, 235 _In_ int nSrcLength) 236 { 237 ::CharUpperBuffA(pszSource, nSrcLength); 238 } 239 240 static LPSTR __cdecl FindString( 241 _In_z_ LPCSTR pszSource, 242 _In_z_ LPCSTR pszSub) 243 { 244 return ::strstr(pszSource, pszSub); 245 } 246 247 static LPSTR __cdecl FindChar( 248 _In_z_ LPCSTR pszSource, 249 _In_ CHAR ch) 250 { 251 return ::strchr(pszSource, ch); 252 } 253 254 static LPSTR __cdecl FindCharReverse( 255 _In_z_ LPCSTR pszSource, 256 _In_ CHAR ch) 257 { 258 return ::strrchr(pszSource, ch); 259 } 260 261 static LPSTR __cdecl FindOneOf( 262 _In_z_ LPCSTR pszSource, 263 _In_z_ LPCSTR pszCharSet) 264 { 265 return ::strpbrk(pszSource, pszCharSet); 266 } 267 268 static int __cdecl Compare( 269 _In_z_ LPCSTR psz1, 270 _In_z_ LPCSTR psz2) 271 { 272 return ::strcmp(psz1, psz2); 273 } 274 275 static int __cdecl CompareNoCase( 276 _In_z_ LPCSTR psz1, 277 _In_z_ LPCSTR psz2) 278 { 279 return ::_stricmp(psz1, psz2); 280 } 281 282 static int __cdecl FormatV( 283 _In_opt_z_ LPSTR pszDest, 284 _In_z_ LPCSTR pszFormat, 285 _In_ va_list args) 286 { 287 if (pszDest == NULL) 288 return ::_vscprintf(pszFormat, args); 289 return ::vsprintf(pszDest, pszFormat, args); 290 } 291 292 static BSTR __cdecl AllocSysString( 293 _In_z_ LPCSTR pszSource, 294 _In_ int nLength) 295 { 296 int nLen = ChTraitsCRT<wchar_t>::GetBaseTypeLength(pszSource, nLength); 297 BSTR bstr = ::SysAllocStringLen(NULL, nLen); 298 if (bstr) 299 { 300 ChTraitsCRT<wchar_t>::ConvertToBaseType(bstr, nLen, pszSource, nLength); 301 } 302 return bstr; 303 } 304 305 }; 306 307 308 namespace _CSTRING_IMPL_ 309 { 310 template <typename _CharType, class StringTraits> 311 struct _MFCDLLTraitsCheck 312 { 313 const static bool c_bIsMFCDLLTraits = false; 314 }; 315 } 316 317 318 // TODO: disable conversion functions when _CSTRING_DISABLE_NARROW_WIDE_CONVERSION is defined. 319 320 template <typename BaseType, class StringTraits> 321 class CStringT : 322 public CSimpleStringT <BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits> 323 { 324 public: 325 typedef CSimpleStringT<BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits> CThisSimpleString; 326 typedef StringTraits StrTraits; 327 typedef typename CThisSimpleString::XCHAR XCHAR; 328 typedef typename CThisSimpleString::PXSTR PXSTR; 329 typedef typename CThisSimpleString::PCXSTR PCXSTR; 330 typedef typename CThisSimpleString::YCHAR YCHAR; 331 typedef typename CThisSimpleString::PYSTR PYSTR; 332 typedef typename CThisSimpleString::PCYSTR PCYSTR; 333 334 public: 335 CStringT() throw() : 336 CThisSimpleString(StringTraits::GetDefaultManager()) 337 { 338 } 339 340 explicit CStringT( _In_ IAtlStringMgr* pStringMgr) throw() : 341 CThisSimpleString(pStringMgr) 342 { 343 } 344 345 static void __cdecl Construct(_In_ CStringT* pString) 346 { 347 new(pString) CStringT; 348 } 349 350 CStringT(_In_ const CStringT& strSrc) : 351 CThisSimpleString(strSrc) 352 { 353 } 354 355 CStringT(_In_ const CThisSimpleString& strSrc) : 356 CThisSimpleString(strSrc) 357 { 358 } 359 360 template<class StringTraits_> 361 CStringT(_In_ const CStringT<YCHAR, StringTraits_> & strSrc) : 362 CThisSimpleString(StringTraits::GetDefaultManager()) 363 { 364 *this = static_cast<const YCHAR*>(strSrc); 365 } 366 367 protected: 368 /* helper function */ 369 template <typename T_CHAR> 370 void LoadFromPtr_(_In_opt_z_ const T_CHAR* pszSrc) 371 { 372 if (pszSrc == NULL) 373 return; 374 if (IS_INTRESOURCE(pszSrc)) 375 LoadString(LOWORD(pszSrc)); 376 else 377 *this = pszSrc; 378 } 379 380 public: 381 CStringT(_In_opt_z_ const XCHAR* pszSrc) : 382 CThisSimpleString(StringTraits::GetDefaultManager()) 383 { 384 LoadFromPtr_(pszSrc); 385 } 386 387 CStringT(_In_opt_z_ const XCHAR* pszSrc, 388 _In_ IAtlStringMgr* pStringMgr) : CThisSimpleString(pStringMgr) 389 { 390 LoadFromPtr_(pszSrc); 391 } 392 393 CStringT(_In_opt_z_ const YCHAR* pszSrc) : 394 CThisSimpleString(StringTraits::GetDefaultManager()) 395 { 396 LoadFromPtr_(pszSrc); 397 } 398 399 CStringT(_In_opt_z_ const YCHAR* pszSrc, 400 _In_ IAtlStringMgr* pStringMgr) : CThisSimpleString(pStringMgr) 401 { 402 LoadFromPtr_(pszSrc); 403 } 404 405 CStringT(_In_reads_z_(nLength) const XCHAR* pch, 406 _In_ int nLength) : 407 CThisSimpleString(pch, nLength, StringTraits::GetDefaultManager()) 408 { 409 } 410 411 CStringT(_In_reads_z_(nLength) const YCHAR* pch, 412 _In_ int nLength) : 413 CThisSimpleString(pch, nLength, StringTraits::GetDefaultManager()) 414 { 415 } 416 417 CStringT& operator=(_In_ const CStringT& strSrc) 418 { 419 CThisSimpleString::operator=(strSrc); 420 return *this; 421 } 422 423 CStringT& operator=(_In_opt_z_ PCXSTR pszSrc) 424 { 425 CThisSimpleString::operator=(pszSrc); 426 return *this; 427 } 428 429 CStringT& operator=(_In_opt_z_ PCYSTR pszSrc) 430 { 431 int length = pszSrc ? StringTraits::GetBaseTypeLength(pszSrc) : 0; 432 if (length > 0) 433 { 434 PXSTR result = CThisSimpleString::GetBuffer(length); 435 StringTraits::ConvertToBaseType(result, length, pszSrc); 436 CThisSimpleString::ReleaseBufferSetLength(length); 437 } 438 else 439 { 440 CThisSimpleString::Empty(); 441 } 442 return *this; 443 } 444 445 CStringT& operator=(_In_ const CThisSimpleString &strSrc) 446 { 447 CThisSimpleString::operator=(strSrc); 448 return *this; 449 } 450 451 friend bool operator==(const CStringT& str1, const CStringT& str2) throw() 452 { 453 return str1.Compare(str2) == 0; 454 } 455 456 friend bool operator==(const CStringT& str1, PCXSTR psz2) throw() 457 { 458 return str1.Compare(psz2) == 0; 459 } 460 461 friend bool operator==(const CStringT& str1, PCYSTR psz2) throw() 462 { 463 CStringT tmp(psz2, str1.GetManager()); 464 return tmp.Compare(str1) == 0; 465 } 466 467 friend bool operator==(const CStringT& str1, XCHAR ch2) throw() 468 { 469 return str1.GetLength() == 1 && str1[0] == ch2; 470 } 471 472 friend bool operator==(PCXSTR psz1, const CStringT& str2) throw() 473 { 474 return str2.Compare(psz1) == 0; 475 } 476 477 friend bool operator==(PCYSTR psz1, const CStringT& str2) throw() 478 { 479 CStringT tmp(psz1, str2.GetManager()); 480 return tmp.Compare(str2) == 0; 481 } 482 483 friend bool operator==(XCHAR ch1, const CStringT& str2) throw() 484 { 485 return str2.GetLength() == 1 && str2[0] == ch1; 486 } 487 488 CStringT& operator+=(_In_ const CThisSimpleString& str) 489 { 490 CThisSimpleString::operator+=(str); 491 return *this; 492 } 493 494 CStringT& operator+=(_In_z_ PCXSTR pszSrc) 495 { 496 CThisSimpleString::operator+=(pszSrc); 497 return *this; 498 } 499 500 CStringT& operator+=(_In_ XCHAR ch) 501 { 502 CThisSimpleString::operator+=(ch); 503 return *this; 504 } 505 506 BOOL LoadString(_In_ UINT nID) 507 { 508 return LoadString(_AtlBaseModule.GetResourceInstance(), nID); 509 } 510 511 _Check_return_ BOOL LoadString(_In_ HINSTANCE hInstance, 512 _In_ UINT nID) 513 { 514 const ATLSTRINGRESOURCEIMAGE* pImage = AtlGetStringResourceImage(hInstance, nID); 515 if (pImage == NULL) return FALSE; 516 517 int nLength = StringTraits::GetBaseTypeLength(pImage->achString, pImage->nLength); 518 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 519 StringTraits::ConvertToBaseType(pszBuffer, nLength, pImage->achString, pImage->nLength); 520 CThisSimpleString::ReleaseBufferSetLength(nLength); 521 522 return TRUE; 523 } 524 525 BOOL GetEnvironmentVariable(_In_z_ PCXSTR pszVar) 526 { 527 int nLength = StringTraits::GetEnvironmentVariable(pszVar, NULL, 0); 528 529 if (nLength > 0) 530 { 531 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 532 StringTraits::GetEnvironmentVariable(pszVar, pszBuffer, nLength); 533 CThisSimpleString::ReleaseBuffer(); 534 return TRUE; 535 } 536 537 CThisSimpleString::Empty(); 538 return FALSE; 539 } 540 541 CStringT& MakeLower() 542 { 543 int nLength = CThisSimpleString::GetLength(); 544 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 545 546 StringTraits::MakeLower(pszBuffer, nLength); 547 CThisSimpleString::ReleaseBufferSetLength(nLength); 548 549 return *this; 550 } 551 552 CStringT& MakeUpper() 553 { 554 int nLength = CThisSimpleString::GetLength(); 555 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 556 557 StringTraits::MakeUpper(pszBuffer, nLength); 558 CThisSimpleString::ReleaseBufferSetLength(nLength); 559 560 return *this; 561 } 562 563 int Find(_In_ PCXSTR pszSub, _In_opt_ int iStart = 0) const throw() 564 { 565 int nLength = CThisSimpleString::GetLength(); 566 567 if (iStart >= nLength || iStart < 0) 568 return -1; 569 570 PCXSTR pszString = CThisSimpleString::GetString(); 571 PCXSTR pszResult = StringTraits::FindString(pszString + iStart, pszSub); 572 573 return pszResult ? ((int)(pszResult - pszString)) : -1; 574 } 575 576 int Find(_In_ XCHAR ch, _In_opt_ int iStart = 0) const throw() 577 { 578 int nLength = CThisSimpleString::GetLength(); 579 580 if (iStart >= nLength || iStart < 0) 581 return -1; 582 583 PCXSTR pszString = CThisSimpleString::GetString(); 584 PCXSTR pszResult = StringTraits::FindChar(pszString + iStart, ch); 585 586 return pszResult ? ((int)(pszResult - pszString)) : -1; 587 } 588 589 int FindOneOf(_In_ PCXSTR pszCharSet) const throw() 590 { 591 PCXSTR pszString = CThisSimpleString::GetString(); 592 PCXSTR pszResult = StringTraits::FindOneOf(pszString, pszCharSet); 593 594 return pszResult ? ((int)(pszResult - pszString)) : -1; 595 } 596 597 int ReverseFind(_In_ XCHAR ch) const throw() 598 { 599 PCXSTR pszString = CThisSimpleString::GetString(); 600 PCXSTR pszResult = StringTraits::FindCharReverse(pszString, ch); 601 602 return pszResult ? ((int)(pszResult - pszString)) : -1; 603 } 604 605 int Compare(_In_z_ PCXSTR psz) const 606 { 607 return StringTraits::Compare(CThisSimpleString::GetString(), psz); 608 } 609 610 int CompareNoCase(_In_z_ PCXSTR psz) const 611 { 612 return StringTraits::CompareNoCase(CThisSimpleString::GetString(), psz); 613 } 614 615 CStringT Mid(int iFirst, int nCount) const 616 { 617 int nLength = CThisSimpleString::GetLength(); 618 619 if (iFirst < 0) 620 iFirst = 0; 621 if (nCount < 0) 622 nCount = 0; 623 if (iFirst > nLength) 624 iFirst = nLength; 625 if (iFirst + nCount > nLength) 626 nCount = nLength - iFirst; 627 628 return CStringT(CThisSimpleString::GetString() + iFirst, nCount); 629 } 630 631 CStringT Mid(int iFirst) const 632 { 633 int nLength = CThisSimpleString::GetLength(); 634 635 if (iFirst < 0) 636 iFirst = 0; 637 if (iFirst > nLength) 638 iFirst = nLength; 639 640 return CStringT(CThisSimpleString::GetString() + iFirst, nLength - iFirst); 641 } 642 643 CStringT Left(int nCount) const 644 { 645 int nLength = CThisSimpleString::GetLength(); 646 647 if (nCount < 0) 648 nCount = 0; 649 if (nCount > nLength) 650 nCount = nLength; 651 652 return CStringT(CThisSimpleString::GetString(), nCount); 653 } 654 655 CStringT Right(int nCount) const 656 { 657 int nLength = CThisSimpleString::GetLength(); 658 659 if (nCount < 0) 660 nCount = 0; 661 if (nCount > nLength) 662 nCount = nLength; 663 664 return CStringT(CThisSimpleString::GetString() + nLength - nCount, nCount); 665 } 666 667 668 void __cdecl Format(UINT nFormatID, ...) 669 { 670 va_list args; 671 va_start(args, nFormatID); 672 CStringT formatString; 673 if (formatString.LoadString(nFormatID)) 674 FormatV(formatString, args); 675 va_end(args); 676 } 677 678 void __cdecl Format(PCXSTR pszFormat, ...) 679 { 680 va_list args; 681 va_start(args, pszFormat); 682 FormatV(pszFormat, args); 683 va_end(args); 684 } 685 686 void FormatV(PCXSTR pszFormat, va_list args) 687 { 688 int nLength = StringTraits::FormatV(NULL, pszFormat, args); 689 690 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 691 StringTraits::FormatV(pszBuffer, pszFormat, args); 692 CThisSimpleString::ReleaseBufferSetLength(nLength); 693 } 694 695 696 int Replace(PCXSTR pszOld, PCXSTR pszNew) 697 { 698 PCXSTR pszString = CThisSimpleString::GetString(); 699 700 const int nLength = CThisSimpleString::GetLength(); 701 const int nOldLen = StringTraits::GetBaseTypeLength(pszOld); 702 const int nNewLen = StringTraits::GetBaseTypeLength(pszNew); 703 const int nDiff = nNewLen - nOldLen; 704 int nResultLength = nLength; 705 706 PCXSTR pszFound; 707 while ((pszFound = StringTraits::FindString(pszString, pszOld))) 708 { 709 nResultLength += nDiff; 710 pszString = pszFound + nOldLen; 711 } 712 713 if (pszString == CThisSimpleString::GetString()) 714 return 0; 715 716 PXSTR pszResult = CThisSimpleString::GetBuffer(nResultLength); 717 PXSTR pszNext; 718 int nCount = 0, nRemaining = nLength; 719 while (nRemaining && (pszNext = StringTraits::FindString(pszResult, pszOld))) 720 { 721 nRemaining -= (pszNext - pszResult); 722 nRemaining -= nOldLen; 723 if (nRemaining > 0) 724 CThisSimpleString::CopyCharsOverlapped(pszNext + nNewLen, nRemaining + 1, pszNext + nOldLen, nRemaining + 1); 725 CThisSimpleString::CopyCharsOverlapped(pszNext, nNewLen, pszNew, nNewLen); 726 pszResult = pszNext + nNewLen; 727 nCount++; 728 } 729 730 CThisSimpleString::ReleaseBufferSetLength(nResultLength); 731 732 return nCount; 733 } 734 735 int Replace(XCHAR chOld, XCHAR chNew) 736 { 737 PCXSTR pszString = CThisSimpleString::GetString(); 738 PXSTR pszFirst = StringTraits::FindChar(pszString, chOld); 739 if (!pszFirst) 740 return 0; 741 742 int nLength = CThisSimpleString::GetLength(); 743 int nCount = 0; 744 745 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 746 pszFirst = pszBuffer + (pszFirst - pszString); 747 do { 748 *pszFirst = chNew; 749 ++nCount; 750 } while ((pszFirst = StringTraits::FindChar(pszFirst + 1, chOld))); 751 752 CThisSimpleString::ReleaseBufferSetLength(nLength); 753 return nCount; 754 } 755 756 757 static PCXSTR DefaultTrimChars() 758 { 759 static XCHAR str[] = { ' ', '\t', '\r', '\n', 0 }; 760 return str; 761 } 762 763 764 CStringT& TrimLeft() 765 { 766 return TrimLeft(DefaultTrimChars()); 767 } 768 769 CStringT& TrimLeft(XCHAR chTarget) 770 { 771 XCHAR str[2] = { chTarget, 0 }; 772 return TrimLeft(str); 773 } 774 775 CStringT& TrimLeft(PCXSTR pszTargets) 776 { 777 int nLength = CThisSimpleString::GetLength(); 778 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 779 int nCount = 0; 780 781 while (nCount < nLength && StringTraits::FindChar(pszTargets, pszBuffer[nCount])) 782 nCount++; 783 784 if (nCount > 0) 785 { 786 CThisSimpleString::CopyCharsOverlapped(pszBuffer, nLength - nCount, pszBuffer + nCount, nLength - nCount); 787 nLength -= nCount; 788 } 789 CThisSimpleString::ReleaseBufferSetLength(nLength); 790 791 return *this; 792 } 793 794 795 CStringT& TrimRight() 796 { 797 return TrimRight(DefaultTrimChars()); 798 } 799 800 CStringT& TrimRight(XCHAR chTarget) 801 { 802 XCHAR str[2] = { chTarget, 0 }; 803 return TrimRight(str); 804 } 805 806 CStringT& TrimRight(PCXSTR pszTargets) 807 { 808 int nLength = CThisSimpleString::GetLength(); 809 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 810 811 while (nLength > 0 && StringTraits::FindChar(pszTargets, pszBuffer[nLength-1])) 812 nLength--; 813 814 CThisSimpleString::ReleaseBufferSetLength(nLength); 815 816 return *this; 817 } 818 819 820 CStringT& Trim() 821 { 822 return Trim(DefaultTrimChars()); 823 } 824 825 CStringT& Trim(XCHAR chTarget) 826 { 827 XCHAR str[2] = { chTarget, 0 }; 828 return Trim(str); 829 } 830 831 CStringT& Trim(PCXSTR pszTargets) 832 { 833 return TrimRight(pszTargets).TrimLeft(pszTargets); 834 } 835 836 837 BSTR AllocSysString() const 838 { 839 return StringTraits::AllocSysString(CThisSimpleString::GetString(), CThisSimpleString::GetLength()); 840 } 841 842 843 }; 844 845 } //namespace ATL 846 847 #endif 848