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