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

GDI/图象编程

开发平台:

Visual C++

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10. #ifndef __ATLSTR_H__
  11. #define __ATLSTR_H__
  12. #pragma once
  13. #ifndef __cplusplus
  14. #error ATL requires C++ compilation (use a .cpp suffix)
  15. #endif
  16. #include <atlbase.h>
  17. #include <winnls.h>
  18. #include <limits.h>
  19. #include <cstringt.h>
  20. #pragma pack(push,_ATL_PACKING)
  21.  
  22. namespace ATL
  23. {
  24. class CAtlStringMgr :
  25. public IAtlStringMgr
  26. {
  27. public:
  28. CAtlStringMgr( __in_opt IAtlMemMgr* pMemMgr = NULL ) throw() :
  29. m_pMemMgr( pMemMgr )
  30. {
  31. m_nil.SetManager( this );
  32. }
  33. virtual ~CAtlStringMgr() throw()
  34. {
  35. }
  36. void SetMemoryManager( __reserved IAtlMemMgr* pMemMgr ) throw()
  37. {
  38. ATLASSUME( m_pMemMgr == NULL );
  39. m_pMemMgr = pMemMgr;
  40. }
  41. // IAtlStringMgr
  42. public:
  43. virtual __bcount_opt(sizeof(CStringData) + nChars*nCharSize) CStringData* Allocate( __in int nChars, __in int nCharSize ) throw()
  44. {
  45. size_t nTotalSize;
  46. CStringData* pData;
  47. size_t nDataBytes;
  48. nChars = AtlAlignUp( nChars + 1, 8 );  // Prevent excessive reallocation.  The heap will usually round up anyway.
  49. if( FAILED(::ATL::AtlMultiply(&nDataBytes, static_cast<size_t>(nChars), static_cast<size_t>(nCharSize))) ||
  50. FAILED(::ATL::AtlAdd(&nTotalSize, static_cast<size_t>(sizeof( CStringData )), nDataBytes)))
  51. {
  52. return NULL;
  53. }
  54. pData = static_cast< CStringData* >( m_pMemMgr->Allocate( nTotalSize ) );
  55. if( pData == NULL )
  56. {
  57. return( NULL );
  58. }
  59. pData->pStringMgr = this;
  60. pData->nRefs = 1;
  61. pData->nAllocLength = nChars - 1;
  62. pData->nDataLength = 0;
  63. return( pData );
  64. }
  65. virtual void Free( __inout CStringData* pData ) throw()
  66. {
  67. ATLASSERT( pData->pStringMgr == this );
  68. m_pMemMgr->Free( pData );
  69. }
  70. virtual __bcount_opt(sizeof(CStringData) + nChars*nCharSize) CStringData* Reallocate( __inout CStringData* pData, __in int nChars, __in int nCharSize ) throw()
  71. {
  72. CStringData* pNewData;
  73. ULONG nTotalSize;
  74. ULONG nDataBytes;
  75. ATLASSERT( pData->pStringMgr == this );
  76. nChars = AtlAlignUp( nChars+1, 8 );  // Prevent excessive reallocation.  The heap will usually round up anyway.
  77. if( FAILED(::ATL::AtlMultiply(&nDataBytes, static_cast<ULONG>(nChars), static_cast<ULONG>(nCharSize))) ||
  78. FAILED(::ATL::AtlAdd(&nTotalSize, static_cast<ULONG>(sizeof( CStringData )), nDataBytes)))
  79. {
  80. return NULL;
  81. }
  82. pNewData = static_cast< CStringData* >( m_pMemMgr->Reallocate( pData, nTotalSize ) );
  83. if( pNewData == NULL )
  84. {
  85. return NULL;
  86. }
  87. pNewData->nAllocLength = nChars - 1;
  88. return pNewData;
  89. }
  90. virtual CStringData* GetNilString() throw()
  91. {
  92. m_nil.AddRef();
  93. return &m_nil;
  94. }
  95. virtual IAtlStringMgr* Clone() throw()
  96. {
  97. return this;
  98. }
  99. protected:
  100. IAtlMemMgr* m_pMemMgr;
  101. CNilStringData m_nil;
  102. };
  103. extern CAtlStringMgr g_strmgr;
  104. template <class ChTraits>
  105. inline typename ChTraits::PCXSTR strstrT(typename ChTraits::PCXSTR pStr,typename ChTraits::PCXSTR pCharSet);
  106. template< typename _CharType = char >
  107. class ChTraitsOS :
  108. public ChTraitsBase< _CharType >
  109. {
  110. public:
  111. static int tclen(__in_z LPCSTR p) throw()
  112. {
  113. ATLASSERT(p != NULL);
  114. LPCSTR pnext = CharNext(p);
  115. return ((pnext-p)>1) ? 2 : 1;
  116. }
  117. static LPCSTR strchr(__in_z LPCSTR p, __in char ch) throw()
  118. {
  119. return AtlstrchrT(p,ch);
  120. }
  121. static LPCSTR strchr_db(__in_z LPCSTR p, __in char ch1, __in char ch2) throw()
  122. {
  123. ATLASSERT(p != NULL);
  124. while (*p != 0)
  125. {
  126. if (*p == ch1 && *(p+1) == ch2)
  127. {
  128. return p;
  129. }
  130. p = CharNext(p);
  131. }
  132. return NULL;
  133. }
  134. static LPCSTR strrchr(__in_z LPCSTR p, __in char ch) throw()
  135. {
  136. ATLASSERT(p != NULL);
  137. const _CharType* pch = NULL;
  138. while (*p != 0)
  139. {
  140. if (*p == ch)
  141. {
  142. pch = p;
  143. }
  144. p = CharNext(p);
  145. }
  146. //for strrchr(buff,'')
  147. if (*p == ch) 
  148. {
  149. pch = p;
  150. }
  151. return const_cast< _CharType* >( pch );
  152. }
  153. static _CharType* _strrev(__inout _CharType* psz) throw()
  154. {
  155. // Optimize NULL, zero-length, and single-char case.
  156. if ((psz == NULL) || (psz[0] == '') || (psz[1] == ''))
  157. return psz;
  158. _CharType* p = psz;
  159. // first go through and reverse the bytes in MBCS chars
  160. while (*p != _T('')) 
  161. {
  162. if (IsDBCSLeadByte(*p++))
  163. {
  164. if (*p)
  165. {
  166. _CharType c = *p;
  167. *p=*(p-1);
  168. *(p-1)=c;
  169. p++;
  170. } else
  171. {
  172.         //  second byte is EOS
  173.                         //There is nothing really satisfying to do here. We have a string
  174.                         //that ends in leadbyte,''. Reversing this would lead to the leadbyte
  175.                         //becoming falsely attached to the character before it:
  176.                         //(XL0 -> LX0, X has suddenly become a trailbyte)
  177.                         //So what we choose to do is assert and purge the dud byte from within the
  178.                         //string.
  179.                     
  180.                     ATLASSERT(FALSE && _T("Bad MBCS string passed into __strev"));
  181.                     // String has at least moved once already, so this is safe 
  182.                     ATLASSERT(p>psz);
  183.                     // move back one to point at the dud leadbyte
  184.                     --p;
  185.                     // now truncate the string one byte earlier 
  186.                     *p='';
  187. }
  188. }
  189. } //end while
  190. _CharType* q = psz;
  191. --p;
  192. while (q < p)
  193. {
  194. _CharType t = *q;
  195. *q = *p;
  196. *p = t;
  197. q++;
  198. p--;
  199. }
  200. return psz;
  201. }
  202. static LPCSTR strstr(__in_z LPCSTR pStr, __in_z LPCSTR pCharSet) throw()
  203. {
  204. return strstrT< ChTraitsOS<XCHAR> >(pStr,pCharSet);
  205. }
  206. static int strspn(__in const _CharType* pStr, __in const _CharType* pCharSet) throw()
  207. {
  208. ATLASSERT(pStr != NULL);
  209. int nRet = 0;
  210. _CharType* p = const_cast<_CharType*>(pStr);
  211. while (*p != 0)
  212. {
  213. _CharType* pNext = CharNext(p);
  214. if(pNext > p + 1)
  215. {
  216. if(strchr_db(pCharSet, *p, *(p+1)) == NULL)
  217. break;
  218. nRet += 2;
  219. }
  220. else
  221. {
  222. if(strchr(pCharSet, *p) == NULL)
  223. break;
  224. nRet++;
  225. }
  226. p = pNext;
  227. }
  228. return nRet;
  229. }
  230. static int strcspn(__in const _CharType* pStr, __in const _CharType* pCharSet) throw()
  231. {
  232. ATLASSERT(pStr != NULL);
  233. int nRet = 0;
  234. _CharType* p = const_cast<_CharType*>(pStr);
  235. while (*p != 0)
  236. {
  237. _CharType* pNext = CharNext(p);
  238. if(pNext > p + 1)
  239. {
  240. if(strchr_db(pCharSet, *p, *(p+1)) != NULL)
  241. break;
  242. nRet += 2;
  243. }
  244. else
  245. {
  246. if(strchr(pCharSet, *p) != NULL)
  247. break;
  248. nRet++;
  249. }
  250. p = pNext;
  251. }
  252. return nRet;
  253. }
  254. static LPCSTR strpbrk(__in_z LPCSTR p, __in_z LPCSTR lpszCharSet) throw()
  255. {
  256. int nRet=0;
  257. nRet=strcspn(p,lpszCharSet);
  258. if (p[nRet]){
  259. p+=nRet;
  260. return p;
  261. }
  262.      return NULL;
  263. }
  264. static _CharType* CharNext(__in const _CharType* p) throw()
  265. {
  266. return AtlCharNext(p);
  267. }
  268. static int IsDigit(__in _CharType ch) throw()
  269. {
  270. WORD type;
  271. GetStringTypeExA(GetThreadLocale(), CT_CTYPE1, &ch, 1, &type);
  272. return (type & C1_DIGIT) == C1_DIGIT;
  273. }
  274. static int IsSpace(__in _CharType ch) throw()
  275. {
  276. WORD type;
  277. GetStringTypeExA(GetThreadLocale(), CT_CTYPE1, &ch, 1, &type);
  278. return (type & C1_SPACE) == C1_SPACE;
  279. }
  280. static int StringCompare(__in const _CharType* pstrOne,
  281. __in const _CharType* pstrOther) throw()
  282. {
  283. return lstrcmpA((LPCSTR) pstrOne, (LPCSTR) pstrOther);
  284. }
  285. static int StringCompareIgnore(__in const _CharType* pstrOne,
  286. __in const _CharType* pstrOther) throw()
  287. {
  288. return lstrcmpiA((LPCSTR) pstrOne, (LPCSTR) pstrOther);
  289. }
  290. static int StringCollate(__in const _CharType* pstrOne,
  291. __in const _CharType* pstrOther) throw()
  292. {
  293. int nRet = CompareStringA(GetThreadLocale(), 0, (LPCSTR)pstrOne, -1, 
  294. (LPCSTR)pstrOther, -1);
  295. ATLASSERT(nRet != 0);
  296. return nRet-2;  // Convert to strcmp convention.  This really is documented.
  297. }
  298. static int StringCollateIgnore(__in const _CharType* pstrOne,
  299. __in const _CharType* pstrOther) throw()
  300. {
  301. int nRet = CompareStringA(GetThreadLocale(), NORM_IGNORECASE, (LPCSTR)pstrOne, -1, 
  302. (LPCSTR)pstrOther, -1);
  303. ATLASSERT(nRet != 0);
  304. return nRet-2;  // Convert to strcmp convention.  This really is documented.
  305. }
  306. static LPCSTR StringFindString(__in_z LPCSTR pstrBlock,
  307. __in_z LPCSTR pstrMatch) throw()
  308. {
  309. return strstr(pstrBlock, pstrMatch);
  310. }
  311. static LPSTR StringFindString(__in_z LPSTR pszBlock, __in_z LPCSTR pszMatch) throw()
  312. {
  313. return( const_cast< LPSTR >( StringFindString( const_cast< LPCSTR >( pszBlock ), pszMatch ) ) );
  314. }
  315. static LPCSTR StringFindChar(__in_z LPCSTR pszBlock,
  316. __in char chMatch) throw()
  317. {
  318. return strchr(pszBlock, chMatch);
  319. }
  320. static LPCSTR StringFindCharRev(__in_z LPCSTR psz, __in char ch) throw()
  321. {
  322. return strrchr(psz, ch);
  323. }
  324. static LPCSTR StringScanSet(__in_z LPCSTR pszBlock,
  325. __in_z LPCSTR pszMatch) throw()
  326. {
  327. return strpbrk(pszBlock, pszMatch);
  328. }
  329. static int StringSpanIncluding(__in const _CharType* pstrBlock,
  330. __in const _CharType* pstrSet) throw()
  331. {
  332. return strspn(pstrBlock, pstrSet);
  333. }
  334. static int StringSpanExcluding(__in const _CharType* pstrBlock,
  335. __in const _CharType* pstrSet) throw()
  336. {
  337. return strcspn(pstrBlock, pstrSet);
  338. }
  339. _ATL_INSECURE_DEPRECATE("ChTraitsOS::StringUppercase must be passed a buffer size")
  340. static _CharType* StringUppercase(__inout _CharType* psz) throw()
  341. {
  342. return CharUpperA( psz );
  343. }
  344. _ATL_INSECURE_DEPRECATE("ChTraitsOS::StringLowercase must be passed a buffer size")
  345. static _CharType* StringLowercase(__inout _CharType* psz) throw()
  346. {
  347. return CharLowerA( psz );
  348. }
  349. static _CharType* StringUppercase(__inout_ecount(size) _CharType* psz, __in size_t size) throw()
  350. {
  351. if(size>UINT_MAX)
  352. {
  353. // API only allows DWORD size
  354. AtlThrow(E_INVALIDARG);
  355. }
  356. DWORD dwSize=static_cast<DWORD>(size);
  357. CharUpperBuffA( psz, dwSize );
  358. return psz;
  359. }
  360. static _CharType* StringLowercase(__inout_ecount(size) _CharType* psz, size_t size) throw()
  361. {
  362. if(size>UINT_MAX)
  363. {
  364. // API only allows DWORD size
  365. AtlThrow(E_INVALIDARG);
  366. }
  367. DWORD dwSize=static_cast<DWORD>(size);
  368. CharLowerBuffA( psz, dwSize );
  369. return psz;
  370. }
  371. static _CharType* StringReverse(__inout _CharType* psz) throw()
  372. {
  373. return _strrev( psz );
  374. }
  375. static int GetFormattedLength(__in __format_string const _CharType* pszFormat, va_list args)
  376. {
  377. _CharType szBuffer[1028];
  378. int nLength = 0;
  379. SetLastError(ERROR_SUCCESS);
  380. #pragma warning(push)
  381. #pragma warning(disable:4996)
  382. // wvsprintf always truncates the output to 1024 character plus the ''.
  383. // Note that we are using wvsprintf only in the MIN_CRT case; wvsprintf is
  384. // an insecure function and should be avoided. Here the use of wvsprintf
  385. // is safe and the only way to get a string formatted without using the CRT.
  386. nLength = wvsprintfA(szBuffer, pszFormat, args);
  387. #pragma warning(pop)
  388. ATLENSURE(GetLastError() == ERROR_SUCCESS);
  389. ATLASSERT(nLength >= 0);
  390. ATLASSERT(nLength <= 1024);
  391. return nLength;
  392. }
  393. _ATL_INSECURE_DEPRECATE("CSimpleStringT::Format must be passed a buffer size")
  394. static int Format(__out _CharType* pszBuffer, __in __format_string const _CharType* pszFormat,
  395. va_list args) throw()
  396. {
  397. #pragma warning(push)
  398. #pragma warning(disable:4996)
  399. return wvsprintfA(pszBuffer, pszFormat, args);
  400. #pragma warning(pop)
  401. }
  402. static int Format(__out_ecount_part(nlength, return) _CharType*  pszBuffer, __in size_t nlength, __in __format_string const _CharType* pszFormat, va_list args )
  403. {
  404. _CharType buffSafe[1030]; //wvsprintf output is max 1024.
  405. int nCharsWritten = 0;
  406. SetLastError(ERROR_SUCCESS);
  407. #pragma warning(push)
  408. #pragma warning(disable:4996)
  409. // wvsprintf always truncates the output to 1024 character plus the ''.
  410. // Note that we are using wvsprintf only in the MIN_CRT case; wvsprintf is
  411. // an insecure function and should be avoided. Here the use of wvsprintf
  412. // is safe and the only way to get a string formatted without using the CRT.
  413. nCharsWritten = wvsprintfA(buffSafe, pszFormat, args);
  414. #pragma warning(pop)
  415. ATLENSURE(GetLastError() == ERROR_SUCCESS);
  416. ATLENSURE(nCharsWritten <= 1024);
  417. //nlength should have room for nCharsWritten + NULL
  418. ATLENSURE_THROW((size_t)nCharsWritten < nlength ,E_INVALIDARG);
  419. Checked::strcpy_s(pszBuffer,nlength,buffSafe);
  420. return nCharsWritten;
  421. }
  422. static int GetBaseTypeLength(__in_z const char* pszSrc) throw()
  423. {
  424. // Returns required buffer length in XCHARs
  425. return lstrlenA(pszSrc);
  426. }
  427. static int GetBaseTypeLength(__in_z const char* pszSrc, __in int nLength) throw()
  428. {
  429. (void)pszSrc;
  430. // Returns required buffer length in XCHARs
  431. return nLength;
  432. }
  433. static int GetBaseTypeLength(__in_z const wchar_t* pszSrc) throw()
  434. {
  435. // Returns required buffer length in XCHARs
  436. return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc, -1, NULL, 0, NULL, NULL)-1;
  437. }
  438. static int GetBaseTypeLength(__in_ecount(nLength) const wchar_t* pszSrc, __in int nLength) throw()
  439. {
  440. // Returns required buffer length in XCHARs
  441. return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc, nLength, NULL, 0, NULL, NULL);
  442. }
  443. static void ConvertToBaseType(__out_ecount(nDestLength) _CharType* pszDest, __in int nDestLength,
  444. __in_ecount(nSrcLength) const char* pszSrc, __in int nSrcLength = -1) throw()
  445. {
  446. if (nSrcLength == -1) { nSrcLength=1 + GetBaseTypeLength(pszSrc); }
  447. // nLen is in chars
  448. Checked::memcpy_s(pszDest, nDestLength*sizeof(_CharType), 
  449. pszSrc, nSrcLength*sizeof(_CharType));
  450. }
  451. static void ConvertToBaseType(__out_ecount(nDestLength) _CharType* pszDest, __in int nDestLength,
  452. __in_ecount(nSrcLength) const wchar_t* pszSrc, __in int nSrcLength = -1) throw()
  453. {
  454. // nLen is in XCHARs
  455. ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL);
  456. }
  457. _ATL_INSECURE_DEPRECATE("ChTraitsOS::ConvertToOem must be passed a buffer size")
  458. static void ConvertToOem(__inout _CharType* pstrString) throw()
  459. {
  460. BOOL fSuccess=::CharToOemA(pstrString, pstrString);
  461. // old version can't report error
  462. ATLASSERT(fSuccess);
  463. }
  464. _ATL_INSECURE_DEPRECATE("ChTraitsOS::ConvertToAnsi must be passed a buffer size")
  465. static void ConvertToAnsi(__inout _CharType* pstrString) throw()
  466. {
  467. BOOL fSuccess=::OemToCharA(pstrString, pstrString);
  468. // old version can't report error
  469. ATLASSERT(fSuccess);
  470. }
  471. static void ConvertToOem(__out_ecount(size) _CharType* pstrString, __in size_t size)
  472. {
  473. if(size>UINT_MAX)
  474. {
  475. // API only allows DWORD size
  476. AtlThrow(E_INVALIDARG);
  477. }
  478. DWORD dwSize=static_cast<DWORD>(size);
  479. BOOL fSuccess=::CharToOemBuffA(pstrString, pstrString, dwSize);
  480. if(!fSuccess)
  481. {
  482. AtlThrowLastWin32();
  483. }
  484. }
  485. static void ConvertToAnsi(__out_ecount(size) _CharType* pstrString, __in size_t size)
  486. {
  487. if(size>UINT_MAX)
  488. {
  489. // API only allows DWORD size
  490. AtlThrow(E_INVALIDARG);
  491. }
  492. DWORD dwSize=static_cast<DWORD>(size);
  493. BOOL fSuccess=::OemToCharBuffA(pstrString, pstrString, dwSize);
  494. if(!fSuccess)
  495. {
  496. AtlThrowLastWin32();
  497. }
  498. }
  499. static void FloodCharacters(__in _CharType ch, __in int nLength, __out_bcount_full(nLength) _CharType* pstr) throw()
  500. {
  501. // nLength is in XCHARs
  502. memset(pstr, ch, nLength);
  503. }
  504. static BSTR AllocSysString(__in_ecount(nDataLength) const _CharType* pchData, __in int nDataLength) throw()
  505. {
  506. int nLen = MultiByteToWideChar(_AtlGetConversionACP(), 0, pchData, nDataLength,
  507. NULL, NULL);
  508. BSTR bstr = ::SysAllocStringLen(NULL, nLen);
  509. if (bstr != NULL)
  510. {
  511. MultiByteToWideChar(_AtlGetConversionACP(), 0, pchData, nDataLength,
  512. bstr, nLen);
  513. }
  514. return bstr;
  515. }
  516. static BOOL ReAllocSysString(__in_bcount(nDataLength) const _CharType* pchData, __inout BSTR* pbstr,
  517. __in int nDataLength) throw()
  518. {
  519. int nLen = MultiByteToWideChar(_AtlGetConversionACP(), 0, pchData,
  520. nDataLength, NULL, NULL);
  521. BOOL bSuccess =::SysReAllocStringLen(pbstr, NULL, nLen);
  522. if (bSuccess)
  523. {
  524. MultiByteToWideChar(_AtlGetConversionACP(), 0, pchData, nDataLength,
  525. *pbstr, nLen);
  526. }
  527. return bSuccess;
  528. }
  529. static DWORD FormatMessage(__in DWORD dwFlags, __in LPCVOID lpSource,
  530. __in DWORD dwMessageID, __in DWORD dwLanguageID, __out_ecount(nSize) char* pstrBuffer,
  531. __in DWORD nSize, va_list* pArguments) throw()
  532. {
  533. return ::FormatMessageA(dwFlags, lpSource, dwMessageID, dwLanguageID,
  534. pstrBuffer, nSize, pArguments);
  535. }
  536. static int SafeStringLen(__in_opt const char* psz) throw()
  537. {
  538. // returns length in bytes
  539. return (psz != NULL) ? lstrlenA(psz) : 0;
  540. }
  541. static int SafeStringLen(__in_opt const wchar_t* psz) throw()
  542. {
  543. // returns length in wchar_ts
  544. return (psz != NULL) ? lstrlenW(psz) : 0;
  545. }
  546. static int GetCharLen(const wchar_t*) throw()
  547. {
  548. // returns char length
  549. return 1;
  550. }
  551. static int GetCharLen(__in_z const char* psz) throw()
  552. {
  553. const char* p = ::CharNextA(psz);
  554. return (p - psz);
  555. }
  556. static DWORD GetEnvironmentVariable(__in const _CharType* pstrVar,
  557. __out_ecount_opt(dwSize) _CharType* pstrBuffer, __in DWORD dwSize) throw()
  558. {
  559. return ::GetEnvironmentVariableA(pstrVar, pstrBuffer, dwSize);
  560. }
  561. };
  562. // specialization for wchar_t
  563. template<>
  564. class ChTraitsOS< wchar_t > :
  565. public ChTraitsBase< wchar_t >
  566. {
  567. protected:
  568. #if defined(_UNICODE) && !defined(_CSTRING_ALWAYS_THUNK)
  569. static int CompareStringW(__in LCID lcid, __in DWORD dwFlags, 
  570. __in_ecount(nLength1) LPCWSTR pszString1, __in int nLength1, __in_ecount(nLength2) LPCWSTR pszString2, __in int nLength2)
  571. {
  572. return ::CompareStringW(lcid, dwFlags, pszString1, nLength1, 
  573. pszString2, nLength2);
  574. }
  575. static BOOL GetStringTypeExW(__in LCID lcid, __in DWORD dwInfoType, __in_ecount(nLength) LPCWSTR pszSrc,
  576. __in int nLength, __out LPWORD pwCharType)
  577. {
  578. return ::GetStringTypeExW(lcid, dwInfoType, pszSrc, nLength, pwCharType);
  579. }
  580. static int lstrcmpiW(__in_z LPCWSTR psz1, __in_z LPCWSTR psz2)
  581. {
  582. return ::lstrcmpiW(psz1, psz2);
  583. }
  584. static LPWSTR CharLowerW(__inout LPWSTR psz)
  585. {
  586. return ::CharLowerW(psz);
  587. }
  588. static LPWSTR CharUpperW(__inout LPWSTR psz)
  589. {
  590. return ::CharUpperW(psz);
  591. }
  592. static DWORD _GetEnvironmentVariableW(__in_z LPCWSTR pszName, __out_ecount_opt(nSize) LPWSTR pszBuffer, __in DWORD nSize)
  593. {
  594. return ::GetEnvironmentVariableW(pszName, pszBuffer, nSize);
  595. }
  596. #else  // !_UNICODE
  597. static int WINAPI CompareStringW(__in LCID lcid, __in DWORD dwFlags, 
  598. __in_ecount(nLength1) LPCWSTR pszString1, __in int nLength1, __in_ecount(nLength2) LPCWSTR pszString2, __in int nLength2)
  599. {
  600. return _strthunks.pfnCompareStringW(lcid, dwFlags, pszString1, nLength1, pszString2, nLength2);
  601. }
  602. static BOOL WINAPI GetStringTypeExW(__in LCID lcid, __in DWORD dwInfoType, __in_ecount(nLength) LPCWSTR pszSrc,
  603. __in int nLength, __out LPWORD pwCharType)
  604. {
  605. return _strthunks.pfnGetStringTypeExW(lcid, dwInfoType, pszSrc, nLength, pwCharType);
  606. }
  607. static int WINAPI lstrcmpiW(__in_z LPCWSTR psz1, __in_z LPCWSTR psz2)
  608. {
  609. return _strthunks.pfnlstrcmpiW(psz1, psz2);
  610. }
  611. static LPWSTR WINAPI CharLowerW(__inout LPWSTR psz)
  612. {
  613. ATLASSERT(HIWORD(psz) != 0);  // No single chars
  614. return _strthunks.pfnCharLowerW(psz);
  615. }
  616. static LPWSTR WINAPI CharUpperW(__inout LPWSTR psz)
  617. {
  618. ATLASSERT(HIWORD(psz) != 0);  // No single chars
  619. return _strthunks.pfnCharUpperW(psz);
  620. }
  621. static DWORD _GetEnvironmentVariableW(__in_z LPCWSTR pszName, __out_ecount_opt(nSize) LPWSTR pszBuffer, DWORD nSize)
  622. {
  623. return _strthunks.pfnGetEnvironmentVariableW(pszName, pszBuffer, nSize);
  624. }
  625. #endif  // !_UNICODE
  626. public:
  627. static int tclen(const wchar_t*) throw()
  628. {
  629. return 1;
  630. }
  631. static LPCWSTR strchr(__in_z LPCWSTR p, __in wchar_t ch) throw()
  632. {
  633. return AtlstrchrT(p,ch);
  634. }
  635. static LPCWSTR strrchr(__in_z LPCWSTR p, __in wchar_t ch) throw()
  636. {
  637. const wchar_t* pch = p+lstrlenW(p);
  638. while ((pch != p) && (*pch != ch))
  639. {
  640. pch--;
  641. }
  642. if (*pch == ch)
  643. {
  644. return pch;
  645. }
  646. else
  647. {
  648. return NULL;
  649. }
  650. }
  651. static wchar_t* _strrev(__inout_z wchar_t* psz) throw()
  652. {
  653. // Optimize NULL, zero-length, and single-char case.
  654. if ((psz == NULL) || (psz[0] == L'') || (psz[1] == L''))
  655. return psz;
  656. wchar_t* p = psz+(lstrlenW( psz )-1);
  657. wchar_t* q = psz;
  658. while(q < p)
  659. {
  660. wchar_t t = *q;
  661. *q = *p;
  662. *p = t;
  663. q++;
  664. p--;
  665. }
  666. return psz;
  667. }
  668. static LPCWSTR strstr(__in_z LPCWSTR pStr, __in_z LPCWSTR pCharSet) throw()
  669. {
  670. return strstrT< ChTraitsOS<XCHAR> >(pStr,pCharSet);
  671. }
  672. static int strspn(__in_z const wchar_t* psz, __in_z const wchar_t* pszCharSet) throw()
  673. {
  674. int nRet = 0;
  675. const wchar_t* p = psz;
  676. while (*p != 0)
  677. {
  678. if(strchr(pszCharSet, *p) == NULL)
  679. break;
  680. nRet++;
  681. p++;
  682. }
  683. return nRet;
  684. }
  685. static int strcspn(__in_z const wchar_t* psz, __in_z const wchar_t* pszCharSet) throw()
  686. {
  687. int nRet = 0;
  688. const wchar_t* p = psz;
  689. while (*p != 0)
  690. {
  691. if(strchr(pszCharSet, *p) != NULL)
  692. break;
  693. nRet++;
  694. p++;
  695. }
  696. return nRet;
  697. }
  698. static LPCWSTR strpbrk(__in_z LPCWSTR psz, __in_z LPCWSTR pszCharSet) throw()
  699. {
  700. const wchar_t* p = psz;
  701. while (*p != 0)
  702. {
  703. if (strchr(pszCharSet, *p) != NULL)
  704. return p;
  705. p++;
  706. }
  707. return NULL;
  708. }
  709. static wchar_t* CharNext(__in_z const wchar_t* p) throw()
  710. {
  711. return AtlCharNext(p);
  712. }
  713. static int IsDigit(__in wchar_t ch) throw()
  714. {
  715. WORD type;
  716. GetStringTypeExW(0, CT_CTYPE1, &ch, 1, &type);
  717. return (type & C1_DIGIT) == C1_DIGIT;
  718. }
  719. static int IsSpace(__in wchar_t ch) throw()
  720. {
  721. WORD type;
  722. GetStringTypeExW(0, CT_CTYPE1, &ch, 1, &type);
  723. return (type & C1_SPACE) == C1_SPACE;
  724. }
  725. static int StringCompare(__in_z const wchar_t* pstrOne,
  726. __in_z const wchar_t* pstrOther) throw()
  727. {
  728. return wcscmp(pstrOne, pstrOther);
  729. }
  730. static int StringCompareIgnore(__in_z const wchar_t* pstrOne,
  731. __in_z const wchar_t* pstrOther) throw()
  732. {
  733. return lstrcmpiW(pstrOne, pstrOther);
  734. }
  735. static int StringCollate(__in_z const wchar_t* pstrOne,
  736. __in_z const wchar_t* pstrOther) throw()
  737. int nRet;
  738. nRet = CompareStringW(GetThreadLocale(), 0, pstrOne, UINT_MAX/sizeof(wchar_t), pstrOther, UINT_MAX/sizeof(wchar_t));
  739. ATLASSERT(nRet != 0);
  740. return nRet-2;  // Convert to strcmp convention.  This really is documented.
  741. }
  742. static int StringCollateIgnore(__in_z const wchar_t* pstrOne,
  743. __in_z const wchar_t* pstrOther) throw()
  744. {
  745. int nRet = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, pstrOne, UINT_MAX/sizeof(wchar_t), pstrOther, UINT_MAX/sizeof(wchar_t));
  746. ATLASSERT(nRet != 0);
  747. return nRet-2;  // Convert to strcmp convention.  This really is documented.
  748. }
  749. static LPCWSTR StringFindString(__in_z LPCWSTR pstrBlock,
  750. __in_z LPCWSTR pstrMatch) throw()
  751. {
  752. return strstr(pstrBlock, pstrMatch);
  753. }
  754. static LPWSTR StringFindString( __in_z LPWSTR pszBlock, __in_z LPCWSTR pszMatch ) throw()
  755. {
  756. return( const_cast< LPWSTR >( StringFindString( const_cast< LPCWSTR >( pszBlock ), pszMatch ) ) );
  757. }
  758. static LPCWSTR StringFindChar(__in_z LPCWSTR pstrBlock,
  759. __in wchar_t pstrMatch) throw()
  760. {
  761. return strchr(pstrBlock, pstrMatch);
  762. }
  763. static LPCWSTR StringFindCharRev(__in_z LPCWSTR pstr, __in wchar_t ch) throw()
  764. {
  765. return strrchr(pstr, ch);
  766. }
  767. static LPCWSTR StringScanSet(__in_z LPCWSTR pszBlock,
  768. __in_z LPCWSTR pszMatch) throw()
  769. {
  770. return strpbrk(pszBlock, pszMatch);
  771. }
  772. static int StringSpanIncluding(__in_z const wchar_t* pszBlock,
  773. __in_z const wchar_t* pszSet) throw()
  774. {
  775. return strspn(pszBlock, pszSet);
  776. }
  777. static int StringSpanExcluding(__in_z const wchar_t* pszBlock,
  778. __in_z const wchar_t* pszSet) throw()
  779. {
  780. return strcspn(pszBlock, pszSet);
  781. }
  782. _ATL_INSECURE_DEPRECATE("ChTraitsOS::StringUppercase must be passed a buffer size")
  783. static wchar_t* StringUppercase(__inout wchar_t* psz) throw()
  784. {
  785. CharUpperW(psz);
  786. return psz;
  787. }
  788. _ATL_INSECURE_DEPRECATE("ChTraitsOS::StringUppercase must be passed a buffer size")
  789. static wchar_t* StringLowercase(__inout wchar_t* psz) throw()
  790. {
  791. CharLowerW(psz);
  792. return psz;
  793. }
  794. static wchar_t* StringUppercase(__inout_ecount(size) wchar_t* psz, __in size_t size) throw()
  795. {
  796. if(size>(UINT_MAX/sizeof(wchar_t)))
  797. {
  798. // API only allows DWORD size
  799. AtlThrow(E_INVALIDARG);
  800. }
  801. DWORD dwSize=static_cast<DWORD>(size);
  802. CharUpperBuffW(psz, dwSize);
  803. return psz;
  804. }
  805. static wchar_t* StringLowercase(__inout_ecount(size) wchar_t* psz, __in size_t size) throw()
  806. {
  807. if(size>(UINT_MAX/sizeof(wchar_t)))
  808. {
  809. // API only allows DWORD size
  810. AtlThrow(E_INVALIDARG);
  811. }
  812. DWORD dwSize=static_cast<DWORD>(size);
  813. CharLowerBuffW(psz, dwSize);
  814. return psz;
  815. }
  816. static wchar_t* StringReverse(__inout_z wchar_t* psz) throw()
  817. {
  818. return _strrev(psz);
  819. }
  820. #ifdef _UNICODE
  821. static int GetFormattedLength(__in __format_string const wchar_t* pszFormat, va_list args)
  822. {
  823. wchar_t szBuffer[1028];
  824. int nLength = 0;
  825. SetLastError(ERROR_SUCCESS);
  826. #pragma warning(push)
  827. #pragma warning(disable:4996)
  828. // wvsprintf always truncates the output to 1024 character plus the ''.
  829. // Note that we are using wvsprintf only in the MIN_CRT case; wvsprintf is
  830. // an insecure function and should be avoided. Here the use of wvsprintf
  831. // is safe and the only way to get a string formatted without using the CRT.
  832. nLength = wvsprintfW(szBuffer, pszFormat, args);
  833. #pragma warning(pop)
  834. ATLENSURE(GetLastError() == ERROR_SUCCESS);
  835. ATLASSERT(nLength >= 0);
  836. ATLASSERT(nLength <= 1024);
  837. return nLength;
  838. }
  839. _ATL_INSECURE_DEPRECATE("ChTraitsOS::Format must be passed a buffer size")
  840. static int Format(__out wchar_t* pszBuffer, __in __format_string const wchar_t* pszFormat,
  841. va_list args) throw()
  842. {
  843. #pragma warning(push)
  844. #pragma warning(disable:4996)
  845. return wvsprintfW(pszBuffer, pszFormat, args);
  846. #pragma warning(pop)
  847. }
  848. static int Format(__out_ecount(nLength) wchar_t* pszBuffer, __in size_t nLength, __in __format_string const wchar_t* pszFormat, va_list args )
  849. {
  850. wchar_t buffSafe[1028];
  851. int nCharsWritten = 0;
  852. SetLastError(ERROR_SUCCESS);
  853. #pragma warning(push)
  854. #pragma warning(disable:4996)
  855. // wvsprintf always truncates the output to 1024 character plus the ''.
  856. // Note that we are using wvsprintf only in the MIN_CRT case; wvsprintf is
  857. // an insecure function and should be avoided. Here the use of wvsprintf
  858. // is safe and the only way to get a string formatted without using the CRT.
  859. nCharsWritten = wvsprintfW(buffSafe, pszFormat, args);
  860. #pragma warning(pop)
  861. ATLENSURE(GetLastError() == ERROR_SUCCESS);
  862. ATLENSURE(nCharsWritten <= 1024);
  863. //nlength should have room for nCharsWritten + NULL
  864. ATLENSURE_THROW((size_t)nCharsWritten < nLength ,E_INVALIDARG);
  865. ATLENSURE_THROW(wcslen(buffSafe) < nLength ,E_INVALIDARG);
  866. #pragma warning(push)
  867. #pragma warning(disable:6386)
  868. /* prefast noise 497597 */
  869. Checked::wcscpy_s(pszBuffer,nLength,buffSafe);
  870. #pragma warning(pop)
  871. return nCharsWritten;
  872. }
  873. #endif
  874. static int GetBaseTypeLength(__in_z const char* pszSrc) throw()
  875. {
  876. // Returns required buffer size in wchar_ts
  877. return ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSrc, -1, NULL, 0)-1;
  878. }
  879. static int GetBaseTypeLength(__in_ecount(nLength) const char* pszSrc, __in int nLength) throw()
  880. {
  881. // Returns required buffer size in wchar_ts
  882. return ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSrc, nLength, NULL, 0);
  883. }
  884. static int GetBaseTypeLength(__in_z const wchar_t* pszSrc) throw()
  885. {
  886. // Returns required buffer size in wchar_ts
  887. return lstrlenW(pszSrc);
  888. }
  889. static int GetBaseTypeLength(__in_ecount(nLength) const wchar_t* pszSrc, __in int nLength) throw()
  890. {
  891. (void)pszSrc;
  892. // Returns required buffer size in wchar_ts
  893. return nLength;
  894. }
  895. static void ConvertToBaseType(__out_ecount(nDestLength) wchar_t* pszDest, int nDestLength,
  896. __in_ecount(nSrcLength) const char* pszSrc, __in int nSrcLength = -1) throw()
  897. {
  898. // nLen is in wchar_ts
  899. ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength);
  900. }
  901. static void ConvertToBaseType(__out_ecount(nDestLength) wchar_t* pszDest, __in int nDestLength,
  902. __in_ecount(nSrcLength) const wchar_t* pszSrc, int nSrcLength = -1) throw()
  903. {
  904. if (nSrcLength == -1) { nSrcLength=1 + GetBaseTypeLength(pszSrc); }
  905. // nLen is in wchar_ts
  906. Checked::wmemcpy_s(pszDest, nDestLength, pszSrc, nSrcLength);
  907. }
  908. // this conversion on Unicode strings makes no sense
  909. /*
  910. static void ConvertToOem(wchar_t*)
  911. {
  912. ATLASSERT(FALSE);
  913. }
  914. */
  915. // this conversion on Unicode strings makes no sense
  916. /*
  917. static void ConvertToAnsi(wchar_t*)
  918. {
  919. ATLASSERT(FALSE);
  920. }
  921. */
  922. static void FloodCharacters(__in wchar_t ch, __in int nLength, __out_ecount_full(nLength) wchar_t* pstr) throw()
  923. {
  924. // nLength is in XCHARs
  925. for (int i = 0; i < nLength; i++)
  926. pstr[i] = ch;
  927. }
  928. static BSTR AllocSysString(__in_ecount(nDataLength) const wchar_t* pchData, __in int nDataLength) throw()
  929. {
  930. BSTR bstr = ::SysAllocStringLen(pchData, nDataLength);
  931. return bstr;
  932. }
  933. static BOOL ReAllocSysString(__in_ecount(nDataLength) const wchar_t* pchData, __inout BSTR* pbstr,
  934. __in int nDataLength) throw()
  935. {
  936. return ::SysReAllocStringLen(pbstr, pchData, nDataLength);
  937. }
  938. #ifdef _UNICODE
  939. static DWORD FormatMessage(__in DWORD dwFlags, __in LPCVOID lpSource,
  940. __in DWORD dwMessageID, __in DWORD dwLanguageID, __out_ecount(nSize) wchar_t* pstrBuffer,
  941. __in DWORD nSize, va_list* pArguments) throw()
  942. {
  943. return ::FormatMessageW(dwFlags, lpSource, dwMessageID, dwLanguageID,
  944. pstrBuffer, nSize, pArguments);
  945. }
  946. #endif
  947. static int SafeStringLen(__in_opt const char* psz) throw()
  948. {
  949. // returns length in bytes
  950. return (psz != NULL) ? lstrlenA(psz) : 0;
  951. }
  952. static int SafeStringLen(__in_opt const wchar_t* psz) throw()
  953. {
  954. // returns length in wchar_ts
  955. return (psz != NULL) ? lstrlenW(psz) : 0;
  956. }
  957. static int GetCharLen(const wchar_t*) throw()
  958. {
  959. // returns char length
  960. return 1;
  961. }
  962. static int GetCharLen(__in_z const char* psz) throw()
  963. {
  964. LPCSTR p = ::CharNextA( psz );
  965. return int( p-psz );
  966. }
  967. static DWORD GetEnvironmentVariable(__in_z const wchar_t* pstrVar,
  968. __out_ecount_opt(dwSize) wchar_t* pstrBuffer, __in DWORD dwSize) throw()
  969. {
  970. return ::GetEnvironmentVariableW(pstrVar, pstrBuffer, dwSize);
  971. }
  972. };
  973. template <class ChTraits>
  974. inline typename ChTraits::PCXSTR strstrT(__in typename ChTraits::PCXSTR pStr,__in typename ChTraits::PCXSTR pCharSet)
  975. {
  976. ATLASSERT(pStr != NULL);
  977. size_t nCharSetLen = ChTraits::GetBaseTypeLength(pCharSet);
  978. if (nCharSetLen == 0)
  979. return pStr;
  980. //lstrlenA returns length in bytes, not chars.
  981. size_t nStrLen = ChTraits::GetBaseTypeLength(pStr);
  982. ChTraits::PCXSTR pStrEnd=pStr + nStrLen;
  983. const ChTraits::XCHAR* pMatch;
  984. const ChTraits::XCHAR* pStart = pStr;
  985. while ((pMatch = ChTraits::strchr(pStart, *pCharSet)) != NULL)
  986. {
  987. size_t nCharsLeftInStr=pStrEnd - pMatch;
  988. if (nCharsLeftInStr < nCharSetLen)
  989. {
  990. break;
  991. }
  992. if (memcmp(pMatch, pCharSet, nCharSetLen*sizeof(ChTraits::XCHAR)) == 0)
  993. {
  994. return pMatch;
  995. }
  996. pStart = ChTraits::CharNext(pMatch);
  997. }
  998. return NULL;
  999. }
  1000. template< typename _BaseType = char, class StringIterator = ChTraitsOS< _BaseType > >
  1001. class StrTraitATL : public StringIterator
  1002. {
  1003. public:
  1004. static HINSTANCE FindStringResourceInstance(__in UINT nID) throw()
  1005. {
  1006. return( AtlFindStringResourceInstance( nID ) );
  1007. }
  1008. static IAtlStringMgr* GetDefaultManager() throw()
  1009. {
  1010. return( &g_strmgr );
  1011. }
  1012. };
  1013. #if !defined(_ATL_CSTRING_NO_CRT) && defined(_ATL_MIN_CRT)
  1014. #define _ATL_CSTRING_NO_CRT
  1015. #endif
  1016. #ifndef _ATL_CSTRING_NO_CRT
  1017. typedef CStringT< wchar_t, StrTraitATL< wchar_t, ChTraitsCRT< wchar_t > > > CAtlStringW;
  1018. typedef CStringT< char, StrTraitATL< char, ChTraitsCRT< char > > > CAtlStringA;
  1019. typedef CStringT< TCHAR, StrTraitATL< TCHAR, ChTraitsCRT< TCHAR > > > CAtlString;
  1020. #else  // _ATL_CSTRING_NO_CRT
  1021. typedef CStringT< wchar_t, StrTraitATL< wchar_t > > CAtlStringW;
  1022. typedef CStringT< char, StrTraitATL< char > > CAtlStringA;
  1023. typedef CStringT< TCHAR, StrTraitATL< TCHAR > > CAtlString;
  1024. #endif  // _ATL_CSTRING_NO_CRT
  1025. #ifndef _AFX
  1026. typedef CAtlStringW CStringW;
  1027. typedef CAtlStringA CStringA;
  1028. typedef CAtlString CString;
  1029. #endif
  1030. template< typename T >
  1031. class CElementTraits;
  1032. template<>
  1033. class CElementTraits< ATL::CAtlStringA > :
  1034. public CStringElementTraits< ATL::CAtlStringA >
  1035. {
  1036. };
  1037. template<>
  1038. class CElementTraits< ATL::CAtlStringW > :
  1039. public CStringElementTraits< ATL::CAtlStringW >
  1040. {
  1041. };
  1042. }; //namespace ATL
  1043. #pragma pack(pop)
  1044. #endif // __ATLSTR_H__
  1045. /////////////////////////////////////////////////////////////////////////////