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

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 __ATLSIMPSTR_H__
  11. #define __ATLSIMPSTR_H__
  12. #pragma once
  13. #include <atldef.h>
  14. #include <atlcore.h>
  15. #include <atlexcept.h>
  16. #include <atlmem.h>
  17. extern "C"
  18. {
  19. LONG __cdecl _InterlockedIncrement( LONG volatile * pn );
  20. LONG __cdecl _InterlockedDecrement( LONG volatile * pn );
  21. };
  22. #pragma intrinsic( _InterlockedIncrement )
  23. #pragma intrinsic( _InterlockedDecrement )
  24. #pragma pack(push,_ATL_PACKING)
  25. namespace ATL
  26. {
  27. struct CStringData;
  28. __interface IAtlStringMgr
  29. {
  30. public:
  31. // Allocate a new CStringData
  32. CStringData* Allocate( int nAllocLength, int nCharSize ) throw();
  33. // Free an existing CStringData
  34. void Free( CStringData* pData ) throw();
  35. // Change the size of an existing CStringData
  36. CStringData* Reallocate( CStringData* pData, int nAllocLength, int nCharSize ) throw();
  37. // Get the CStringData for a Nil string
  38. CStringData* GetNilString() throw();
  39. IAtlStringMgr* Clone() throw();
  40. };
  41. #ifdef _M_IX86
  42. #ifndef _M_CEE
  43. #define _AtlInterlockedIncrement _InterlockedIncrement
  44. #define _AtlInterlockedDecrement _InterlockedDecrement
  45. #else
  46. #define _AtlInterlockedIncrement InterlockedIncrement
  47. #define _AtlInterlockedDecrement InterlockedDecrement
  48. /* managed code must use the non-intrinsics */
  49. #ifdef InterlockedIncrement
  50. #undef InterlockedIncrement
  51. #endif
  52. #ifdef InterlockedDecrement
  53. #undef InterlockedDecrement
  54. #endif
  55. #endif  // !_M_CEE
  56. #else
  57. #define _AtlInterlockedIncrement InterlockedIncrement
  58. #define _AtlInterlockedDecrement InterlockedDecrement
  59. #endif  // _M_IX86_
  60. struct CStringData
  61. {
  62. IAtlStringMgr* pStringMgr;  // String manager for this CStringData
  63. int nDataLength;  // Length of currently used data in XCHARs (not including terminating null)
  64. int nAllocLength;  // Length of allocated data in XCHARs (not including terminating null)
  65. long nRefs;     // Reference count: negative == locked
  66. // XCHAR data[nAllocLength+1]  // A CStringData is always followed in memory by the actual array of character data
  67. void* data() throw()
  68. {
  69. return (this+1);
  70. }
  71. void AddRef() throw()
  72. {
  73. ATLASSERT(nRefs > 0);
  74. _AtlInterlockedIncrement(&nRefs);
  75. }
  76. bool IsLocked() const throw()
  77. {
  78. return nRefs < 0;
  79. }
  80. bool IsShared() const throw()
  81. {
  82. return( nRefs > 1 ); 
  83. }
  84. void Lock() throw()
  85. {
  86. ATLASSERT( nRefs <= 1 );
  87. nRefs--;  // Locked buffers can't be shared, so no interlocked operation necessary
  88. if( nRefs == 0 )
  89. {
  90. nRefs = -1;
  91. }
  92. }
  93. void Release() throw()
  94. {
  95. ATLASSERT( nRefs != 0 );
  96. if( _AtlInterlockedDecrement( &nRefs ) <= 0 )
  97. {
  98. pStringMgr->Free( this );
  99. }
  100. }
  101. void Unlock() throw()
  102. {
  103. ATLASSERT( IsLocked() );
  104. if(IsLocked())
  105. {
  106. nRefs++;  // Locked buffers can't be shared, so no interlocked operation necessary
  107. if( nRefs == 0 )
  108. {
  109. nRefs = 1;
  110. }
  111. }
  112. }
  113. };
  114. class CNilStringData :
  115. public CStringData
  116. {
  117. public:
  118. CNilStringData() throw()
  119. {
  120. pStringMgr = NULL;
  121. nRefs = 2;  // Never gets freed by IAtlStringMgr
  122. nDataLength = 0;
  123. nAllocLength = 0;
  124. achNil[0] = 0;
  125. achNil[1] = 0;
  126. }
  127. void SetManager( __in IAtlStringMgr* pMgr ) throw()
  128. {
  129. ATLASSERT( pStringMgr == NULL );
  130. pStringMgr = pMgr;
  131. }
  132. public:
  133. wchar_t achNil[2];
  134. };
  135. template< typename BaseType, const int t_nSize >
  136. class CStaticString
  137. {
  138. public:
  139. CStaticString( __in const BaseType* psz ) :
  140. m_psz( psz )
  141. {
  142. }
  143. operator const BaseType*() const
  144. {
  145. return m_psz;
  146. }
  147. static int __cdecl GetLength() 
  148. {
  149. return (t_nSize/sizeof( BaseType ))-1;
  150. }
  151. private:
  152. const BaseType* m_psz;
  153. private:
  154. CStaticString( const CStaticString& str ) throw();
  155. CStaticString& operator=( const CStaticString& str ) throw();
  156. };
  157. #define _ST( psz ) ATL::CStaticString< TCHAR, sizeof( _T( psz ) ) >( _T( psz ) )
  158. #define _SA( psz ) ATL::CStaticString< char, sizeof( psz ) >( psz )
  159. #define _SW( psz ) ATL::CStaticString< wchar_t, sizeof( L##psz ) >( L##psz )
  160. #define _SO( psz ) _SW( psz )
  161. template< typename BaseType = char >
  162. class ChTraitsBase
  163. {
  164. public:
  165. typedef char XCHAR;
  166. typedef LPSTR PXSTR;
  167. typedef LPCSTR PCXSTR;
  168. typedef wchar_t YCHAR;
  169. typedef LPWSTR PYSTR;
  170. typedef LPCWSTR PCYSTR;
  171. };
  172. template<>
  173. class ChTraitsBase< wchar_t >
  174. {
  175. public:
  176. typedef wchar_t XCHAR;
  177. typedef LPWSTR PXSTR;
  178. typedef LPCWSTR PCXSTR;
  179. typedef char YCHAR;
  180. typedef LPSTR PYSTR;
  181. typedef LPCSTR PCYSTR;
  182. };
  183. template< typename TCharType, bool t_bMFCDLL = false >
  184. class CStrBufT;
  185. template< typename BaseType , bool t_bMFCDLL = false>
  186. class CSimpleStringT
  187. {
  188. public:
  189. typedef typename ChTraitsBase< BaseType >::XCHAR XCHAR;
  190. typedef typename ChTraitsBase< BaseType >::PXSTR PXSTR;
  191. typedef typename ChTraitsBase< BaseType >::PCXSTR PCXSTR;
  192. typedef typename ChTraitsBase< BaseType >::YCHAR YCHAR;
  193. typedef typename ChTraitsBase< BaseType >::PYSTR PYSTR;
  194. typedef typename ChTraitsBase< BaseType >::PCYSTR PCYSTR;
  195. public:
  196. explicit CSimpleStringT( __in IAtlStringMgr* pStringMgr )
  197. {
  198. ATLENSURE( pStringMgr != NULL );
  199. CStringData* pData = pStringMgr->GetNilString();
  200. Attach( pData );
  201. }
  202. CSimpleStringT( __in const CSimpleStringT& strSrc )
  203. {
  204. CStringData* pSrcData = strSrc.GetData();
  205. CStringData* pNewData = CloneData( pSrcData );
  206. Attach( pNewData );
  207. }
  208. CSimpleStringT( __in const CSimpleStringT<BaseType, !t_bMFCDLL>& strSrc )
  209. {
  210. CStringData* pSrcData = strSrc.GetData();
  211. CStringData* pNewData = CloneData( pSrcData );
  212. Attach( pNewData );
  213. }
  214. CSimpleStringT( __in PCXSTR pszSrc, __in IAtlStringMgr* pStringMgr )
  215. {
  216. ATLENSURE( pStringMgr != NULL );
  217. int nLength = StringLength( pszSrc );
  218. CStringData* pData = pStringMgr->Allocate( nLength, sizeof( XCHAR ) );
  219. if( pData == NULL )
  220. {
  221. ThrowMemoryException();
  222. }
  223. Attach( pData );
  224. SetLength( nLength );
  225. #if _SECURE_ATL
  226.         CopyChars( m_pszData, nLength, pszSrc, nLength );
  227. #else
  228.         CopyChars( m_pszData, pszSrc, nLength );
  229. #endif
  230. }
  231. CSimpleStringT( __in_ecount(nLength) const XCHAR* pchSrc, __in int nLength, __in IAtlStringMgr* pStringMgr )
  232. {
  233. ATLENSURE( pStringMgr != NULL );
  234. if(pchSrc == NULL && nLength != 0)
  235. AtlThrow(E_INVALIDARG);
  236. CStringData* pData = pStringMgr->Allocate( nLength, sizeof( XCHAR ) );
  237. if( pData == NULL )
  238. {
  239. ThrowMemoryException();
  240. }
  241. Attach( pData );
  242. SetLength( nLength );
  243. #if _SECURE_ATL
  244.         CopyChars( m_pszData, nLength, pchSrc, nLength );
  245. #else
  246. CopyChars( m_pszData, pchSrc, nLength );
  247. #endif
  248. }
  249. ~CSimpleStringT() throw()
  250. {
  251. CStringData* pData = GetData();
  252. pData->Release();
  253. }
  254. operator CSimpleStringT<BaseType, !t_bMFCDLL>&()
  255. {
  256. return *(CSimpleStringT<BaseType, !t_bMFCDLL>*)this;
  257. }
  258. CSimpleStringT& operator=( __in const CSimpleStringT& strSrc )
  259. {
  260. CStringData* pSrcData = strSrc.GetData();
  261. CStringData* pOldData = GetData();
  262. if( pSrcData != pOldData)
  263. {
  264. if( pOldData->IsLocked() || pSrcData->pStringMgr != pOldData->pStringMgr )
  265. {
  266. SetString( strSrc.GetString(), strSrc.GetLength() );
  267. }
  268. else
  269. {
  270. CStringData* pNewData = CloneData( pSrcData );
  271. pOldData->Release();
  272. Attach( pNewData );
  273. }
  274. }
  275. return( *this );
  276. }
  277. CSimpleStringT& operator=( __in const CSimpleStringT<BaseType, !t_bMFCDLL>& strSrc )
  278. {
  279. CStringData* pSrcData = strSrc.GetData();
  280. CStringData* pOldData = GetData();
  281. if( pSrcData != pOldData)
  282. {
  283. if( pOldData->IsLocked() || pSrcData->pStringMgr != pOldData->pStringMgr )
  284. {
  285. SetString( strSrc.GetString(), strSrc.GetLength() );
  286. }
  287. else
  288. {
  289. CStringData* pNewData = CloneData( pSrcData );
  290. pOldData->Release();
  291. Attach( pNewData );
  292. }
  293. }
  294. return( *this );
  295. }
  296. CSimpleStringT& operator=( __in PCXSTR pszSrc )
  297. {
  298. SetString( pszSrc );
  299. return( *this );
  300. }
  301. CSimpleStringT& operator+=( __in const CSimpleStringT& strSrc )
  302. {
  303. Append( strSrc );
  304. return( *this );
  305. }
  306. template <bool bMFCDLL>
  307. CSimpleStringT& operator+=( __in const CSimpleStringT<BaseType, bMFCDLL>& strSrc )
  308. {
  309. Append( strSrc );
  310. return( *this );
  311. }
  312. CSimpleStringT& operator+=( __in PCXSTR pszSrc )
  313. {
  314. Append( pszSrc );
  315. return( *this );
  316. }
  317. template< int t_nSize >
  318. CSimpleStringT& operator+=( __in const CStaticString< XCHAR, t_nSize >& strSrc )
  319. {
  320. Append( static_cast<const XCHAR *>(strSrc), strSrc.GetLength() );
  321. return( *this );
  322. }
  323. CSimpleStringT& operator+=( __in char ch )
  324. {
  325. AppendChar( XCHAR( ch ) );
  326. return( *this );
  327. }
  328. CSimpleStringT& operator+=( __in unsigned char ch )
  329. {
  330. AppendChar( XCHAR( ch ) );
  331. return( *this );
  332. }
  333. CSimpleStringT& operator+=( __in wchar_t ch )
  334. {
  335. AppendChar( XCHAR( ch ) );
  336. return( *this );
  337. }
  338. XCHAR operator[]( __in int iChar ) const
  339. {
  340. ATLASSERT( (iChar >= 0) && (iChar <= GetLength()) );  // Indexing the '' is OK
  341. if( (iChar < 0) || (iChar > GetLength()) )
  342. AtlThrow(E_INVALIDARG);
  343. return( m_pszData[iChar] );
  344. }
  345. operator PCXSTR() const throw()
  346. {
  347. return( m_pszData );
  348. }
  349. void Append( __in PCXSTR pszSrc )
  350. {
  351. Append( pszSrc, StringLength( pszSrc ) );
  352. }
  353. void Append( __in_ecount(nLength) PCXSTR pszSrc, __in int nLength )
  354. {
  355. // See comment in SetString() about why we do this
  356. UINT_PTR nOffset = pszSrc-GetString();
  357. UINT nOldLength = GetLength();
  358. if (nOldLength < 0)
  359. {
  360. // protects from underflow
  361. nOldLength = 0;
  362. }
  363. int nNewLength = nOldLength+nLength;
  364. PXSTR pszBuffer = GetBuffer( nNewLength );
  365. if( nOffset <= nOldLength )
  366. {
  367. pszSrc = pszBuffer+nOffset;
  368. // No need to call CopyCharsOverlapped, since the destination is
  369. // beyond the end of the original buffer
  370. }
  371. #if _SECURE_ATL
  372.         CopyChars( pszBuffer+nOldLength, nLength, pszSrc, nLength );
  373. #else
  374.         CopyChars( pszBuffer+nOldLength, pszSrc, nLength );
  375. #endif
  376. ReleaseBufferSetLength( nNewLength );
  377. }
  378. void AppendChar( __in XCHAR ch )
  379. {
  380. UINT nOldLength = GetLength();
  381. int nNewLength = nOldLength+1;
  382. PXSTR pszBuffer = GetBuffer( nNewLength );
  383. pszBuffer[nOldLength] = ch;
  384. ReleaseBufferSetLength( nNewLength );
  385. }
  386. void Append( __in const CSimpleStringT& strSrc )
  387. {
  388. Append( strSrc.GetString(), strSrc.GetLength() );
  389. }
  390. template <bool bMFCDLL>
  391. void Append( __in const CSimpleStringT<BaseType, bMFCDLL>& strSrc )
  392. {
  393. Append( strSrc.GetString(), strSrc.GetLength() );
  394. }
  395. void Empty() throw()
  396. {
  397. CStringData* pOldData = GetData();
  398. IAtlStringMgr* pStringMgr = pOldData->pStringMgr;
  399. if( pOldData->nDataLength == 0 )
  400. {
  401. return;
  402. }
  403. if( pOldData->IsLocked() )
  404. {
  405. // Don't reallocate a locked buffer that's shrinking
  406. SetLength( 0 );
  407. }
  408. else
  409. {
  410. pOldData->Release();
  411. CStringData* pNewData = pStringMgr->GetNilString();
  412. Attach( pNewData );
  413. }
  414. }
  415. void FreeExtra()
  416. {
  417. CStringData* pOldData = GetData();
  418. int nLength = pOldData->nDataLength;
  419. IAtlStringMgr* pStringMgr = pOldData->pStringMgr;
  420. if( pOldData->nAllocLength == nLength )
  421. {
  422. return;
  423. }
  424. if( !pOldData->IsLocked() )  // Don't reallocate a locked buffer that's shrinking
  425. {
  426. CStringData* pNewData = pStringMgr->Allocate( nLength, sizeof( XCHAR ) );
  427. if( pNewData == NULL )
  428. {
  429. SetLength( nLength );
  430. return;
  431. }
  432. #if _SECURE_ATL
  433.             CopyChars( PXSTR( pNewData->data() ), nLength, 
  434. PCXSTR( pOldData->data() ), nLength );
  435. #else
  436. CopyChars( PXSTR( pNewData->data() ), PCXSTR( pOldData->data() ), nLength );
  437. #endif
  438. pOldData->Release();
  439. Attach( pNewData );
  440. SetLength( nLength );
  441. }
  442. }
  443. int GetAllocLength() const throw()
  444. {
  445. return( GetData()->nAllocLength );
  446. }
  447. XCHAR GetAt( __in int iChar ) const
  448. {
  449. ATLASSERT( (iChar >= 0) && (iChar <= GetLength()) );  // Indexing the '' is OK
  450. if( (iChar < 0) || (iChar > GetLength()) )
  451. AtlThrow(E_INVALIDARG);
  452. return( m_pszData[iChar] );
  453. }
  454. PXSTR GetBuffer()
  455. {
  456. CStringData* pData = GetData();
  457. if( pData->IsShared() )
  458. {
  459. Fork( pData->nDataLength );
  460. }
  461. return( m_pszData );
  462. }
  463. __out_ecount(nMinBufferLength + 1) PXSTR GetBuffer( __in int nMinBufferLength )
  464. {
  465. return( PrepareWrite( nMinBufferLength ) );
  466. }
  467. __out_ecount(nLength + 1) PXSTR GetBufferSetLength( __in int nLength )
  468. {
  469. PXSTR pszBuffer = GetBuffer( nLength );
  470. SetLength( nLength );
  471. return( pszBuffer );
  472. }
  473. int GetLength() const throw()
  474. {
  475. return( GetData()->nDataLength );
  476. }
  477. IAtlStringMgr* GetManager() const throw()
  478. {
  479. IAtlStringMgr* pStringMgr = GetData()->pStringMgr;
  480. return pStringMgr ? pStringMgr->Clone() : NULL;
  481. }
  482. __out_ecount(m_nLength) PCXSTR GetString() const throw()
  483. {
  484. return( m_pszData );
  485. }
  486. bool IsEmpty() const throw()
  487. {
  488. return( GetLength() == 0 );
  489. }
  490. PXSTR LockBuffer()
  491. {
  492. CStringData* pData = GetData();
  493. if( pData->IsShared() )
  494. {
  495. Fork( pData->nDataLength );
  496. pData = GetData();  // Do it again, because the fork might have changed it
  497. }
  498. pData->Lock();
  499. return( m_pszData );
  500. }
  501. void UnlockBuffer() throw()
  502. {
  503. CStringData* pData = GetData();
  504. pData->Unlock();
  505. }
  506. void Preallocate( __in int nLength )
  507. {
  508. PrepareWrite( nLength );
  509. }
  510. void ReleaseBuffer( __in int nNewLength = -1 )
  511. {
  512. if( nNewLength == -1 )
  513. {
  514. nNewLength = StringLength( m_pszData );
  515. }
  516. SetLength( nNewLength );
  517. }
  518. void ReleaseBufferSetLength( __in int nNewLength )
  519. {
  520. ATLASSERT( nNewLength >= 0 );
  521. SetLength( nNewLength );
  522. }
  523. void Truncate( __in int nNewLength )
  524. {
  525. ATLASSERT( nNewLength <= GetLength() );
  526. GetBuffer( nNewLength );
  527. ReleaseBufferSetLength( nNewLength );
  528. }
  529. void SetAt( __in int iChar, __in XCHAR ch )
  530. {
  531. ATLASSERT( (iChar >= 0) && (iChar < GetLength()) );
  532. if( (iChar < 0) || (iChar >= GetLength()) )
  533. AtlThrow(E_INVALIDARG);
  534. int nLength = GetLength();
  535. PXSTR pszBuffer = GetBuffer();
  536. pszBuffer[iChar] = ch;
  537. ReleaseBufferSetLength( nLength );
  538. }
  539. void SetManager( __in IAtlStringMgr* pStringMgr )
  540. {
  541. ATLASSERT( IsEmpty() );
  542. CStringData* pData = GetData();
  543. pData->Release();
  544. pData = pStringMgr->GetNilString();
  545. Attach( pData );
  546. }
  547. void SetString( __in PCXSTR pszSrc )
  548. {
  549. SetString( pszSrc, StringLength( pszSrc ) );
  550. }
  551. void SetString( __in_ecount(nLength) PCXSTR pszSrc, __in int nLength )
  552. {
  553. if( nLength == 0 )
  554. {
  555. Empty();
  556. }
  557. else
  558. {
  559. // It is possible that pszSrc points to a location inside of our 
  560. // buffer.  GetBuffer() might change m_pszData if (1) the buffer 
  561. // is shared or (2) the buffer is too small to hold the new 
  562. // string.  We detect this aliasing, and modify pszSrc to point
  563. // into the newly allocated buffer instead.
  564. if(pszSrc == NULL)
  565. AtlThrow(E_INVALIDARG);
  566. UINT nOldLength = GetLength();
  567. UINT_PTR nOffset = pszSrc-GetString();
  568. // If 0 <= nOffset <= nOldLength, then pszSrc points into our 
  569. // buffer
  570. PXSTR pszBuffer = GetBuffer( nLength );
  571. if( nOffset <= nOldLength )
  572. {
  573. #if _SECURE_ATL
  574.                 CopyCharsOverlapped( pszBuffer, nLength, 
  575. pszBuffer+nOffset, nLength );
  576. #else
  577. CopyCharsOverlapped( pszBuffer, pszBuffer+nOffset, nLength );
  578. #endif
  579. }
  580. else
  581. {
  582. #if _SECURE_ATL
  583. CopyChars( pszBuffer, nLength, pszSrc, nLength );
  584. #else
  585. CopyChars( pszBuffer, pszSrc, nLength );
  586. #endif
  587. }
  588. ReleaseBufferSetLength( nLength );
  589. }
  590. }
  591. public:
  592. friend CSimpleStringT operator+(
  593. __in const CSimpleStringT& str1,
  594. __in const CSimpleStringT& str2 )
  595. {
  596. CSimpleStringT s( str1.GetManager() );
  597. Concatenate( s, str1, str1.GetLength(), str2, str2.GetLength() );
  598. return( s );
  599. }
  600. friend CSimpleStringT operator+(
  601. __in const CSimpleStringT& str1,
  602. __in PCXSTR psz2 )
  603. {
  604. CSimpleStringT s( str1.GetManager() );
  605. Concatenate( s, str1, str1.GetLength(), psz2, StringLength( psz2 ) );
  606. return( s );
  607. }
  608. friend CSimpleStringT operator+(
  609. __in PCXSTR psz1,
  610. __in const CSimpleStringT& str2 )
  611. {
  612. CSimpleStringT s( str2.GetManager() );
  613. Concatenate( s, psz1, StringLength( psz1 ), str2, str2.GetLength() );
  614. return( s );
  615. }
  616. _ATL_INSECURE_DEPRECATE("CSimpleStringT::CopyChars must be passed a buffer size")
  617. static void __cdecl CopyChars
  618. ( __out_ecount(nChars) XCHAR* pchDest, __in_ecount(nChars) const XCHAR* pchSrc, __in int nChars ) throw()
  619. {
  620. #pragma warning (push)
  621. #pragma warning(disable : 4996)
  622. memcpy( pchDest, pchSrc, nChars*sizeof( XCHAR ) );
  623. #pragma warning (pop)
  624. }
  625. static void __cdecl CopyChars
  626. ( __out_ecount_part(nDestLen,nChars) XCHAR* pchDest, __in size_t nDestLen, __in_ecount(nChars) const XCHAR* pchSrc, __in int nChars ) throw()
  627. {
  628. memcpy_s( pchDest, nDestLen*sizeof( XCHAR ), 
  629. pchSrc, nChars*sizeof( XCHAR ) );
  630. }
  631. _ATL_INSECURE_DEPRECATE("CSimpleStringT::CopyCharsOverlapped must be passed a buffer size")
  632. static void __cdecl CopyCharsOverlapped
  633. ( __out_ecount(nChars) XCHAR* pchDest, __in_ecount(nChars) const XCHAR* pchSrc, __in int nChars ) throw()
  634. {
  635. #pragma warning (push)
  636. #pragma warning(disable : 4996)
  637. memmove( pchDest, pchSrc, nChars*sizeof( XCHAR ) );
  638. #pragma warning (pop)
  639. }
  640. static void __cdecl CopyCharsOverlapped
  641. ( __out_ecount_part(nDestLen, nDestLen) XCHAR* pchDest, __in size_t nDestLen, __in_ecount(nChars) const XCHAR* pchSrc, __in int nChars ) throw()
  642. {
  643. memmove_s( pchDest, nDestLen*sizeof( XCHAR ), 
  644. pchSrc, nChars*sizeof( XCHAR ) );
  645. }
  646. #ifdef _ATL_MIN_CRT
  647. ATL_NOINLINE static int __cdecl StringLength( __in_z_opt PCXSTR psz ) throw()
  648. {
  649. int nLength = 0;
  650. if( psz != NULL )
  651. {
  652. const XCHAR* pch = psz;
  653. while( *pch != 0 )
  654. {
  655. nLength++;
  656. pch++;
  657. }
  658. }
  659. return( nLength );
  660. }
  661. #else
  662. static int __cdecl StringLength( __in_z_opt const char* psz ) throw()
  663. {
  664. if( psz == NULL )
  665. {
  666. return( 0 );
  667. }
  668. return( int( strlen( psz ) ) );
  669. }
  670. static int __cdecl StringLength( __in_z_opt const wchar_t* psz ) throw()
  671. {
  672. if( psz == NULL )
  673. {
  674. return( 0 );
  675. }
  676. return( int( wcslen( psz ) ) );
  677. }
  678. #endif
  679. protected:
  680. static void __cdecl Concatenate( __out CSimpleStringT& strResult, __in_ecount(nLength1) PCXSTR psz1, __in int nLength1, __in_ecount(nLength2) PCXSTR psz2, __in int nLength2 )
  681. {
  682. int nNewLength = nLength1+nLength2;
  683. PXSTR pszBuffer = strResult.GetBuffer( nNewLength );
  684. #if _SECURE_ATL
  685.         CopyChars( pszBuffer, nLength1, psz1, nLength1 );
  686. CopyChars( pszBuffer+nLength1, nLength2, psz2, nLength2 );
  687. #else
  688.         CopyChars( pszBuffer, psz1, nLength1 );
  689. CopyChars( pszBuffer+nLength1, psz2, nLength2 );
  690. #endif
  691. strResult.ReleaseBufferSetLength( nNewLength );
  692. }
  693. ATL_NOINLINE __declspec( noreturn ) static void __cdecl ThrowMemoryException()
  694. {
  695. AtlThrow( E_OUTOFMEMORY );
  696. }
  697. // Implementation
  698. private:
  699. void Attach( __in CStringData* pData ) throw()
  700. {
  701. m_pszData = static_cast< PXSTR >( pData->data() );
  702. }
  703. ATL_NOINLINE void Fork( __in int nLength )
  704. {
  705. CStringData* pOldData = GetData();
  706. int nOldLength = pOldData->nDataLength;
  707. CStringData* pNewData = pOldData->pStringMgr->Clone()->Allocate( nLength, sizeof( XCHAR ) );
  708. if( pNewData == NULL )
  709. {
  710. ThrowMemoryException();
  711. }
  712. int nCharsToCopy = ((nOldLength < nLength) ? nOldLength : nLength)+1;  // Copy ''
  713. #if _SECURE_ATL
  714.         CopyChars( PXSTR( pNewData->data() ), nCharsToCopy, 
  715. PCXSTR( pOldData->data() ), nCharsToCopy );
  716. #else
  717.         CopyChars( PXSTR( pNewData->data() ), PCXSTR( pOldData->data() ), nCharsToCopy );
  718. #endif
  719. pNewData->nDataLength = nOldLength;
  720. pOldData->Release();
  721. Attach( pNewData );
  722. }
  723. CStringData* GetData() const throw()
  724. {
  725. return( reinterpret_cast< CStringData* >( m_pszData )-1 );
  726. }
  727. PXSTR PrepareWrite( __in int nLength )
  728. {
  729. CStringData* pOldData = GetData();
  730. int nShared = 1-pOldData->nRefs;  // nShared < 0 means true, >= 0 means false
  731. int nTooShort = pOldData->nAllocLength-nLength;  // nTooShort < 0 means true, >= 0 means false
  732. if( (nShared|nTooShort) < 0 )  // If either sign bit is set (i.e. either is less than zero), we need to copy data
  733. {
  734. PrepareWrite2( nLength );
  735. }
  736. return( m_pszData );
  737. }
  738. ATL_NOINLINE void PrepareWrite2( __in int nLength )
  739. {
  740. CStringData* pOldData = GetData();
  741. if( pOldData->nDataLength > nLength )
  742. {
  743. nLength = pOldData->nDataLength;
  744. }
  745. if( pOldData->IsShared() )
  746. {
  747. Fork( nLength );
  748. }
  749. else if( pOldData->nAllocLength < nLength )
  750. {
  751. // Grow exponentially, until we hit 1K.
  752. int nNewLength = pOldData->nAllocLength;
  753. if( nNewLength > 1024 )
  754. {
  755. nNewLength += 1024;
  756. }
  757. else
  758. {
  759. nNewLength *= 2;
  760. }
  761. if( nNewLength < nLength )
  762. {
  763. nNewLength = nLength;
  764. }
  765. Reallocate( nNewLength );
  766. }
  767. }
  768. ATL_NOINLINE void Reallocate( __in int nLength )
  769. {
  770. CStringData* pOldData = GetData();
  771. ATLASSERT( pOldData->nAllocLength < nLength );
  772. IAtlStringMgr* pStringMgr = pOldData->pStringMgr;
  773.                 if ( pOldData->nAllocLength >= nLength || nLength <= 0)
  774.                 {
  775. ThrowMemoryException();
  776.                         return;
  777.                 }
  778. CStringData* pNewData = pStringMgr->Reallocate( pOldData, nLength, sizeof( XCHAR ) );
  779. if( pNewData == NULL )
  780. {
  781. ThrowMemoryException();
  782. }
  783. Attach( pNewData );
  784. }
  785. void SetLength( __in int nLength )
  786. {
  787. ATLASSERT( nLength >= 0 );
  788. ATLASSERT( nLength <= GetData()->nAllocLength );
  789. if( nLength < 0 || nLength > GetData()->nAllocLength)
  790. AtlThrow(E_INVALIDARG);
  791. GetData()->nDataLength = nLength;
  792. m_pszData[nLength] = 0;
  793. }
  794. static CStringData* __cdecl CloneData( __in CStringData* pData )
  795. {
  796. CStringData* pNewData = NULL;
  797. IAtlStringMgr* pNewStringMgr = pData->pStringMgr->Clone();
  798. if( !pData->IsLocked() && (pNewStringMgr == pData->pStringMgr) )
  799. {
  800. pNewData = pData;
  801. pNewData->AddRef();
  802. }
  803. else
  804. {
  805. pNewData = pNewStringMgr->Allocate( pData->nDataLength, sizeof( XCHAR ) );
  806. if( pNewData == NULL )
  807. {
  808. ThrowMemoryException();
  809. }
  810. pNewData->nDataLength = pData->nDataLength;
  811. #if _SECURE_ATL
  812.             CopyChars( PXSTR( pNewData->data() ), pData->nDataLength+1,
  813. PCXSTR( pData->data() ), pData->nDataLength+1 );  // Copy ''
  814. #else
  815. CopyChars( PXSTR( pNewData->data() ), PCXSTR( pData->data() ), pData->nDataLength+1 );  // Copy ''
  816. #endif
  817. }
  818. return( pNewData );
  819. }
  820. public :
  821. typedef CStrBufT<BaseType, t_bMFCDLL> CStrBuf;
  822. private:
  823. PXSTR m_pszData;
  824. friend class CSimpleStringT<BaseType, !t_bMFCDLL>;
  825. };
  826. template< typename TCharType, bool t_bMFCDLL >
  827. class CStrBufT
  828. {
  829. public:
  830. typedef CSimpleStringT< TCharType, t_bMFCDLL> StringType;
  831. typedef typename StringType::XCHAR XCHAR;
  832. typedef typename StringType::PXSTR PXSTR;
  833. typedef typename StringType::PCXSTR PCXSTR;
  834. static const DWORD AUTO_LENGTH = 0x01;  // Automatically determine the new length of the string at release.  The string must be null-terminated.
  835. static const DWORD SET_LENGTH = 0x02;  // Set the length of the string object at GetBuffer time
  836. public:
  837. explicit CStrBufT( __in StringType& str ) throw( ... ) :
  838. m_str( str ),
  839. m_pszBuffer( NULL ),
  840. #ifdef _DEBUG
  841. m_nBufferLength( str.GetLength() ),
  842. #endif
  843. m_nLength( str.GetLength() )
  844. {
  845. m_pszBuffer = m_str.GetBuffer();
  846. }
  847. CStrBufT( __in StringType& str, __in int nMinLength, __in DWORD dwFlags = AUTO_LENGTH ) throw( ... ) :
  848. m_str( str ),
  849. m_pszBuffer( NULL ),
  850. #ifdef _DEBUG
  851. m_nBufferLength( nMinLength ),
  852. #endif
  853. m_nLength( (dwFlags&AUTO_LENGTH) ? -1 : nMinLength )
  854. {
  855. if( dwFlags&SET_LENGTH )
  856. {
  857. m_pszBuffer = m_str.GetBufferSetLength( nMinLength );
  858. }
  859. else
  860. {
  861. m_pszBuffer = m_str.GetBuffer( nMinLength );
  862. }
  863. }
  864. ~CStrBufT()
  865. {
  866. m_str.ReleaseBuffer( m_nLength );
  867. }
  868. operator PXSTR() throw()
  869. {
  870. return( m_pszBuffer );
  871. }
  872. operator PCXSTR() const throw()
  873. {
  874. return( m_pszBuffer );
  875. }
  876. void SetLength( __in int nLength )
  877. {
  878. ATLASSERT( nLength >= 0 );
  879. ATLASSERT( nLength <= m_nBufferLength );
  880. if( nLength < 0 )
  881. AtlThrow(E_INVALIDARG);
  882. m_nLength = nLength;
  883. }
  884. // Implementation
  885. private:
  886. StringType& m_str;
  887. PXSTR m_pszBuffer;
  888. int m_nLength;
  889. #ifdef _DEBUG
  890. int m_nBufferLength;
  891. #endif
  892. // Private copy constructor and copy assignment operator to prevent accidental use
  893. private:
  894. CStrBufT( const CStrBufT& ) throw();
  895. CStrBufT& operator=( const CStrBufT& ) throw();
  896. };
  897. typedef CSimpleStringT< TCHAR > CSimpleString;
  898. typedef CSimpleStringT< char > CSimpleStringA;
  899. typedef CSimpleStringT< wchar_t > CSimpleStringW;
  900. typedef CStrBufT< TCHAR > CStrBuf;
  901. typedef CStrBufT< char > CStrBufA;
  902. typedef CStrBufT< wchar_t > CStrBufW;
  903. };  // namespace ATL
  904. #pragma pack(pop)
  905. #endif  // __ATLSIMPSTR_H__