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
FormatV(
137 _In_opt_z_ LPWSTR pszDest
,
138 _In_z_ LPCWSTR pszFormat
,
142 return ::_vscwprintf(pszFormat
, args
);
143 return ::vswprintf(pszDest
, pszFormat
, args
);
146 static BSTR __cdecl
AllocSysString(
147 _In_z_ LPCWSTR pszSource
,
150 return ::SysAllocStringLen(pszSource
, nLength
);
155 // Template specialization
158 class ChTraitsCRT
<char> : public ChTraitsBase
<char>
162 static int __cdecl
GetBaseTypeLength(_In_z_ LPCWSTR pszSource
) throw()
164 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource
, -1, NULL
, 0, NULL
, NULL
) - 1;
167 static int __cdecl
GetBaseTypeLength(_In_z_ LPCSTR pszSource
) throw()
169 if (pszSource
== NULL
) return 0;
170 return static_cast<int>(strlen(pszSource
));
173 static int __cdecl
GetBaseTypeLength(
174 _In_reads_(nLength
) LPCWSTR pszSource
,
175 _In_
int nLength
) throw()
177 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource
, nLength
, NULL
, 0, NULL
, NULL
);
180 static int __cdecl
GetBaseTypeLength(
181 _In_reads_(nLength
) LPCSTR pszSource
,
182 _In_
int nLength
) throw()
187 static void __cdecl
ConvertToBaseType(
188 _Out_writes_(nDestLength
) LPSTR pszDest
,
189 _In_
int nDestLength
,
191 _In_
int nSrcLength
= -1)
193 if (nSrcLength
== -1)
194 nSrcLength
= 1 + GetBaseTypeLength(pszSrc
);
196 ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc
, nSrcLength
, pszDest
, nDestLength
, NULL
, NULL
);
199 static void __cdecl
ConvertToBaseType(
200 _Out_writes_(nDestLength
) LPSTR pszDest
,
201 _In_
int nDestLength
,
203 _In_
int nSrcLength
= -1)
205 if (nSrcLength
== -1)
206 nSrcLength
= 1 + GetBaseTypeLength(pszSrc
);
208 memcpy(pszDest
, pszSrc
, nSrcLength
);
211 static void __cdecl
MakeLower(
212 _Out_writes_(nSrcLength
) LPSTR pszSource
,
215 ::CharLowerBuffA(pszSource
, nSrcLength
);
218 static DWORD
GetEnvironmentVariable(
219 _In_z_ LPCSTR pszVar
,
220 _Out_writes_opt_(nBufLength
) LPSTR pszBuf
,
221 _In_opt_
int nBufLength
)
223 return ::GetEnvironmentVariableA(pszVar
, pszBuf
, nBufLength
);
226 static void __cdecl
MakeUpper(
227 _Out_writes_(nSrcLength
) LPSTR pszSource
,
230 ::CharUpperBuffA(pszSource
, nSrcLength
);
233 static LPSTR __cdecl
FindString(
234 _In_z_ LPCSTR pszSource
,
235 _In_z_ LPCSTR pszSub
)
237 return ::strstr(pszSource
, pszSub
);
240 static LPSTR __cdecl
FindChar(
241 _In_z_ LPCSTR pszSource
,
244 return ::strchr(pszSource
, ch
);
247 static LPSTR __cdecl
FindCharReverse(
248 _In_z_ LPCSTR pszSource
,
251 return ::strrchr(pszSource
, ch
);
254 static LPSTR __cdecl
FindOneOf(
255 _In_z_ LPCSTR pszSource
,
256 _In_z_ LPCSTR pszCharSet
)
258 return ::strpbrk(pszSource
, pszCharSet
);
261 static int __cdecl
Compare(
265 return ::strcmp(psz1
, psz2
);
268 static int __cdecl
FormatV(
269 _In_opt_z_ LPSTR pszDest
,
270 _In_z_ LPCSTR pszFormat
,
274 return ::_vscprintf(pszFormat
, args
);
275 return ::vsprintf(pszDest
, pszFormat
, args
);
278 static BSTR __cdecl
AllocSysString(
279 _In_z_ LPCSTR pszSource
,
282 int nLen
= ChTraitsCRT
<wchar_t>::GetBaseTypeLength(pszSource
, nLength
);
283 BSTR bstr
= ::SysAllocStringLen(NULL
, nLen
);
286 ChTraitsCRT
<wchar_t>::ConvertToBaseType(bstr
, nLen
, pszSource
, nLength
);
294 namespace _CSTRING_IMPL_
296 template <typename _CharType
, class StringTraits
>
297 struct _MFCDLLTraitsCheck
299 const static bool c_bIsMFCDLLTraits
= false;
304 // TODO: disable conversion functions when _CSTRING_DISABLE_NARROW_WIDE_CONVERSION is defined.
306 template <typename BaseType
, class StringTraits
>
308 public CSimpleStringT
<BaseType
, _CSTRING_IMPL_::_MFCDLLTraitsCheck
<BaseType
, StringTraits
>::c_bIsMFCDLLTraits
>
311 typedef CSimpleStringT
<BaseType
, _CSTRING_IMPL_::_MFCDLLTraitsCheck
<BaseType
, StringTraits
>::c_bIsMFCDLLTraits
> CThisSimpleString
;
312 typedef StringTraits StrTraits
;
313 typedef typename
CThisSimpleString::XCHAR XCHAR
;
314 typedef typename
CThisSimpleString::PXSTR PXSTR
;
315 typedef typename
CThisSimpleString::PCXSTR PCXSTR
;
316 typedef typename
CThisSimpleString::YCHAR YCHAR
;
317 typedef typename
CThisSimpleString::PYSTR PYSTR
;
318 typedef typename
CThisSimpleString::PCYSTR PCYSTR
;
322 CThisSimpleString(StringTraits::GetDefaultManager())
326 explicit CStringT( _In_ IAtlStringMgr
* pStringMgr
) throw() :
327 CThisSimpleString(pStringMgr
)
331 static void __cdecl
Construct(_In_ CStringT
* pString
)
333 new(pString
) CStringT
;
336 CStringT(_In_
const CStringT
& strSrc
) :
337 CThisSimpleString(strSrc
)
341 CStringT(_In_
const CThisSimpleString
& strSrc
) :
342 CThisSimpleString(strSrc
)
346 template<class StringTraits_
>
347 CStringT(_In_
const CStringT
<YCHAR
, StringTraits_
> & strSrc
) :
348 CThisSimpleString(StringTraits::GetDefaultManager())
350 *this = static_cast<const YCHAR
*>(strSrc
);
354 /* helper function */
355 template <typename T_CHAR
>
356 void LoadFromPtr_(_In_opt_z_
const T_CHAR
* pszSrc
)
360 if (IS_INTRESOURCE(pszSrc
))
361 LoadString(LOWORD(pszSrc
));
367 CStringT(_In_opt_z_
const XCHAR
* pszSrc
) :
368 CThisSimpleString(StringTraits::GetDefaultManager())
370 LoadFromPtr_(pszSrc
);
373 CStringT(_In_opt_z_
const XCHAR
* pszSrc
,
374 _In_ IAtlStringMgr
* pStringMgr
) : CThisSimpleString(pStringMgr
)
376 LoadFromPtr_(pszSrc
);
379 CStringT(_In_opt_z_
const YCHAR
* pszSrc
) :
380 CThisSimpleString(StringTraits::GetDefaultManager())
382 LoadFromPtr_(pszSrc
);
385 CStringT(_In_opt_z_
const YCHAR
* pszSrc
,
386 _In_ IAtlStringMgr
* pStringMgr
) : CThisSimpleString(pStringMgr
)
388 LoadFromPtr_(pszSrc
);
391 CStringT(_In_reads_z_(nLength
) const XCHAR
* pch
,
393 CThisSimpleString(pch
, nLength
, StringTraits::GetDefaultManager())
397 CStringT(_In_reads_z_(nLength
) const YCHAR
* pch
,
399 CThisSimpleString(pch
, nLength
, StringTraits::GetDefaultManager())
403 CStringT
& operator=(_In_
const CStringT
& strSrc
)
405 CThisSimpleString::operator=(strSrc
);
409 CStringT
& operator=(_In_opt_z_ PCXSTR pszSrc
)
411 CThisSimpleString::operator=(pszSrc
);
415 CStringT
& operator=(_In_opt_z_ PCYSTR pszSrc
)
417 int length
= pszSrc
? StringTraits::GetBaseTypeLength(pszSrc
) : 0;
420 PXSTR result
= CThisSimpleString::GetBuffer(length
);
421 StringTraits::ConvertToBaseType(result
, length
, pszSrc
);
422 CThisSimpleString::ReleaseBufferSetLength(length
);
426 CThisSimpleString::Empty();
431 CStringT
& operator=(_In_
const CThisSimpleString
&strSrc
)
433 CThisSimpleString::operator=(strSrc
);
437 friend bool operator==(const CStringT
& str1
, const CStringT
& str2
) throw()
439 return str1
.Compare(str2
) == 0;
442 friend bool operator==(const CStringT
& str1
, PCXSTR psz2
) throw()
444 return str1
.Compare(psz2
) == 0;
447 friend bool operator==(const CStringT
& str1
, PCYSTR psz2
) throw()
449 CStringT
tmp(psz2
, str1
.GetManager());
450 return tmp
.Compare(str1
) == 0;
453 friend bool operator==(const CStringT
& str1
, XCHAR ch2
) throw()
455 return str1
.GetLength() == 1 && str1
[0] == ch2
;
458 friend bool operator==(PCXSTR psz1
, const CStringT
& str2
) throw()
460 return str2
.Compare(psz1
) == 0;
463 friend bool operator==(PCYSTR psz1
, const CStringT
& str2
) throw()
465 CStringT
tmp(psz1
, str2
.GetManager());
466 return tmp
.Compare(str2
) == 0;
469 friend bool operator==(XCHAR ch1
, const CStringT
& str2
) throw()
471 return str2
.GetLength() == 1 && str2
[0] == ch1
;
474 CStringT
& operator+=(_In_
const CThisSimpleString
& str
)
476 CThisSimpleString::operator+=(str
);
480 CStringT
& operator+=(_In_z_ PCXSTR pszSrc
)
482 CThisSimpleString::operator+=(pszSrc
);
486 CStringT
& operator+=(_In_ XCHAR ch
)
488 CThisSimpleString::operator+=(ch
);
492 BOOL
LoadString(_In_ UINT nID
)
494 return LoadString(_AtlBaseModule
.GetResourceInstance(), nID
);
497 _Check_return_ BOOL
LoadString(_In_ HINSTANCE hInstance
,
500 const ATLSTRINGRESOURCEIMAGE
* pImage
= AtlGetStringResourceImage(hInstance
, nID
);
501 if (pImage
== NULL
) return FALSE
;
503 int nLength
= StringTraits::GetBaseTypeLength(pImage
->achString
, pImage
->nLength
);
504 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
505 StringTraits::ConvertToBaseType(pszBuffer
, nLength
, pImage
->achString
, pImage
->nLength
);
506 CThisSimpleString::ReleaseBufferSetLength(nLength
);
511 BOOL
GetEnvironmentVariable(_In_z_ PCXSTR pszVar
)
513 int nLength
= StringTraits::GetEnvironmentVariable(pszVar
, NULL
, 0);
517 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
518 StringTraits::GetEnvironmentVariable(pszVar
, pszBuffer
, nLength
);
519 CThisSimpleString::ReleaseBuffer();
523 CThisSimpleString::Empty();
527 CStringT
& MakeLower()
529 int nLength
= CThisSimpleString::GetLength();
530 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
532 StringTraits::MakeLower(pszBuffer
, nLength
);
533 CThisSimpleString::ReleaseBufferSetLength(nLength
);
538 CStringT
& MakeUpper()
540 int nLength
= CThisSimpleString::GetLength();
541 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
543 StringTraits::MakeUpper(pszBuffer
, nLength
);
544 CThisSimpleString::ReleaseBufferSetLength(nLength
);
549 int Find(_In_ PCXSTR pszSub
, _In_opt_
int iStart
= 0) const throw()
551 int nLength
= CThisSimpleString::GetLength();
553 if (iStart
>= nLength
|| iStart
< 0)
556 PCXSTR pszString
= CThisSimpleString::GetString();
557 PCXSTR pszResult
= StringTraits::FindString(pszString
+ iStart
, pszSub
);
559 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
562 int Find(_In_ XCHAR ch
, _In_opt_
int iStart
= 0) const throw()
564 int nLength
= CThisSimpleString::GetLength();
566 if (iStart
>= nLength
|| iStart
< 0)
569 PCXSTR pszString
= CThisSimpleString::GetString();
570 PCXSTR pszResult
= StringTraits::FindChar(pszString
+ iStart
, ch
);
572 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
575 int FindOneOf(_In_ PCXSTR pszCharSet
) const throw()
577 PCXSTR pszString
= CThisSimpleString::GetString();
578 PCXSTR pszResult
= StringTraits::FindOneOf(pszString
, pszCharSet
);
580 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
583 int ReverseFind(_In_ XCHAR ch
) const throw()
585 PCXSTR pszString
= CThisSimpleString::GetString();
586 PCXSTR pszResult
= StringTraits::FindCharReverse(pszString
, ch
);
588 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
591 int Compare(_In_z_ PCXSTR psz
) const
593 return StringTraits::Compare(CThisSimpleString::GetString(), psz
);
597 CStringT
Mid(int iFirst
, int nCount
) const
599 int nLength
= CThisSimpleString::GetLength();
605 if (iFirst
> nLength
)
607 if (iFirst
+ nCount
> nLength
)
608 nCount
= nLength
- iFirst
;
610 return CStringT(CThisSimpleString::GetString() + iFirst
, nCount
);
613 CStringT
Mid(int iFirst
) const
615 int nLength
= CThisSimpleString::GetLength();
619 if (iFirst
> nLength
)
622 return CStringT(CThisSimpleString::GetString() + iFirst
, nLength
- iFirst
);
625 CStringT
Left(int nCount
) const
627 int nLength
= CThisSimpleString::GetLength();
631 if (nCount
> nLength
)
634 return CStringT(CThisSimpleString::GetString(), nCount
);
637 CStringT
Right(int nCount
) const
639 int nLength
= CThisSimpleString::GetLength();
643 if (nCount
> nLength
)
646 return CStringT(CThisSimpleString::GetString() + nLength
- nCount
, nCount
);
650 void __cdecl
Format(UINT nFormatID
, ...)
653 va_start(args
, nFormatID
);
654 CStringT formatString
;
655 if (formatString
.LoadString(nFormatID
))
656 FormatV(formatString
, args
);
660 void __cdecl
Format(PCXSTR pszFormat
, ...)
663 va_start(args
, pszFormat
);
664 FormatV(pszFormat
, args
);
668 void FormatV(PCXSTR pszFormat
, va_list args
)
670 int nLength
= StringTraits::FormatV(NULL
, pszFormat
, args
);
672 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
673 StringTraits::FormatV(pszBuffer
, pszFormat
, args
);
674 CThisSimpleString::ReleaseBufferSetLength(nLength
);
678 int Replace(PCXSTR pszOld
, PCXSTR pszNew
)
680 PCXSTR pszString
= CThisSimpleString::GetString();
682 const int nLength
= CThisSimpleString::GetLength();
683 const int nOldLen
= StringTraits::GetBaseTypeLength(pszOld
);
684 const int nNewLen
= StringTraits::GetBaseTypeLength(pszNew
);
685 const int nDiff
= nNewLen
- nOldLen
;
686 int nResultLength
= nLength
;
689 while ((pszFound
= StringTraits::FindString(pszString
, pszOld
)))
691 nResultLength
+= nDiff
;
692 pszString
= pszFound
+ nOldLen
;
695 if (pszString
== CThisSimpleString::GetString())
698 PXSTR pszResult
= CThisSimpleString::GetBuffer(nResultLength
);
700 int nCount
= 0, nRemaining
= nLength
;
701 while (nRemaining
&& (pszNext
= StringTraits::FindString(pszResult
, pszOld
)))
703 nRemaining
-= (pszNext
- pszResult
);
704 nRemaining
-= nOldLen
;
706 CThisSimpleString::CopyCharsOverlapped(pszNext
+ nNewLen
, nRemaining
+ 1, pszNext
+ nOldLen
, nRemaining
+ 1);
707 CThisSimpleString::CopyCharsOverlapped(pszNext
, nNewLen
, pszNew
, nNewLen
);
708 pszResult
= pszNext
+ nNewLen
;
712 CThisSimpleString::ReleaseBufferSetLength(nResultLength
);
717 int Replace(XCHAR chOld
, XCHAR chNew
)
719 PCXSTR pszString
= CThisSimpleString::GetString();
720 PXSTR pszFirst
= StringTraits::FindChar(pszString
, chOld
);
724 int nLength
= CThisSimpleString::GetLength();
727 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
728 pszFirst
= pszBuffer
+ (pszFirst
- pszString
);
732 } while ((pszFirst
= StringTraits::FindChar(pszFirst
+ 1, chOld
)));
734 CThisSimpleString::ReleaseBufferSetLength(nLength
);
739 static PCXSTR
DefaultTrimChars()
741 static XCHAR str
[] = { ' ', '\t', '\r', '\n', 0 };
748 return TrimLeft(DefaultTrimChars());
751 CStringT
& TrimLeft(XCHAR chTarget
)
753 XCHAR str
[2] = { chTarget
, 0 };
754 return TrimLeft(str
);
757 CStringT
& TrimLeft(PCXSTR pszTargets
)
759 int nLength
= CThisSimpleString::GetLength();
760 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
763 while (nCount
< nLength
&& StringTraits::FindChar(pszTargets
, pszBuffer
[nCount
]))
768 CThisSimpleString::CopyCharsOverlapped(pszBuffer
, nLength
- nCount
, pszBuffer
+ nCount
, nLength
- nCount
);
771 CThisSimpleString::ReleaseBufferSetLength(nLength
);
777 CStringT
& TrimRight()
779 return TrimRight(DefaultTrimChars());
782 CStringT
& TrimRight(XCHAR chTarget
)
784 XCHAR str
[2] = { chTarget
, 0 };
785 return TrimRight(str
);
788 CStringT
& TrimRight(PCXSTR pszTargets
)
790 int nLength
= CThisSimpleString::GetLength();
791 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
793 while (nLength
> 0 && StringTraits::FindChar(pszTargets
, pszBuffer
[nLength
-1]))
796 CThisSimpleString::ReleaseBufferSetLength(nLength
);
804 return Trim(DefaultTrimChars());
807 CStringT
& Trim(XCHAR chTarget
)
809 XCHAR str
[2] = { chTarget
, 0 };
813 CStringT
& Trim(PCXSTR pszTargets
)
815 return TrimRight(pszTargets
).TrimLeft(pszTargets
);
819 BSTR
AllocSysString() const
821 return StringTraits::AllocSysString(CThisSimpleString::GetString(), CThisSimpleString::GetLength());