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