Advertisement
Guest User

Untitled

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