cstringt.h
上传用户:hfwmdy
上传日期:2016-01-14
资源大小:83k
文件大小:82k
源码类别:

GDI/图象编程

开发平台:

Visual C++

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. /////////////////////////////////////////////////////////////////////////////
  11. // CSTRINGT.H - Framework-independent, templateable string class
  12. #ifndef __CSTRINGT_H__
  13. #define __CSTRINGT_H__
  14. #pragma once
  15. #ifndef _ATL_NO_PRAGMA_WARNINGS
  16. #pragma warning (push)
  17. #pragma warning(disable : 4668) // is not defined as a preprocessor macro, replacing with '0' for '#if/#elif
  18. #pragma warning(disable : 4820) // padding added after member
  19. #pragma warning(disable : 4127)  // conditional expression constant
  20. #endif //!_ATL_NO_PRAGMA_WARNINGS
  21. #pragma warning(disable:4786) // avoid 255-character limit warnings
  22. #ifdef _MANAGED
  23. #include <vcclr.h>  // For PtrToStringChars
  24. #endif
  25. #include <atlsimpstr.h>
  26. #include <stddef.h>
  27. #ifndef _INC_NEW
  28. #include <new.h>
  29. #endif
  30. #include <stdio.h>
  31. #include <wchar.h>
  32. #include <limits.h>
  33. #ifndef _ATL_MIN_CRT
  34. #include <mbstring.h>
  35. #endif
  36. #ifdef _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
  37. #define CSTRING_EXPLICIT explicit
  38. #else
  39. #define CSTRING_EXPLICIT
  40. #endif
  41. #include <atlconv.h>
  42. #include <atlmem.h>
  43. struct tagVARIANT;
  44. typedef tagVARIANT VARIANT;
  45. #ifndef _AFX
  46. #define _AFX_FUNCNAME(_Name) _Name
  47. #endif
  48. #pragma push_macro("new")
  49. #undef new
  50. #if defined(_AFX)
  51. #pragma push_macro("FormatMessage")
  52. #undef FormatMessage
  53. #endif
  54. /////////////////////////////////////////////////////////////////////////////
  55. // Naming conventions:
  56. //    The term "length" can be confusing when dealing with ANSI, Unicode, and
  57. //    MBCS character sets, so this file will use the following naming 
  58. //    conventions to differentiate between the different meanings of 
  59. //    "length":
  60. //
  61. //    'Byte Length' - Length of a buffer in bytes, regardless of character 
  62. //       size
  63. //    'Char Length' - Number of distinct characters in string.  For wide-
  64. //       character strings, this is equivalent to half the 'Byte Length'.  
  65. //       For ANSI strings, this is equivalent to the 'Byte Length'.  For MBCS
  66. //       strings, 'Char Length' counts a lead-byte/trail-byte combination
  67. //       as one character.
  68. //    'Length' - When neither of the above terms is used, 'Length' refers to 
  69. //       length in XCHARs, which is equal to 'Byte Length'/sizeof(XCHAR).
  70. /////////////////////////////////////////////////////////////////////////////
  71. namespace ATL
  72. {
  73. // This struct have the same memory layout as CString and is used to enable
  74. // const statically initialized CString without making a copy on the heap
  75. template <class StringType,int t_nChars> struct CConstFixedStringT
  76. {
  77. CStringData m_data;
  78. typename StringType::XCHAR m_achData[t_nChars];
  79. };
  80. #define IMPLEMENT_CONST_STRING_PTR(StringType, value, name) const CConstFixedStringT<StringType, sizeof(value)/sizeof(StringType::XCHAR)> _init##name ={  {NULL, sizeof(value)/sizeof(StringType::XCHAR)-1,  sizeof(value)/sizeof(StringType::XCHAR)-1,  -1}, value }; const StringType::XCHAR* const _value##name = _init##name.m_achData; extern const StringType* const name = CONST_STRING_PTR(StringType, name);
  81. #define DECLARE_CONST_STRING_PTR(StringType, name) extern const StringType* const name;
  82. #define CONST_STRING_PTR(StringType, name) reinterpret_cast<const StringType* const>(&_value##name)
  83. /////////////////////////////////////////////////////////////////////////////
  84. // inline helpers
  85. inline int _wcstombsz(__out_ecount(count) char* mbstr, __in_z const wchar_t* wcstr, __in ULONG count) throw()
  86. {
  87. // count is number of bytes
  88. if (count == 0 && mbstr != NULL)
  89. return 0;
  90. int result = ::WideCharToMultiByte(_AtlGetConversionACP(), 0, wcstr, -1,
  91. mbstr, count, NULL, NULL);
  92. ATLASSERT(mbstr == NULL || result <= (int)count);
  93. return result;
  94. }
  95. inline int _mbstowcsz(__out_ecount_z(count) wchar_t* wcstr, __in_z const char* mbstr, __in ULONG count)
  96. {
  97. // count is number of wchar_t's
  98. if (count == 0 && wcstr != NULL)
  99. return 0;
  100. int result = ::MultiByteToWideChar(_AtlGetConversionACP(), 0, mbstr, -1,
  101. wcstr, count);
  102. ATLENSURE(wcstr == NULL || result <= (int)count);
  103. if ((result > 0) && (wcstr != NULL))
  104. {
  105. wcstr[result-1] = 0;
  106. }
  107. return result;
  108. }
  109. #if !defined(_UNICODE) || defined(_CSTRING_ALWAYS_THUNK)
  110. // Win9x doesn't support Unicode versions of these useful string functions.
  111. // If the app was built without _UNICODE defined, we thunk at runtime to
  112. // either the real Unicode implementation (on NT), or a conversion helper
  113. // (on Win9x).
  114. #pragma warning( push )
  115. #pragma warning( disable : 4793 )
  116. inline void _AtlInstallStringThunk(void** ppThunk, void* pfnWin9x, void* pfnNT) throw()
  117. {
  118. #pragma warning (push)
  119. #pragma warning (disable : 4640) // construction of local static object is not thread-safe
  120. static bool s_bWin9x = (::GetVersion()&0x80000000) != 0;
  121. #pragma warning (pop)
  122. void* pfn;
  123. if (s_bWin9x)
  124. pfn = pfnWin9x;
  125. else
  126. {
  127. #ifdef _CSTRING_ALWAYS_THUNK
  128. pfn = pfnWin9x;
  129. (void)pfnNT;
  130. #else
  131. pfn = pfnNT;
  132. #endif
  133. }
  134. InterlockedExchangePointer(ppThunk, pfn);
  135. }
  136. #pragma warning( pop )
  137. typedef int (WINAPI* ATLCOMPARESTRINGW)(LCID, DWORD, LPCWSTR, int, LPCWSTR, int);
  138. typedef BOOL (WINAPI* ATLGETSTRINGTYPEEXW)(LCID, DWORD, LPCWSTR, int, LPWORD);
  139. typedef int (WINAPI* ATLLSTRCMPIW)(LPCWSTR, LPCWSTR);
  140. typedef LPWSTR (WINAPI* ATLCHARLOWERW)(LPWSTR);
  141. typedef LPWSTR (WINAPI* ATLCHARUPPERW)(LPWSTR);
  142. typedef DWORD (WINAPI* ATLGETENVIRONMENTVARIABLEW)(LPCWSTR, LPWSTR, DWORD);
  143. struct _AtlStringThunks
  144. {
  145. ATLCOMPARESTRINGW pfnCompareStringW;
  146. ATLGETSTRINGTYPEEXW pfnGetStringTypeExW;
  147. ATLLSTRCMPIW pfnlstrcmpiW;
  148. ATLCHARLOWERW pfnCharLowerW;
  149. ATLCHARUPPERW pfnCharUpperW;
  150. ATLGETENVIRONMENTVARIABLEW pfnGetEnvironmentVariableW;
  151. };
  152. extern _AtlStringThunks _strthunks;
  153. inline DWORD WINAPI GetEnvironmentVariableWFake(__in_z LPCWSTR pszName, 
  154. __out_ecount_part_opt(nSize, return) LPWSTR pszBuffer, __in DWORD nSize)
  155. {
  156. ULONG nSizeA;
  157. ULONG nSizeW;
  158. CTempBuffer<char> pszBufferA;
  159. CW2A pszNameA(pszName);
  160. nSizeA = ::GetEnvironmentVariableA(pszNameA, NULL, 0);
  161. if( nSizeA == 0 || nSizeA==ULONG_MAX)
  162. {
  163. return 0;
  164. }
  165. pszBufferA.Allocate(nSizeA + 1);
  166. if( 0 == ::GetEnvironmentVariableA(pszNameA, pszBufferA, nSizeA))
  167. {
  168. return 0;
  169. }
  170. nSizeW = ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszBufferA, -1, NULL, 0);
  171. if( nSize == 0 )
  172. {
  173. return nSizeW;
  174. }
  175. if( nSize >= nSizeW )
  176. {
  177. nSizeW = ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszBufferA, -1, pszBuffer, nSizeW );
  178. }
  179. return nSizeW;
  180. }
  181. inline DWORD WINAPI GetEnvironmentVariableWThunk(__in_z LPCWSTR pszName, 
  182. __out_ecount_part_opt(nSize, return) LPWSTR pszBuffer, __in DWORD nSize)
  183. {
  184. _AtlInstallStringThunk(reinterpret_cast<void**>(&_strthunks.pfnGetEnvironmentVariableW), 
  185. GetEnvironmentVariableWFake, ::GetEnvironmentVariableW);
  186. return _strthunks.pfnGetEnvironmentVariableW(pszName, pszBuffer, nSize);
  187. }
  188. inline int WINAPI CompareStringWFake(__in LCID lcid, __in DWORD dwFlags, 
  189. __in_ecount(nLength1) LPCWSTR pszString1, __in int nLength1, __in_ecount(nLength2) LPCWSTR pszString2, __in int nLength2)
  190. {
  191. USES_CONVERSION_EX;
  192. LPCSTR pszAString1 = NULL;
  193. if(pszString1 != NULL)
  194. {
  195. pszAString1 = W2A_EX(pszString1,_ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  196. if(pszAString1 == NULL)
  197. AtlThrow(E_OUTOFMEMORY);
  198. }
  199. LPCSTR pszAString2 = NULL;
  200. if(pszString2 != NULL)
  201. {
  202. pszAString2 = W2A_EX(pszString2,_ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  203. if(pszAString2 == NULL)
  204. AtlThrow(E_OUTOFMEMORY);
  205. }
  206. return ::CompareStringA(lcid, dwFlags, pszAString1, nLength1, pszAString2, nLength2);
  207. }
  208. inline int WINAPI CompareStringWThunk(__in LCID lcid, __in DWORD dwFlags, 
  209. __in_ecount(nLength1) LPCWSTR pszString1, __in int nLength1, __in_ecount(nLength2) LPCWSTR pszString2, __in int nLength2)
  210. {
  211. _AtlInstallStringThunk(reinterpret_cast<void**>(&_strthunks.pfnCompareStringW), CompareStringWFake, ::CompareStringW);
  212. return _strthunks.pfnCompareStringW(lcid, dwFlags, pszString1, nLength1, pszString2, nLength2);
  213. }
  214. inline BOOL WINAPI GetStringTypeExWFake(__in LCID lcid, __in DWORD dwInfoType, __in_ecount(nLength) LPCWSTR pszSrc,
  215. __in int nLength, __out LPWORD pwCharType)
  216. {
  217. int nLengthA;
  218. CTempBuffer<char> pszA;
  219. nLengthA = ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc, nLength, NULL, 0, NULL, NULL);
  220. pszA.Allocate(nLengthA);
  221. ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc, nLength, pszA, nLengthA, NULL, NULL);
  222. if (nLength == -1)
  223. nLengthA = -1;
  224. return ::GetStringTypeExA(lcid, dwInfoType, pszA, nLengthA, pwCharType);
  225. }
  226. inline BOOL WINAPI GetStringTypeExWThunk(__in LCID lcid, __in DWORD dwInfoType, __in_ecount(nLength) LPCWSTR pszSrc,
  227. __in int nLength, __out LPWORD pwCharType)
  228. {
  229. _AtlInstallStringThunk(reinterpret_cast<void**>(&_strthunks.pfnGetStringTypeExW), GetStringTypeExWFake, ::GetStringTypeExW);
  230. return _strthunks.pfnGetStringTypeExW(lcid, dwInfoType, pszSrc, nLength, pwCharType);
  231. }
  232. inline int WINAPI lstrcmpiWFake(__in_z LPCWSTR psz1, __in_z LPCWSTR psz2)
  233. {
  234. USES_CONVERSION_EX;
  235. return ::lstrcmpiA(W2A_EX_DEF(psz1), W2A_EX_DEF(psz2));
  236. }
  237. inline int WINAPI lstrcmpiWThunk(__in_z LPCWSTR psz1, __in_z LPCWSTR psz2)
  238. {
  239. _AtlInstallStringThunk(reinterpret_cast<void**>(&_strthunks.pfnlstrcmpiW), lstrcmpiWFake, ::lstrcmpiW);
  240. return _strthunks.pfnlstrcmpiW(psz1, psz2);
  241. }
  242. inline LPWSTR WINAPI CharLowerWFake(__inout_z LPWSTR psz)
  243. {
  244. ATLENSURE(psz);
  245. USES_CONVERSION_EX;
  246. LPSTR pszA;
  247. pszA = W2A_EX_DEF(psz);
  248. ::CharLowerA(pszA);
  249. Checked::wcscpy_s(psz, wcslen(psz) + 1, A2W_EX_DEF(pszA));
  250. return psz;
  251. }
  252. inline LPWSTR WINAPI CharLowerWThunk(__inout LPWSTR psz)
  253. {
  254. _AtlInstallStringThunk(reinterpret_cast<void**>(&_strthunks.pfnCharLowerW), CharLowerWFake, ::CharLowerW);
  255. return _strthunks.pfnCharLowerW(psz);
  256. }
  257. inline LPWSTR WINAPI CharUpperWFake(__inout_z LPWSTR psz)
  258. {
  259. ATLENSURE(psz);
  260. USES_CONVERSION_EX;
  261. LPSTR pszA;
  262. pszA = W2A_EX_DEF(psz);
  263. ::CharUpperA(pszA);
  264. Checked::wcscpy_s(psz, wcslen(psz) + 1, A2W_EX_DEF(pszA));
  265. return psz;
  266. }
  267. inline LPWSTR WINAPI CharUpperWThunk(__inout LPWSTR psz)
  268. {
  269. _AtlInstallStringThunk(reinterpret_cast<void**>(&_strthunks.pfnCharUpperW), CharUpperWFake, ::CharUpperW);
  270. return _strthunks.pfnCharUpperW(psz);
  271. }
  272. __declspec(selectany) _AtlStringThunks _strthunks =
  273. {
  274. CompareStringWThunk,
  275. GetStringTypeExWThunk,
  276. lstrcmpiWThunk,
  277. CharLowerWThunk,
  278. CharUpperWThunk,
  279. GetEnvironmentVariableWThunk
  280. };
  281. #endif  // !_UNICODE
  282. /////////////////////////////////////////////////////////////////////////////
  283. //
  284. #ifndef _ATL_MIN_CRT
  285. template< typename _CharType = char >
  286. class ChTraitsCRT :
  287. public ChTraitsBase< _CharType >
  288. {
  289. public:
  290. static char* __cdecl CharNext( __in_z const char* p ) throw()
  291. {
  292. return reinterpret_cast< char* >( _mbsinc( reinterpret_cast< const unsigned char* >( p ) ) );
  293. }
  294. static int __cdecl IsDigit( __in char ch ) throw()
  295. {
  296. return _ismbcdigit( ch );
  297. }
  298. static int __cdecl IsSpace( __in char ch ) throw()
  299. {
  300. return _ismbcspace( ch );
  301. }
  302. static int __cdecl StringCompare( __in_z LPCSTR pszA, __in_z LPCSTR pszB ) throw()
  303. {
  304. return _mbscmp( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ) );
  305. }
  306. static int __cdecl StringCompareIgnore( __in_z LPCSTR pszA, __in_z LPCSTR pszB ) throw()
  307. {
  308. return _mbsicmp( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ) );
  309. }
  310. static int __cdecl StringCollate( __in_z LPCSTR pszA, __in_z LPCSTR pszB ) throw()
  311. {
  312. return _mbscoll( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ) );
  313. }
  314. static int __cdecl StringCollateIgnore( __in_z LPCSTR pszA, __in_z LPCSTR pszB ) throw()
  315. {
  316. return _mbsicoll( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ) );
  317. }
  318. static LPCSTR __cdecl StringFindString( __in_z LPCSTR pszBlock, __in_z LPCSTR pszMatch ) throw()
  319. {
  320. return reinterpret_cast< LPCSTR >( _mbsstr( reinterpret_cast< const unsigned char* >( pszBlock ),
  321. reinterpret_cast< const unsigned char* >( pszMatch ) ) );
  322. }
  323. static LPSTR __cdecl StringFindString( __in_z LPSTR pszBlock, __in_z LPCSTR pszMatch ) throw()
  324. {
  325. return( const_cast< LPSTR >( StringFindString( const_cast< LPCSTR >( pszBlock ), pszMatch ) ) );
  326. }
  327. static LPCSTR __cdecl StringFindChar( __in_z LPCSTR pszBlock, __in char chMatch ) throw()
  328. {
  329. return reinterpret_cast< LPCSTR >( _mbschr( reinterpret_cast< const unsigned char* >( pszBlock ), (unsigned char)chMatch ) );
  330. }
  331. static LPCSTR __cdecl StringFindCharRev( __in_z LPCSTR psz, __in char ch ) throw()
  332. {
  333. return reinterpret_cast< LPCSTR >( _mbsrchr( reinterpret_cast< const unsigned char* >( psz ), (unsigned char)ch ) );
  334. }
  335. static LPCSTR __cdecl StringScanSet( __in_z LPCSTR pszBlock, __in_z LPCSTR pszMatch ) throw()
  336. {
  337. return reinterpret_cast< LPCSTR >( _mbspbrk( reinterpret_cast< const unsigned char* >( pszBlock ),
  338. reinterpret_cast< const unsigned char* >( pszMatch ) ) );
  339. }
  340. static int __cdecl StringSpanIncluding( __in_z LPCSTR pszBlock, __in_z LPCSTR pszSet ) throw()
  341. {
  342. return (int)_mbsspn( reinterpret_cast< const unsigned char* >( pszBlock ), reinterpret_cast< const unsigned char* >( pszSet ) );
  343. }
  344. static int __cdecl StringSpanExcluding( __in_z LPCSTR pszBlock, __in_z LPCSTR pszSet ) throw()
  345. {
  346. return (int)_mbscspn( reinterpret_cast< const unsigned char* >( pszBlock ), reinterpret_cast< const unsigned char* >( pszSet ) );
  347. }
  348. _ATL_INSECURE_DEPRECATE("You must pass an output size to ChTraitsCRT::StringUppercase")
  349. static LPSTR __cdecl StringUppercase( __inout LPSTR psz ) throw()
  350. {
  351. #pragma warning (push)
  352. #pragma warning(disable : 4996)
  353. return reinterpret_cast< LPSTR >( _mbsupr( reinterpret_cast< unsigned char* >( psz ) ) );
  354. #pragma warning (pop)
  355. }
  356. _ATL_INSECURE_DEPRECATE("You must pass an output size to ChTraitsCRT::StringLowercase")
  357. static LPSTR __cdecl StringLowercase( __inout LPSTR psz ) throw()
  358. {
  359. #pragma warning (push)
  360. #pragma warning(disable : 4996)
  361. return reinterpret_cast< LPSTR >( _mbslwr( reinterpret_cast< unsigned char* >( psz ) ) );
  362. #pragma warning (pop)
  363. }
  364. static LPSTR __cdecl StringUppercase( __inout_ecount(size) LPSTR psz, __in size_t size ) throw()
  365. {
  366. Checked::mbsupr_s(reinterpret_cast< unsigned char* >( psz ), size);
  367. return psz;
  368. }
  369. static LPSTR __cdecl StringLowercase( __inout_ecount(size) LPSTR psz, __in size_t size ) throw()
  370. {
  371. Checked::mbslwr_s( reinterpret_cast< unsigned char* >( psz ), size );
  372. return psz;
  373. }
  374. static LPSTR __cdecl StringReverse( __inout LPSTR psz ) throw()
  375. {
  376. return reinterpret_cast< LPSTR >( _mbsrev( reinterpret_cast< unsigned char* >( psz ) ) );
  377. }
  378. static int __cdecl GetFormattedLength( __in __format_string LPCSTR pszFormat, va_list args ) throw()
  379. {
  380. return _vscprintf( pszFormat, args );
  381. }
  382. _ATL_INSECURE_DEPRECATE("You must pass an output size to ChTraitsCRT::Format")
  383. static int __cdecl Format( __out LPSTR pszBuffer, __in __format_string LPCSTR pszFormat, va_list args ) throw()
  384. {
  385. #pragma warning (push)
  386. #pragma warning(disable : 4996)
  387. return vsprintf( pszBuffer, pszFormat, args );
  388. #pragma warning (pop)
  389. }
  390. static int __cdecl Format
  391. ( __out_ecount_part(nlength, return) LPSTR pszBuffer, __in size_t nlength, __in __format_string LPCSTR pszFormat, va_list args ) throw()
  392. {
  393. return vsprintf_s( pszBuffer, nlength, pszFormat, args );
  394. }
  395. static int __cdecl GetBaseTypeLength( __in_z LPCSTR pszSrc ) throw()
  396. {
  397. // Returns required buffer length in XCHARs
  398. return int( strlen( pszSrc ) );
  399. }
  400. static int __cdecl GetBaseTypeLength( __in_ecount(nLength) LPCSTR pszSrc, int nLength ) throw()
  401. {
  402. (void)pszSrc;
  403. // Returns required buffer length in XCHARs
  404. return nLength;
  405. }
  406. static int __cdecl GetBaseTypeLength( __in_z LPCWSTR pszSource ) throw()
  407. {
  408. // Returns required buffer length in XCHARs
  409. return ::WideCharToMultiByte( _AtlGetConversionACP(), 0, pszSource, -1, NULL, 0, NULL, NULL )-1;
  410. }
  411. static int __cdecl GetBaseTypeLength( __in_ecount(nLength) LPCWSTR pszSource, int nLength ) throw()
  412. {
  413. // Returns required buffer length in XCHARs
  414. return ::WideCharToMultiByte( _AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0, NULL, NULL );
  415. }
  416. static void __cdecl ConvertToBaseType( __out_ecount(nDestLength) LPSTR pszDest, __in int nDestLength,
  417. __in_z LPCSTR pszSrc, int nSrcLength = -1 ) throw()
  418. {
  419. if (nSrcLength == -1) { nSrcLength=1 + GetBaseTypeLength(pszSrc); }
  420. // nLen is in XCHARs
  421. Checked::memcpy_s( pszDest, nDestLength*sizeof( char ), 
  422. pszSrc, nSrcLength*sizeof( char ) );
  423. }
  424. static void __cdecl ConvertToBaseType( __out_ecount(nDestLength) LPSTR pszDest, __in int nDestLength,
  425. __in_z LPCWSTR pszSrc, __in int nSrcLength = -1) throw()
  426. {
  427. // nLen is in XCHARs
  428. ::WideCharToMultiByte( _AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL );
  429. }
  430. _ATL_INSECURE_DEPRECATE("You must pass an output size to ChTraitsCRT::ConvertToOem")
  431. static void ConvertToOem(__inout _CharType* pstrString) throw()
  432. {
  433. BOOL fSuccess=::CharToOemA(pstrString, pstrString);
  434. // old version can't report error
  435. ATLASSERT(fSuccess);
  436. }
  437. _ATL_INSECURE_DEPRECATE("You must pass an output size to ChTraitsCRT::ConvertToAnsi")
  438. static void ConvertToAnsi(__inout _CharType* pstrString) throw()
  439. {
  440. BOOL fSuccess=::OemToCharA(pstrString, pstrString);
  441. // old version can't report error
  442. ATLASSERT(fSuccess);
  443. }
  444. static void ConvertToOem(__inout_ecount(size) _CharType* pstrString, __in size_t size)
  445. {
  446. if(size>UINT_MAX)
  447. {
  448. // API only allows DWORD size
  449. AtlThrow(E_INVALIDARG);
  450. }
  451. DWORD dwSize=static_cast<DWORD>(size);
  452. BOOL fSuccess=::CharToOemBuffA(pstrString, pstrString, dwSize);
  453. if(!fSuccess)
  454. {
  455. AtlThrowLastWin32();
  456. }
  457. }
  458. static void ConvertToAnsi(__inout_ecount(size) _CharType* pstrString, __in size_t size)
  459. {
  460. if(size>UINT_MAX)
  461. {
  462. // API only allows DWORD size
  463. AtlThrow(E_INVALIDARG);
  464. }
  465. DWORD dwSize=static_cast<DWORD>(size);
  466. BOOL fSuccess=::OemToCharBuffA(pstrString, pstrString, dwSize);
  467. if(!fSuccess)
  468. {
  469. AtlThrowLastWin32();
  470. }
  471. }
  472. static void __cdecl FloodCharacters( __in char ch, __in int nLength, __out_ecount_full(nLength) char* pch ) throw()
  473. {
  474. // nLength is in XCHARs
  475. memset( pch, ch, nLength );
  476. }
  477. static BSTR __cdecl AllocSysString( __in_ecount(nDataLength) const char* pchData, int nDataLength ) throw()
  478. {
  479. int nLen = ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pchData, nDataLength,
  480. NULL, NULL );
  481. BSTR bstr = ::SysAllocStringLen( NULL, nLen );
  482. if( bstr != NULL )
  483. {
  484. ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pchData, nDataLength,
  485. bstr, nLen );
  486. }
  487. return bstr;
  488. }
  489. static BOOL __cdecl ReAllocSysString( __in_ecount(nDataLength) const char* pchData, __out BSTR* pbstr, __in int nDataLength ) throw()
  490. {
  491. int nLen = ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pchData, nDataLength, NULL, NULL );
  492. BOOL bSuccess = ::SysReAllocStringLen( pbstr, NULL, nLen );
  493. if( bSuccess )
  494. {
  495. ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pchData, nDataLength, *pbstr, nLen );
  496. }
  497. return bSuccess;
  498. }
  499. static DWORD __cdecl _AFX_FUNCNAME(FormatMessage)( __in DWORD dwFlags, LPCVOID pSource,
  500. __in DWORD dwMessageID, __in DWORD dwLanguageID, __out_ecount(nSize) LPSTR pszBuffer,
  501. DWORD nSize, va_list* pArguments ) throw()
  502. {
  503. return ::FormatMessageA( dwFlags, pSource, dwMessageID, dwLanguageID,
  504. pszBuffer, nSize, pArguments );
  505. }
  506. #if defined(_AFX)
  507. static DWORD __cdecl FormatMessage( __in DWORD dwFlags, LPCVOID pSource,
  508. __in DWORD dwMessageID, __in DWORD dwLanguageID, __out_ecount(nSize) LPSTR pszBuffer,
  509. DWORD nSize, va_list* pArguments ) throw()
  510. {
  511. return _AFX_FUNCNAME(FormatMessage)(dwFlags, pSource, dwMessageID, dwLanguageID, pszBuffer, nSize, pArguments);
  512. }
  513. #endif
  514. static int __cdecl SafeStringLen( __in_z_opt LPCSTR psz ) throw()
  515. {
  516. // returns length in bytes
  517. return (psz != NULL) ? int( strlen( psz ) ) : 0;
  518. }
  519. static int __cdecl SafeStringLen( __in_z_opt LPCWSTR psz ) throw()
  520. {
  521. // returns length in wchar_ts
  522. return (psz != NULL) ? int( wcslen( psz ) ) : 0;
  523. }
  524. static int __cdecl GetCharLen( __in_z const wchar_t* pch ) throw()
  525. {
  526. (void)pch;
  527. // returns char length
  528. return 1;
  529. }
  530. static int __cdecl GetCharLen( __in_z const char* pch ) throw()
  531. {
  532. // returns char length
  533. return int( _mbclen( reinterpret_cast< const unsigned char* >( pch ) ) );
  534. }
  535. static DWORD __cdecl GetEnvironmentVariable( __in_z LPCSTR pszVar,
  536. __out_ecount_opt(dwSize) LPSTR pszBuffer, __in DWORD dwSize ) throw()
  537. {
  538. return ::GetEnvironmentVariableA( pszVar, pszBuffer, dwSize );
  539. }
  540. };
  541. // specialization for wchar_t
  542. template<>
  543. class ChTraitsCRT< wchar_t > :
  544. public ChTraitsBase< wchar_t >
  545. {
  546. #if defined(_UNICODE) && !defined(_CSTRING_ALWAYS_THUNK)
  547. static DWORD __cdecl _GetEnvironmentVariableW( __in_z LPCWSTR pszName, __out_ecount_part_opt(nSize, return) LPWSTR pszBuffer, __in DWORD nSize ) throw()
  548. {
  549. return ::GetEnvironmentVariableW( pszName, pszBuffer, nSize );
  550. }
  551. #else  // !_UNICODE
  552. static DWORD WINAPI _GetEnvironmentVariableW( __in_z LPCWSTR pszName, 
  553. __out_ecount_part_opt(nSize,return) LPWSTR pszBuffer, __in DWORD nSize ) throw()
  554. {
  555. return _strthunks.pfnGetEnvironmentVariableW( pszName, pszBuffer, nSize );
  556. }
  557. #endif  // !_UNICODE
  558. public:
  559. static LPWSTR __cdecl CharNext( __in_z LPCWSTR psz ) throw()
  560. {
  561. return const_cast< LPWSTR >( psz+1 );
  562. }
  563. static int __cdecl IsDigit( __in wchar_t ch ) throw()
  564. {
  565. return iswdigit( static_cast<unsigned short>(ch) );
  566. }
  567. static int __cdecl IsSpace( __in wchar_t ch ) throw()
  568. {
  569. return iswspace( static_cast<unsigned short>(ch) );
  570. }
  571. static int __cdecl StringCompare( __in_z LPCWSTR pszA, __in_z LPCWSTR pszB ) throw()
  572. {
  573. return wcscmp( pszA, pszB );
  574. }
  575. static int __cdecl StringCompareIgnore( __in_z LPCWSTR pszA, __in_z LPCWSTR pszB ) throw()
  576. {
  577. return _wcsicmp( pszA, pszB );
  578. }
  579. static int __cdecl StringCollate( __in_z LPCWSTR pszA, __in_z LPCWSTR pszB ) throw()
  580. {
  581. return wcscoll( pszA, pszB );
  582. }
  583. static int __cdecl StringCollateIgnore( __in_z LPCWSTR pszA, __in_z LPCWSTR pszB ) throw()
  584. {
  585. return _wcsicoll( pszA, pszB );
  586. }
  587. static LPCWSTR __cdecl StringFindString( __in_z LPCWSTR pszBlock, __in_z LPCWSTR pszMatch ) throw()
  588. {
  589. return wcsstr( pszBlock, pszMatch );
  590. }
  591. static LPWSTR __cdecl StringFindString( __in_z LPWSTR pszBlock, __in_z LPCWSTR pszMatch ) throw()
  592. {
  593. return( const_cast< LPWSTR >( StringFindString( const_cast< LPCWSTR >( pszBlock ), pszMatch ) ) );
  594. }
  595. static LPCWSTR __cdecl StringFindChar( __in_z LPCWSTR pszBlock, __in wchar_t chMatch ) throw()
  596. {
  597. return wcschr( pszBlock, chMatch );
  598. }
  599. static LPCWSTR __cdecl StringFindCharRev( __in_z LPCWSTR psz, __in wchar_t ch ) throw()
  600. {
  601. return wcsrchr( psz, ch );
  602. }
  603. static LPCWSTR __cdecl StringScanSet( __in_z LPCWSTR pszBlock, __in_z LPCWSTR pszMatch ) throw()
  604. {
  605. return wcspbrk( pszBlock, pszMatch );
  606. }
  607. static int __cdecl StringSpanIncluding( __in_z LPCWSTR pszBlock, __in_z LPCWSTR pszSet ) throw()
  608. {
  609. return (int)wcsspn( pszBlock, pszSet );
  610. }
  611. static int __cdecl StringSpanExcluding( __in_z LPCWSTR pszBlock, __in_z LPCWSTR pszSet ) throw()
  612. {
  613. return (int)wcscspn( pszBlock, pszSet );
  614. }
  615. _ATL_INSECURE_DEPRECATE("You must pass an output size to ChTraitsCRT::StringUppercase")
  616. static LPWSTR __cdecl StringUppercase( __inout LPWSTR psz ) throw()
  617. {
  618. #pragma warning (push)
  619. #pragma warning(disable : 4996)
  620. return _wcsupr( psz );
  621. #pragma warning (pop)
  622. }
  623. _ATL_INSECURE_DEPRECATE("You must pass an output size to ChTraitsCRT::StringLowercase")
  624. static LPWSTR __cdecl StringLowercase( __inout LPWSTR psz ) throw()
  625. {
  626. #pragma warning (push)
  627. #pragma warning(disable : 4996)
  628. return _wcslwr( psz );
  629. #pragma warning (pop)
  630. }
  631. static LPWSTR __cdecl StringUppercase( __inout_ecount(size) LPWSTR psz, __in size_t size ) throw()
  632. {
  633. #if _SECURE_ATL
  634. errno_t err = _wcsupr_s( psz, size );
  635. return (err == 0) ? psz : NULL;
  636. #else
  637. size;
  638. return _wcsupr( psz );
  639. #endif
  640. }
  641. static LPWSTR __cdecl StringLowercase( __inout_ecount(size) LPWSTR psz, __in size_t size ) throw()
  642. {
  643. #if _SECURE_ATL
  644. errno_t err = _wcslwr_s( psz, size );
  645. return (err == 0) ? psz : NULL;
  646. #else
  647. size;
  648. return _wcslwr( psz );
  649. #endif
  650. }
  651. static LPWSTR __cdecl StringReverse( __inout LPWSTR psz ) throw()
  652. {
  653. return _wcsrev( psz );
  654. }
  655. static int __cdecl GetFormattedLength( __in __format_string LPCWSTR pszFormat, va_list args) throw()
  656. {
  657. return _vscwprintf( pszFormat, args );
  658. }
  659. _ATL_INSECURE_DEPRECATE("You must pass an output size to ChTraitsCRT::Format")
  660. static int __cdecl Format( __out LPWSTR pszBuffer, __in __format_string LPCWSTR pszFormat, va_list args) throw()
  661. {
  662. #pragma warning (push)
  663. #pragma warning(disable : 4996)
  664. return vswprintf( pszBuffer, pszFormat, args );
  665. #pragma warning (pop)
  666. }
  667. static int __cdecl Format
  668. ( __out_ecount(nLength) LPWSTR pszBuffer, __in size_t nLength, __in __format_string LPCWSTR pszFormat, va_list args) throw()
  669. {
  670. return vswprintf_s( pszBuffer, nLength, pszFormat, args );
  671. }
  672. static int __cdecl GetBaseTypeLength( __in_z LPCSTR pszSrc ) throw()
  673. {
  674. // Returns required buffer size in wchar_ts
  675. return ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pszSrc, -1, NULL, 0 )-1;
  676. }
  677. static int __cdecl GetBaseTypeLength( __in_ecount(nLength) LPCSTR pszSrc, __in int nLength ) throw()
  678. {
  679. // Returns required buffer size in wchar_ts
  680. return ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pszSrc, nLength, NULL, 0 );
  681. }
  682. static int __cdecl GetBaseTypeLength( __in_z LPCWSTR pszSrc ) throw()
  683. {
  684. // Returns required buffer size in wchar_ts
  685. return (int)wcslen( pszSrc );
  686. }
  687. static int __cdecl GetBaseTypeLength( __in_ecount(nLength) LPCWSTR pszSrc, __in int nLength ) throw()
  688. {
  689. (void)pszSrc;
  690. // Returns required buffer size in wchar_ts
  691. return nLength;
  692. }
  693. static void __cdecl ConvertToBaseType( __out_ecount(nDestLength) LPWSTR pszDest, __in int nDestLength,
  694. __in_z LPCSTR pszSrc, __in int nSrcLength = -1) throw()
  695. {
  696. // nLen is in wchar_ts
  697. ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength );
  698. }
  699. static void __cdecl ConvertToBaseType( __out_ecount(nDestLength) LPWSTR pszDest, __in int nDestLength,
  700. __in_z LPCWSTR pszSrc, int nSrcLength = -1 ) throw()
  701. {
  702. if (nSrcLength == -1) { nSrcLength=1 + GetBaseTypeLength(pszSrc); }
  703. // nLen is in wchar_ts
  704. Checked::wmemcpy_s(pszDest, nDestLength, pszSrc, nSrcLength);
  705. }
  706. static void __cdecl FloodCharacters( __in wchar_t ch, __in int nLength, __out_ecount_full(nLength) LPWSTR psz ) throw()
  707. {
  708. // nLength is in XCHARs
  709. for( int i = 0; i < nLength; i++ )
  710. {
  711. psz[i] = ch;
  712. }
  713. }
  714. static BSTR __cdecl AllocSysString( __in_ecount(nDataLength) const wchar_t* pchData, __in int nDataLength ) throw()
  715. {
  716. return ::SysAllocStringLen( pchData, nDataLength );
  717. }
  718. static BOOL __cdecl ReAllocSysString( __in_ecount(nDataLength) const wchar_t* pchData, __inout BSTR* pbstr, __in int nDataLength ) throw()
  719. {
  720. return ::SysReAllocStringLen( pbstr, pchData, nDataLength );
  721. }
  722. static int __cdecl SafeStringLen( __in_z_opt LPCSTR psz ) throw()
  723. {
  724. // returns length in bytes
  725. return (psz != NULL) ? (int)strlen( psz ) : 0;
  726. }
  727. static int __cdecl SafeStringLen( __in_opt LPCWSTR psz ) throw()
  728. {
  729. // returns length in wchar_ts
  730. return (psz != NULL) ? (int)wcslen( psz ) : 0;
  731. }
  732. static int __cdecl GetCharLen( __in_z const wchar_t* pch ) throw()
  733. {
  734. (void)pch;
  735. // returns char length
  736. return 1;
  737. }
  738. static int __cdecl GetCharLen( __in_z const char* pch ) throw()
  739. {
  740. // returns char length
  741. return (int)( _mbclen( reinterpret_cast< const unsigned char* >( pch ) ) );
  742. }
  743. static DWORD __cdecl GetEnvironmentVariable( __in_z LPCWSTR pszVar, __out_ecount_opt(dwSize) LPWSTR pszBuffer, __in DWORD dwSize ) throw()
  744. {
  745. return _GetEnvironmentVariableW( pszVar, pszBuffer, dwSize );
  746. }
  747. static void __cdecl ConvertToOem( __reserved LPWSTR /*psz*/ )
  748. {
  749. ATLENSURE(FALSE); // Unsupported Feature 
  750. }
  751. static void __cdecl ConvertToAnsi( __reserved LPWSTR /*psz*/ )
  752. {
  753. ATLENSURE(FALSE); // Unsupported Feature 
  754. }
  755. static void __cdecl ConvertToOem( __reserved LPWSTR /*psz*/, size_t )
  756. {
  757. ATLENSURE(FALSE); // Unsupported Feature 
  758. }
  759. static void __cdecl ConvertToAnsi( __reserved LPWSTR /*psz*/, size_t ) 
  760. {
  761. ATLENSURE(FALSE); // Unsupported Feature 
  762. }
  763. #ifdef _UNICODE
  764. public:
  765. static DWORD __cdecl _AFX_FUNCNAME(FormatMessage)( __in DWORD dwFlags, LPCVOID pSource,
  766. __in DWORD dwMessageID, __in DWORD dwLanguageID, __out_ecount(nSize) LPWSTR pszBuffer,
  767. __in DWORD nSize, va_list* pArguments ) throw()
  768. {
  769. return ::FormatMessageW( dwFlags, pSource, dwMessageID, dwLanguageID,
  770. pszBuffer, nSize, pArguments );
  771. }
  772. #if defined(_AFX)
  773. static DWORD __cdecl FormatMessage( __in DWORD dwFlags, LPCVOID pSource,
  774. __in DWORD dwMessageID, __in DWORD dwLanguageID, __out_ecount(nSize) LPWSTR pszBuffer,
  775. __in DWORD nSize, va_list* pArguments ) throw()
  776. {
  777. return _AFX_FUNCNAME(FormatMessage)(dwFlags, pSource, dwMessageID, dwLanguageID, pszBuffer, nSize, pArguments);
  778. }
  779. #endif
  780. #else
  781. static DWORD __cdecl _AFX_FUNCNAME(FormatMessage)( DWORD /*dwFlags*/, LPCVOID /*pSource*/,
  782. DWORD /*dwMessageID*/, DWORD /*dwLanguageID*/, __reserved LPWSTR /*pszBuffer*/,
  783. DWORD /*nSize*/, va_list* /*pArguments*/ )
  784. {
  785. ATLENSURE(FALSE); // Unsupported Feature 
  786. return 0;
  787. }
  788. #if defined(_AFX)
  789. static DWORD __cdecl FormatMessage( DWORD dwFlags, LPCVOID pSource,
  790. DWORD dwMessageID, DWORD dwLanguageID, __reserved LPWSTR pszBuffer,
  791. DWORD nSize, va_list* pArguments )
  792. {
  793. return _AFX_FUNCNAME(FormatMessage)(dwFlags, pSource, dwMessageID, dwLanguageID, pszBuffer, nSize, pArguments);
  794. }
  795. #endif
  796. #endif
  797. };
  798. #endif  // _ATL_MIN_CRT
  799. } // namespace ATL
  800. #ifndef _ATL_MIN_CRT
  801. // Forward declare
  802. template< typename _CharType = char, class StringIterator = ATL::ChTraitsCRT< _CharType > >
  803. class StrTraitMFC_DLL;
  804. #endif // _ATL_MIN_CRT
  805. namespace ATL
  806. {
  807. namespace _CSTRING_IMPL_
  808. {
  809. template <typename _CharType, class StringTraits>
  810. struct _MFCDLLTraitsCheck
  811. {
  812. const static bool c_bIsMFCDLLTraits = false;
  813. };
  814. #ifndef _ATL_MIN_CRT
  815. template<typename _CharType> 
  816. struct _MFCDLLTraitsCheck<_CharType, StrTraitMFC_DLL<_CharType, ATL::ChTraitsCRT< _CharType > > >
  817. {
  818. const static bool c_bIsMFCDLLTraits = true;
  819. };
  820. #endif // _ATL_MIN_CRT
  821. }
  822. // The CStringT class has a few varargs member functions that will cause 4793
  823. // warnings if compiled /clr. Because of the way template classes are parsed,
  824. // we need to disable the warning for the entire class.
  825. //#pragma warning( push )
  826. //#pragma warning( disable : 4793 )
  827. template< typename BaseType, class StringTraits >
  828. class CStringT :
  829. public CSimpleStringT< BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits >
  830. {
  831. public:
  832. typedef CSimpleStringT< BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits > CThisSimpleString;
  833. typedef StringTraits StrTraits;
  834. typedef typename CThisSimpleString::XCHAR XCHAR;
  835. typedef typename CThisSimpleString::PXSTR PXSTR;
  836. typedef typename CThisSimpleString::PCXSTR PCXSTR;
  837. typedef typename CThisSimpleString::YCHAR YCHAR;
  838. typedef typename CThisSimpleString::PYSTR PYSTR;
  839. typedef typename CThisSimpleString::PCYSTR PCYSTR;
  840. public:
  841. CStringT() throw() :
  842. CThisSimpleString( StringTraits::GetDefaultManager() )
  843. {
  844. }
  845. explicit CStringT( IAtlStringMgr* pStringMgr ) throw() :
  846. CThisSimpleString( pStringMgr )
  847. }
  848. CStringT( const VARIANT& varSrc );
  849. CStringT( const VARIANT& varSrc, IAtlStringMgr* pStringMgr );
  850. static void __cdecl Construct( CStringT* pString )
  851. {
  852. new( pString ) CStringT;
  853. }
  854. // Copy constructor
  855. CStringT( const CStringT& strSrc ) :
  856. CThisSimpleString( strSrc )
  857. {
  858. }
  859. // Construct from CSimpleStringT
  860. operator CSimpleStringT<BaseType, !_CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits >&()
  861. {
  862. return *(CSimpleStringT<BaseType, !_CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits >*)this;
  863. }
  864. template <bool bMFCDLL>
  865. CStringT( __in const CSimpleStringT<BaseType, bMFCDLL>& strSrc ) :
  866. CThisSimpleString( strSrc )
  867. {
  868. }
  869. CStringT( __in const XCHAR* pszSrc ) :
  870. CThisSimpleString( StringTraits::GetDefaultManager() )
  871. {
  872. if( !CheckImplicitLoad( pszSrc ) )
  873. {
  874. // nDestLength is in XCHARs
  875. *this = pszSrc;
  876. }
  877. }
  878. CStringT( __in_z LPCSTR pszSrc, __in IAtlStringMgr* pStringMgr ) :
  879. CThisSimpleString( pStringMgr )
  880. {
  881. if( !CheckImplicitLoad( pszSrc ) )
  882. {
  883. // nDestLength is in XCHARs
  884. *this = pszSrc;
  885. }
  886. }
  887. CSTRING_EXPLICIT CStringT( __in const YCHAR* pszSrc ) :
  888. CThisSimpleString( StringTraits::GetDefaultManager() )
  889. {
  890. if( !CheckImplicitLoad( pszSrc ) )
  891. {
  892. *this = pszSrc;
  893. }
  894. }
  895. CStringT( __in_z LPCWSTR pszSrc, __in IAtlStringMgr* pStringMgr ) :
  896. CThisSimpleString( pStringMgr )
  897. {
  898. if( !CheckImplicitLoad( pszSrc ) )
  899. {
  900. *this = pszSrc;
  901. }
  902. }
  903. // This template will compile only for
  904. // class SystemString == System::String
  905. #if defined(__cplusplus_cli)
  906. template <class SystemString>
  907. CStringT( SystemString^ pString ) :
  908. CThisSimpleString( StringTraits::GetDefaultManager() )
  909. {
  910. cli::pin_ptr<const System::Char> pChar = PtrToStringChars( pString );
  911. const wchar_t *psz = pChar;
  912. *this = psz;
  913. }
  914. #elif defined(_MANAGED)
  915. template<class SystemString>
  916. CStringT( SystemString __gc* pString ) :
  917. CThisSimpleString( StringTraits::GetDefaultManager() )
  918. {
  919. const wchar_t __pin* psz = PtrToStringChars( pString );
  920. *this = psz;
  921. }
  922. #endif
  923. CSTRING_EXPLICIT CStringT( const unsigned char* pszSrc ) :
  924. CThisSimpleString( StringTraits::GetDefaultManager() )
  925. {
  926. *this = reinterpret_cast< const char* >( pszSrc );
  927. }
  928. //ctors to prevent from oldSyntax template ctor (above) hijack certain types.
  929. //MFC dll instantiate all CStringT methods inside the dll and declares dllimport for 
  930. //all methods in user build (see afxstr.h), so need to include the methods in MFC dll builds.
  931. #if defined(_AFXDLL) && defined(_MFC_DLL_BLD) || !defined(__cplusplus_cli) && defined(_MANAGED)
  932. /*CSTRING_EXPLICIT*/ CStringT( __in_z char* pszSrc ) :
  933. CThisSimpleString( StringTraits::GetDefaultManager() )
  934. {
  935. const char *psz = reinterpret_cast< const char* >( pszSrc );
  936. if (!CheckImplicitLoad( psz ))
  937. {
  938. *this = psz;
  939. }
  940. }
  941. CSTRING_EXPLICIT CStringT( __in unsigned char* pszSrc ) :
  942. CThisSimpleString( StringTraits::GetDefaultManager() )
  943. {
  944. const char *psz = reinterpret_cast< const char* >( pszSrc );
  945. if (!CheckImplicitLoad( psz ))
  946. {
  947. *this = psz;
  948. }
  949. }
  950. CSTRING_EXPLICIT CStringT( __in_z wchar_t* pszSrc ) :
  951. CThisSimpleString( StringTraits::GetDefaultManager() )
  952. {
  953. const wchar_t *psz = reinterpret_cast< const wchar_t* >( pszSrc );
  954. if (!CheckImplicitLoad( psz ))
  955. {
  956. *this = psz;
  957. }
  958. }
  959. #endif
  960. CStringT( __in const unsigned char* pszSrc, __in IAtlStringMgr* pStringMgr ) :
  961. CThisSimpleString( pStringMgr )
  962. {
  963. *this = reinterpret_cast< const char* >( pszSrc );
  964. }
  965. CSTRING_EXPLICIT CStringT( __in char ch, __in int nLength = 1 ) :
  966. CThisSimpleString( StringTraits::GetDefaultManager() )
  967. {
  968. ATLASSERT( nLength >= 0 );
  969. if( nLength > 0 )
  970. {
  971. PXSTR pszBuffer = GetBuffer( nLength );
  972. StringTraits::FloodCharacters( XCHAR( ch ), nLength, pszBuffer );
  973. ReleaseBufferSetLength( nLength );
  974. }
  975. }
  976. CSTRING_EXPLICIT CStringT( __in wchar_t ch, __in int nLength = 1 ) :
  977. CThisSimpleString( StringTraits::GetDefaultManager() )
  978. {
  979. ATLASSERT( nLength >= 0 );
  980. if( nLength > 0 )
  981. {
  982. //Convert ch to the BaseType
  983. wchar_t pszCh[2] = { ch , 0 };
  984. int nBaseTypeCharLen = 1;
  985. if(ch != L'')
  986. {
  987. nBaseTypeCharLen = StringTraits::GetBaseTypeLength(pszCh);
  988. }
  989. CTempBuffer<XCHAR,10> buffBaseTypeChar;
  990. buffBaseTypeChar.Allocate(nBaseTypeCharLen+1);
  991. StringTraits::ConvertToBaseType( buffBaseTypeChar, nBaseTypeCharLen+1, pszCh, 1 );
  992. //Allocate enough characters in String and flood (replicate) with the (converted character)*nLength
  993. PXSTR pszBuffer = GetBuffer( nLength*nBaseTypeCharLen );
  994. if (nBaseTypeCharLen == 1)
  995. {   //Optimization for a common case - wide char translates to 1 ansi/wide char.
  996. StringTraits::FloodCharacters( buffBaseTypeChar[0], nLength, pszBuffer );
  997. } else
  998. {
  999. XCHAR* p=pszBuffer;
  1000. for (int i=0 ; i < nLength ;++i)
  1001. {
  1002. for (int j=0 ; j < nBaseTypeCharLen ;++j)
  1003. {
  1004. *p=buffBaseTypeChar[j];
  1005. ++p;
  1006. }
  1007. }
  1008. }
  1009. ReleaseBufferSetLength( nLength*nBaseTypeCharLen );
  1010. }
  1011. }
  1012. CStringT( __in_ecount(nLength) const XCHAR* pch, __in int nLength ) :
  1013. CThisSimpleString( pch, nLength, StringTraits::GetDefaultManager() )
  1014. {
  1015. }
  1016. CStringT( __in_ecount(nLength) const XCHAR* pch, __in int nLength, __in IAtlStringMgr* pStringMgr ) :
  1017. CThisSimpleString( pch, nLength, pStringMgr )
  1018. {
  1019. }
  1020. CStringT( __in_ecount(nLength) const YCHAR* pch, __in int nLength ) :
  1021. CThisSimpleString( StringTraits::GetDefaultManager() )
  1022. {
  1023. ATLASSERT( nLength >= 0 );
  1024. if( nLength > 0 )
  1025. {
  1026. ATLASSERT( AtlIsValidAddress( pch, nLength*sizeof( YCHAR ), FALSE ) );
  1027. if(pch == NULL)
  1028. AtlThrow(E_INVALIDARG);
  1029. int nDestLength = StringTraits::GetBaseTypeLength( pch, nLength );
  1030. PXSTR pszBuffer = GetBuffer( nDestLength );
  1031. StringTraits::ConvertToBaseType( pszBuffer, nDestLength, pch, nLength );
  1032. ReleaseBufferSetLength( nDestLength );
  1033. }
  1034. }
  1035. CStringT( __in_ecount(nLength) const YCHAR* pch, __in int nLength, __in IAtlStringMgr* pStringMgr ) :
  1036. CThisSimpleString( pStringMgr )
  1037. {
  1038. ATLASSERT( nLength >= 0 );
  1039. if( nLength > 0 )
  1040. {
  1041. ATLASSERT( AtlIsValidAddress( pch, nLength*sizeof( YCHAR ), FALSE ) );
  1042. if(pch == NULL)
  1043. AtlThrow(E_INVALIDARG);
  1044. int nDestLength = StringTraits::GetBaseTypeLength( pch, nLength );
  1045. PXSTR pszBuffer = GetBuffer( nDestLength );
  1046. StringTraits::ConvertToBaseType( pszBuffer, nDestLength, pch, nLength );
  1047. ReleaseBufferSetLength( nDestLength );
  1048. }
  1049. }
  1050. // Destructor
  1051. ~CStringT() throw()
  1052. {
  1053. }
  1054. // Assignment operators
  1055. CStringT& operator=( __in const CStringT& strSrc )
  1056. {
  1057. CThisSimpleString::operator=( strSrc );
  1058. return( *this );
  1059. }
  1060. template <bool bMFCDLL>
  1061. CStringT& operator=( __in const CSimpleStringT<BaseType, bMFCDLL>& strSrc )
  1062. {
  1063. CThisSimpleString::operator=( strSrc );
  1064. return( *this );
  1065. }
  1066. CStringT& operator=( __in PCXSTR pszSrc )
  1067. {
  1068. CThisSimpleString::operator=( pszSrc );
  1069. return( *this );
  1070. }
  1071. CStringT& operator=( __in PCYSTR pszSrc )
  1072. {
  1073. // nDestLength is in XCHARs
  1074. int nDestLength = (pszSrc != NULL) ? StringTraits::GetBaseTypeLength( pszSrc ) : 0;
  1075. if( nDestLength > 0 )
  1076. {
  1077. PXSTR pszBuffer = GetBuffer( nDestLength );
  1078. StringTraits::ConvertToBaseType( pszBuffer, nDestLength, pszSrc);
  1079. ReleaseBufferSetLength( nDestLength );
  1080. }
  1081. else
  1082. {
  1083. Empty();
  1084. }
  1085. return( *this );
  1086. }
  1087. CStringT& operator=( __in const unsigned char* pszSrc )
  1088. {
  1089. return( operator=( reinterpret_cast< const char* >( pszSrc ) ) );
  1090. }
  1091. CStringT& operator=( __in char ch )
  1092. {
  1093. char ach[2] = { ch, 0 };
  1094. return( operator=( ach ) );
  1095. }
  1096. CStringT& operator=( __in wchar_t ch )
  1097. {
  1098. wchar_t ach[2] = { ch, 0 };
  1099. return( operator=( ach ) );
  1100. }
  1101. CStringT& operator=( __in const VARIANT& var );
  1102. CStringT& operator+=( __in const CThisSimpleString& str )
  1103. {
  1104. CThisSimpleString::operator+=( str );
  1105. return( *this );
  1106. }
  1107. template <bool bMFCDLL>
  1108. CStringT& operator+=( __in const CSimpleStringT<BaseType, bMFCDLL>& str )
  1109. {
  1110. CThisSimpleString::operator+=( str );
  1111. return( *this );
  1112. }
  1113. CStringT& operator+=( __in PCXSTR pszSrc )
  1114. {
  1115. CThisSimpleString::operator+=( pszSrc );
  1116. return( *this );
  1117. }
  1118. template< int t_nSize >
  1119. CStringT& operator+=( __in const CStaticString< XCHAR, t_nSize >& strSrc )
  1120. {
  1121. CThisSimpleString::operator+=( strSrc );
  1122. return( *this );
  1123. }
  1124. CStringT& operator+=( __in PCYSTR pszSrc )
  1125. {
  1126. CStringT str( pszSrc, GetManager() );
  1127. return( operator+=( str ) );
  1128. }
  1129. CStringT& operator+=( __in char ch )
  1130. {
  1131. CThisSimpleString::operator+=( ch );
  1132. return( *this );
  1133. }
  1134. CStringT& operator+=( __in unsigned char ch )
  1135. {
  1136. CThisSimpleString::operator+=( ch );
  1137. return( *this );
  1138. }
  1139. CStringT& operator+=( __in wchar_t ch )
  1140. {
  1141. CThisSimpleString::operator+=( ch );
  1142. return( *this );
  1143. }
  1144. CStringT& operator+=( __in const VARIANT& var );
  1145. // Override from base class
  1146. IAtlStringMgr* GetManager() const throw()
  1147. {
  1148. IAtlStringMgr* pStringMgr = CThisSimpleString::GetManager();
  1149. if(pStringMgr) { return pStringMgr; }
  1150. pStringMgr = StringTraits::GetDefaultManager();
  1151. return pStringMgr->Clone();
  1152. }
  1153. // Comparison
  1154. int Compare( __in PCXSTR psz ) const
  1155. {
  1156. ATLENSURE( AtlIsValidString( psz ) );
  1157. return( StringTraits::StringCompare( GetString(), psz ) );
  1158. }
  1159. int CompareNoCase( __in PCXSTR psz ) const throw()
  1160. {
  1161. ATLASSERT( AtlIsValidString( psz ) );
  1162. return( StringTraits::StringCompareIgnore( GetString(), psz ) );
  1163. }
  1164. int Collate( __in PCXSTR psz ) const throw()
  1165. {
  1166. ATLASSERT( AtlIsValidString( psz ) );
  1167. return( StringTraits::StringCollate( GetString(), psz ) );
  1168. }
  1169. int CollateNoCase( __in PCXSTR psz ) const throw()
  1170. {
  1171. ATLASSERT( AtlIsValidString( psz ) );
  1172. return( StringTraits::StringCollateIgnore( GetString(), psz ) );
  1173. }
  1174. // Advanced manipulation
  1175. // Delete 'nCount' characters, starting at index 'iIndex'
  1176. int Delete( __in int iIndex, __in int nCount = 1 )
  1177. {
  1178. if( iIndex < 0 )
  1179. iIndex = 0;
  1180. if( nCount < 0 )
  1181. nCount = 0;
  1182. int nLength = GetLength();
  1183. if( (::ATL::AtlAddThrow(nCount, iIndex)) > nLength )
  1184. {
  1185. nCount = nLength-iIndex;
  1186. }
  1187. if( nCount > 0 )
  1188. {
  1189. int nNewLength = nLength-nCount;
  1190. int nXCHARsToCopy = nLength-(iIndex+nCount)+1;
  1191. PXSTR pszBuffer = GetBuffer();
  1192. Checked::memmove_s( pszBuffer+iIndex, nXCHARsToCopy*sizeof( XCHAR ), 
  1193. pszBuffer+iIndex+nCount, nXCHARsToCopy*sizeof( XCHAR ) );
  1194. ReleaseBufferSetLength( nNewLength );
  1195. }
  1196. return( GetLength() );
  1197. }
  1198. // Insert character 'ch' before index 'iIndex'
  1199. int Insert( __in int iIndex, __in XCHAR ch )
  1200. {
  1201. if( iIndex < 0 )
  1202. iIndex = 0;
  1203. if( iIndex > GetLength() )
  1204. {
  1205. iIndex = GetLength();
  1206. }
  1207. int nNewLength = GetLength()+1;
  1208. PXSTR pszBuffer = GetBuffer( nNewLength );
  1209. // move existing bytes down 
  1210.         Checked::memmove_s( pszBuffer+iIndex+1, (nNewLength-iIndex)*sizeof( XCHAR ), 
  1211. pszBuffer+iIndex, (nNewLength-iIndex)*sizeof( XCHAR ) );
  1212. pszBuffer[iIndex] = ch;
  1213. ReleaseBufferSetLength( nNewLength );
  1214. return( nNewLength );
  1215. }
  1216. // Insert string 'psz' before index 'iIndex'
  1217. int Insert( __in int iIndex, __in PCXSTR psz )
  1218. {
  1219. if( iIndex < 0 )
  1220. iIndex = 0;
  1221. if( iIndex > GetLength() )
  1222. {
  1223. iIndex = GetLength();
  1224. }
  1225. // nInsertLength and nNewLength are in XCHARs
  1226. int nInsertLength = StringTraits::SafeStringLen( psz );
  1227. int nNewLength = GetLength();
  1228. if( nInsertLength > 0 )
  1229. {
  1230. nNewLength += nInsertLength;
  1231. PXSTR pszBuffer = GetBuffer( nNewLength );
  1232. // move existing bytes down 
  1233.             Checked::memmove_s( pszBuffer+iIndex+nInsertLength, (nNewLength-iIndex-nInsertLength+1)*sizeof( XCHAR ), 
  1234. pszBuffer+iIndex, (nNewLength-iIndex-nInsertLength+1)*sizeof( XCHAR ) );
  1235. Checked::memcpy_s( pszBuffer+iIndex, nInsertLength*sizeof( XCHAR ), 
  1236. psz, nInsertLength*sizeof( XCHAR ) );
  1237. ReleaseBufferSetLength( nNewLength );
  1238. }
  1239. return( nNewLength );
  1240. }
  1241. // Replace all occurrences of character 'chOld' with character 'chNew'
  1242. int Replace( __in XCHAR chOld, __in XCHAR chNew )
  1243. {
  1244. int nCount = 0;
  1245. // short-circuit the nop case
  1246. if( chOld != chNew )
  1247. {
  1248. // otherwise modify each character that matches in the string
  1249. bool bCopied = false;
  1250. PXSTR pszBuffer = const_cast< PXSTR >( GetString() );  // We don't actually write to pszBuffer until we've called GetBuffer().
  1251. int nLength = GetLength();
  1252. int iChar = 0;
  1253. while( iChar < nLength )
  1254. {
  1255. // replace instances of the specified character only
  1256. if( pszBuffer[iChar] == chOld )
  1257. {
  1258. if( !bCopied )
  1259. {
  1260. bCopied = true;
  1261. pszBuffer = GetBuffer( nLength );
  1262. }
  1263. pszBuffer[iChar] = chNew;
  1264. nCount++;
  1265. }
  1266. iChar = int( StringTraits::CharNext( pszBuffer+iChar )-pszBuffer );
  1267. }
  1268. if( bCopied )
  1269. {
  1270. ReleaseBufferSetLength( nLength );
  1271. }
  1272. }
  1273. return( nCount );
  1274. }
  1275. // Replace all occurrences of string 'pszOld' with string 'pszNew'
  1276. int Replace( __in PCXSTR pszOld, __in PCXSTR pszNew )
  1277. {
  1278. // can't have empty or NULL lpszOld
  1279. // nSourceLen is in XCHARs
  1280. int nSourceLen = StringTraits::SafeStringLen( pszOld );
  1281. if( nSourceLen == 0 )
  1282. return( 0 );
  1283. // nReplacementLen is in XCHARs
  1284. int nReplacementLen = StringTraits::SafeStringLen( pszNew );
  1285. // loop once to figure out the size of the result string
  1286. int nCount = 0;
  1287. {
  1288. PCXSTR pszStart = GetString();
  1289. PCXSTR pszEnd = pszStart+GetLength();
  1290. while( pszStart < pszEnd )
  1291. {
  1292. PCXSTR pszTarget;
  1293. while( (pszTarget = StringTraits::StringFindString( pszStart, pszOld ) ) != NULL)
  1294. {
  1295. nCount++;
  1296. pszStart = pszTarget+nSourceLen;
  1297. }
  1298. pszStart += StringTraits::SafeStringLen( pszStart )+1;
  1299. }
  1300. }
  1301. // if any changes were made, make them
  1302. if( nCount > 0 )
  1303. {
  1304. // if the buffer is too small, just
  1305. //   allocate a new buffer (slow but sure)
  1306. int nOldLength = GetLength();
  1307. int nNewLength = nOldLength+(nReplacementLen-nSourceLen)*nCount;
  1308. PXSTR pszBuffer = GetBuffer( __max( nNewLength, nOldLength ) );
  1309. PXSTR pszStart = pszBuffer;
  1310. PXSTR pszEnd = pszStart+nOldLength;
  1311. // loop again to actually do the work
  1312. while( pszStart < pszEnd )
  1313. {
  1314. PXSTR pszTarget;
  1315. while( (pszTarget = StringTraits::StringFindString( pszStart, pszOld ) ) != NULL )
  1316. {
  1317. int nBalance = nOldLength-int(pszTarget-pszBuffer+nSourceLen);
  1318.                     Checked::memmove_s( pszTarget+nReplacementLen, nBalance*sizeof( XCHAR ), 
  1319. pszTarget+nSourceLen, nBalance*sizeof( XCHAR ) );
  1320. Checked::memcpy_s( pszTarget, nReplacementLen*sizeof( XCHAR ), 
  1321. pszNew, nReplacementLen*sizeof( XCHAR ) );
  1322. pszStart = pszTarget+nReplacementLen;
  1323. pszTarget[nReplacementLen+nBalance] = 0;
  1324. nOldLength += (nReplacementLen-nSourceLen);
  1325. }
  1326. pszStart += StringTraits::SafeStringLen( pszStart )+1;
  1327. }
  1328. ATLASSERT( pszBuffer[nNewLength] == 0 );
  1329. ReleaseBufferSetLength( nNewLength );
  1330. }
  1331. return( nCount );
  1332. }
  1333. // Remove all occurrences of character 'chRemove'
  1334. int Remove( __in XCHAR chRemove )
  1335. {
  1336. int nLength = GetLength();
  1337. PXSTR pszBuffer = GetBuffer( nLength );
  1338. PXSTR pszSource = pszBuffer;
  1339. PXSTR pszDest = pszBuffer;
  1340. PXSTR pszEnd = pszBuffer+nLength;
  1341. while( pszSource < pszEnd )
  1342. {
  1343. PXSTR pszNewSource = StringTraits::CharNext( pszSource );
  1344. if( *pszSource != chRemove )
  1345. {
  1346. // Copy the source to the destination.  Remember to copy all bytes of an MBCS character
  1347.     // Copy the source to the destination.  Remember to copy all bytes of an MBCS character
  1348. size_t NewSourceGap = (pszNewSource-pszSource);
  1349. PXSTR pszNewDest = pszDest + NewSourceGap;
  1350. size_t i = 0;
  1351. for (i = 0;  pszDest != pszNewDest && i < NewSourceGap; i++)
  1352. {
  1353. *pszDest = *pszSource;
  1354. pszSource++;
  1355. pszDest++;
  1356. }
  1357. }
  1358. pszSource = pszNewSource;
  1359. }
  1360. *pszDest = 0;
  1361. int nCount = int( pszSource-pszDest );
  1362. ReleaseBufferSetLength( nLength-nCount );
  1363. return( nCount );
  1364. }
  1365. CStringT Tokenize( __in PCXSTR pszTokens, __inout int& iStart ) const
  1366. {
  1367. ATLASSERT( iStart >= 0 );
  1368. if(iStart < 0)
  1369. AtlThrow(E_INVALIDARG);
  1370. if( (pszTokens == NULL) || (*pszTokens == (XCHAR)0) )
  1371. {
  1372. if (iStart < GetLength())
  1373. {
  1374. return( CStringT( GetString()+iStart, GetManager() ) );
  1375. }
  1376. }
  1377. else
  1378. {
  1379. PCXSTR pszPlace = GetString()+iStart;
  1380. PCXSTR pszEnd = GetString()+GetLength();
  1381. if( pszPlace < pszEnd )
  1382. {
  1383. int nIncluding = StringTraits::StringSpanIncluding( pszPlace,
  1384. pszTokens );
  1385. if( (pszPlace+nIncluding) < pszEnd )
  1386. {
  1387. pszPlace += nIncluding;
  1388. int nExcluding = StringTraits::StringSpanExcluding( pszPlace, pszTokens );
  1389. int iFrom = iStart+nIncluding;
  1390. int nUntil = nExcluding;
  1391. iStart = iFrom+nUntil+1;
  1392. return( Mid( iFrom, nUntil ) );
  1393. }
  1394. }
  1395. }
  1396. // return empty string, done tokenizing
  1397. iStart = -1;
  1398. return( CStringT( GetManager() ) );
  1399. }
  1400. // find routines
  1401. // Find the first occurrence of character 'ch', starting at index 'iStart'
  1402. int Find( __in XCHAR ch, __in int iStart = 0 ) const throw()
  1403. {
  1404. // iStart is in XCHARs
  1405. ATLASSERT( iStart >= 0 );
  1406. // nLength is in XCHARs
  1407. int nLength = GetLength();
  1408. if( iStart < 0 || iStart >= nLength)
  1409. {
  1410. return( -1 );
  1411. }
  1412. // find first single character
  1413. PCXSTR psz = StringTraits::StringFindChar( GetString()+iStart, ch );
  1414. // return -1 if not found and index otherwise
  1415. return( (psz == NULL) ? -1 : int( psz-GetString() ) );
  1416. }
  1417. // look for a specific sub-string
  1418. // Find the first occurrence of string 'pszSub', starting at index 'iStart'
  1419. int Find( __in PCXSTR pszSub, __in int iStart = 0 ) const throw()
  1420. {
  1421. // iStart is in XCHARs
  1422. ATLASSERT( iStart >= 0 );
  1423. ATLASSERT( AtlIsValidString( pszSub ) );
  1424. if(pszSub == NULL)
  1425. {
  1426. return( -1 );
  1427. }
  1428. // nLength is in XCHARs
  1429. int nLength = GetLength();
  1430. if( iStart < 0 || iStart > nLength )
  1431. {
  1432. return( -1 );
  1433. }
  1434. // find first matching substring
  1435. PCXSTR psz = StringTraits::StringFindString( GetString()+iStart, pszSub );
  1436. // return -1 for not found, distance from beginning otherwise
  1437. return( (psz == NULL) ? -1 : int( psz-GetString() ) );
  1438. }
  1439. // Find the first occurrence of any of the characters in string 'pszCharSet'
  1440. int FindOneOf( __in PCXSTR pszCharSet ) const throw()
  1441. {
  1442. ATLASSERT( AtlIsValidString( pszCharSet ) );
  1443. PCXSTR psz = StringTraits::StringScanSet( GetString(), pszCharSet );
  1444. return( (psz == NULL) ? -1 : int( psz-GetString() ) );
  1445. }
  1446. // Find the last occurrence of character 'ch'
  1447. int ReverseFind( __in XCHAR ch ) const throw()
  1448. {
  1449. // find last single character
  1450. PCXSTR psz = StringTraits::StringFindCharRev( GetString(), ch );
  1451. // return -1 if not found, distance from beginning otherwise
  1452. return( (psz == NULL) ? -1 : int( psz-GetString() ) );
  1453. }
  1454. // manipulation
  1455. // Convert the string to uppercase
  1456. CStringT& MakeUpper()
  1457. {
  1458. int nLength = GetLength();
  1459. PXSTR pszBuffer = GetBuffer( nLength );
  1460. StringTraits::StringUppercase( pszBuffer, nLength+1 );
  1461. ReleaseBufferSetLength( nLength );
  1462. return( *this );
  1463. }
  1464. // Convert the string to lowercase
  1465. CStringT& MakeLower()
  1466. {
  1467. int nLength = GetLength();
  1468. PXSTR pszBuffer = GetBuffer( nLength );
  1469. StringTraits::StringLowercase( pszBuffer, nLength+1 );
  1470. ReleaseBufferSetLength( nLength );
  1471. return( *this );
  1472. }
  1473. // Reverse the string
  1474. CStringT& MakeReverse()
  1475. {
  1476. int nLength = GetLength();
  1477. PXSTR pszBuffer = GetBuffer( nLength );
  1478. StringTraits::StringReverse( pszBuffer );
  1479. ReleaseBufferSetLength( nLength );
  1480. return( *this );
  1481. }
  1482. // trimming
  1483. // Remove all trailing whitespace
  1484. CStringT& TrimRight()
  1485. {
  1486. // find beginning of trailing spaces by starting
  1487. // at beginning (DBCS aware)
  1488. PCXSTR psz = GetString();
  1489. PCXSTR pszLast = NULL;
  1490. while( *psz != 0 )
  1491. {
  1492. if( StringTraits::IsSpace( *psz ) )
  1493. {
  1494. if( pszLast == NULL )
  1495. pszLast = psz;
  1496. }
  1497. else
  1498. {
  1499. pszLast = NULL;
  1500. }
  1501. psz = StringTraits::CharNext( psz );
  1502. }
  1503. if( pszLast != NULL )
  1504. {
  1505. // truncate at trailing space start
  1506. int iLast = int( pszLast-GetString() );
  1507. Truncate( iLast );
  1508. }
  1509. return( *this );
  1510. }
  1511. // Remove all leading whitespace
  1512. CStringT& TrimLeft()
  1513. {
  1514. // find first non-space character
  1515. PCXSTR psz = GetString();
  1516. while( StringTraits::IsSpace( *psz ) )
  1517. {
  1518. psz = StringTraits::CharNext( psz );
  1519. }
  1520. if( psz != GetString() )
  1521. {
  1522. // fix up data and length
  1523. int iFirst = int( psz-GetString() );
  1524. PXSTR pszBuffer = GetBuffer( GetLength() );
  1525. psz = pszBuffer+iFirst;
  1526. int nDataLength = GetLength()-iFirst;
  1527.             Checked::memmove_s( pszBuffer, (nDataLength+1)*sizeof( XCHAR ), 
  1528. psz, (nDataLength+1)*sizeof( XCHAR ) );
  1529. ReleaseBufferSetLength( nDataLength );
  1530. }
  1531. return( *this );
  1532. }
  1533. // Remove all leading and trailing whitespace
  1534. CStringT& Trim()
  1535. {
  1536. return( TrimRight().TrimLeft() );
  1537. }
  1538. // Remove all leading and trailing occurrences of character 'chTarget'
  1539. CStringT& Trim( __in XCHAR chTarget )
  1540. {
  1541. return( TrimRight( chTarget ).TrimLeft( chTarget ) );
  1542. }
  1543. // Remove all leading and trailing occurrences of any of the characters in the string 'pszTargets'
  1544. CStringT& Trim( __in PCXSTR pszTargets )
  1545. {
  1546. return( TrimRight( pszTargets ).TrimLeft( pszTargets ) );
  1547. }
  1548. // trimming anything (either side)
  1549. // Remove all trailing occurrences of character 'chTarget'
  1550. CStringT& TrimRight( __in XCHAR chTarget )
  1551. {
  1552. // find beginning of trailing matches
  1553. // by starting at beginning (DBCS aware)
  1554. PCXSTR psz = GetString();
  1555. PCXSTR pszLast = NULL;
  1556. while( *psz != 0 )
  1557. {
  1558. if( *psz == chTarget )
  1559. {
  1560. if( pszLast == NULL )
  1561. {
  1562. pszLast = psz;
  1563. }
  1564. }
  1565. else
  1566. {
  1567. pszLast = NULL;
  1568. }
  1569. psz = StringTraits::CharNext( psz );
  1570. }
  1571. if( pszLast != NULL )
  1572. {
  1573. // truncate at left-most matching character  
  1574. int iLast = int( pszLast-GetString() );
  1575. Truncate( iLast );
  1576. }
  1577. return( *this );
  1578. }
  1579. // Remove all trailing occurrences of any of the characters in string 'pszTargets'
  1580. CStringT& TrimRight( __in PCXSTR pszTargets )
  1581. {
  1582. // if we're not trimming anything, we're not doing any work
  1583. if( (pszTargets == NULL) || (*pszTargets == 0) )
  1584. {
  1585. return( *this );
  1586. }
  1587. // find beginning of trailing matches
  1588. // by starting at beginning (DBCS aware)
  1589. PCXSTR psz = GetString();
  1590. PCXSTR pszLast = NULL;
  1591. while( *psz != 0 )
  1592. {
  1593. if( StringTraits::StringFindChar( pszTargets, *psz ) != NULL )
  1594. {
  1595. if( pszLast == NULL )
  1596. {
  1597. pszLast = psz;
  1598. }
  1599. }
  1600. else
  1601. {
  1602. pszLast = NULL;
  1603. }
  1604. psz = StringTraits::CharNext( psz );
  1605. }
  1606. if( pszLast != NULL )
  1607. {
  1608. // truncate at left-most matching character  
  1609. int iLast = int( pszLast-GetString() );
  1610. Truncate( iLast );
  1611. }
  1612. return( *this );
  1613. }
  1614. // Remove all leading occurrences of character 'chTarget'
  1615. CStringT& TrimLeft( __in XCHAR chTarget )
  1616. {
  1617. // find first non-matching character
  1618. PCXSTR psz = GetString();
  1619. while( chTarget == *psz )
  1620. {
  1621. psz = StringTraits::CharNext( psz );
  1622. }
  1623. if( psz != GetString() )
  1624. {
  1625. // fix up data and length
  1626. int iFirst = int( psz-GetString() );
  1627. PXSTR pszBuffer = GetBuffer( GetLength() );
  1628. psz = pszBuffer+iFirst;
  1629. int nDataLength = GetLength()-iFirst;
  1630.             Checked::memmove_s( pszBuffer, (nDataLength+1)*sizeof( XCHAR ), 
  1631. psz, (nDataLength+1)*sizeof( XCHAR ) );
  1632. ReleaseBufferSetLength( nDataLength );
  1633. }
  1634. return( *this );
  1635. }
  1636. // Remove all leading occurrences of any of the characters in string 'pszTargets'
  1637. CStringT& TrimLeft( __in PCXSTR pszTargets )
  1638. {
  1639. // if we're not trimming anything, we're not doing any work
  1640. if( (pszTargets == NULL) || (*pszTargets == 0) )
  1641. {
  1642. return( *this );
  1643. }
  1644. PCXSTR psz = GetString();
  1645. while( (*psz != 0) && (StringTraits::StringFindChar( pszTargets, *psz ) != NULL) )
  1646. {
  1647. psz = StringTraits::CharNext( psz );
  1648. }
  1649. if( psz != GetString() )
  1650. {
  1651. // fix up data and length
  1652. int iFirst = int( psz-GetString() );
  1653. PXSTR pszBuffer = GetBuffer( GetLength() );
  1654. psz = pszBuffer+iFirst;
  1655. int nDataLength = GetLength()-iFirst;
  1656.             Checked::memmove_s( pszBuffer, (nDataLength+1)*sizeof( XCHAR ), 
  1657. psz, (nDataLength+1)*sizeof( XCHAR ) );
  1658. ReleaseBufferSetLength( nDataLength );
  1659. }
  1660. return( *this );
  1661. }
  1662. // Convert the string to the OEM character set
  1663. void AnsiToOem()
  1664. {
  1665. int nLength = GetLength();
  1666. PXSTR pszBuffer = GetBuffer( nLength );
  1667. StringTraits::ConvertToOem( pszBuffer, nLength+1 );
  1668. ReleaseBufferSetLength( nLength );
  1669. }
  1670. // Convert the string to the ANSI character set
  1671. void OemToAnsi()
  1672. {
  1673. int nLength = GetLength();
  1674. PXSTR pszBuffer = GetBuffer( nLength );
  1675. StringTraits::ConvertToAnsi( pszBuffer, nLength+1 );
  1676. ReleaseBufferSetLength( nLength );
  1677. }
  1678. // Very simple sub-string extraction
  1679. // Return the substring starting at index 'iFirst'
  1680. CStringT Mid( __in int iFirst ) const
  1681. {
  1682. return( Mid( iFirst, GetLength()-iFirst ) );
  1683. }
  1684. // Return the substring starting at index 'iFirst', with length 'nCount'
  1685. CStringT Mid( __in int iFirst, __in int nCount ) const
  1686. {
  1687. // nCount is in XCHARs
  1688. // out-of-bounds requests return sensible things
  1689. if (iFirst < 0)
  1690. iFirst = 0;
  1691. if (nCount < 0)
  1692. nCount = 0;
  1693. if( (::ATL::AtlAddThrow(iFirst,nCount)) > GetLength() )
  1694. {
  1695. nCount = GetLength()-iFirst;
  1696. }
  1697. if( iFirst > GetLength() )
  1698. {
  1699. nCount = 0;
  1700. }
  1701. ATLASSERT( (nCount == 0) || ((iFirst+nCount) <= GetLength()) );
  1702. // optimize case of returning entire string
  1703. if( (iFirst == 0) && ((iFirst+nCount) == GetLength()) )
  1704. {
  1705. return( *this );
  1706. }
  1707. return( CStringT( GetString()+iFirst, nCount, GetManager() ) );
  1708. }
  1709. // Return the substring consisting of the rightmost 'nCount' characters
  1710. CStringT Right( __in int nCount ) const
  1711. {
  1712. // nCount is in XCHARs
  1713. if (nCount < 0)
  1714. nCount = 0;
  1715. int nLength = GetLength();
  1716. if( nCount >= nLength )
  1717. {
  1718. return( *this );
  1719. }
  1720. return( CStringT( GetString()+nLength-nCount, nCount, GetManager() ) );
  1721. }
  1722. // Return the substring consisting of the leftmost 'nCount' characters
  1723. CStringT Left( __in int nCount ) const
  1724. {
  1725. // nCount is in XCHARs
  1726. if (nCount < 0)
  1727. nCount = 0;
  1728. int nLength = GetLength();
  1729. if( nCount >= nLength )
  1730. {
  1731. return( *this );
  1732. }
  1733. return( CStringT( GetString(), nCount, GetManager() ) );
  1734. }
  1735. // Return the substring consisting of the leftmost characters in the set 'pszCharSet'
  1736. CStringT SpanIncluding( __in PCXSTR pszCharSet ) const
  1737. {
  1738. ATLASSERT( AtlIsValidString( pszCharSet ) );
  1739. if(pszCharSet == NULL)
  1740. AtlThrow(E_INVALIDARG);
  1741. return( Left( StringTraits::StringSpanIncluding( GetString(), pszCharSet ) ) );
  1742. }
  1743. // Return the substring consisting of the leftmost characters not in the set 'pszCharSet'
  1744. CStringT SpanExcluding( __in PCXSTR pszCharSet ) const
  1745. {
  1746. ATLASSERT( AtlIsValidString( pszCharSet ) );
  1747. if(pszCharSet == NULL)
  1748. AtlThrow(E_INVALIDARG);
  1749. return( Left( StringTraits::StringSpanExcluding( GetString(), pszCharSet ) ) );
  1750.   }
  1751. // Format data using format string 'pszFormat'
  1752. void __cdecl Format( __in __format_string PCXSTR pszFormat, ... );
  1753. // Format data using format string loaded from resource 'nFormatID'
  1754. void __cdecl Format( __format_string UINT nFormatID, ... );
  1755. // Append formatted data using format string loaded from resource 'nFormatID'
  1756. void __cdecl AppendFormat( __in UINT nFormatID, ... );
  1757. // Append formatted data using format string 'pszFormat'
  1758. void __cdecl AppendFormat( __in __format_string PCXSTR pszFormat, ... );
  1759. void AppendFormatV( __in __format_string PCXSTR pszFormat, va_list args )
  1760. {
  1761. ATLASSERT( AtlIsValidString( pszFormat ) );
  1762. int nCurrentLength = GetLength();
  1763. int nAppendLength = StringTraits::GetFormattedLength( pszFormat, args );
  1764. PXSTR pszBuffer = GetBuffer( nCurrentLength+nAppendLength );
  1765. #if _SECURE_ATL
  1766.         StringTraits::Format( pszBuffer+nCurrentLength, 
  1767. nAppendLength+1, pszFormat, args );
  1768. #else
  1769. StringTraits::Format( pszBuffer+nCurrentLength, pszFormat, args );
  1770. #endif
  1771. ReleaseBufferSetLength( nCurrentLength+nAppendLength );
  1772. }
  1773. void FormatV( __in __format_string PCXSTR pszFormat, va_list args )
  1774. {
  1775. ATLASSERT( AtlIsValidString( pszFormat ) );
  1776. if(pszFormat == NULL)
  1777. AtlThrow(E_INVALIDARG);
  1778. int nLength = StringTraits::GetFormattedLength( pszFormat, args );
  1779. PXSTR pszBuffer = GetBuffer( nLength );
  1780. #if _SECURE_ATL
  1781.         StringTraits::Format( pszBuffer, nLength+1, pszFormat, args );
  1782. #else
  1783. StringTraits::Format( pszBuffer, pszFormat, args );
  1784. #endif
  1785. ReleaseBufferSetLength( nLength );
  1786. }
  1787. // Format a message using format string 'pszFormat'
  1788. void __cdecl _AFX_FUNCNAME(FormatMessage)( __in __format_string PCXSTR pszFormat, ... );
  1789. // Format a message using format string loaded from resource 'nFormatID'
  1790. void __cdecl _AFX_FUNCNAME(FormatMessage)( __in UINT nFormatID, ... );
  1791. #if defined(_AFX)
  1792. void __cdecl FormatMessage( __in __format_string PCXSTR pszFormat, ... );
  1793. void __cdecl FormatMessage( __in UINT nFormatID, ... );
  1794. #endif
  1795. // Format a message using format string 'pszFormat' and va_list
  1796. void FormatMessageV( __in __format_string PCXSTR pszFormat, va_list* pArgList )
  1797. {
  1798. // format message into temporary buffer pszTemp
  1799. CHeapPtr< XCHAR, CLocalAllocator > pszTemp;
  1800. DWORD dwResult = StringTraits::_AFX_FUNCNAME(FormatMessage)( FORMAT_MESSAGE_FROM_STRING|
  1801. FORMAT_MESSAGE_ALLOCATE_BUFFER, pszFormat, 0, 0, reinterpret_cast< PXSTR >( &pszTemp ),
  1802. 0, pArgList );
  1803. if( dwResult == 0 )
  1804. {
  1805. ThrowMemoryException();
  1806. }
  1807. *this = pszTemp;
  1808. }
  1809. // OLE BSTR support
  1810. // Allocate a BSTR containing a copy of the string
  1811. BSTR AllocSysString() const
  1812. {
  1813. BSTR bstrResult = StringTraits::AllocSysString( GetString(), GetLength() );
  1814. #pragma warning(push)
  1815. #pragma warning(disable:4068)
  1816. #pragma prefast(push)
  1817. #pragma prefast(disable:325, "We are deliberately checking if this has already been allocated")
  1818. if( bstrResult == NULL )
  1819. {
  1820. ThrowMemoryException();
  1821. }
  1822. #pragma prefast(pop)
  1823. #pragma warning(pop)
  1824. return( bstrResult );
  1825. }
  1826. BSTR SetSysString( __out BSTR* pbstr ) const
  1827. {
  1828. ATLASSERT( AtlIsValidAddress( pbstr, sizeof( BSTR ) ) );
  1829. if( !StringTraits::ReAllocSysString( GetString(), pbstr,
  1830. GetLength() ) )
  1831. {
  1832. ThrowMemoryException();
  1833. }
  1834. #pragma warning(push)
  1835. #pragma warning(disable:4068)
  1836. #pragma prefast(push)
  1837. #pragma prefast(disable:325, "We are deliberately checking if this has already been allocated")
  1838. ATLASSERT( *pbstr != NULL );
  1839. #pragma prefast(pop)
  1840. #pragma warning(pop)
  1841.         return( *pbstr );
  1842. }
  1843. // Set the string to the value of environment variable 'pszVar'
  1844. __checkReturn BOOL GetEnvironmentVariable( __in PCXSTR pszVar )
  1845. {
  1846. ULONG nLength = StringTraits::GetEnvironmentVariable( pszVar, NULL, 0 );
  1847. BOOL bRetVal = FALSE;
  1848. if( nLength == 0 )
  1849. {
  1850. Empty();
  1851. }
  1852. else
  1853. {
  1854. PXSTR pszBuffer = GetBuffer( nLength );
  1855. StringTraits::GetEnvironmentVariable( pszVar, pszBuffer, nLength );
  1856. ReleaseBuffer();
  1857. bRetVal = TRUE;
  1858. }
  1859. return( bRetVal );
  1860. }
  1861. // Load the string from resource 'nID'
  1862. __checkReturn BOOL LoadString( __in UINT nID )
  1863. {
  1864. HINSTANCE hInst = StringTraits::FindStringResourceInstance( nID );
  1865. if( hInst == NULL )
  1866. {
  1867. return( FALSE );
  1868. }
  1869. return( LoadString( hInst, nID ) );
  1870. }
  1871. // Load the string from resource 'nID' in module 'hInstance'
  1872. __checkReturn BOOL LoadString( __in HINSTANCE hInstance, __in UINT nID )
  1873. {
  1874. const ATLSTRINGRESOURCEIMAGE* pImage = AtlGetStringResourceImage( hInstance, nID );
  1875. if( pImage == NULL )
  1876. {
  1877. return( FALSE );
  1878. }
  1879. int nLength = StringTraits::GetBaseTypeLength( pImage->achString, pImage->nLength );
  1880. PXSTR pszBuffer = GetBuffer( nLength );
  1881. StringTraits::ConvertToBaseType( pszBuffer, nLength, pImage->achString, pImage->nLength );
  1882. ReleaseBufferSetLength( nLength );
  1883. return( TRUE );
  1884. }
  1885. // Load the string from resource 'nID' in module 'hInstance', using language 'wLanguageID'
  1886. __checkReturn BOOL LoadString( __in HINSTANCE hInstance, __in UINT nID, __in WORD wLanguageID )
  1887. {
  1888. const ATLSTRINGRESOURCEIMAGE* pImage = AtlGetStringResourceImage( hInstance, nID, wLanguageID );
  1889. if( pImage == NULL )
  1890. {
  1891. return( FALSE );
  1892. }
  1893. int nLength = StringTraits::GetBaseTypeLength( pImage->achString, pImage->nLength );
  1894. PXSTR pszBuffer = GetBuffer( nLength );
  1895. StringTraits::ConvertToBaseType( pszBuffer, nLength, pImage->achString, pImage->nLength );
  1896. ReleaseBufferSetLength( nLength );
  1897. return( TRUE );
  1898. }
  1899. friend CStringT operator+( __in const CStringT& str1, __in const CStringT& str2 )
  1900. {
  1901. CStringT strResult( str1.GetManager() );
  1902. Concatenate( strResult, str1, str1.GetLength(), str2, str2.GetLength() );
  1903. return( strResult );
  1904. }
  1905. friend CStringT operator+( __in const CStringT& str1, __in PCXSTR psz2 )
  1906. {
  1907. CStringT strResult( str1.GetManager() );
  1908. Concatenate( strResult, str1, str1.GetLength(), psz2, StringLength( psz2 ) );
  1909. return( strResult );
  1910. }
  1911. friend CStringT operator+( __in PCXSTR psz1, __in const CStringT& str2 )
  1912. {
  1913. CStringT strResult( str2.GetManager() );
  1914. Concatenate( strResult, psz1, StringLength( psz1 ), str2, str2.GetLength() );
  1915. return( strResult );
  1916. }
  1917. friend CStringT operator+( __in const CStringT& str1, __in wchar_t ch2 )
  1918. {
  1919. CStringT strResult( str1.GetManager() );
  1920. XCHAR chTemp = XCHAR( ch2 );
  1921. Concatenate( strResult, str1, str1.GetLength(), &chTemp, 1 );
  1922. return( strResult );
  1923. }
  1924. friend CStringT operator+( __in const CStringT& str1, __in char ch2 )
  1925. {
  1926. CStringT strResult( str1.GetManager() );
  1927. XCHAR chTemp = XCHAR( ch2 );
  1928. Concatenate( strResult, str1, str1.GetLength(), &chTemp, 1 );
  1929. return( strResult );
  1930. }
  1931. friend CStringT operator+( __in wchar_t ch1, __in const CStringT& str2 )
  1932. {
  1933. CStringT strResult( str2.GetManager() );
  1934. XCHAR chTemp = XCHAR( ch1 );
  1935. Concatenate( strResult, &chTemp, 1, str2, str2.GetLength() );
  1936. return( strResult );
  1937. }
  1938. friend CStringT operator+( __in char ch1, __in const CStringT& str2 )
  1939. {
  1940. CStringT strResult( str2.GetManager() );
  1941. XCHAR chTemp = XCHAR( ch1 );
  1942. Concatenate( strResult, &chTemp, 1, str2, str2.GetLength() );
  1943. return( strResult );
  1944. }
  1945. friend bool operator==( __in const CStringT& str1, __in const CStringT& str2 ) throw()
  1946. {
  1947. return( str1.Compare( str2 ) == 0 );
  1948. }
  1949. friend bool operator==(
  1950. __in const CStringT& str1, __in PCXSTR psz2 ) throw()
  1951. {
  1952. return( str1.Compare( psz2 ) == 0 );
  1953. }
  1954. friend bool operator==(
  1955. __in PCXSTR psz1, __in const CStringT& str2 ) throw()
  1956. {
  1957. return( str2.Compare( psz1 ) == 0 );
  1958. }
  1959. friend bool operator==(
  1960. __in const CStringT& str1, __in PCYSTR psz2 ) throw( ... )
  1961. {
  1962. CStringT str2( psz2, str1.GetManager() );
  1963. return( str1 == str2 );
  1964. }
  1965. friend bool operator==(
  1966. __in PCYSTR psz1, __in const CStringT& str2 ) throw( ... )
  1967. {
  1968. CStringT str1( psz1, str2.GetManager() );
  1969. return( str1 == str2 );
  1970. }
  1971. friend bool operator!=(
  1972. __in const CStringT& str1, __in const CStringT& str2 ) throw()
  1973. {
  1974. return( str1.Compare( str2 ) != 0 );
  1975. }
  1976. friend bool operator!=(
  1977. __in const CStringT& str1, __in PCXSTR psz2 ) throw()
  1978. {
  1979. return( str1.Compare( psz2 ) != 0 );
  1980. }
  1981. friend bool operator!=(
  1982. __in PCXSTR psz1, __in const CStringT& str2 ) throw()
  1983. {
  1984. return( str2.Compare( psz1 ) != 0 );
  1985. }
  1986. friend bool operator!=(
  1987. __in const CStringT& str1, __in PCYSTR psz2 ) throw( ... )
  1988. {
  1989. CStringT str2( psz2, str1.GetManager() );
  1990. return( str1 != str2 );
  1991. }
  1992. friend bool operator!=(
  1993. __in PCYSTR psz1, __in const CStringT& str2 ) throw( ... )
  1994. {
  1995. CStringT str1( psz1, str2.GetManager() );
  1996. return( str1 != str2 );
  1997. }
  1998. friend bool operator<( __in const CStringT& str1, __in const CStringT& str2 ) throw()
  1999. {
  2000. return( str1.Compare( str2 ) < 0 );
  2001. }
  2002. friend bool operator<( __in const CStringT& str1, __in PCXSTR psz2 ) throw()
  2003. {
  2004. return( str1.Compare( psz2 ) < 0 );
  2005. }
  2006. friend bool operator<( __in PCXSTR psz1, __in const CStringT& str2 ) throw()
  2007. {
  2008. return( str2.Compare( psz1 ) > 0 );
  2009. }
  2010. friend bool operator>( __in const CStringT& str1, __in const CStringT& str2 ) throw()
  2011. {
  2012. return( str1.Compare( str2 ) > 0 );
  2013. }
  2014. friend bool operator>( __in const CStringT& str1, __in PCXSTR psz2 ) throw()
  2015. {
  2016. return( str1.Compare( psz2 ) > 0 );
  2017. }
  2018. friend bool operator>( __in PCXSTR psz1, __in const CStringT& str2 ) throw()
  2019. {
  2020. return( str2.Compare( psz1 ) < 0 );
  2021. }
  2022. friend bool operator<=( __in const CStringT& str1, __in const CStringT& str2 ) throw()
  2023. {
  2024. return( str1.Compare( str2 ) <= 0 );
  2025. }
  2026. friend bool operator<=( __in const CStringT& str1, __in PCXSTR psz2 ) throw()
  2027. {
  2028. return( str1.Compare( psz2 ) <= 0 );
  2029. }
  2030. friend bool operator<=( __in PCXSTR psz1, __in const CStringT& str2 ) throw()
  2031. {
  2032. return( str2.Compare( psz1 ) >= 0 );
  2033. }
  2034. friend bool operator>=( __in const CStringT& str1, __in const CStringT& str2 ) throw()
  2035. {
  2036. return( str1.Compare( str2 ) >= 0 );
  2037. }
  2038. friend bool operator>=( __in const CStringT& str1, __in PCXSTR psz2 ) throw()
  2039. {
  2040. return( str1.Compare( psz2 ) >= 0 );
  2041. }
  2042. friend bool operator>=( __in PCXSTR psz1, __in const CStringT& str2 ) throw()
  2043. {
  2044. return( str2.Compare( psz1 ) <= 0 );
  2045. }
  2046. friend bool operator==( __in XCHAR ch1, __in const CStringT& str2 ) throw()
  2047. {
  2048. return( (str2.GetLength() == 1) && (str2[0] == ch1) );
  2049. }
  2050. friend bool operator==( __in const CStringT& str1, __in XCHAR ch2 ) throw()
  2051. {
  2052. return( (str1.GetLength() == 1) && (str1[0] == ch2) );
  2053. }
  2054. friend bool operator!=( __in XCHAR ch1, __in const CStringT& str2 ) throw()
  2055. {
  2056. return( (str2.GetLength() != 1) || (str2[0] != ch1) );
  2057. }
  2058. friend bool operator!=( __in const CStringT& str1, __in XCHAR ch2 ) throw()
  2059. {
  2060. return( (str1.GetLength() != 1) || (str1[0] != ch2) );
  2061. }
  2062. private:
  2063. bool CheckImplicitLoad( __in_opt const void* pv )
  2064. {
  2065. bool bRet = false;
  2066. if( (pv != NULL) && IS_INTRESOURCE( pv ) )
  2067. {
  2068. UINT nID = LOWORD( reinterpret_cast< DWORD_PTR >( pv ) );
  2069. if( !LoadString( nID ) )
  2070. {
  2071. ATLTRACE( atlTraceString, 2, _T( "Warning: implicit LoadString(%u) failedn" ), nID );
  2072. }
  2073. bRet = true;
  2074. }
  2075. return( bRet );
  2076. }
  2077. };
  2078. #ifndef _CSTRING_BUFFER_SIZE
  2079. #define _CSTRING_BUFFER_SIZE(_CStringObj) ((_CStringObj).GetAllocLength() + 1)
  2080. #endif
  2081. #pragma warning(push)
  2082. #pragma warning(disable : 4793)
  2083. // Format data using format string 'pszFormat'
  2084. template< typename BaseType, class StringTraits >
  2085. inline void __cdecl CStringT<BaseType, StringTraits>::Format( __in __format_string PCXSTR pszFormat, ... )
  2086. {
  2087. ATLASSERT( AtlIsValidString( pszFormat ) );
  2088. va_list argList;
  2089. va_start( argList, pszFormat );
  2090. FormatV( pszFormat, argList );
  2091. va_end( argList );
  2092. }
  2093. // Format data using format string loaded from resource 'nFormatID'
  2094. template< typename BaseType, class StringTraits >
  2095. inline void __cdecl CStringT<BaseType, StringTraits>::Format( __format_string UINT nFormatID, ... )
  2096. {
  2097. CStringT strFormat( GetManager() );
  2098. ATLVERIFY( strFormat.LoadString( nFormatID ) );
  2099. va_list argList;
  2100. va_start( argList, nFormatID );
  2101. FormatV( strFormat, argList );
  2102. va_end( argList );
  2103. }
  2104. // Append formatted data using format string loaded from resource 'nFormatID'
  2105. template< typename BaseType, class StringTraits >
  2106. inline void __cdecl CStringT<BaseType, StringTraits>::AppendFormat( __in UINT nFormatID, ... )
  2107. {
  2108. va_list argList;
  2109. va_start( argList, nFormatID );
  2110. CStringT strFormat( GetManager() );
  2111. ATLVERIFY( strFormat.LoadString( nFormatID ) ); 
  2112. AppendFormatV( strFormat, argList );
  2113. va_end( argList );
  2114. }
  2115. // Append formatted data using format string 'pszFormat'
  2116. template< typename BaseType, class StringTraits >
  2117. inline void __cdecl CStringT<BaseType, StringTraits>::AppendFormat( __in __format_string PCXSTR pszFormat, ... )
  2118. {
  2119. ATLASSERT( AtlIsValidString( pszFormat ) );
  2120. va_list argList;
  2121. va_start( argList, pszFormat );
  2122. AppendFormatV( pszFormat, argList );
  2123. va_end( argList );
  2124. }
  2125. // Format a message using format string 'pszFormat'
  2126. template< typename BaseType, class StringTraits >
  2127. inline void __cdecl CStringT<BaseType, StringTraits>::_AFX_FUNCNAME(FormatMessage)( __in __format_string PCXSTR pszFormat, ... )
  2128. {
  2129. if(pszFormat == NULL)
  2130. AtlThrow(E_INVALIDARG);
  2131. va_list argList;
  2132. va_start( argList, pszFormat );
  2133. FormatMessageV( pszFormat, &argList );
  2134. va_end( argList );
  2135. }
  2136. #if defined(_AFX)
  2137. template< typename BaseType, class StringTraits >
  2138. inline void __cdecl CStringT<BaseType, StringTraits>::FormatMessage( __in __format_string PCXSTR pszFormat, ... )
  2139. {
  2140. if(pszFormat == NULL)
  2141. AtlThrow(E_INVALIDARG);
  2142. va_list argList;
  2143. va_start( argList, pszFormat );
  2144. FormatMessageV( pszFormat, &argList );
  2145. va_end( argList );
  2146. }
  2147. #endif
  2148. // Format a message using format string loaded from resource 'nFormatID'
  2149. template< typename BaseType, class StringTraits >
  2150. inline void __cdecl CStringT<BaseType, StringTraits>::_AFX_FUNCNAME(FormatMessage)( __in UINT nFormatID, ... )
  2151. {
  2152. // get format string from string table
  2153. CStringT strFormat( GetManager() );
  2154. ATLVERIFY( strFormat.LoadString( nFormatID ) );
  2155. if(strFormat.GetLength() == 0)
  2156. AtlThrow(E_INVALIDARG);
  2157. va_list argList;
  2158. va_start( argList, nFormatID );
  2159. FormatMessageV( strFormat, &argList );
  2160. va_end( argList );
  2161. }
  2162. #if defined(_AFX)
  2163. template< typename BaseType, class StringTraits >
  2164. inline void __cdecl CStringT<BaseType, StringTraits>::FormatMessage( __in UINT nFormatID, ... )
  2165. {
  2166. // get format string from string table
  2167. CStringT strFormat( GetManager() );
  2168. ATLVERIFY( strFormat.LoadString( nFormatID ) );
  2169. if(strFormat.GetLength() == 0)
  2170. AtlThrow(E_INVALIDARG);
  2171. va_list argList;
  2172. va_start( argList, nFormatID );
  2173. FormatMessageV( strFormat, &argList );
  2174. va_end( argList );
  2175. }
  2176. #endif
  2177. #pragma warning( pop )
  2178. class IFixedStringLog
  2179. {
  2180. public:
  2181. virtual void OnAllocateSpill( int nActualChars, int nFixedChars, const CStringData* pData ) throw() = 0;
  2182. virtual void OnReallocateSpill( int nActualChars, int nFixedChars, const CStringData* pData ) throw() = 0;
  2183. };
  2184. class CFixedStringMgr :
  2185. public IAtlStringMgr
  2186. {
  2187. public:
  2188. CFixedStringMgr( __in CStringData* pData, __in int nChars, __in_opt IAtlStringMgr* pMgr = NULL ) throw() :
  2189. m_pData( pData ),
  2190. m_pMgr( pMgr )
  2191. {
  2192. m_pData->nRefs = -1;
  2193. m_pData->nDataLength = 0;
  2194. m_pData->nAllocLength = nChars;
  2195. m_pData->pStringMgr = this;
  2196. *static_cast< wchar_t* >( m_pData->data() ) = 0;
  2197. }
  2198. virtual ~CFixedStringMgr() throw()
  2199. {
  2200. }
  2201. // IAtlStringMgr
  2202. public:
  2203. virtual CStringData* Allocate( __in int nChars, __in int nCharSize ) throw()
  2204. {
  2205. ATLASSUME( m_pData->nRefs == -1 );
  2206. ATLASSUME( m_pData->nDataLength == 0 );
  2207. if( nChars > m_pData->nAllocLength )
  2208. {
  2209. if( s_pLog != NULL )
  2210. {
  2211. s_pLog->OnAllocateSpill( nChars, m_pData->nAllocLength, m_pData );
  2212. }
  2213. CStringData* pData = m_pMgr->Allocate( nChars, nCharSize );
  2214. if( pData != NULL )
  2215. {
  2216. pData->pStringMgr = this;
  2217. pData->nRefs = -1;  // Locked
  2218. }
  2219. return pData;
  2220. }
  2221. m_pData->nRefs = -1;  // Locked
  2222. m_pData->nDataLength = 0;
  2223. m_pData->pStringMgr = this;
  2224. return m_pData;
  2225. }
  2226. virtual void Free( __inout CStringData* pData ) throw()
  2227. {
  2228. ATLASSERT( pData->nRefs <= 0 );
  2229. if( pData != m_pData )
  2230. {
  2231. // Must have been allocated from the backup manager
  2232. pData->pStringMgr = m_pMgr;
  2233. m_pMgr->Free( pData );
  2234. }
  2235. // Always make sure the fixed buffer is ready to be used as the nil string.
  2236. m_pData->nRefs = -1;
  2237. m_pData->nDataLength = 0;
  2238. *static_cast< wchar_t* >( m_pData->data() ) = 0;
  2239. }
  2240. virtual CStringData* Reallocate( __inout CStringData* pData, __in int nChars, __in int nCharSize ) throw()
  2241. {
  2242. CStringData* pNewData;
  2243. ATLASSERT( pData->nRefs < 0 );
  2244. if( pData != m_pData )
  2245. {
  2246. pData->pStringMgr = m_pMgr;
  2247. pNewData = m_pMgr->Reallocate( pData, nChars, nCharSize );
  2248. if( pNewData == NULL )
  2249. {
  2250. pData->pStringMgr = this;
  2251. }
  2252. else
  2253. {
  2254. pNewData->pStringMgr = this;
  2255. }
  2256. }
  2257. else
  2258. {
  2259. if( nChars > pData->nAllocLength )
  2260. {
  2261. if( s_pLog != NULL )
  2262. {
  2263. s_pLog->OnReallocateSpill( nChars, pData->nAllocLength, pData );
  2264. }
  2265. pNewData = m_pMgr->Allocate( nChars, nCharSize );
  2266. if( pNewData == NULL )
  2267. {
  2268. return NULL;
  2269. }
  2270. // Copy the string data 
  2271.                 Checked::memcpy_s( pNewData->data(), nChars*nCharSize, 
  2272. pData->data(), (pData->nAllocLength+1)*nCharSize );
  2273. pNewData->nRefs = pData->nRefs;  // Locked
  2274. pNewData->pStringMgr = this;
  2275. pNewData->nDataLength = pData->nDataLength;
  2276. }
  2277. else
  2278. {
  2279. // Don't do anything if the buffer is already big enough.
  2280. pNewData = pData;
  2281. }
  2282. }
  2283. return pNewData;
  2284. }
  2285. virtual CStringData* GetNilString() throw()
  2286. {
  2287. ATLASSUME( m_pData->nRefs == -1 );
  2288. ATLASSUME( m_pData->nDataLength == 0 );
  2289. return m_pData;
  2290. }
  2291. virtual IAtlStringMgr* Clone() throw()
  2292. {
  2293. return m_pMgr;
  2294. }
  2295. public:
  2296. static IFixedStringLog* s_pLog;
  2297. IAtlStringMgr* GetBackupManager() const throw()
  2298. {
  2299. return m_pMgr;
  2300. }
  2301. protected:
  2302. IAtlStringMgr* m_pMgr;
  2303. CStringData* m_pData;
  2304. };
  2305. __declspec( selectany ) IFixedStringLog* CFixedStringMgr::s_pLog = NULL;
  2306. #pragma warning( push )
  2307. #pragma warning( disable: 4355 )  // 'this' used in base member initializer list
  2308. template< class StringType, int t_nChars >
  2309. class CFixedStringT :
  2310. private CFixedStringMgr,  // This class must be first, since it needs to be initialized before StringType
  2311. public StringType
  2312. {
  2313. public:
  2314. CFixedStringT() throw() :
  2315. CFixedStringMgr( &m_data, t_nChars, StrTraits::GetDefaultManager() ),
  2316. StringType( static_cast< IAtlStringMgr* >( this ) )
  2317. {
  2318. }
  2319. explicit CFixedStringT( __in IAtlStringMgr* pStringMgr ) throw() :
  2320. CFixedStringMgr( &m_data, t_nChars, pStringMgr ),
  2321. StringType( static_cast< IAtlStringMgr* >( this ) )
  2322. {
  2323. }
  2324. CFixedStringT( __in const CFixedStringT< StringType, t_nChars >& str ) :
  2325. CFixedStringMgr( &m_data, t_nChars, StrTraits::GetDefaultManager() ),
  2326. StringType( str.GetString(), str.GetLength(), static_cast< CFixedStringMgr* >( this ) )
  2327. {
  2328. }
  2329. CFixedStringT( __in const StringType& str ) :
  2330. CFixedStringMgr( &m_data, t_nChars, StrTraits::GetDefaultManager() ),
  2331. StringType( str.GetString(), str.GetLength(), static_cast< CFixedStringMgr* >( this ) )
  2332. {
  2333. }
  2334. CFixedStringT( __in const typename StringType::XCHAR* psz ) :
  2335. CFixedStringMgr( &m_data, t_nChars, StrTraits::GetDefaultManager() ),
  2336. StringType( psz, static_cast< CFixedStringMgr* >( this ) )
  2337. {
  2338. }
  2339. CFixedStringT( __in_ecount(nLength) const typename StringType::XCHAR* psz, __in int nLength ) :
  2340. CFixedStringMgr( &m_data, t_nChars, StrTraits::GetDefaultManager() ),
  2341. StringType( psz, nLength, static_cast< CFixedStringMgr* >( this ) )
  2342. {
  2343. }
  2344. explicit CFixedStringT( __in const typename StringType::YCHAR* psz ) :
  2345. CFixedStringMgr( &m_data, t_nChars, StrTraits::GetDefaultManager() ),
  2346. StringType( psz, static_cast< CFixedStringMgr* >( this ) )
  2347. {
  2348. }
  2349. explicit CFixedStringT( __in const unsigned char* psz ) :
  2350. CFixedStringMgr( &m_data, t_nChars, StrTraits::GetDefaultManager() ),
  2351. StringType( psz, static_cast< CFixedStringMgr* >( this ) )
  2352. {
  2353. }
  2354. ~CFixedStringT() throw()
  2355. {
  2356. Empty();
  2357. }
  2358. CFixedStringT< StringType, t_nChars >& operator=( __in const CFixedStringT< StringType, t_nChars >& str )
  2359. {
  2360. StringType::operator=( str );
  2361. return *this;
  2362. }
  2363. CFixedStringT< StringType, t_nChars >& operator=( __in_z const char* psz )
  2364. {
  2365. StringType::operator=( psz );
  2366. return *this;
  2367. }
  2368. CFixedStringT< StringType, t_nChars >& operator=( __in_z const wchar_t* psz )
  2369. {
  2370. StringType::operator=( psz );
  2371. return *this;
  2372. }
  2373. CFixedStringT< StringType, t_nChars >& operator=( __in_z const unsigned char* psz )
  2374. {
  2375. StringType::operator=( psz );
  2376. return *this;
  2377. }
  2378. CFixedStringT< StringType, t_nChars >& operator=( __in const StringType& str )
  2379. {
  2380. StringType::operator=( str );
  2381. return *this;
  2382. }
  2383. // Implementation
  2384. protected:
  2385. CStringData m_data;
  2386. typename StringType::XCHAR m_achData[t_nChars+1];
  2387. };
  2388. #pragma warning( pop )
  2389. class CFixedStringLog :
  2390. public IFixedStringLog
  2391. {
  2392. public:
  2393. CFixedStringLog() throw()
  2394. {
  2395. CFixedStringMgr::s_pLog = this;
  2396. }
  2397. virtual ~CFixedStringLog() throw()
  2398. {
  2399. CFixedStringMgr::s_pLog = NULL;
  2400. }
  2401. public:
  2402. void OnAllocateSpill( __in int nActualChars, __in int nFixedChars, __in const CStringData* pData ) throw()
  2403. {
  2404. (void)nActualChars;
  2405. (void)nFixedChars;
  2406. (void)pData;
  2407. ATLTRACE( atlTraceString, 0, _T( "CFixedStringMgr::Allocate() spilling to heap.  %d chars (fixed size = %d chars)n" ), nActualChars, nFixedChars );
  2408. }
  2409. void OnReallocateSpill( __in int nActualChars, __in int nFixedChars, __in const CStringData* pData ) throw()
  2410. {
  2411. (void)nActualChars;
  2412. (void)nFixedChars;
  2413. (void)pData;
  2414. ATLTRACE( atlTraceString, 0, _T( "CFixedStringMgr::Reallocate() spilling to heap.  %d chars (fixed size = %d chars)n" ), nActualChars, nFixedChars );
  2415. }
  2416. };
  2417. template< typename T >
  2418. class CStringElementTraits
  2419. {
  2420. public:
  2421. typedef typename T::PCXSTR INARGTYPE;
  2422. typedef T& OUTARGTYPE;
  2423. static void __cdecl CopyElements( __out_ecount_full(nElements) T* pDest, const __in_ecount(nElements) T* pSrc, __in size_t nElements )
  2424. {
  2425. for( size_t iElement = 0; iElement < nElements; iElement++ )
  2426. {
  2427. pDest[iElement] = pSrc[iElement];
  2428. }
  2429. }
  2430. static void __cdecl RelocateElements( __out_ecount_full(nElements) T* pDest, __in_ecount(nElements) T* pSrc, __in size_t nElements )
  2431. {
  2432. Checked::memmove_s( pDest, nElements*sizeof( T ), pSrc, nElements*sizeof( T ) );
  2433. }
  2434. static ULONG __cdecl Hash( __in INARGTYPE str )
  2435. {
  2436. ATLENSURE( str != NULL );
  2437. ULONG nHash = 0;
  2438. const T::XCHAR* pch = str;
  2439. while( *pch != 0 )
  2440. {
  2441. nHash = (nHash<<5)+nHash+(*pch);
  2442. pch++;
  2443. }
  2444. return( nHash );
  2445. }
  2446. static bool __cdecl CompareElements( __in INARGTYPE str1, __in INARGTYPE str2 )
  2447. {
  2448. return( T::StrTraits::StringCompare( str1, str2 ) == 0 );
  2449. }
  2450. static int __cdecl CompareElementsOrdered( __in INARGTYPE str1, __in INARGTYPE str2 )
  2451. {
  2452. return( T::StrTraits::StringCompare( str1, str2 ) );
  2453. }
  2454. };
  2455. #pragma pop_macro("new")
  2456. #if defined(_AFX)
  2457. #pragma pop_macro("FormatMessage")
  2458. #endif
  2459. };  // namespace ATL
  2460. #ifdef __ATLCOMCLI_H__
  2461. #include <cstringt.inl>
  2462. #endif // __ATLCOMCLI_H__
  2463. #ifndef _ATL_NO_PRAGMA_WARNINGS
  2464. #pragma warning (pop)
  2465. #endif
  2466. #endif // __CSTRINGT_H__ (whole file)