5 #include <atlsimpstr.h>
14 inline UINT WINAPI
_AtlGetConversionACP() throw()
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
) throw()
31 if (pszSource
== NULL
) return -1;
32 return static_cast<int>(wcslen(pszSource
));
35 static int __cdecl
GetBaseTypeLength(_In_z_ LPCSTR pszSource
) throw()
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
) throw()
48 static int __cdecl
GetBaseTypeLength(
49 _In_reads_(nLength
) LPCSTR pszSource
,
50 _In_
int nLength
) throw()
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_ LPCWSTR pszSource
,
103 _In_z_ LPCWSTR pszSub
)
105 return ::wcsstr(pszSource
, pszSub
);
108 static LPWSTR __cdecl
FindChar(
109 _In_z_ LPCWSTR pszSource
,
112 return ::wcschr(pszSource
, ch
);
115 static LPWSTR __cdecl
FindCharReverse(
116 _In_z_ LPCWSTR pszSource
,
119 return ::wcsrchr(pszSource
, ch
);
122 static LPWSTR __cdecl
FindOneOf(
123 _In_z_ LPCWSTR pszSource
,
124 _In_z_ LPCWSTR pszCharSet
)
126 return ::wcspbrk(pszSource
, pszCharSet
);
129 static int __cdecl
Compare(
133 return ::wcscmp(psz1
, psz2
);
136 static int __cdecl
CompareNoCase(
140 return ::_wcsicmp(psz1
, psz2
);
143 static int __cdecl
FormatV(
144 _In_opt_z_ LPWSTR pszDest
,
145 _In_z_ LPCWSTR pszFormat
,
149 return ::_vscwprintf(pszFormat
, args
);
150 return ::vswprintf(pszDest
, pszFormat
, args
);
153 static BSTR __cdecl
AllocSysString(
154 _In_z_ LPCWSTR pszSource
,
157 return ::SysAllocStringLen(pszSource
, nLength
);
162 // Template specialization
165 class ChTraitsCRT
<char> : public ChTraitsBase
<char>
169 static int __cdecl
GetBaseTypeLength(_In_z_ LPCWSTR pszSource
) throw()
171 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource
, -1, NULL
, 0, NULL
, NULL
) - 1;
174 static int __cdecl
GetBaseTypeLength(_In_z_ LPCSTR pszSource
) throw()
176 if (pszSource
== NULL
) return 0;
177 return static_cast<int>(strlen(pszSource
));
180 static int __cdecl
GetBaseTypeLength(
181 _In_reads_(nLength
) LPCWSTR pszSource
,
182 _In_
int nLength
) throw()
184 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource
, nLength
, NULL
, 0, NULL
, NULL
);
187 static int __cdecl
GetBaseTypeLength(
188 _In_reads_(nLength
) LPCSTR pszSource
,
189 _In_
int nLength
) throw()
194 static void __cdecl
ConvertToBaseType(
195 _Out_writes_(nDestLength
) LPSTR pszDest
,
196 _In_
int nDestLength
,
198 _In_
int nSrcLength
= -1)
200 if (nSrcLength
== -1)
201 nSrcLength
= 1 + GetBaseTypeLength(pszSrc
);
203 ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc
, nSrcLength
, pszDest
, nDestLength
, NULL
, NULL
);
206 static void __cdecl
ConvertToBaseType(
207 _Out_writes_(nDestLength
) LPSTR pszDest
,
208 _In_
int nDestLength
,
210 _In_
int nSrcLength
= -1)
212 if (nSrcLength
== -1)
213 nSrcLength
= 1 + GetBaseTypeLength(pszSrc
);
215 memcpy(pszDest
, pszSrc
, nSrcLength
);
218 static void __cdecl
MakeLower(
219 _Out_writes_(nSrcLength
) LPSTR pszSource
,
222 ::CharLowerBuffA(pszSource
, nSrcLength
);
225 static DWORD
GetEnvironmentVariable(
226 _In_z_ LPCSTR pszVar
,
227 _Out_writes_opt_(nBufLength
) LPSTR pszBuf
,
228 _In_opt_
int nBufLength
)
230 return ::GetEnvironmentVariableA(pszVar
, pszBuf
, nBufLength
);
233 static void __cdecl
MakeUpper(
234 _Out_writes_(nSrcLength
) LPSTR pszSource
,
237 ::CharUpperBuffA(pszSource
, nSrcLength
);
240 static LPSTR __cdecl
FindString(
241 _In_z_ LPCSTR pszSource
,
242 _In_z_ LPCSTR pszSub
)
244 return ::strstr(pszSource
, pszSub
);
247 static LPSTR __cdecl
FindChar(
248 _In_z_ LPCSTR pszSource
,
251 return ::strchr(pszSource
, ch
);
254 static LPSTR __cdecl
FindCharReverse(
255 _In_z_ LPCSTR pszSource
,
258 return ::strrchr(pszSource
, ch
);
261 static LPSTR __cdecl
FindOneOf(
262 _In_z_ LPCSTR pszSource
,
263 _In_z_ LPCSTR pszCharSet
)
265 return ::strpbrk(pszSource
, pszCharSet
);
268 static int __cdecl
Compare(
272 return ::strcmp(psz1
, psz2
);
275 static int __cdecl
CompareNoCase(
279 return ::_stricmp(psz1
, psz2
);
282 static int __cdecl
FormatV(
283 _In_opt_z_ LPSTR pszDest
,
284 _In_z_ LPCSTR pszFormat
,
288 return ::_vscprintf(pszFormat
, args
);
289 return ::vsprintf(pszDest
, pszFormat
, args
);
292 static BSTR __cdecl
AllocSysString(
293 _In_z_ LPCSTR pszSource
,
296 int nLen
= ChTraitsCRT
<wchar_t>::GetBaseTypeLength(pszSource
, nLength
);
297 BSTR bstr
= ::SysAllocStringLen(NULL
, nLen
);
300 ChTraitsCRT
<wchar_t>::ConvertToBaseType(bstr
, nLen
, pszSource
, nLength
);
308 namespace _CSTRING_IMPL_
310 template <typename _CharType
, class StringTraits
>
311 struct _MFCDLLTraitsCheck
313 const static bool c_bIsMFCDLLTraits
= false;
318 // TODO: disable conversion functions when _CSTRING_DISABLE_NARROW_WIDE_CONVERSION is defined.
320 template <typename BaseType
, class StringTraits
>
322 public CSimpleStringT
<BaseType
, _CSTRING_IMPL_::_MFCDLLTraitsCheck
<BaseType
, StringTraits
>::c_bIsMFCDLLTraits
>
325 typedef CSimpleStringT
<BaseType
, _CSTRING_IMPL_::_MFCDLLTraitsCheck
<BaseType
, StringTraits
>::c_bIsMFCDLLTraits
> CThisSimpleString
;
326 typedef StringTraits StrTraits
;
327 typedef typename
CThisSimpleString::XCHAR XCHAR
;
328 typedef typename
CThisSimpleString::PXSTR PXSTR
;
329 typedef typename
CThisSimpleString::PCXSTR PCXSTR
;
330 typedef typename
CThisSimpleString::YCHAR YCHAR
;
331 typedef typename
CThisSimpleString::PYSTR PYSTR
;
332 typedef typename
CThisSimpleString::PCYSTR PCYSTR
;
336 CThisSimpleString(StringTraits::GetDefaultManager())
340 explicit CStringT( _In_ IAtlStringMgr
* pStringMgr
) throw() :
341 CThisSimpleString(pStringMgr
)
345 static void __cdecl
Construct(_In_ CStringT
* pString
)
347 new(pString
) CStringT
;
350 CStringT(_In_
const CStringT
& strSrc
) :
351 CThisSimpleString(strSrc
)
355 CStringT(_In_
const CThisSimpleString
& strSrc
) :
356 CThisSimpleString(strSrc
)
360 template<class StringTraits_
>
361 CStringT(_In_
const CStringT
<YCHAR
, StringTraits_
> & strSrc
) :
362 CThisSimpleString(StringTraits::GetDefaultManager())
364 *this = static_cast<const YCHAR
*>(strSrc
);
368 /* helper function */
369 template <typename T_CHAR
>
370 void LoadFromPtr_(_In_opt_z_
const T_CHAR
* pszSrc
)
374 if (IS_INTRESOURCE(pszSrc
))
375 LoadString(LOWORD(pszSrc
));
381 CStringT(_In_opt_z_
const XCHAR
* pszSrc
) :
382 CThisSimpleString(StringTraits::GetDefaultManager())
384 LoadFromPtr_(pszSrc
);
387 CStringT(_In_opt_z_
const XCHAR
* pszSrc
,
388 _In_ IAtlStringMgr
* pStringMgr
) : CThisSimpleString(pStringMgr
)
390 LoadFromPtr_(pszSrc
);
393 CStringT(_In_opt_z_
const YCHAR
* pszSrc
) :
394 CThisSimpleString(StringTraits::GetDefaultManager())
396 LoadFromPtr_(pszSrc
);
399 CStringT(_In_opt_z_
const YCHAR
* pszSrc
,
400 _In_ IAtlStringMgr
* pStringMgr
) : CThisSimpleString(pStringMgr
)
402 LoadFromPtr_(pszSrc
);
405 CStringT(_In_reads_z_(nLength
) const XCHAR
* pch
,
407 CThisSimpleString(pch
, nLength
, StringTraits::GetDefaultManager())
411 CStringT(_In_reads_z_(nLength
) const YCHAR
* pch
,
413 CThisSimpleString(pch
, nLength
, StringTraits::GetDefaultManager())
417 CStringT
& operator=(_In_
const CStringT
& strSrc
)
419 CThisSimpleString::operator=(strSrc
);
423 CStringT
& operator=(_In_opt_z_ PCXSTR pszSrc
)
425 CThisSimpleString::operator=(pszSrc
);
429 CStringT
& operator=(_In_opt_z_ PCYSTR pszSrc
)
431 int length
= pszSrc
? StringTraits::GetBaseTypeLength(pszSrc
) : 0;
434 PXSTR result
= CThisSimpleString::GetBuffer(length
);
435 StringTraits::ConvertToBaseType(result
, length
, pszSrc
);
436 CThisSimpleString::ReleaseBufferSetLength(length
);
440 CThisSimpleString::Empty();
445 CStringT
& operator=(_In_
const CThisSimpleString
&strSrc
)
447 CThisSimpleString::operator=(strSrc
);
451 friend bool operator==(const CStringT
& str1
, const CStringT
& str2
) throw()
453 return str1
.Compare(str2
) == 0;
456 friend bool operator==(const CStringT
& str1
, PCXSTR psz2
) throw()
458 return str1
.Compare(psz2
) == 0;
461 friend bool operator==(const CStringT
& str1
, PCYSTR psz2
) throw()
463 CStringT
tmp(psz2
, str1
.GetManager());
464 return tmp
.Compare(str1
) == 0;
467 friend bool operator==(const CStringT
& str1
, XCHAR ch2
) throw()
469 return str1
.GetLength() == 1 && str1
[0] == ch2
;
472 friend bool operator==(PCXSTR psz1
, const CStringT
& str2
) throw()
474 return str2
.Compare(psz1
) == 0;
477 friend bool operator==(PCYSTR psz1
, const CStringT
& str2
) throw()
479 CStringT
tmp(psz1
, str2
.GetManager());
480 return tmp
.Compare(str2
) == 0;
483 friend bool operator==(XCHAR ch1
, const CStringT
& str2
) throw()
485 return str2
.GetLength() == 1 && str2
[0] == ch1
;
488 CStringT
& operator+=(_In_
const CThisSimpleString
& str
)
490 CThisSimpleString::operator+=(str
);
494 CStringT
& operator+=(_In_z_ PCXSTR pszSrc
)
496 CThisSimpleString::operator+=(pszSrc
);
500 CStringT
& operator+=(_In_ XCHAR ch
)
502 CThisSimpleString::operator+=(ch
);
506 BOOL
LoadString(_In_ UINT nID
)
508 return LoadString(_AtlBaseModule
.GetResourceInstance(), nID
);
511 _Check_return_ BOOL
LoadString(_In_ HINSTANCE hInstance
,
514 const ATLSTRINGRESOURCEIMAGE
* pImage
= AtlGetStringResourceImage(hInstance
, nID
);
515 if (pImage
== NULL
) return FALSE
;
517 int nLength
= StringTraits::GetBaseTypeLength(pImage
->achString
, pImage
->nLength
);
518 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
519 StringTraits::ConvertToBaseType(pszBuffer
, nLength
, pImage
->achString
, pImage
->nLength
);
520 CThisSimpleString::ReleaseBufferSetLength(nLength
);
525 BOOL
GetEnvironmentVariable(_In_z_ PCXSTR pszVar
)
527 int nLength
= StringTraits::GetEnvironmentVariable(pszVar
, NULL
, 0);
531 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
532 StringTraits::GetEnvironmentVariable(pszVar
, pszBuffer
, nLength
);
533 CThisSimpleString::ReleaseBuffer();
537 CThisSimpleString::Empty();
541 CStringT
& MakeLower()
543 int nLength
= CThisSimpleString::GetLength();
544 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
546 StringTraits::MakeLower(pszBuffer
, nLength
);
547 CThisSimpleString::ReleaseBufferSetLength(nLength
);
552 CStringT
& MakeUpper()
554 int nLength
= CThisSimpleString::GetLength();
555 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
557 StringTraits::MakeUpper(pszBuffer
, nLength
);
558 CThisSimpleString::ReleaseBufferSetLength(nLength
);
563 int Find(_In_ PCXSTR pszSub
, _In_opt_
int iStart
= 0) const throw()
565 int nLength
= CThisSimpleString::GetLength();
567 if (iStart
>= nLength
|| iStart
< 0)
570 PCXSTR pszString
= CThisSimpleString::GetString();
571 PCXSTR pszResult
= StringTraits::FindString(pszString
+ iStart
, pszSub
);
573 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
576 int Find(_In_ XCHAR ch
, _In_opt_
int iStart
= 0) const throw()
578 int nLength
= CThisSimpleString::GetLength();
580 if (iStart
>= nLength
|| iStart
< 0)
583 PCXSTR pszString
= CThisSimpleString::GetString();
584 PCXSTR pszResult
= StringTraits::FindChar(pszString
+ iStart
, ch
);
586 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
589 int FindOneOf(_In_ PCXSTR pszCharSet
) const throw()
591 PCXSTR pszString
= CThisSimpleString::GetString();
592 PCXSTR pszResult
= StringTraits::FindOneOf(pszString
, pszCharSet
);
594 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
597 int ReverseFind(_In_ XCHAR ch
) const throw()
599 PCXSTR pszString
= CThisSimpleString::GetString();
600 PCXSTR pszResult
= StringTraits::FindCharReverse(pszString
, ch
);
602 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
605 int Compare(_In_z_ PCXSTR psz
) const
607 return StringTraits::Compare(CThisSimpleString::GetString(), psz
);
610 int CompareNoCase(_In_z_ PCXSTR psz
) const
612 return StringTraits::CompareNoCase(CThisSimpleString::GetString(), psz
);
615 CStringT
Mid(int iFirst
, int nCount
) const
617 int nLength
= CThisSimpleString::GetLength();
623 if (iFirst
> nLength
)
625 if (iFirst
+ nCount
> nLength
)
626 nCount
= nLength
- iFirst
;
628 return CStringT(CThisSimpleString::GetString() + iFirst
, nCount
);
631 CStringT
Mid(int iFirst
) const
633 int nLength
= CThisSimpleString::GetLength();
637 if (iFirst
> nLength
)
640 return CStringT(CThisSimpleString::GetString() + iFirst
, nLength
- iFirst
);
643 CStringT
Left(int nCount
) const
645 int nLength
= CThisSimpleString::GetLength();
649 if (nCount
> nLength
)
652 return CStringT(CThisSimpleString::GetString(), nCount
);
655 CStringT
Right(int nCount
) const
657 int nLength
= CThisSimpleString::GetLength();
661 if (nCount
> nLength
)
664 return CStringT(CThisSimpleString::GetString() + nLength
- nCount
, nCount
);
668 void __cdecl
Format(UINT nFormatID
, ...)
671 va_start(args
, nFormatID
);
672 CStringT formatString
;
673 if (formatString
.LoadString(nFormatID
))
674 FormatV(formatString
, args
);
678 void __cdecl
Format(PCXSTR pszFormat
, ...)
681 va_start(args
, pszFormat
);
682 FormatV(pszFormat
, args
);
686 void FormatV(PCXSTR pszFormat
, va_list args
)
688 int nLength
= StringTraits::FormatV(NULL
, pszFormat
, args
);
690 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
691 StringTraits::FormatV(pszBuffer
, pszFormat
, args
);
692 CThisSimpleString::ReleaseBufferSetLength(nLength
);
696 int Replace(PCXSTR pszOld
, PCXSTR pszNew
)
698 PCXSTR pszString
= CThisSimpleString::GetString();
700 const int nLength
= CThisSimpleString::GetLength();
701 const int nOldLen
= StringTraits::GetBaseTypeLength(pszOld
);
702 const int nNewLen
= StringTraits::GetBaseTypeLength(pszNew
);
703 const int nDiff
= nNewLen
- nOldLen
;
704 int nResultLength
= nLength
;
707 while ((pszFound
= StringTraits::FindString(pszString
, pszOld
)))
709 nResultLength
+= nDiff
;
710 pszString
= pszFound
+ nOldLen
;
713 if (pszString
== CThisSimpleString::GetString())
716 PXSTR pszResult
= CThisSimpleString::GetBuffer(nResultLength
);
718 int nCount
= 0, nRemaining
= nLength
;
719 while (nRemaining
&& (pszNext
= StringTraits::FindString(pszResult
, pszOld
)))
721 nRemaining
-= (pszNext
- pszResult
);
722 nRemaining
-= nOldLen
;
724 CThisSimpleString::CopyCharsOverlapped(pszNext
+ nNewLen
, nRemaining
+ 1, pszNext
+ nOldLen
, nRemaining
+ 1);
725 CThisSimpleString::CopyCharsOverlapped(pszNext
, nNewLen
, pszNew
, nNewLen
);
726 pszResult
= pszNext
+ nNewLen
;
730 CThisSimpleString::ReleaseBufferSetLength(nResultLength
);
735 int Replace(XCHAR chOld
, XCHAR chNew
)
737 PCXSTR pszString
= CThisSimpleString::GetString();
738 PXSTR pszFirst
= StringTraits::FindChar(pszString
, chOld
);
742 int nLength
= CThisSimpleString::GetLength();
745 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
746 pszFirst
= pszBuffer
+ (pszFirst
- pszString
);
750 } while ((pszFirst
= StringTraits::FindChar(pszFirst
+ 1, chOld
)));
752 CThisSimpleString::ReleaseBufferSetLength(nLength
);
757 static PCXSTR
DefaultTrimChars()
759 static XCHAR str
[] = { ' ', '\t', '\r', '\n', 0 };
766 return TrimLeft(DefaultTrimChars());
769 CStringT
& TrimLeft(XCHAR chTarget
)
771 XCHAR str
[2] = { chTarget
, 0 };
772 return TrimLeft(str
);
775 CStringT
& TrimLeft(PCXSTR pszTargets
)
777 int nLength
= CThisSimpleString::GetLength();
778 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
781 while (nCount
< nLength
&& StringTraits::FindChar(pszTargets
, pszBuffer
[nCount
]))
786 CThisSimpleString::CopyCharsOverlapped(pszBuffer
, nLength
- nCount
, pszBuffer
+ nCount
, nLength
- nCount
);
789 CThisSimpleString::ReleaseBufferSetLength(nLength
);
795 CStringT
& TrimRight()
797 return TrimRight(DefaultTrimChars());
800 CStringT
& TrimRight(XCHAR chTarget
)
802 XCHAR str
[2] = { chTarget
, 0 };
803 return TrimRight(str
);
806 CStringT
& TrimRight(PCXSTR pszTargets
)
808 int nLength
= CThisSimpleString::GetLength();
809 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
811 while (nLength
> 0 && StringTraits::FindChar(pszTargets
, pszBuffer
[nLength
-1]))
814 CThisSimpleString::ReleaseBufferSetLength(nLength
);
822 return Trim(DefaultTrimChars());
825 CStringT
& Trim(XCHAR chTarget
)
827 XCHAR str
[2] = { chTarget
, 0 };
831 CStringT
& Trim(PCXSTR pszTargets
)
833 return TrimRight(pszTargets
).TrimLeft(pszTargets
);
837 BSTR
AllocSysString() const
839 return StringTraits::AllocSysString(CThisSimpleString::GetString(), CThisSimpleString::GetLength());