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