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 template<class StringTraits_
>
323 CStringT(_In_
const CStringT
<YCHAR
, StringTraits_
> & strSrc
) :
324 CThisSimpleString(StringTraits::GetDefaultManager())
326 *this = static_cast<const YCHAR
*>(strSrc
);
330 /* helper function */
331 template <typename T_CHAR
>
332 void LoadFromPtr_(_In_opt_z_
const T_CHAR
* pszSrc
)
336 if (IS_INTRESOURCE(pszSrc
))
337 LoadString(LOWORD(pszSrc
));
343 CStringT(_In_opt_z_
const XCHAR
* pszSrc
) :
344 CThisSimpleString(StringTraits::GetDefaultManager())
346 LoadFromPtr_(pszSrc
);
349 CStringT(_In_opt_z_
const XCHAR
* pszSrc
,
350 _In_ IAtlStringMgr
* pStringMgr
) : CThisSimpleString(pStringMgr
)
352 LoadFromPtr_(pszSrc
);
355 CStringT(_In_opt_z_
const YCHAR
* pszSrc
) :
356 CThisSimpleString(StringTraits::GetDefaultManager())
358 LoadFromPtr_(pszSrc
);
361 CStringT(_In_opt_z_
const YCHAR
* pszSrc
,
362 _In_ IAtlStringMgr
* pStringMgr
) : CThisSimpleString(pStringMgr
)
364 LoadFromPtr_(pszSrc
);
367 CStringT(_In_reads_z_(nLength
) const XCHAR
* pch
,
369 CThisSimpleString(pch
, nLength
, StringTraits::GetDefaultManager())
373 CStringT(_In_reads_z_(nLength
) const YCHAR
* pch
,
375 CThisSimpleString(pch
, nLength
, StringTraits::GetDefaultManager())
379 CStringT
& operator=(_In_
const CStringT
& strSrc
)
381 CThisSimpleString::operator=(strSrc
);
385 CStringT
& operator=(_In_opt_z_ PCXSTR pszSrc
)
387 CThisSimpleString::operator=(pszSrc
);
391 CStringT
& operator=(_In_opt_z_ PCYSTR pszSrc
)
393 int length
= pszSrc
? StringTraits::GetBaseTypeLength(pszSrc
) : 0;
396 PXSTR result
= CThisSimpleString::GetBuffer(length
);
397 StringTraits::ConvertToBaseType(result
, length
, pszSrc
);
398 CThisSimpleString::ReleaseBufferSetLength(length
);
402 CThisSimpleString::Empty();
407 friend bool operator==(const CStringT
& str1
, const CStringT
& str2
) throw()
409 return str1
.Compare(str2
) == 0;
412 friend bool operator==(const CStringT
& str1
, PCXSTR psz2
) throw()
414 return str1
.Compare(psz2
) == 0;
417 friend bool operator==(const CStringT
& str1
, PCYSTR psz2
) throw()
419 CStringT
tmp(psz2
, str1
.GetManager());
423 friend bool operator==(const CStringT
& str1
, XCHAR ch2
) throw()
425 return str1
.GetLength() == 1 && str1
[0] == ch2
;
428 friend bool operator==(PCXSTR psz1
, const CStringT
& str2
) throw()
430 return str2
.Compare(psz1
) == 0;
433 friend bool operator==(PCYSTR psz1
, const CStringT
& str2
) throw()
435 CStringT
tmp(psz1
, str2
.GetManager());
436 return tmp
.Compare(str2
) == 0;
439 friend bool operator==(XCHAR ch1
, const CStringT
& str2
) throw()
441 return str2
.GetLength() == 1 && str2
[0] == ch1
;
444 CStringT
& operator+=(_In_
const CThisSimpleString
& str
)
446 CThisSimpleString::operator+=(str
);
450 CStringT
& operator+=(_In_z_ PCXSTR pszSrc
)
452 CThisSimpleString::operator+=(pszSrc
);
456 CStringT
& operator+=(_In_ XCHAR ch
)
458 CThisSimpleString::operator+=(ch
);
462 BOOL
LoadString(_In_ UINT nID
)
464 return LoadString(_AtlBaseModule
.GetResourceInstance(), nID
);
467 _Check_return_ BOOL
LoadString(_In_ HINSTANCE hInstance
,
470 const ATLSTRINGRESOURCEIMAGE
* pImage
= AtlGetStringResourceImage(hInstance
, nID
);
471 if (pImage
== NULL
) return FALSE
;
473 int nLength
= StringTraits::GetBaseTypeLength(pImage
->achString
, pImage
->nLength
);
474 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
475 StringTraits::ConvertToBaseType(pszBuffer
, nLength
, pImage
->achString
, pImage
->nLength
);
476 CThisSimpleString::ReleaseBufferSetLength(nLength
);
481 BOOL
GetEnvironmentVariable(_In_z_ PCXSTR pszVar
)
483 int nLength
= StringTraits::GetEnvironmentVariable(pszVar
, NULL
, 0);
487 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
488 StringTraits::GetEnvironmentVariable(pszVar
, pszBuffer
, nLength
);
489 CThisSimpleString::ReleaseBuffer();
493 CThisSimpleString::Empty();
497 CStringT
& MakeLower()
499 int nLength
= CThisSimpleString::GetLength();
500 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
502 StringTraits::MakeLower(pszBuffer
, nLength
);
503 CThisSimpleString::ReleaseBufferSetLength(nLength
);
508 CStringT
& MakeUpper()
510 int nLength
= CThisSimpleString::GetLength();
511 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
513 StringTraits::MakeUpper(pszBuffer
, nLength
);
514 CThisSimpleString::ReleaseBufferSetLength(nLength
);
519 int Find(_In_ PCXSTR pszSub
, _In_opt_
int iStart
= 0) const throw()
521 int nLength
= CThisSimpleString::GetLength();
523 if (iStart
>= nLength
|| iStart
< 0)
526 PCXSTR pszString
= CThisSimpleString::GetString();
527 PCXSTR pszResult
= StringTraits::FindString(pszString
+ iStart
, pszSub
);
529 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
532 int Find(_In_ XCHAR ch
, _In_opt_
int iStart
= 0) const throw()
534 int nLength
= CThisSimpleString::GetLength();
536 if (iStart
>= nLength
|| iStart
< 0)
539 PCXSTR pszString
= CThisSimpleString::GetString();
540 PCXSTR pszResult
= StringTraits::FindChar(pszString
+ iStart
, ch
);
542 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
545 int FindOneOf(_In_ PCXSTR pszCharSet
) const throw()
547 PCXSTR pszString
= CThisSimpleString::GetString();
548 PCXSTR pszResult
= StringTraits::FindOneOf(pszString
, pszCharSet
);
550 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
553 int ReverseFind(_In_ XCHAR ch
) const throw()
555 PCXSTR pszString
= CThisSimpleString::GetString();
556 PCXSTR pszResult
= StringTraits::FindCharReverse(pszString
, ch
);
558 return pszResult
? ((int)(pszResult
- pszString
)) : -1;
561 int Compare(_In_z_ PCXSTR psz
) const
563 return StringTraits::Compare(CThisSimpleString::GetString(), psz
);
567 CStringT
Mid(int iFirst
, int nCount
) const
569 int nLength
= CThisSimpleString::GetLength();
575 if (iFirst
> nLength
)
577 if (iFirst
+ nCount
> nLength
)
578 nCount
= nLength
- iFirst
;
580 return CStringT(CThisSimpleString::GetString() + iFirst
, nCount
);
583 CStringT
Mid(int iFirst
) const
585 int nLength
= CThisSimpleString::GetLength();
589 if (iFirst
> nLength
)
592 return CStringT(CThisSimpleString::GetString() + iFirst
, nLength
- iFirst
);
595 CStringT
Left(int nCount
) const
597 int nLength
= CThisSimpleString::GetLength();
601 if (nCount
> nLength
)
604 return CStringT(CThisSimpleString::GetString(), nCount
);
607 CStringT
Right(int nCount
) const
609 int nLength
= CThisSimpleString::GetLength();
613 if (nCount
> nLength
)
616 return CStringT(CThisSimpleString::GetString() + nLength
- nCount
, nCount
);
620 void __cdecl
Format(UINT nFormatID
, ...)
623 va_start(args
, nFormatID
);
624 CStringT formatString
;
625 if (formatString
.LoadString(nFormatID
))
626 FormatV(formatString
, args
);
630 void __cdecl
Format(PCXSTR pszFormat
, ...)
633 va_start(args
, pszFormat
);
634 FormatV(pszFormat
, args
);
638 void FormatV(PCXSTR pszFormat
, va_list args
)
640 int nLength
= StringTraits::FormatV(NULL
, pszFormat
, args
);
642 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
643 StringTraits::FormatV(pszBuffer
, pszFormat
, args
);
644 CThisSimpleString::ReleaseBufferSetLength(nLength
);
648 int Replace(PCXSTR pszOld
, PCXSTR pszNew
)
650 PCXSTR pszString
= CThisSimpleString::GetString();
652 const int nLength
= CThisSimpleString::GetLength();
653 const int nOldLen
= StringTraits::GetBaseTypeLength(pszOld
);
654 const int nNewLen
= StringTraits::GetBaseTypeLength(pszNew
);
655 const int nDiff
= nNewLen
- nOldLen
;
656 int nResultLength
= nLength
;
659 while ((pszFound
= StringTraits::FindString(pszString
, pszOld
)))
661 nResultLength
+= nDiff
;
662 pszString
= pszFound
+ nOldLen
;
665 if (pszString
== CThisSimpleString::GetString())
668 PXSTR pszResult
= CThisSimpleString::GetBuffer(nResultLength
);
670 int nCount
= 0, nRemaining
= nLength
;
671 while (nRemaining
&& (pszNext
= StringTraits::FindString(pszResult
, pszOld
)))
673 nRemaining
-= (pszNext
- pszResult
);
674 nRemaining
-= nOldLen
;
676 CThisSimpleString::CopyCharsOverlapped(pszNext
+ nNewLen
, nRemaining
+ 1, pszNext
+ nOldLen
, nRemaining
+ 1);
677 CThisSimpleString::CopyCharsOverlapped(pszNext
, nNewLen
, pszNew
, nNewLen
);
678 pszResult
= pszNext
+ nNewLen
;
682 CThisSimpleString::ReleaseBufferSetLength(nResultLength
);
687 int Replace(XCHAR chOld
, XCHAR chNew
)
689 PCXSTR pszString
= CThisSimpleString::GetString();
690 PXSTR pszFirst
= StringTraits::FindChar(pszString
, chOld
);
694 int nLength
= CThisSimpleString::GetLength();
697 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
698 pszFirst
= pszBuffer
+ (pszFirst
- pszString
);
702 } while ((pszFirst
= StringTraits::FindChar(pszFirst
+ 1, chOld
)));
704 CThisSimpleString::ReleaseBufferSetLength(nLength
);
709 static PCXSTR
DefaultTrimChars()
711 static XCHAR str
[] = { ' ', '\t', '\r', '\n', 0 };
718 return TrimLeft(DefaultTrimChars());
721 CStringT
& TrimLeft(XCHAR chTarget
)
723 XCHAR str
[2] = { chTarget
, 0 };
724 return TrimLeft(str
);
727 CStringT
& TrimLeft(PCXSTR pszTargets
)
729 int nLength
= CThisSimpleString::GetLength();
730 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
733 while (nCount
< nLength
&& StringTraits::FindChar(pszTargets
, pszBuffer
[nCount
]))
738 CThisSimpleString::CopyCharsOverlapped(pszBuffer
, nLength
- nCount
, pszBuffer
+ nCount
, nLength
- nCount
);
741 CThisSimpleString::ReleaseBufferSetLength(nLength
);
747 CStringT
& TrimRight()
749 return TrimRight(DefaultTrimChars());
752 CStringT
& TrimRight(XCHAR chTarget
)
754 XCHAR str
[2] = { chTarget
, 0 };
755 return TrimRight(str
);
758 CStringT
& TrimRight(PCXSTR pszTargets
)
760 int nLength
= CThisSimpleString::GetLength();
761 PXSTR pszBuffer
= CThisSimpleString::GetBuffer(nLength
);
763 while (nLength
> 0 && StringTraits::FindChar(pszTargets
, pszBuffer
[nLength
-1]))
766 CThisSimpleString::ReleaseBufferSetLength(nLength
);
774 return Trim(DefaultTrimChars());
777 CStringT
& Trim(XCHAR chTarget
)
779 XCHAR str
[2] = { chTarget
, 0 };
783 CStringT
& Trim(PCXSTR pszTargets
)
785 return TrimRight(pszTargets
).TrimLeft(pszTargets
);