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
);
149 // Template specialization
152 class ChTraitsCRT
<char> : public ChTraitsBase
<char>
156 static int __cdecl
GetBaseTypeLength(_In_z_ LPCWSTR pszSource
) throw()
158 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource
, -1, NULL
, 0, NULL
, NULL
) - 1;
161 static int __cdecl
GetBaseTypeLength(_In_z_ LPCSTR pszSource
) throw()
163 if (pszSource
== NULL
) return 0;
164 return static_cast<int>(strlen(pszSource
));
167 static int __cdecl
GetBaseTypeLength(
168 _In_reads_(nLength
) LPCWSTR pszSource
,
169 _In_
int nLength
) throw()
171 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource
, nLength
, NULL
, 0, NULL
, NULL
);
174 static int __cdecl
GetBaseTypeLength(
175 _In_reads_(nLength
) LPCSTR pszSource
,
176 _In_
int nLength
) throw()
181 static void __cdecl
ConvertToBaseType(
182 _Out_writes_(nDestLength
) LPSTR pszDest
,
183 _In_
int nDestLength
,
185 _In_
int nSrcLength
= -1)
187 if (nSrcLength
== -1)
188 nSrcLength
= 1 + GetBaseTypeLength(pszSrc
);
190 ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc
, nSrcLength
, pszDest
, nDestLength
, NULL
, NULL
);
193 static void __cdecl
ConvertToBaseType(
194 _Out_writes_(nDestLength
) LPSTR pszDest
,
195 _In_
int nDestLength
,
197 _In_
int nSrcLength
= -1)
199 if (nSrcLength
== -1)
200 nSrcLength
= 1 + GetBaseTypeLength(pszSrc
);
202 memcpy(pszDest
, pszSrc
, nSrcLength
);
205 static void __cdecl
MakeLower(
206 _Out_writes_(nSrcLength
) LPSTR pszSource
,
209 ::CharLowerBuffA(pszSource
, nSrcLength
);
212 static DWORD
GetEnvironmentVariable(
213 _In_z_ LPCSTR pszVar
,
214 _Out_writes_opt_(nBufLength
) LPSTR pszBuf
,
215 _In_opt_
int nBufLength
)
217 return ::GetEnvironmentVariableA(pszVar
, pszBuf
, nBufLength
);
220 static void __cdecl
MakeUpper(
221 _Out_writes_(nSrcLength
) LPSTR pszSource
,
224 ::CharUpperBuffA(pszSource
, nSrcLength
);
227 static LPSTR __cdecl
FindString(
228 _In_z_ LPCSTR pszSource
,
229 _In_z_ LPCSTR pszSub
)
231 return ::strstr(pszSource
, pszSub
);
234 static LPSTR __cdecl
FindChar(
235 _In_z_ LPCSTR pszSource
,
238 return ::strchr(pszSource
, ch
);
241 static LPSTR __cdecl
FindCharReverse(
242 _In_z_ LPCSTR pszSource
,
245 return ::strrchr(pszSource
, ch
);
248 static LPSTR __cdecl
FindOneOf(
249 _In_z_ LPCSTR pszSource
,
250 _In_z_ LPCSTR pszCharSet
)
252 return ::strpbrk(pszSource
, pszCharSet
);
255 static int __cdecl
Compare(
259 return ::strcmp(psz1
, psz2
);
262 static int __cdecl
FormatV(
263 _In_opt_z_ LPSTR pszDest
,
264 _In_z_ LPCSTR pszFormat
,
268 return ::_vscprintf(pszFormat
, args
);
269 return ::vsprintf(pszDest
, pszFormat
, args
);
275 namespace _CSTRING_IMPL_
277 template <typename _CharType
, class StringTraits
>
278 struct _MFCDLLTraitsCheck
280 const static bool c_bIsMFCDLLTraits
= false;
285 // TODO: disable conversion functions when _CSTRING_DISABLE_NARROW_WIDE_CONVERSION is defined.
287 template <typename BaseType
, class StringTraits
>
289 public CSimpleStringT
<BaseType
, _CSTRING_IMPL_::_MFCDLLTraitsCheck
<BaseType
, StringTraits
>::c_bIsMFCDLLTraits
>
292 typedef CSimpleStringT
<BaseType
, _CSTRING_IMPL_::_MFCDLLTraitsCheck
<BaseType
, StringTraits
>::c_bIsMFCDLLTraits
> CThisSimpleString
;
293 typedef StringTraits StrTraits
;
294 typedef typename
CThisSimpleString::XCHAR XCHAR
;
295 typedef typename
CThisSimpleString::PXSTR PXSTR
;
296 typedef typename
CThisSimpleString::PCXSTR PCXSTR
;
297 typedef typename
CThisSimpleString::YCHAR YCHAR
;
298 typedef typename
CThisSimpleString::PYSTR PYSTR
;
299 typedef typename
CThisSimpleString::PCYSTR PCYSTR
;
303 CThisSimpleString(StringTraits::GetDefaultManager())
307 explicit CStringT( _In_ IAtlStringMgr
* pStringMgr
) throw() :
308 CThisSimpleString(pStringMgr
)
312 static void __cdecl
Construct(_In_ CStringT
* pString
)
314 new(pString
) CStringT
;
317 CStringT(_In_
const CStringT
& strSrc
) :
318 CThisSimpleString(strSrc
)
322 CStringT(_In_
const CThisSimpleString
& strSrc
) :
323 CThisSimpleString(strSrc
)
327 template<class StringTraits_
>
328 CStringT(_In_
const CStringT
<YCHAR
, StringTraits_
> & strSrc
) :
329 CThisSimpleString(StringTraits::GetDefaultManager())
331 *this = static_cast<const YCHAR
*>(strSrc
);
335 /* helper function */
336 template <typename T_CHAR
>
337 void LoadFromPtr_(_In_opt_z_
const T_CHAR
* pszSrc
)
341 if (IS_INTRESOURCE(pszSrc
))
342 LoadString(LOWORD(pszSrc
));
348 CStringT(_In_opt_z_
const XCHAR
* pszSrc
) :
349 CThisSimpleString(StringTraits::GetDefaultManager())
351 LoadFromPtr_(pszSrc
);
354 CStringT(_In_opt_z_
const XCHAR
* pszSrc
,
355 _In_ IAtlStringMgr
* pStringMgr
) : CThisSimpleString(pStringMgr
)
357 LoadFromPtr_(pszSrc
);
360 CStringT(_In_opt_z_
const YCHAR
* pszSrc
) :
361 CThisSimpleString(StringTraits::GetDefaultManager())
363 LoadFromPtr_(pszSrc
);
366 CStringT(_In_opt_z_
const YCHAR
* pszSrc
,
367 _In_ IAtlStringMgr
* pStringMgr
) : CThisSimpleString(pStringMgr
)
369 LoadFromPtr_(pszSrc
);
372 CStringT(_In_reads_z_(nLength
) const XCHAR
* pch
,
374 CThisSimpleString(pch
, nLength
, StringTraits::GetDefaultManager())
378 CStringT(_In_reads_z_(nLength
) const YCHAR
* pch
,
380 CThisSimpleString(pch
, nLength
, StringTraits::GetDefaultManager())
384 CStringT
& operator=(_In_
const CStringT
& strSrc
)
386 CThisSimpleString::operator=(strSrc
);
390 CStringT
& operator=(_In_opt_z_ PCXSTR pszSrc
)
392 CThisSimpleString::operator=(pszSrc
);
396 CStringT
& operator=(_In_opt_z_ PCYSTR pszSrc
)
398 int length
= pszSrc
? StringTraits::GetBaseTypeLength(pszSrc
) : 0;
401 PXSTR result
= CThisSimpleString::GetBuffer(length
);
402 StringTraits::ConvertToBaseType(result
, length
, pszSrc
);
403 CThisSimpleString::ReleaseBufferSetLength(length
);
407 CThisSimpleString::Empty();
412 CStringT
& operator=(_In_
const CThisSimpleString
&strSrc
)
414 CThisSimpleString::operator=(strSrc
);
418 friend bool operator==(const CStringT
& str1
, const CStringT
& str2
) throw()
420 return str1
.Compare(str2
) == 0;
423 friend bool operator==(const CStringT
& str1
, PCXSTR psz2
) throw()
425 return str1
.Compare(psz2
) == 0;
428 friend bool operator==(const CStringT
& str1
, PCYSTR psz2
) throw()
430 CStringT
tmp(psz2
, str1
.GetManager());
431 return tmp
.Compare(str1
) == 0;
434 friend bool operator==(const CStringT
& str1
, XCHAR ch2
) throw()
436 return str1
.GetLength() == 1 && str1
[0] == ch2
;
439 friend bool operator==(PCXSTR psz1
, const CStringT
& str2
) throw()
441 return str2
.Compare(psz1
) == 0;
444 friend bool operator==(PCYSTR psz1
, const CStringT
& str2
) throw()
446 CStringT
tmp(psz1
, str2
.GetManager());
447 return tmp
.Compare(str2
) == 0;
450 friend bool operator==(XCHAR ch1
, const CStringT
& str2
) throw()
452 return str2
.GetLength() == 1 && str2
[0] == ch1
;
455 CStringT
& operator+=(_In_
const CThisSimpleString
& str
)
457 CThisSimpleString::operator+=(str
);
461 CStringT
& operator+=(_In_z_ PCXSTR pszSrc
)
463 CThisSimpleString::operator+=(pszSrc
);
467 CStringT
& operator+=(_In_ XCHAR ch
)
469 CThisSimpleString::operator+=(ch
);
473 BOOL
LoadString(_In_ UINT nID
)
475 return LoadString(_AtlBaseModule
.GetResourceInstance(), nID
);
478 _Check_return_ BOOL
LoadString(_In_ HINSTANCE hInstance
,
481 const ATLSTRINGRESOURCEIMAGE
* pImage
= AtlGetStringResourceImage(hInstance
, nID
);
482 if (pImage
== NULL
) return FALSE
;
484 int nLength
= StringTraits::GetBaseTypeLength(pImage
->achString
, pImage
->nLength
);
485 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
486 StringTraits::ConvertToBaseType(pszBuffer
, nLength
, pImage
->achString
, pImage
->nLength
);
487 CThisSimpleString::ReleaseBufferSetLength(nLength
);
492 BOOL
GetEnvironmentVariable(_In_z_ PCXSTR pszVar
)
494 int nLength
= StringTraits::GetEnvironmentVariable(pszVar
, NULL
, 0);
498 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
499 StringTraits::GetEnvironmentVariable(pszVar
, pszBuffer
, nLength
);
500 CThisSimpleString::ReleaseBuffer();
504 CThisSimpleString::Empty();
508 CStringT
& MakeLower()
510 int nLength
= CThisSimpleString::GetLength();
511 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
513 StringTraits::MakeLower(pszBuffer
, nLength
);
514 CThisSimpleString::ReleaseBufferSetLength(nLength
);
519 CStringT
& MakeUpper()
521 int nLength
= CThisSimpleString::GetLength();
522 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
524 StringTraits::MakeUpper(pszBuffer
, nLength
);
525 CThisSimpleString::ReleaseBufferSetLength(nLength
);
530 int Find(_In_ PCXSTR pszSub
, _In_opt_
int iStart
= 0) const throw()
532 int nLength
= CThisSimpleString::GetLength();
534 if (iStart
>= nLength
|| iStart
< 0)
537 PCXSTR pszString
= CThisSimpleString::GetString();
538 PCXSTR pszResult
= StringTraits::FindString(pszString
+ iStart
, pszSub
);
540 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
543 int Find(_In_ XCHAR ch
, _In_opt_
int iStart
= 0) const throw()
545 int nLength
= CThisSimpleString::GetLength();
547 if (iStart
>= nLength
|| iStart
< 0)
550 PCXSTR pszString
= CThisSimpleString::GetString();
551 PCXSTR pszResult
= StringTraits::FindChar(pszString
+ iStart
, ch
);
553 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
556 int FindOneOf(_In_ PCXSTR pszCharSet
) const throw()
558 PCXSTR pszString
= CThisSimpleString::GetString();
559 PCXSTR pszResult
= StringTraits::FindOneOf(pszString
, pszCharSet
);
561 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
564 int ReverseFind(_In_ XCHAR ch
) const throw()
566 PCXSTR pszString
= CThisSimpleString::GetString();
567 PCXSTR pszResult
= StringTraits::FindCharReverse(pszString
, ch
);
569 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
572 int Compare(_In_z_ PCXSTR psz
) const
574 return StringTraits::Compare(CThisSimpleString::GetString(), psz
);
578 CStringT
Mid(int iFirst
, int nCount
) const
580 int nLength
= CThisSimpleString::GetLength();
586 if (iFirst
> nLength
)
588 if (iFirst
+ nCount
> nLength
)
589 nCount
= nLength
- iFirst
;
591 return CStringT(CThisSimpleString::GetString() + iFirst
, nCount
);
594 CStringT
Mid(int iFirst
) const
596 int nLength
= CThisSimpleString::GetLength();
600 if (iFirst
> nLength
)
603 return CStringT(CThisSimpleString::GetString() + iFirst
, nLength
- iFirst
);
606 CStringT
Left(int nCount
) const
608 int nLength
= CThisSimpleString::GetLength();
612 if (nCount
> nLength
)
615 return CStringT(CThisSimpleString::GetString(), nCount
);
618 CStringT
Right(int nCount
) const
620 int nLength
= CThisSimpleString::GetLength();
624 if (nCount
> nLength
)
627 return CStringT(CThisSimpleString::GetString() + nLength
- nCount
, nCount
);
631 void __cdecl
Format(UINT nFormatID
, ...)
634 va_start(args
, nFormatID
);
635 CStringT formatString
;
636 if (formatString
.LoadString(nFormatID
))
637 FormatV(formatString
, args
);
641 void __cdecl
Format(PCXSTR pszFormat
, ...)
644 va_start(args
, pszFormat
);
645 FormatV(pszFormat
, args
);
649 void FormatV(PCXSTR pszFormat
, va_list args
)
651 int nLength
= StringTraits::FormatV(NULL
, pszFormat
, args
);
653 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
654 StringTraits::FormatV(pszBuffer
, pszFormat
, args
);
655 CThisSimpleString::ReleaseBufferSetLength(nLength
);
659 int Replace(PCXSTR pszOld
, PCXSTR pszNew
)
661 PCXSTR pszString
= CThisSimpleString::GetString();
663 const int nLength
= CThisSimpleString::GetLength();
664 const int nOldLen
= StringTraits::GetBaseTypeLength(pszOld
);
665 const int nNewLen
= StringTraits::GetBaseTypeLength(pszNew
);
666 const int nDiff
= nNewLen
- nOldLen
;
667 int nResultLength
= nLength
;
670 while ((pszFound
= StringTraits::FindString(pszString
, pszOld
)))
672 nResultLength
+= nDiff
;
673 pszString
= pszFound
+ nOldLen
;
676 if (pszString
== CThisSimpleString::GetString())
679 PXSTR pszResult
= CThisSimpleString::GetBuffer(nResultLength
);
681 int nCount
= 0, nRemaining
= nLength
;
682 while (nRemaining
&& (pszNext
= StringTraits::FindString(pszResult
, pszOld
)))
684 nRemaining
-= (pszNext
- pszResult
);
685 nRemaining
-= nOldLen
;
687 CThisSimpleString::CopyCharsOverlapped(pszNext
+ nNewLen
, nRemaining
+ 1, pszNext
+ nOldLen
, nRemaining
+ 1);
688 CThisSimpleString::CopyCharsOverlapped(pszNext
, nNewLen
, pszNew
, nNewLen
);
689 pszResult
= pszNext
+ nNewLen
;
693 CThisSimpleString::ReleaseBufferSetLength(nResultLength
);
698 int Replace(XCHAR chOld
, XCHAR chNew
)
700 PCXSTR pszString
= CThisSimpleString::GetString();
701 PXSTR pszFirst
= StringTraits::FindChar(pszString
, chOld
);
705 int nLength
= CThisSimpleString::GetLength();
708 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
709 pszFirst
= pszBuffer
+ (pszFirst
- pszString
);
713 } while ((pszFirst
= StringTraits::FindChar(pszFirst
+ 1, chOld
)));
715 CThisSimpleString::ReleaseBufferSetLength(nLength
);
720 static PCXSTR
DefaultTrimChars()
722 static XCHAR str
[] = { ' ', '\t', '\r', '\n', 0 };
729 return TrimLeft(DefaultTrimChars());
732 CStringT
& TrimLeft(XCHAR chTarget
)
734 XCHAR str
[2] = { chTarget
, 0 };
735 return TrimLeft(str
);
738 CStringT
& TrimLeft(PCXSTR pszTargets
)
740 int nLength
= CThisSimpleString::GetLength();
741 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
744 while (nCount
< nLength
&& StringTraits::FindChar(pszTargets
, pszBuffer
[nCount
]))
749 CThisSimpleString::CopyCharsOverlapped(pszBuffer
, nLength
- nCount
, pszBuffer
+ nCount
, nLength
- nCount
);
752 CThisSimpleString::ReleaseBufferSetLength(nLength
);
758 CStringT
& TrimRight()
760 return TrimRight(DefaultTrimChars());
763 CStringT
& TrimRight(XCHAR chTarget
)
765 XCHAR str
[2] = { chTarget
, 0 };
766 return TrimRight(str
);
769 CStringT
& TrimRight(PCXSTR pszTargets
)
771 int nLength
= CThisSimpleString::GetLength();
772 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
774 while (nLength
> 0 && StringTraits::FindChar(pszTargets
, pszBuffer
[nLength
-1]))
777 CThisSimpleString::ReleaseBufferSetLength(nLength
);
785 return Trim(DefaultTrimChars());
788 CStringT
& Trim(XCHAR chTarget
)
790 XCHAR str
[2] = { chTarget
, 0 };
794 CStringT
& Trim(PCXSTR pszTargets
)
796 return TrimRight(pszTargets
).TrimLeft(pszTargets
);