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 friend bool operator!=(const CStringT& str1, const CStringT& str2) throw() 537 { 538 return str1.Compare(str2) != 0; 539 } 540 541 friend bool operator!=(const CStringT& str1, PCXSTR psz2) throw() 542 { 543 return str1.Compare(psz2) != 0; 544 } 545 546 friend bool operator!=(const CStringT& str1, PCYSTR psz2) throw() 547 { 548 CStringT tmp(psz2, str1.GetManager()); 549 return tmp.Compare(str1) != 0; 550 } 551 552 friend bool operator!=(const CStringT& str1, XCHAR ch2) throw() 553 { 554 return str1.GetLength() != 1 || str1[0] != ch2; 555 } 556 557 friend bool operator!=(PCXSTR psz1, const CStringT& str2) throw() 558 { 559 return str2.Compare(psz1) != 0; 560 } 561 562 friend bool operator!=(PCYSTR psz1, const CStringT& str2) throw() 563 { 564 CStringT tmp(psz1, str2.GetManager()); 565 return tmp.Compare(str2) != 0; 566 } 567 568 friend bool operator!=(XCHAR ch1, const CStringT& str2) throw() 569 { 570 return str2.GetLength() != 1 || str2[0] != ch1; 571 } 572 573 CStringT& operator+=(_In_ const CThisSimpleString& str) 574 { 575 CThisSimpleString::operator+=(str); 576 return *this; 577 } 578 579 CStringT& operator+=(_In_z_ PCXSTR pszSrc) 580 { 581 CThisSimpleString::operator+=(pszSrc); 582 return *this; 583 } 584 585 CStringT& operator+=(_In_ XCHAR ch) 586 { 587 CThisSimpleString::operator+=(ch); 588 return *this; 589 } 590 591 BOOL LoadString(_In_ UINT nID) 592 { 593 return LoadString(_AtlBaseModule.GetResourceInstance(), nID); 594 } 595 596 _Check_return_ BOOL LoadString(_In_ HINSTANCE hInstance, 597 _In_ UINT nID) 598 { 599 const ATLSTRINGRESOURCEIMAGE* pImage = AtlGetStringResourceImage(hInstance, nID); 600 if (pImage == NULL) return FALSE; 601 602 int nLength = StringTraits::GetBaseTypeLength(pImage->achString, pImage->nLength); 603 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 604 StringTraits::ConvertToBaseType(pszBuffer, nLength, pImage->achString, pImage->nLength); 605 CThisSimpleString::ReleaseBufferSetLength(nLength); 606 607 return TRUE; 608 } 609 610 BOOL GetEnvironmentVariable(_In_z_ PCXSTR pszVar) 611 { 612 int nLength = StringTraits::GetEnvironmentVariable(pszVar, NULL, 0); 613 614 if (nLength > 0) 615 { 616 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 617 StringTraits::GetEnvironmentVariable(pszVar, pszBuffer, nLength); 618 CThisSimpleString::ReleaseBuffer(); 619 return TRUE; 620 } 621 622 CThisSimpleString::Empty(); 623 return FALSE; 624 } 625 626 CStringT& MakeLower() 627 { 628 int nLength = CThisSimpleString::GetLength(); 629 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 630 631 StringTraits::MakeLower(pszBuffer, nLength); 632 CThisSimpleString::ReleaseBufferSetLength(nLength); 633 634 return *this; 635 } 636 637 CStringT& MakeUpper() 638 { 639 int nLength = CThisSimpleString::GetLength(); 640 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 641 642 StringTraits::MakeUpper(pszBuffer, nLength); 643 CThisSimpleString::ReleaseBufferSetLength(nLength); 644 645 return *this; 646 } 647 648 int Find(_In_ PCXSTR pszSub, _In_opt_ int iStart = 0) const throw() 649 { 650 int nLength = CThisSimpleString::GetLength(); 651 652 if (iStart >= nLength || iStart < 0) 653 return -1; 654 655 PCXSTR pszString = CThisSimpleString::GetString(); 656 PCXSTR pszResult = StringTraits::FindString(pszString + iStart, pszSub); 657 658 return pszResult ? ((int)(pszResult - pszString)) : -1; 659 } 660 661 int Find(_In_ XCHAR ch, _In_opt_ int iStart = 0) const throw() 662 { 663 int nLength = CThisSimpleString::GetLength(); 664 665 if (iStart >= nLength || iStart < 0) 666 return -1; 667 668 PCXSTR pszString = CThisSimpleString::GetString(); 669 PCXSTR pszResult = StringTraits::FindChar(pszString + iStart, ch); 670 671 return pszResult ? ((int)(pszResult - pszString)) : -1; 672 } 673 674 int FindOneOf(_In_ PCXSTR pszCharSet) const throw() 675 { 676 PCXSTR pszString = CThisSimpleString::GetString(); 677 PCXSTR pszResult = StringTraits::FindOneOf(pszString, pszCharSet); 678 679 return pszResult ? ((int)(pszResult - pszString)) : -1; 680 } 681 682 int ReverseFind(_In_ XCHAR ch) const throw() 683 { 684 PCXSTR pszString = CThisSimpleString::GetString(); 685 PCXSTR pszResult = StringTraits::FindCharReverse(pszString, ch); 686 687 return pszResult ? ((int)(pszResult - pszString)) : -1; 688 } 689 690 int Compare(_In_z_ PCXSTR psz) const 691 { 692 return StringTraits::Compare(CThisSimpleString::GetString(), psz); 693 } 694 695 int CompareNoCase(_In_z_ PCXSTR psz) const 696 { 697 return StringTraits::CompareNoCase(CThisSimpleString::GetString(), psz); 698 } 699 700 CStringT Mid(int iFirst, int nCount) const 701 { 702 int nLength = CThisSimpleString::GetLength(); 703 704 if (iFirst < 0) 705 iFirst = 0; 706 if (nCount < 0) 707 nCount = 0; 708 if (iFirst > nLength) 709 iFirst = nLength; 710 if (iFirst + nCount > nLength) 711 nCount = nLength - iFirst; 712 713 return CStringT(CThisSimpleString::GetString() + iFirst, nCount); 714 } 715 716 CStringT Mid(int iFirst) const 717 { 718 int nLength = CThisSimpleString::GetLength(); 719 720 if (iFirst < 0) 721 iFirst = 0; 722 if (iFirst > nLength) 723 iFirst = nLength; 724 725 return CStringT(CThisSimpleString::GetString() + iFirst, nLength - iFirst); 726 } 727 728 CStringT Left(int nCount) const 729 { 730 int nLength = CThisSimpleString::GetLength(); 731 732 if (nCount < 0) 733 nCount = 0; 734 if (nCount > nLength) 735 nCount = nLength; 736 737 return CStringT(CThisSimpleString::GetString(), nCount); 738 } 739 740 CStringT Right(int nCount) const 741 { 742 int nLength = CThisSimpleString::GetLength(); 743 744 if (nCount < 0) 745 nCount = 0; 746 if (nCount > nLength) 747 nCount = nLength; 748 749 return CStringT(CThisSimpleString::GetString() + nLength - nCount, nCount); 750 } 751 752 753 void __cdecl Format(UINT nFormatID, ...) 754 { 755 va_list args; 756 va_start(args, nFormatID); 757 CStringT formatString; 758 if (formatString.LoadString(nFormatID)) 759 FormatV(formatString, args); 760 va_end(args); 761 } 762 763 void __cdecl Format(PCXSTR pszFormat, ...) 764 { 765 va_list args; 766 va_start(args, pszFormat); 767 FormatV(pszFormat, args); 768 va_end(args); 769 } 770 771 void FormatV(PCXSTR pszFormat, va_list args) 772 { 773 int nLength = StringTraits::FormatV(NULL, pszFormat, args); 774 775 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 776 StringTraits::FormatV(pszBuffer, pszFormat, args); 777 CThisSimpleString::ReleaseBufferSetLength(nLength); 778 } 779 780 void __cdecl FormatMessage(UINT nFormatID, ...) 781 { 782 va_list va; 783 va_start(va, nFormatID); 784 785 CStringT str; 786 if (str.LoadString(nFormatID)) 787 FormatMessageV(str, &va); 788 789 va_end(va); 790 } 791 792 void __cdecl FormatMessage(PCXSTR pszFormat, ...) 793 { 794 va_list va; 795 va_start(va, pszFormat); 796 FormatMessageV(pszFormat, &va); 797 va_end(va); 798 } 799 800 void 801 FormatMessageV(PCXSTR pszFormat, va_list *pArgList) 802 { 803 PXSTR psz = StringTraits::FormatMessageV(pszFormat, pArgList); 804 if (!psz) 805 CThisSimpleString::ThrowMemoryException(); 806 807 *this = psz; 808 ::LocalFree(psz); 809 } 810 811 int Replace(PCXSTR pszOld, PCXSTR pszNew) 812 { 813 PCXSTR pszString = CThisSimpleString::GetString(); 814 815 const int nLength = CThisSimpleString::GetLength(); 816 const int nOldLen = StringTraits::GetBaseTypeLength(pszOld); 817 const int nNewLen = StringTraits::GetBaseTypeLength(pszNew); 818 const int nDiff = nNewLen - nOldLen; 819 int nResultLength = nLength; 820 821 PCXSTR pszFound; 822 while ((pszFound = StringTraits::FindString(pszString, pszOld))) 823 { 824 nResultLength += nDiff; 825 pszString = pszFound + nOldLen; 826 } 827 828 if (pszString == CThisSimpleString::GetString()) 829 return 0; 830 831 PXSTR pszResult = CThisSimpleString::GetBuffer(nResultLength); 832 PXSTR pszNext; 833 int nCount = 0, nRemaining = nLength; 834 while (nRemaining && (pszNext = StringTraits::FindString(pszResult, pszOld))) 835 { 836 nRemaining -= (pszNext - pszResult); 837 nRemaining -= nOldLen; 838 if (nRemaining > 0) 839 CThisSimpleString::CopyCharsOverlapped(pszNext + nNewLen, nRemaining + 1, pszNext + nOldLen, nRemaining + 1); 840 CThisSimpleString::CopyCharsOverlapped(pszNext, nNewLen, pszNew, nNewLen); 841 pszResult = pszNext + nNewLen; 842 nCount++; 843 } 844 845 CThisSimpleString::ReleaseBufferSetLength(nResultLength); 846 847 return nCount; 848 } 849 850 int Replace(XCHAR chOld, XCHAR chNew) 851 { 852 PCXSTR pszString = CThisSimpleString::GetString(); 853 PXSTR pszFirst = StringTraits::FindChar(pszString, chOld); 854 if (!pszFirst) 855 return 0; 856 857 int nLength = CThisSimpleString::GetLength(); 858 int nCount = 0; 859 860 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 861 pszFirst = pszBuffer + (pszFirst - pszString); 862 do { 863 *pszFirst = chNew; 864 ++nCount; 865 } while ((pszFirst = StringTraits::FindChar(pszFirst + 1, chOld))); 866 867 CThisSimpleString::ReleaseBufferSetLength(nLength); 868 return nCount; 869 } 870 871 872 CStringT Tokenize(_In_z_ PCXSTR pszTokens, _Inout_ int& iStart) const 873 { 874 ATLASSERT(iStart >= 0); 875 876 if (iStart < 0) 877 AtlThrow(E_INVALIDARG); 878 879 if (!pszTokens || !pszTokens[0]) 880 { 881 if (iStart < CThisSimpleString::GetLength()) 882 { 883 return Mid(iStart); 884 } 885 iStart = -1; 886 return CStringT(); 887 } 888 889 if (iStart < CThisSimpleString::GetLength()) 890 { 891 int iRangeOffset = StringTraits::StringSpanIncluding(CThisSimpleString::GetString() + iStart, pszTokens); 892 893 if (iRangeOffset + iStart < CThisSimpleString::GetLength()) 894 { 895 int iNewStart = iStart + iRangeOffset; 896 int nCount = StringTraits::StringSpanExcluding(CThisSimpleString::GetString() + iNewStart, pszTokens); 897 898 iStart = iNewStart + nCount + 1; 899 900 return Mid(iNewStart, nCount); 901 } 902 } 903 904 iStart = -1; 905 return CStringT(); 906 } 907 908 static PCXSTR DefaultTrimChars() 909 { 910 static XCHAR str[] = { ' ', '\t', '\r', '\n', 0 }; 911 return str; 912 } 913 914 915 CStringT& TrimLeft() 916 { 917 return TrimLeft(DefaultTrimChars()); 918 } 919 920 CStringT& TrimLeft(XCHAR chTarget) 921 { 922 XCHAR str[2] = { chTarget, 0 }; 923 return TrimLeft(str); 924 } 925 926 CStringT& TrimLeft(PCXSTR pszTargets) 927 { 928 int nLength = CThisSimpleString::GetLength(); 929 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 930 int nCount = 0; 931 932 while (nCount < nLength && StringTraits::FindChar(pszTargets, pszBuffer[nCount])) 933 nCount++; 934 935 if (nCount > 0) 936 { 937 CThisSimpleString::CopyCharsOverlapped(pszBuffer, nLength - nCount, pszBuffer + nCount, nLength - nCount); 938 nLength -= nCount; 939 } 940 CThisSimpleString::ReleaseBufferSetLength(nLength); 941 942 return *this; 943 } 944 945 946 CStringT& TrimRight() 947 { 948 return TrimRight(DefaultTrimChars()); 949 } 950 951 CStringT& TrimRight(XCHAR chTarget) 952 { 953 XCHAR str[2] = { chTarget, 0 }; 954 return TrimRight(str); 955 } 956 957 CStringT& TrimRight(PCXSTR pszTargets) 958 { 959 int nLength = CThisSimpleString::GetLength(); 960 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); 961 962 while (nLength > 0 && StringTraits::FindChar(pszTargets, pszBuffer[nLength-1])) 963 nLength--; 964 965 CThisSimpleString::ReleaseBufferSetLength(nLength); 966 967 return *this; 968 } 969 970 971 CStringT& Trim() 972 { 973 return Trim(DefaultTrimChars()); 974 } 975 976 CStringT& Trim(XCHAR chTarget) 977 { 978 XCHAR str[2] = { chTarget, 0 }; 979 return Trim(str); 980 } 981 982 CStringT& Trim(PCXSTR pszTargets) 983 { 984 return TrimRight(pszTargets).TrimLeft(pszTargets); 985 } 986 987 988 BSTR AllocSysString() const 989 { 990 return StringTraits::AllocSysString(CThisSimpleString::GetString(), CThisSimpleString::GetLength()); 991 } 992 993 994 }; 995 996 } //namespace ATL 997 998 #endif 999