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