5 #include <atlsimpstr.h>
14 inline UINT WINAPI
_AtlGetConversionACP() noexcept
16 #ifdef _CONVERSION_DONT_USE_THREAD_LOCALE
24 template<typename _CharType
= wchar_t>
25 class ChTraitsCRT
: public ChTraitsBase
<_CharType
>
29 static int __cdecl
GetBaseTypeLength(_In_z_ LPCWSTR pszSource
) noexcept
31 if (pszSource
== NULL
) return -1;
32 return static_cast<int>(wcslen(pszSource
));
35 static int __cdecl
GetBaseTypeLength(_In_z_ LPCSTR pszSource
) noexcept
37 if (pszSource
== NULL
) return 0;
38 return ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSource
, -1, NULL
, 0) - 1;
41 static int __cdecl
GetBaseTypeLength(
42 _In_reads_(nLength
) LPCWSTR pszSource
,
43 _In_
int nLength
) noexcept
48 static int __cdecl
GetBaseTypeLength(
49 _In_reads_(nLength
) LPCSTR pszSource
,
50 _In_
int nLength
) noexcept
52 return ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSource
, nLength
, NULL
, 0);
55 static void __cdecl
ConvertToBaseType(
56 _Out_writes_(nDestLength
) LPWSTR pszDest
,
59 _In_
int nSrcLength
= -1)
62 nSrcLength
= 1 + GetBaseTypeLength(pszSrc
);
64 wmemcpy(pszDest
, pszSrc
, nSrcLength
);
67 static void __cdecl
ConvertToBaseType(
68 _Out_writes_(nDestLength
) LPWSTR pszDest
,
71 _In_
int nSrcLength
= -1)
74 nSrcLength
= 1 + GetBaseTypeLength(pszSrc
);
76 ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSrc
, nSrcLength
, pszDest
, nDestLength
);
79 static void __cdecl
MakeLower(
80 _Out_writes_(nSrcLength
) LPWSTR pszSource
,
83 ::CharLowerBuffW(pszSource
, nSrcLength
);
86 static DWORD
GetEnvironmentVariable(
87 _In_z_ LPCWSTR pszVar
,
88 _Out_writes_opt_(nBufLength
) LPWSTR pszBuf
,
89 _In_opt_
int nBufLength
)
91 return ::GetEnvironmentVariableW(pszVar
, pszBuf
, nBufLength
);
94 static void __cdecl
MakeUpper(
95 _Out_writes_(nSrcLength
) LPWSTR pszSource
,
98 ::CharUpperBuffW(pszSource
, nSrcLength
);
101 static LPWSTR __cdecl
FindString(
102 _In_z_ LPWSTR pszSource
,
103 _In_z_ LPCWSTR pszSub
)
105 return ::wcsstr(pszSource
, pszSub
);
107 static LPCWSTR __cdecl
FindString(
108 _In_z_ LPCWSTR pszSource
,
109 _In_z_ LPCWSTR pszSub
)
111 return ::wcsstr(pszSource
, pszSub
);
114 static LPWSTR __cdecl
FindChar(
115 _In_z_ LPWSTR pszSource
,
118 return ::wcschr(pszSource
, ch
);
120 static LPCWSTR __cdecl
FindChar(
121 _In_z_ LPCWSTR pszSource
,
124 return ::wcschr(pszSource
, ch
);
127 static LPWSTR __cdecl
FindCharReverse(
128 _In_z_ LPWSTR pszSource
,
131 return ::wcsrchr(pszSource
, ch
);
133 static LPCWSTR __cdecl
FindCharReverse(
134 _In_z_ LPCWSTR pszSource
,
137 return ::wcsrchr(pszSource
, ch
);
140 static LPWSTR __cdecl
FindOneOf(
141 _In_z_ LPWSTR pszSource
,
142 _In_z_ LPCWSTR pszCharSet
)
144 return ::wcspbrk(pszSource
, pszCharSet
);
146 static LPCWSTR __cdecl
FindOneOf(
147 _In_z_ LPCWSTR pszSource
,
148 _In_z_ LPCWSTR pszCharSet
)
150 return ::wcspbrk(pszSource
, pszCharSet
);
153 static int __cdecl
Compare(
157 return ::wcscmp(psz1
, psz2
);
160 static int __cdecl
CompareNoCase(
164 return ::_wcsicmp(psz1
, psz2
);
167 static int __cdecl
StringSpanIncluding(
168 _In_z_ LPCWSTR pszBlock
,
169 _In_z_ LPCWSTR pszSet
)
171 return (int)::wcsspn(pszBlock
, pszSet
);
174 static int __cdecl
StringSpanExcluding(
175 _In_z_ LPCWSTR pszBlock
,
176 _In_z_ LPCWSTR pszSet
)
178 return (int)::wcscspn(pszBlock
, pszSet
);
181 static int __cdecl
FormatV(
182 _In_opt_z_ LPWSTR pszDest
,
183 _In_z_ LPCWSTR pszFormat
,
187 return ::_vscwprintf(pszFormat
, args
);
188 return ::vswprintf(pszDest
, pszFormat
, args
);
192 FormatMessageV(_In_z_ LPCWSTR pszFormat
, _In_opt_
va_list *pArgList
)
196 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_STRING
, pszFormat
, 0, 0,
197 reinterpret_cast<LPWSTR
>(&psz
), 0, pArgList
);
201 static BSTR __cdecl
AllocSysString(
202 _In_z_ LPCWSTR pszSource
,
205 return ::SysAllocStringLen(pszSource
, nLength
);
210 // Template specialization
213 class ChTraitsCRT
<char> : public ChTraitsBase
<char>
217 static int __cdecl
GetBaseTypeLength(_In_z_ LPCWSTR pszSource
) noexcept
219 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource
, -1, NULL
, 0, NULL
, NULL
) - 1;
222 static int __cdecl
GetBaseTypeLength(_In_z_ LPCSTR pszSource
) noexcept
224 if (pszSource
== NULL
) return 0;
225 return static_cast<int>(strlen(pszSource
));
228 static int __cdecl
GetBaseTypeLength(
229 _In_reads_(nLength
) LPCWSTR pszSource
,
230 _In_
int nLength
) noexcept
232 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource
, nLength
, NULL
, 0, NULL
, NULL
);
235 static int __cdecl
GetBaseTypeLength(
236 _In_reads_(nLength
) LPCSTR pszSource
,
237 _In_
int nLength
) noexcept
242 static void __cdecl
ConvertToBaseType(
243 _Out_writes_(nDestLength
) LPSTR pszDest
,
244 _In_
int nDestLength
,
246 _In_
int nSrcLength
= -1)
248 if (nSrcLength
== -1)
249 nSrcLength
= 1 + GetBaseTypeLength(pszSrc
);
251 ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc
, nSrcLength
, pszDest
, nDestLength
, NULL
, NULL
);
254 static void __cdecl
ConvertToBaseType(
255 _Out_writes_(nDestLength
) LPSTR pszDest
,
256 _In_
int nDestLength
,
258 _In_
int nSrcLength
= -1)
260 if (nSrcLength
== -1)
261 nSrcLength
= 1 + GetBaseTypeLength(pszSrc
);
263 memcpy(pszDest
, pszSrc
, nSrcLength
);
266 static void __cdecl
MakeLower(
267 _Out_writes_(nSrcLength
) LPSTR pszSource
,
270 ::CharLowerBuffA(pszSource
, nSrcLength
);
273 static DWORD
GetEnvironmentVariable(
274 _In_z_ LPCSTR pszVar
,
275 _Out_writes_opt_(nBufLength
) LPSTR pszBuf
,
276 _In_opt_
int nBufLength
)
278 return ::GetEnvironmentVariableA(pszVar
, pszBuf
, nBufLength
);
281 static void __cdecl
MakeUpper(
282 _Out_writes_(nSrcLength
) LPSTR pszSource
,
285 ::CharUpperBuffA(pszSource
, nSrcLength
);
288 static LPSTR __cdecl
FindString(
289 _In_z_ LPSTR pszSource
,
290 _In_z_ LPCSTR pszSub
)
292 return ::strstr(pszSource
, pszSub
);
294 static LPCSTR __cdecl
FindString(
295 _In_z_ LPCSTR pszSource
,
296 _In_z_ LPCSTR pszSub
)
298 return ::strstr(pszSource
, pszSub
);
301 static LPSTR __cdecl
FindChar(
302 _In_z_ LPSTR pszSource
,
305 return ::strchr(pszSource
, ch
);
307 static LPCSTR __cdecl
FindChar(
308 _In_z_ LPCSTR pszSource
,
311 return ::strchr(pszSource
, ch
);
314 static LPSTR __cdecl
FindCharReverse(
315 _In_z_ LPSTR pszSource
,
318 return ::strrchr(pszSource
, ch
);
320 static LPCSTR __cdecl
FindCharReverse(
321 _In_z_ LPCSTR pszSource
,
324 return ::strrchr(pszSource
, ch
);
327 static LPSTR __cdecl
FindOneOf(
328 _In_z_ LPSTR pszSource
,
329 _In_z_ LPCSTR pszCharSet
)
331 return ::strpbrk(pszSource
, pszCharSet
);
333 static LPCSTR __cdecl
FindOneOf(
334 _In_z_ LPCSTR pszSource
,
335 _In_z_ LPCSTR pszCharSet
)
337 return ::strpbrk(pszSource
, pszCharSet
);
340 static int __cdecl
Compare(
344 return ::strcmp(psz1
, psz2
);
347 static int __cdecl
CompareNoCase(
351 return ::_stricmp(psz1
, psz2
);
354 static int __cdecl
StringSpanIncluding(
355 _In_z_ LPCSTR pszBlock
,
356 _In_z_ LPCSTR pszSet
)
358 return (int)::strspn(pszBlock
, pszSet
);
361 static int __cdecl
StringSpanExcluding(
362 _In_z_ LPCSTR pszBlock
,
363 _In_z_ LPCSTR pszSet
)
365 return (int)::strcspn(pszBlock
, pszSet
);
368 static int __cdecl
FormatV(
369 _In_opt_z_ LPSTR pszDest
,
370 _In_z_ LPCSTR pszFormat
,
374 return ::_vscprintf(pszFormat
, args
);
375 return ::vsprintf(pszDest
, pszFormat
, args
);
379 FormatMessageV(_In_z_ LPCSTR pszFormat
, _In_opt_
va_list *pArgList
)
383 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_STRING
, pszFormat
, 0, 0, reinterpret_cast<LPSTR
>(&psz
),
388 static BSTR __cdecl
AllocSysString(
389 _In_z_ LPCSTR pszSource
,
392 int nLen
= ChTraitsCRT
<wchar_t>::GetBaseTypeLength(pszSource
, nLength
);
393 BSTR bstr
= ::SysAllocStringLen(NULL
, nLen
);
396 ChTraitsCRT
<wchar_t>::ConvertToBaseType(bstr
, nLen
, pszSource
, nLength
);
404 namespace _CSTRING_IMPL_
406 template <typename _CharType
, class StringTraits
>
407 struct _MFCDLLTraitsCheck
409 const static bool c_bIsMFCDLLTraits
= false;
414 // TODO: disable conversion functions when _CSTRING_DISABLE_NARROW_WIDE_CONVERSION is defined.
416 template <typename BaseType
, class StringTraits
>
418 public CSimpleStringT
<BaseType
, _CSTRING_IMPL_::_MFCDLLTraitsCheck
<BaseType
, StringTraits
>::c_bIsMFCDLLTraits
>
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
;
431 CStringT() noexcept
:
432 CThisSimpleString(StringTraits::GetDefaultManager())
436 explicit CStringT( _In_ IAtlStringMgr
* pStringMgr
) noexcept
:
437 CThisSimpleString(pStringMgr
)
441 static void __cdecl
Construct(_In_ CStringT
* pString
)
443 new(pString
) CStringT
;
446 CStringT(_In_
const CStringT
& strSrc
) :
447 CThisSimpleString(strSrc
)
451 CStringT(_In_
const CThisSimpleString
& strSrc
) :
452 CThisSimpleString(strSrc
)
456 template<class StringTraits_
>
457 CStringT(_In_
const CStringT
<YCHAR
, StringTraits_
> & strSrc
) :
458 CThisSimpleString(StringTraits::GetDefaultManager())
460 *this = static_cast<const YCHAR
*>(strSrc
);
464 /* helper function */
465 template <typename T_CHAR
>
466 void LoadFromPtr_(_In_opt_z_
const T_CHAR
* pszSrc
)
470 if (IS_INTRESOURCE(pszSrc
))
471 LoadString(LOWORD(pszSrc
));
477 CStringT(_In_opt_z_
const XCHAR
* pszSrc
) :
478 CThisSimpleString(StringTraits::GetDefaultManager())
480 LoadFromPtr_(pszSrc
);
483 CStringT(_In_opt_z_
const XCHAR
* pszSrc
,
484 _In_ IAtlStringMgr
* pStringMgr
) : CThisSimpleString(pStringMgr
)
486 LoadFromPtr_(pszSrc
);
489 CStringT(_In_opt_z_
const YCHAR
* pszSrc
) :
490 CThisSimpleString(StringTraits::GetDefaultManager())
492 LoadFromPtr_(pszSrc
);
495 CStringT(_In_opt_z_
const YCHAR
* pszSrc
,
496 _In_ IAtlStringMgr
* pStringMgr
) : CThisSimpleString(pStringMgr
)
498 LoadFromPtr_(pszSrc
);
501 CStringT(_In_reads_z_(nLength
) const XCHAR
* pch
,
503 CThisSimpleString(pch
, nLength
, StringTraits::GetDefaultManager())
507 CStringT(_In_reads_z_(nLength
) const YCHAR
* pch
,
509 CThisSimpleString(pch
, nLength
, StringTraits::GetDefaultManager())
513 CStringT
& operator=(_In_
const CStringT
& strSrc
)
515 CThisSimpleString::operator=(strSrc
);
519 CStringT
& operator=(_In_opt_z_ PCXSTR pszSrc
)
521 CThisSimpleString::operator=(pszSrc
);
525 CStringT
& operator=(_In_opt_z_ PCYSTR pszSrc
)
527 int length
= pszSrc
? StringTraits::GetBaseTypeLength(pszSrc
) : 0;
530 PXSTR result
= CThisSimpleString::GetBuffer(length
);
531 StringTraits::ConvertToBaseType(result
, length
, pszSrc
);
532 CThisSimpleString::ReleaseBufferSetLength(length
);
536 CThisSimpleString::Empty();
541 CStringT
& operator=(_In_
const CThisSimpleString
&strSrc
)
543 CThisSimpleString::operator=(strSrc
);
547 friend bool operator==(const CStringT
& str1
, const CStringT
& str2
) noexcept
549 return str1
.Compare(str2
) == 0;
552 friend bool operator==(const CStringT
& str1
, PCXSTR psz2
) noexcept
554 return str1
.Compare(psz2
) == 0;
557 friend bool operator==(const CStringT
& str1
, PCYSTR psz2
) noexcept
559 CStringT
tmp(psz2
, str1
.GetManager());
560 return tmp
.Compare(str1
) == 0;
563 friend bool operator==(const CStringT
& str1
, XCHAR ch2
) noexcept
565 return str1
.GetLength() == 1 && str1
[0] == ch2
;
568 friend bool operator==(PCXSTR psz1
, const CStringT
& str2
) noexcept
570 return str2
.Compare(psz1
) == 0;
573 friend bool operator==(PCYSTR psz1
, const CStringT
& str2
) noexcept
575 CStringT
tmp(psz1
, str2
.GetManager());
576 return tmp
.Compare(str2
) == 0;
579 friend bool operator==(XCHAR ch1
, const CStringT
& str2
) noexcept
581 return str2
.GetLength() == 1 && str2
[0] == ch1
;
584 friend bool operator!=(const CStringT
& str1
, const CStringT
& str2
) noexcept
586 return str1
.Compare(str2
) != 0;
589 friend bool operator!=(const CStringT
& str1
, PCXSTR psz2
) noexcept
591 return str1
.Compare(psz2
) != 0;
594 friend bool operator!=(const CStringT
& str1
, PCYSTR psz2
) noexcept
596 CStringT
tmp(psz2
, str1
.GetManager());
597 return tmp
.Compare(str1
) != 0;
600 friend bool operator!=(const CStringT
& str1
, XCHAR ch2
) noexcept
602 return str1
.GetLength() != 1 || str1
[0] != ch2
;
605 friend bool operator!=(PCXSTR psz1
, const CStringT
& str2
) noexcept
607 return str2
.Compare(psz1
) != 0;
610 friend bool operator!=(PCYSTR psz1
, const CStringT
& str2
) noexcept
612 CStringT
tmp(psz1
, str2
.GetManager());
613 return tmp
.Compare(str2
) != 0;
616 friend bool operator!=(XCHAR ch1
, const CStringT
& str2
) noexcept
618 return str2
.GetLength() != 1 || str2
[0] != ch1
;
621 CStringT
& operator+=(_In_
const CThisSimpleString
& str
)
623 CThisSimpleString::operator+=(str
);
627 CStringT
& operator+=(_In_z_ PCXSTR pszSrc
)
629 CThisSimpleString::operator+=(pszSrc
);
633 CStringT
& operator+=(_In_ XCHAR ch
)
635 CThisSimpleString::operator+=(ch
);
639 BOOL
LoadString(_In_ UINT nID
)
641 return LoadString(_AtlBaseModule
.GetResourceInstance(), nID
);
644 _Check_return_ BOOL
LoadString(_In_ HINSTANCE hInstance
,
647 const ATLSTRINGRESOURCEIMAGE
* pImage
= AtlGetStringResourceImage(hInstance
, nID
);
648 if (pImage
== NULL
) return FALSE
;
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
);
658 BOOL
GetEnvironmentVariable(_In_z_ PCXSTR pszVar
)
660 int nLength
= StringTraits::GetEnvironmentVariable(pszVar
, NULL
, 0);
664 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
665 StringTraits::GetEnvironmentVariable(pszVar
, pszBuffer
, nLength
);
666 CThisSimpleString::ReleaseBuffer();
670 CThisSimpleString::Empty();
674 CStringT
& MakeLower()
676 int nLength
= CThisSimpleString::GetLength();
677 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
679 StringTraits::MakeLower(pszBuffer
, nLength
);
680 CThisSimpleString::ReleaseBufferSetLength(nLength
);
685 CStringT
& MakeUpper()
687 int nLength
= CThisSimpleString::GetLength();
688 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
690 StringTraits::MakeUpper(pszBuffer
, nLength
);
691 CThisSimpleString::ReleaseBufferSetLength(nLength
);
696 int Find(_In_ PCXSTR pszSub
, _In_opt_
int iStart
= 0) const noexcept
698 int nLength
= CThisSimpleString::GetLength();
700 if (iStart
>= nLength
|| iStart
< 0)
703 PCXSTR pszString
= CThisSimpleString::GetString();
704 PCXSTR pszResult
= StringTraits::FindString(pszString
+ iStart
, pszSub
);
706 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
709 int Find(_In_ XCHAR ch
, _In_opt_
int iStart
= 0) const noexcept
711 int nLength
= CThisSimpleString::GetLength();
713 if (iStart
>= nLength
|| iStart
< 0)
716 PCXSTR pszString
= CThisSimpleString::GetString();
717 PCXSTR pszResult
= StringTraits::FindChar(pszString
+ iStart
, ch
);
719 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
722 int FindOneOf(_In_ PCXSTR pszCharSet
) const noexcept
724 PCXSTR pszString
= CThisSimpleString::GetString();
725 PCXSTR pszResult
= StringTraits::FindOneOf(pszString
, pszCharSet
);
727 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
730 int ReverseFind(_In_ XCHAR ch
) const noexcept
732 PCXSTR pszString
= CThisSimpleString::GetString();
733 PCXSTR pszResult
= StringTraits::FindCharReverse(pszString
, ch
);
735 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
738 int Compare(_In_z_ PCXSTR psz
) const
740 return StringTraits::Compare(CThisSimpleString::GetString(), psz
);
743 int CompareNoCase(_In_z_ PCXSTR psz
) const
745 return StringTraits::CompareNoCase(CThisSimpleString::GetString(), psz
);
748 CStringT
Mid(int iFirst
, int nCount
) const
750 int nLength
= CThisSimpleString::GetLength();
756 if (iFirst
> nLength
)
758 if (iFirst
+ nCount
> nLength
)
759 nCount
= nLength
- iFirst
;
761 return CStringT(CThisSimpleString::GetString() + iFirst
, nCount
);
764 CStringT
Mid(int iFirst
) const
766 int nLength
= CThisSimpleString::GetLength();
770 if (iFirst
> nLength
)
773 return CStringT(CThisSimpleString::GetString() + iFirst
, nLength
- iFirst
);
776 CStringT
Left(int nCount
) const
778 int nLength
= CThisSimpleString::GetLength();
782 if (nCount
> nLength
)
785 return CStringT(CThisSimpleString::GetString(), nCount
);
788 CStringT
Right(int nCount
) const
790 int nLength
= CThisSimpleString::GetLength();
794 if (nCount
> nLength
)
797 return CStringT(CThisSimpleString::GetString() + nLength
- nCount
, nCount
);
800 void __cdecl
AppendFormat(UINT nFormatID
, ...)
803 va_start(args
, nFormatID
);
804 CStringT formatString
;
805 if (formatString
.LoadString(nFormatID
))
806 AppendFormatV(formatString
, args
);
810 void __cdecl
AppendFormat(PCXSTR pszFormat
, ...)
813 va_start(args
, pszFormat
);
814 AppendFormatV(pszFormat
, args
);
818 void __cdecl
Format(UINT nFormatID
, ...)
821 va_start(args
, nFormatID
);
822 CStringT formatString
;
823 if (formatString
.LoadString(nFormatID
))
824 FormatV(formatString
, args
);
828 void __cdecl
Format(PCXSTR pszFormat
, ...)
831 va_start(args
, pszFormat
);
832 FormatV(pszFormat
, args
);
836 void AppendFormatV(PCXSTR pszFormat
, va_list args
)
838 int nLength
= StringTraits::FormatV(NULL
, pszFormat
, args
);
839 int nCurrent
= CThisSimpleString::GetLength();
841 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
+ nCurrent
);
842 StringTraits::FormatV(pszBuffer
+ nCurrent
, pszFormat
, args
);
843 CThisSimpleString::ReleaseBufferSetLength(nLength
+ nCurrent
);
846 void FormatV(PCXSTR pszFormat
, va_list args
)
848 int nLength
= StringTraits::FormatV(NULL
, pszFormat
, args
);
850 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
851 StringTraits::FormatV(pszBuffer
, pszFormat
, args
);
852 CThisSimpleString::ReleaseBufferSetLength(nLength
);
855 void __cdecl
FormatMessage(UINT nFormatID
, ...)
858 va_start(va
, nFormatID
);
861 if (str
.LoadString(nFormatID
))
862 FormatMessageV(str
, &va
);
867 void __cdecl
FormatMessage(PCXSTR pszFormat
, ...)
870 va_start(va
, pszFormat
);
871 FormatMessageV(pszFormat
, &va
);
876 FormatMessageV(PCXSTR pszFormat
, va_list *pArgList
)
878 PXSTR psz
= StringTraits::FormatMessageV(pszFormat
, pArgList
);
880 CThisSimpleString::ThrowMemoryException();
886 int Replace(PCXSTR pszOld
, PCXSTR pszNew
)
888 PCXSTR pszString
= CThisSimpleString::GetString();
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
;
897 while ((pszFound
= StringTraits::FindString(pszString
, pszOld
)))
899 nResultLength
+= nDiff
;
900 pszString
= pszFound
+ nOldLen
;
903 if (pszString
== CThisSimpleString::GetString())
906 PXSTR pszResult
= CThisSimpleString::GetBuffer(nResultLength
);
908 int nCount
= 0, nRemaining
= nLength
;
909 while (nRemaining
&& (pszNext
= StringTraits::FindString(pszResult
, pszOld
)))
911 nRemaining
-= (pszNext
- pszResult
);
912 nRemaining
-= nOldLen
;
914 CThisSimpleString::CopyCharsOverlapped(pszNext
+ nNewLen
, nRemaining
+ 1, pszNext
+ nOldLen
, nRemaining
+ 1);
915 CThisSimpleString::CopyCharsOverlapped(pszNext
, nNewLen
, pszNew
, nNewLen
);
916 pszResult
= pszNext
+ nNewLen
;
920 CThisSimpleString::ReleaseBufferSetLength(nResultLength
);
925 int Replace(XCHAR chOld
, XCHAR chNew
)
927 PXSTR pszString
= CThisSimpleString::GetString();
928 PXSTR pszFirst
= StringTraits::FindChar(pszString
, chOld
);
932 int nLength
= CThisSimpleString::GetLength();
935 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
936 pszFirst
= pszBuffer
+ (pszFirst
- pszString
);
940 } while ((pszFirst
= StringTraits::FindChar(pszFirst
+ 1, chOld
)));
942 CThisSimpleString::ReleaseBufferSetLength(nLength
);
947 CStringT
Tokenize(_In_z_ PCXSTR pszTokens
, _Inout_
int& iStart
) const
949 ATLASSERT(iStart
>= 0);
952 AtlThrow(E_INVALIDARG
);
954 if (!pszTokens
|| !pszTokens
[0])
956 if (iStart
< CThisSimpleString::GetLength())
964 if (iStart
< CThisSimpleString::GetLength())
966 int iRangeOffset
= StringTraits::StringSpanIncluding(CThisSimpleString::GetString() + iStart
, pszTokens
);
968 if (iRangeOffset
+ iStart
< CThisSimpleString::GetLength())
970 int iNewStart
= iStart
+ iRangeOffset
;
971 int nCount
= StringTraits::StringSpanExcluding(CThisSimpleString::GetString() + iNewStart
, pszTokens
);
973 iStart
= iNewStart
+ nCount
+ 1;
975 return Mid(iNewStart
, nCount
);
983 static PCXSTR
DefaultTrimChars()
985 static XCHAR str
[] = { ' ', '\t', '\r', '\n', 0 };
992 return TrimLeft(DefaultTrimChars());
995 CStringT
& TrimLeft(XCHAR chTarget
)
997 XCHAR str
[2] = { chTarget
, 0 };
998 return TrimLeft(str
);
1001 CStringT
& TrimLeft(PCXSTR pszTargets
)
1003 int nLength
= CThisSimpleString::GetLength();
1004 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
1007 while (nCount
< nLength
&& StringTraits::FindChar(pszTargets
, pszBuffer
[nCount
]))
1012 CThisSimpleString::CopyCharsOverlapped(pszBuffer
, nLength
- nCount
, pszBuffer
+ nCount
, nLength
- nCount
);
1015 CThisSimpleString::ReleaseBufferSetLength(nLength
);
1021 CStringT
& TrimRight()
1023 return TrimRight(DefaultTrimChars());
1026 CStringT
& TrimRight(XCHAR chTarget
)
1028 XCHAR str
[2] = { chTarget
, 0 };
1029 return TrimRight(str
);
1032 CStringT
& TrimRight(PCXSTR pszTargets
)
1034 int nLength
= CThisSimpleString::GetLength();
1035 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
1037 while (nLength
> 0 && StringTraits::FindChar(pszTargets
, pszBuffer
[nLength
-1]))
1040 CThisSimpleString::ReleaseBufferSetLength(nLength
);
1048 return Trim(DefaultTrimChars());
1051 CStringT
& Trim(XCHAR chTarget
)
1053 XCHAR str
[2] = { chTarget
, 0 };
1057 CStringT
& Trim(PCXSTR pszTargets
)
1059 return TrimRight(pszTargets
).TrimLeft(pszTargets
);
1063 BSTR
AllocSysString() const
1065 return StringTraits::AllocSysString(CThisSimpleString::GetString(), CThisSimpleString::GetLength());