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() noexcept 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) noexcept 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) noexcept 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) noexcept 44 { 45 return nLength; 46 } 47 48 static int __cdecl GetBaseTypeLength( 49 _In_reads_(nLength) LPCSTR pszSource, 50 _In_ int nLength) noexcept 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_ LPWSTR pszSource, 103 _In_z_ LPCWSTR pszSub) 104 { 105 return ::wcsstr(pszSource, pszSub); 106 } 107 static LPCWSTR __cdecl FindString( 108 _In_z_ LPCWSTR pszSource, 109 _In_z_ LPCWSTR pszSub) 110 { 111 return ::wcsstr(pszSource, pszSub); 112 } 113 114 static LPWSTR __cdecl FindChar( 115 _In_z_ LPWSTR pszSource, 116 _In_ WCHAR ch) 117 { 118 return ::wcschr(pszSource, ch); 119 } 120 static LPCWSTR __cdecl FindChar( 121 _In_z_ LPCWSTR pszSource, 122 _In_ WCHAR ch) 123 { 124 return ::wcschr(pszSource, ch); 125 } 126 127 static LPWSTR __cdecl FindCharReverse( 128 _In_z_ LPWSTR pszSource, 129 _In_ WCHAR ch) 130 { 131 return ::wcsrchr(pszSource, ch); 132 } 133 static LPCWSTR __cdecl FindCharReverse( 134 _In_z_ LPCWSTR pszSource, 135 _In_ WCHAR ch) 136 { 137 return ::wcsrchr(pszSource, ch); 138 } 139 140 static LPWSTR __cdecl FindOneOf( 141 _In_z_ LPWSTR pszSource, 142 _In_z_ LPCWSTR pszCharSet) 143 { 144 return ::wcspbrk(pszSource, pszCharSet); 145 } 146 static LPCWSTR __cdecl FindOneOf( 147 _In_z_ LPCWSTR pszSource, 148 _In_z_ LPCWSTR pszCharSet) 149 { 150 return ::wcspbrk(pszSource, pszCharSet); 151 } 152 153 static int __cdecl Compare( 154 _In_z_ LPCWSTR psz1, 155 _In_z_ LPCWSTR psz2) 156 { 157 return ::wcscmp(psz1, psz2); 158 } 159 160 static int __cdecl CompareNoCase( 161 _In_z_ LPCWSTR psz1, 162 _In_z_ LPCWSTR psz2) 163 { 164 return ::_wcsicmp(psz1, psz2); 165 } 166 167 static int __cdecl StringSpanIncluding( 168 _In_z_ LPCWSTR pszBlock, 169 _In_z_ LPCWSTR pszSet) 170 { 171 return (int)::wcsspn(pszBlock, pszSet); 172 } 173 174 static int __cdecl StringSpanExcluding( 175 _In_z_ LPCWSTR pszBlock, 176 _In_z_ LPCWSTR pszSet) 177 { 178 return (int)::wcscspn(pszBlock, pszSet); 179 } 180 181 static int __cdecl FormatV( 182 _In_opt_z_ LPWSTR pszDest, 183 _In_z_ LPCWSTR pszFormat, 184 _In_ va_list args) 185 { 186 if (pszDest == NULL) 187 return ::_vscwprintf(pszFormat, args); 188 return ::vswprintf(pszDest, pszFormat, args); 189 } 190 191 static LPWSTR 192 FormatMessageV(_In_z_ LPCWSTR pszFormat, _In_opt_ va_list *pArgList) 193 { 194 LPWSTR psz; 195 ::FormatMessageW( 196 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, pszFormat, 0, 0, 197 reinterpret_cast<LPWSTR>(&psz), 0, pArgList); 198 return psz; 199 } 200 201 static BSTR __cdecl AllocSysString( 202 _In_z_ LPCWSTR pszSource, 203 _In_ int nLength) 204 { 205 return ::SysAllocStringLen(pszSource, nLength); 206 } 207 }; 208 209 210 // Template specialization 211 212 template<> 213 class ChTraitsCRT<char> : public ChTraitsBase<char> 214 { 215 public: 216 217 static int __cdecl GetBaseTypeLength(_In_z_ LPCWSTR pszSource) noexcept 218 { 219 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, -1, NULL, 0, NULL, NULL) - 1; 220 } 221 222 static int __cdecl GetBaseTypeLength(_In_z_ LPCSTR pszSource) noexcept 223 { 224 if (pszSource == NULL) return 0; 225 return static_cast<int>(strlen(pszSource)); 226 } 227 228 static int __cdecl GetBaseTypeLength( 229 _In_reads_(nLength) LPCWSTR pszSource, 230 _In_ int nLength) noexcept 231 { 232 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0, NULL, NULL); 233 } 234 235 static int __cdecl GetBaseTypeLength( 236 _In_reads_(nLength) LPCSTR pszSource, 237 _In_ int nLength) noexcept 238 { 239 return nLength; 240 } 241 242 static void __cdecl ConvertToBaseType( 243 _Out_writes_(nDestLength) LPSTR pszDest, 244 _In_ int nDestLength, 245 _In_ LPCWSTR pszSrc, 246 _In_ int nSrcLength = -1) 247 { 248 if (nSrcLength == -1) 249 nSrcLength = 1 + GetBaseTypeLength(pszSrc); 250 251 ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL); 252 } 253 254 static void __cdecl ConvertToBaseType( 255 _Out_writes_(nDestLength) LPSTR pszDest, 256 _In_ int nDestLength, 257 _In_ LPCSTR pszSrc, 258 _In_ int nSrcLength = -1) 259 { 260 if (nSrcLength == -1) 261 nSrcLength = 1 + GetBaseTypeLength(pszSrc); 262 263 memcpy(pszDest, pszSrc, nSrcLength); 264 } 265 266 static void __cdecl MakeLower( 267 _Out_writes_(nSrcLength) LPSTR pszSource, 268 _In_ int nSrcLength) 269 { 270 ::CharLowerBuffA(pszSource, nSrcLength); 271 } 272 273 static DWORD GetEnvironmentVariable( 274 _In_z_ LPCSTR pszVar, 275 _Out_writes_opt_(nBufLength) LPSTR pszBuf, 276 _In_opt_ int nBufLength) 277 { 278 return ::GetEnvironmentVariableA(pszVar, pszBuf, nBufLength); 279 } 280 281 static void __cdecl MakeUpper( 282 _Out_writes_(nSrcLength) LPSTR pszSource, 283 _In_ int nSrcLength) 284 { 285 ::CharUpperBuffA(pszSource, nSrcLength); 286 } 287 288 static LPSTR __cdecl FindString( 289 _In_z_ LPSTR pszSource, 290 _In_z_ LPCSTR pszSub) 291 { 292 return ::strstr(pszSource, pszSub); 293 } 294 static LPCSTR __cdecl FindString( 295 _In_z_ LPCSTR pszSource, 296 _In_z_ LPCSTR pszSub) 297 { 298 return ::strstr(pszSource, pszSub); 299 } 300 301 static LPSTR __cdecl FindChar( 302 _In_z_ LPSTR pszSource, 303 _In_ CHAR ch) 304 { 305 return ::strchr(pszSource, ch); 306 } 307 static LPCSTR __cdecl FindChar( 308 _In_z_ LPCSTR pszSource, 309 _In_ CHAR ch) 310 { 311 return ::strchr(pszSource, ch); 312 } 313 314 static LPSTR __cdecl FindCharReverse( 315 _In_z_ LPSTR pszSource, 316 _In_ CHAR ch) 317 { 318 return ::strrchr(pszSource, ch); 319 } 320 static LPCSTR __cdecl FindCharReverse( 321 _In_z_ LPCSTR pszSource, 322 _In_ CHAR ch) 323 { 324 return ::strrchr(pszSource, ch); 325 } 326 327 static LPSTR __cdecl FindOneOf( 328 _In_z_ LPSTR pszSource, 329 _In_z_ LPCSTR pszCharSet) 330 { 331 return ::strpbrk(pszSource, pszCharSet); 332 } 333 static LPCSTR __cdecl FindOneOf( 334 _In_z_ LPCSTR pszSource, 335 _In_z_ LPCSTR pszCharSet) 336 { 337 return ::strpbrk(pszSource, pszCharSet); 338 } 339 340 static int __cdecl Compare( 341 _In_z_ LPCSTR psz1, 342 _In_z_ LPCSTR psz2) 343 { 344 return ::strcmp(psz1, psz2); 345 } 346 347 static int __cdecl CompareNoCase( 348 _In_z_ LPCSTR psz1, 349 _In_z_ LPCSTR psz2) 350 { 351 return ::_stricmp(psz1, psz2); 352 } 353 354 static int __cdecl StringSpanIncluding( 355 _In_z_ LPCSTR pszBlock, 356 _In_z_ LPCSTR pszSet) 357 { 358 return (int)::strspn(pszBlock, pszSet); 359 } 360 361 static int __cdecl StringSpanExcluding( 362 _In_z_ LPCSTR pszBlock, 363 _In_z_ LPCSTR pszSet) 364 { 365 return (int)::strcspn(pszBlock, pszSet); 366 } 367 368 static int __cdecl FormatV( 369 _In_opt_z_ LPSTR pszDest, 370 _In_z_ LPCSTR pszFormat, 371 _In_ va_list args) 372 { 373 if (pszDest == NULL) 374 return ::_vscprintf(pszFormat, args); 375 return ::vsprintf(pszDest, pszFormat, args); 376 } 377 378 static LPSTR 379 FormatMessageV(_In_z_ LPCSTR pszFormat, _In_opt_ va_list *pArgList) 380 { 381 LPSTR psz; 382 ::FormatMessageA( 383 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, pszFormat, 0, 0, reinterpret_cast<LPSTR>(&psz), 384 0, pArgList); 385 return psz; 386 } 387 388 static BSTR __cdecl AllocSysString( 389 _In_z_ LPCSTR pszSource, 390 _In_ int nLength) 391 { 392 int nLen = ChTraitsCRT<wchar_t>::GetBaseTypeLength(pszSource, nLength); 393 BSTR bstr = ::SysAllocStringLen(NULL, nLen); 394 if (bstr) 395 { 396 ChTraitsCRT<wchar_t>::ConvertToBaseType(bstr, nLen, pszSource, nLength); 397 } 398 return bstr; 399 } 400 401 }; 402 403 404 namespace _CSTRING_IMPL_ 405 { 406 template <typename _CharType, class StringTraits> 407 struct _MFCDLLTraitsCheck 408 { 409 const static bool c_bIsMFCDLLTraits = false; 410 }; 411 } 412 413 414 // TODO: disable conversion functions when _CSTRING_DISABLE_NARROW_WIDE_CONVERSION is defined. 415 416 template <typename BaseType, class StringTraits> 417 class CStringT : 418 public CSimpleStringT <BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits> 419 { 420 public: 421 typedef CSimpleStringT<BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits> CThisSimpleString; 422 typedef StringTraits StrTraits; 423 typedef typename CThisSimpleString::XCHAR XCHAR; 424 typedef typename CThisSimpleString::PXSTR PXSTR; 425 typedef typename CThisSimpleString::PCXSTR PCXSTR; 426 typedef typename CThisSimpleString::YCHAR YCHAR; 427 typedef typename CThisSimpleString::PYSTR PYSTR; 428 typedef typename CThisSimpleString::PCYSTR PCYSTR; 429 430 public: 431 CStringT() noexcept : 432 CThisSimpleString(StringTraits::GetDefaultManager()) 433 { 434 } 435 436 explicit CStringT( _In_ IAtlStringMgr* pStringMgr) noexcept : 437 CThisSimpleString(pStringMgr) 438 { 439 } 440 441 static void __cdecl Construct(_In_ CStringT* pString) 442 { 443 new(pString) CStringT; 444 } 445 446 CStringT(_In_ const CStringT& strSrc) : 447 CThisSimpleString(strSrc) 448 { 449 } 450 451 CStringT(_In_ const CThisSimpleString& strSrc) : 452 CThisSimpleString(strSrc) 453 { 454 } 455 456 template<class StringTraits_> 457 CStringT(_In_ const CStringT<YCHAR, StringTraits_> & strSrc) : 458 CThisSimpleString(StringTraits::GetDefaultManager()) 459 { 460 *this = static_cast<const YCHAR*>(strSrc); 461 } 462 463 protected: 464 /* helper function */ 465 template <typename T_CHAR> 466 void LoadFromPtr_(_In_opt_z_ const T_CHAR* pszSrc) 467 { 468 if (pszSrc == NULL) 469 return; 470 if (IS_INTRESOURCE(pszSrc)) 471 LoadString(LOWORD(pszSrc)); 472 else 473 *this = pszSrc; 474 } 475 476 public: 477 CStringT(_In_opt_z_ const XCHAR* pszSrc) : 478 CThisSimpleString(StringTraits::GetDefaultManager()) 479 { 480 LoadFromPtr_(pszSrc); 481 } 482 483 CStringT(_In_opt_z_ const XCHAR* pszSrc, 484 _In_ IAtlStringMgr* pStringMgr) : CThisSimpleString(pStringMgr) 485 { 486 LoadFromPtr_(pszSrc); 487 } 488 489 CStringT(_In_opt_z_ const YCHAR* pszSrc) : 490 CThisSimpleString(StringTraits::GetDefaultManager()) 491 { 492 LoadFromPtr_(pszSrc); 493 } 494 495 CStringT(_In_opt_z_ const YCHAR* pszSrc, 496 _In_ IAtlStringMgr* pStringMgr) : CThisSimpleString(pStringMgr) 497 { 498 LoadFromPtr_(pszSrc); 499 } 500 501 CStringT(_In_reads_z_(nLength) const XCHAR* pch, 502 _In_ int nLength) : 503 CThisSimpleString(pch, nLength, StringTraits::GetDefaultManager()) 504 { 505 } 506 507 CStringT(_In_reads_z_(nLength) const YCHAR* pch, 508 _In_ int nLength) : 509 CThisSimpleString(pch, nLength, StringTraits::GetDefaultManager()) 510 { 511 } 512 513 CStringT& operator=(_In_ const CStringT& strSrc) 514 { 515 CThisSimpleString::operator=(strSrc); 516 return *this; 517 } 518 519 CStringT& operator=(_In_opt_z_ PCXSTR pszSrc) 520 { 521 CThisSimpleString::operator=(pszSrc); 522 return *this; 523 } 524 525 CStringT& operator=(_In_opt_z_ PCYSTR pszSrc) 526 { 527 int length = pszSrc ? StringTraits::GetBaseTypeLength(pszSrc) : 0; 528 if (length > 0) 529 { 530 PXSTR result = CThisSimpleString::GetBuffer(length); 531 StringTraits::ConvertToBaseType(result, length, pszSrc); 532 CThisSimpleString::ReleaseBufferSetLength(length); 533 } 534 else 535 { 536 CThisSimpleString::Empty(); 537 } 538 return *this; 539 } 540 541 CStringT& operator=(_In_ const CThisSimpleString &strSrc) 542 { 543 CThisSimpleString::operator=(strSrc); 544 return *this; 545 } 546 547 friend bool operator==(const CStringT& str1, const CStringT& str2) noexcept 548 { 549 return str1.Compare(str2) == 0; 550 } 551 552 friend bool operator==(const CStringT& str1, PCXSTR psz2) noexcept 553 { 554 return str1.Compare(psz2) == 0; 555 } 556 557 friend bool operator==(const CStringT& str1, PCYSTR psz2) noexcept 558 { 559 CStringT tmp(psz2, str1.GetManager()); 560 return tmp.Compare(str1) == 0; 561 } 562 563 friend bool operator==(const CStringT& str1, XCHAR ch2) noexcept 564 { 565 return str1.GetLength() == 1 && str1[0] == ch2; 566 } 567 568 friend bool operator==(PCXSTR psz1, const CStringT& str2) noexcept 569 { 570 return str2.Compare(psz1) == 0; 571 } 572 573 friend bool operator==(PCYSTR psz1, const CStringT& str2) noexcept 574 { 575 CStringT tmp(psz1, str2.GetManager()); 576 return tmp.Compare(str2) == 0; 577 } 578 579 friend bool operator==(XCHAR ch1, const CStringT& str2) noexcept 580 { 581 return str2.GetLength() == 1 && str2[0] == ch1; 582 } 583 584 friend bool operator!=(const CStringT& str1, const CStringT& str2) noexcept 585 { 586 return str1.Compare(str2) != 0; 587 } 588 589 friend bool operator!=(const CStringT& str1, PCXSTR psz2) noexcept 590 { 591 return str1.Compare(psz2) != 0; 592 } 593 594 friend bool operator!=(const CStringT& str1, PCYSTR psz2) noexcept 595 { 596 CStringT tmp(psz2, str1.GetManager()); 597 return tmp.Compare(str1) != 0; 598 } 599 600 friend bool operator!=(const CStringT& str1, XCHAR ch2) noexcept 601 { 602 return str1.GetLength() != 1 || str1[0] != ch2; 603 } 604 605 friend bool operator!=(PCXSTR psz1, const CStringT& str2) noexcept 606 { 607 return str2.Compare(psz1) != 0; 608 } 609 610 friend bool operator!=(PCYSTR psz1, const CStringT& str2) noexcept 611 { 612 CStringT tmp(psz1, str2.GetManager()); 613 return tmp.Compare(str2) != 0; 614 } 615 616 friend bool operator!=(XCHAR ch1, const CStringT& str2) noexcept 617 { 618 return str2.GetLength() != 1 || str2[0] != ch1; 619 } 620 621 CStringT& operator+=(_In_ const CThisSimpleString& str) 622 { 623 CThisSimpleString::operator+=(str); 624 return *this; 625 } 626 627 CStringT& operator+=(_In_z_ PCXSTR pszSrc) 628 { 629 CThisSimpleString::operator+=(pszSrc); 630 return *this; 631 } 632 633 CStringT& operator+=(_In_ XCHAR ch) 634 { 635 CThisSimpleString::operator+=(ch); 636 return *this; 637 } 638 639 BOOL LoadString(_In_ UINT nID) 640 { 641 return LoadString(_AtlBaseModule.GetResourceInstance(), nID); 642 } 643 644 _Check_return_ BOOL LoadString(_In_ HINSTANCE hInstance, 645 _In_ UINT nID) 646 { 647 const ATLSTRINGRESOURCEIMAGE* pImage = AtlGetStringResourceImage(hInstance, nID); 648 if (pImage == NULL) return FALSE; 649 650 int nLength = StringTraits::GetBaseTypeLength(pImage->achString, pImage->nLength); 651 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 652 StringTraits::ConvertToBaseType(pszBuffer, nLength, pImage->achString, pImage->nLength); 653 CThisSimpleString::ReleaseBufferSetLength(nLength); 654 655 return TRUE; 656 } 657 658 BOOL GetEnvironmentVariable(_In_z_ PCXSTR pszVar) 659 { 660 int nLength = StringTraits::GetEnvironmentVariable(pszVar, NULL, 0); 661 662 if (nLength > 0) 663 { 664 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 665 StringTraits::GetEnvironmentVariable(pszVar, pszBuffer, nLength); 666 CThisSimpleString::ReleaseBuffer(); 667 return TRUE; 668 } 669 670 CThisSimpleString::Empty(); 671 return FALSE; 672 } 673 674 CStringT& MakeLower() 675 { 676 int nLength = CThisSimpleString::GetLength(); 677 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 678 679 StringTraits::MakeLower(pszBuffer, nLength); 680 CThisSimpleString::ReleaseBufferSetLength(nLength); 681 682 return *this; 683 } 684 685 CStringT& MakeUpper() 686 { 687 int nLength = CThisSimpleString::GetLength(); 688 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 689 690 StringTraits::MakeUpper(pszBuffer, nLength); 691 CThisSimpleString::ReleaseBufferSetLength(nLength); 692 693 return *this; 694 } 695 696 int Find(_In_ PCXSTR pszSub, _In_opt_ int iStart = 0) const noexcept 697 { 698 int nLength = CThisSimpleString::GetLength(); 699 700 if (iStart >= nLength || iStart < 0) 701 return -1; 702 703 PCXSTR pszString = CThisSimpleString::GetString(); 704 PCXSTR pszResult = StringTraits::FindString(pszString + iStart, pszSub); 705 706 return pszResult ? ((int)(pszResult - pszString)) : -1; 707 } 708 709 int Find(_In_ XCHAR ch, _In_opt_ int iStart = 0) const noexcept 710 { 711 int nLength = CThisSimpleString::GetLength(); 712 713 if (iStart >= nLength || iStart < 0) 714 return -1; 715 716 PCXSTR pszString = CThisSimpleString::GetString(); 717 PCXSTR pszResult = StringTraits::FindChar(pszString + iStart, ch); 718 719 return pszResult ? ((int)(pszResult - pszString)) : -1; 720 } 721 722 int FindOneOf(_In_ PCXSTR pszCharSet) const noexcept 723 { 724 PCXSTR pszString = CThisSimpleString::GetString(); 725 PCXSTR pszResult = StringTraits::FindOneOf(pszString, pszCharSet); 726 727 return pszResult ? ((int)(pszResult - pszString)) : -1; 728 } 729 730 int ReverseFind(_In_ XCHAR ch) const noexcept 731 { 732 PCXSTR pszString = CThisSimpleString::GetString(); 733 PCXSTR pszResult = StringTraits::FindCharReverse(pszString, ch); 734 735 return pszResult ? ((int)(pszResult - pszString)) : -1; 736 } 737 738 int Compare(_In_z_ PCXSTR psz) const 739 { 740 return StringTraits::Compare(CThisSimpleString::GetString(), psz); 741 } 742 743 int CompareNoCase(_In_z_ PCXSTR psz) const 744 { 745 return StringTraits::CompareNoCase(CThisSimpleString::GetString(), psz); 746 } 747 748 CStringT Mid(int iFirst, int nCount) const 749 { 750 int nLength = CThisSimpleString::GetLength(); 751 752 if (iFirst < 0) 753 iFirst = 0; 754 if (nCount < 0) 755 nCount = 0; 756 if (iFirst > nLength) 757 iFirst = nLength; 758 if (iFirst + nCount > nLength) 759 nCount = nLength - iFirst; 760 761 return CStringT(CThisSimpleString::GetString() + iFirst, nCount); 762 } 763 764 CStringT Mid(int iFirst) const 765 { 766 int nLength = CThisSimpleString::GetLength(); 767 768 if (iFirst < 0) 769 iFirst = 0; 770 if (iFirst > nLength) 771 iFirst = nLength; 772 773 return CStringT(CThisSimpleString::GetString() + iFirst, nLength - iFirst); 774 } 775 776 CStringT Left(int nCount) const 777 { 778 int nLength = CThisSimpleString::GetLength(); 779 780 if (nCount < 0) 781 nCount = 0; 782 if (nCount > nLength) 783 nCount = nLength; 784 785 return CStringT(CThisSimpleString::GetString(), nCount); 786 } 787 788 CStringT Right(int nCount) const 789 { 790 int nLength = CThisSimpleString::GetLength(); 791 792 if (nCount < 0) 793 nCount = 0; 794 if (nCount > nLength) 795 nCount = nLength; 796 797 return CStringT(CThisSimpleString::GetString() + nLength - nCount, nCount); 798 } 799 800 void __cdecl AppendFormat(UINT nFormatID, ...) 801 { 802 va_list args; 803 va_start(args, nFormatID); 804 CStringT formatString; 805 if (formatString.LoadString(nFormatID)) 806 AppendFormatV(formatString, args); 807 va_end(args); 808 } 809 810 void __cdecl AppendFormat(PCXSTR pszFormat, ...) 811 { 812 va_list args; 813 va_start(args, pszFormat); 814 AppendFormatV(pszFormat, args); 815 va_end(args); 816 } 817 818 void __cdecl Format(UINT nFormatID, ...) 819 { 820 va_list args; 821 va_start(args, nFormatID); 822 CStringT formatString; 823 if (formatString.LoadString(nFormatID)) 824 FormatV(formatString, args); 825 va_end(args); 826 } 827 828 void __cdecl Format(PCXSTR pszFormat, ...) 829 { 830 va_list args; 831 va_start(args, pszFormat); 832 FormatV(pszFormat, args); 833 va_end(args); 834 } 835 836 void AppendFormatV(PCXSTR pszFormat, va_list args) 837 { 838 int nLength = StringTraits::FormatV(NULL, pszFormat, args); 839 int nCurrent = CThisSimpleString::GetLength(); 840 841 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength + nCurrent); 842 StringTraits::FormatV(pszBuffer + nCurrent, pszFormat, args); 843 CThisSimpleString::ReleaseBufferSetLength(nLength + nCurrent); 844 } 845 846 void FormatV(PCXSTR pszFormat, va_list args) 847 { 848 int nLength = StringTraits::FormatV(NULL, pszFormat, args); 849 850 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 851 StringTraits::FormatV(pszBuffer, pszFormat, args); 852 CThisSimpleString::ReleaseBufferSetLength(nLength); 853 } 854 855 void __cdecl FormatMessage(UINT nFormatID, ...) 856 { 857 va_list va; 858 va_start(va, nFormatID); 859 860 CStringT str; 861 if (str.LoadString(nFormatID)) 862 FormatMessageV(str, &va); 863 864 va_end(va); 865 } 866 867 void __cdecl FormatMessage(PCXSTR pszFormat, ...) 868 { 869 va_list va; 870 va_start(va, pszFormat); 871 FormatMessageV(pszFormat, &va); 872 va_end(va); 873 } 874 875 void 876 FormatMessageV(PCXSTR pszFormat, va_list *pArgList) 877 { 878 PXSTR psz = StringTraits::FormatMessageV(pszFormat, pArgList); 879 if (!psz) 880 CThisSimpleString::ThrowMemoryException(); 881 882 *this = psz; 883 ::LocalFree(psz); 884 } 885 886 int Replace(PCXSTR pszOld, PCXSTR pszNew) 887 { 888 PCXSTR pszString = CThisSimpleString::GetString(); 889 890 const int nLength = CThisSimpleString::GetLength(); 891 const int nOldLen = StringTraits::GetBaseTypeLength(pszOld); 892 const int nNewLen = StringTraits::GetBaseTypeLength(pszNew); 893 const int nDiff = nNewLen - nOldLen; 894 int nResultLength = nLength; 895 896 PCXSTR pszFound; 897 while ((pszFound = StringTraits::FindString(pszString, pszOld))) 898 { 899 nResultLength += nDiff; 900 pszString = pszFound + nOldLen; 901 } 902 903 if (pszString == CThisSimpleString::GetString()) 904 return 0; 905 906 PXSTR pszResult = CThisSimpleString::GetBuffer(nResultLength); 907 PXSTR pszNext; 908 int nCount = 0, nRemaining = nLength; 909 while (nRemaining && (pszNext = StringTraits::FindString(pszResult, pszOld))) 910 { 911 nRemaining -= (pszNext - pszResult); 912 nRemaining -= nOldLen; 913 if (nRemaining > 0) 914 CThisSimpleString::CopyCharsOverlapped(pszNext + nNewLen, nRemaining + 1, pszNext + nOldLen, nRemaining + 1); 915 CThisSimpleString::CopyCharsOverlapped(pszNext, nNewLen, pszNew, nNewLen); 916 pszResult = pszNext + nNewLen; 917 nCount++; 918 } 919 920 CThisSimpleString::ReleaseBufferSetLength(nResultLength); 921 922 return nCount; 923 } 924 925 int Replace(XCHAR chOld, XCHAR chNew) 926 { 927 PXSTR pszString = CThisSimpleString::GetString(); 928 PXSTR pszFirst = StringTraits::FindChar(pszString, chOld); 929 if (!pszFirst) 930 return 0; 931 932 int nLength = CThisSimpleString::GetLength(); 933 int nCount = 0; 934 935 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 936 pszFirst = pszBuffer + (pszFirst - pszString); 937 do { 938 *pszFirst = chNew; 939 ++nCount; 940 } while ((pszFirst = StringTraits::FindChar(pszFirst + 1, chOld))); 941 942 CThisSimpleString::ReleaseBufferSetLength(nLength); 943 return nCount; 944 } 945 946 947 CStringT Tokenize(_In_z_ PCXSTR pszTokens, _Inout_ int& iStart) const 948 { 949 ATLASSERT(iStart >= 0); 950 951 if (iStart < 0) 952 AtlThrow(E_INVALIDARG); 953 954 if (!pszTokens || !pszTokens[0]) 955 { 956 if (iStart < CThisSimpleString::GetLength()) 957 { 958 return Mid(iStart); 959 } 960 iStart = -1; 961 return CStringT(); 962 } 963 964 if (iStart < CThisSimpleString::GetLength()) 965 { 966 int iRangeOffset = StringTraits::StringSpanIncluding(CThisSimpleString::GetString() + iStart, pszTokens); 967 968 if (iRangeOffset + iStart < CThisSimpleString::GetLength()) 969 { 970 int iNewStart = iStart + iRangeOffset; 971 int nCount = StringTraits::StringSpanExcluding(CThisSimpleString::GetString() + iNewStart, pszTokens); 972 973 iStart = iNewStart + nCount + 1; 974 975 return Mid(iNewStart, nCount); 976 } 977 } 978 979 iStart = -1; 980 return CStringT(); 981 } 982 983 static PCXSTR DefaultTrimChars() 984 { 985 static XCHAR str[] = { ' ', '\t', '\r', '\n', 0 }; 986 return str; 987 } 988 989 990 CStringT& TrimLeft() 991 { 992 return TrimLeft(DefaultTrimChars()); 993 } 994 995 CStringT& TrimLeft(XCHAR chTarget) 996 { 997 XCHAR str[2] = { chTarget, 0 }; 998 return TrimLeft(str); 999 } 1000 1001 CStringT& TrimLeft(PCXSTR pszTargets) 1002 { 1003 int nLength = CThisSimpleString::GetLength(); 1004 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 1005 int nCount = 0; 1006 1007 while (nCount < nLength && StringTraits::FindChar(pszTargets, pszBuffer[nCount])) 1008 nCount++; 1009 1010 if (nCount > 0) 1011 { 1012 CThisSimpleString::CopyCharsOverlapped(pszBuffer, nLength - nCount, pszBuffer + nCount, nLength - nCount); 1013 nLength -= nCount; 1014 } 1015 CThisSimpleString::ReleaseBufferSetLength(nLength); 1016 1017 return *this; 1018 } 1019 1020 1021 CStringT& TrimRight() 1022 { 1023 return TrimRight(DefaultTrimChars()); 1024 } 1025 1026 CStringT& TrimRight(XCHAR chTarget) 1027 { 1028 XCHAR str[2] = { chTarget, 0 }; 1029 return TrimRight(str); 1030 } 1031 1032 CStringT& TrimRight(PCXSTR pszTargets) 1033 { 1034 int nLength = CThisSimpleString::GetLength(); 1035 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 1036 1037 while (nLength > 0 && StringTraits::FindChar(pszTargets, pszBuffer[nLength-1])) 1038 nLength--; 1039 1040 CThisSimpleString::ReleaseBufferSetLength(nLength); 1041 1042 return *this; 1043 } 1044 1045 1046 CStringT& Trim() 1047 { 1048 return Trim(DefaultTrimChars()); 1049 } 1050 1051 CStringT& Trim(XCHAR chTarget) 1052 { 1053 XCHAR str[2] = { chTarget, 0 }; 1054 return Trim(str); 1055 } 1056 1057 CStringT& Trim(PCXSTR pszTargets) 1058 { 1059 return TrimRight(pszTargets).TrimLeft(pszTargets); 1060 } 1061 1062 1063 BSTR AllocSysString() const 1064 { 1065 return StringTraits::AllocSysString(CThisSimpleString::GetString(), CThisSimpleString::GetLength()); 1066 } 1067 1068 1069 }; 1070 1071 } //namespace ATL 1072 1073 #endif 1074