Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1241 lines
28 KiB

  1. /*++
  2. Copyright (c) 1985 - 1999, Microsoft Corporation
  3. Module Name:
  4. template.h
  5. Abstract:
  6. This file defines the Template Class.
  7. Author:
  8. Revision History:
  9. Notes:
  10. --*/
  11. #ifndef _TEMPLATE_H_
  12. #define _TEMPLATE_H_
  13. /////////////////////////////////////////////////////////////////////////////
  14. // Basic types
  15. // abstract iteration position
  16. struct __POSITION { };
  17. typedef __POSITION* POSITION;
  18. const POSITION BEFORE_START_POSITION = (POSITION)-1;
  19. /////////////////////////////////////////////////////////////////////////////
  20. // global helpers (can be overridden)
  21. #undef new
  22. inline void * __cdecl operator new(size_t, void *_P)
  23. {
  24. return (_P);
  25. }
  26. template<class TYPE>
  27. void
  28. ConstructElements(
  29. TYPE* pElements,
  30. INT_PTR nCount
  31. )
  32. {
  33. ASSERT(nCount);
  34. // first do bit-wise zero initialization
  35. memset((void*)pElements, 0, (size_t)nCount * sizeof(TYPE));
  36. // then call the constructor(s)
  37. for (; nCount--; pElements++)
  38. ::new((void*)pElements) TYPE;
  39. }
  40. #undef new
  41. // retore mem.h trick
  42. #ifdef DEBUG
  43. #define new new(TEXT(__FILE__), __LINE__)
  44. #endif // DEBUG
  45. template<class TYPE>
  46. void
  47. DestructElements(
  48. TYPE* pElements,
  49. INT_PTR nCount
  50. )
  51. {
  52. ASSERT(nCount);
  53. // call the destructor(s)
  54. for (; nCount--; pElements++)
  55. pElements->~TYPE();
  56. }
  57. template<class TYPE, class ARG_TYPE>
  58. BOOL
  59. CompareElements(
  60. const TYPE* pElement1,
  61. const ARG_TYPE* pElement2
  62. )
  63. {
  64. return *pElement1 == *pElement2;
  65. }
  66. template<class ARG_KEY>
  67. UINT
  68. HashKey(
  69. ARG_KEY key
  70. )
  71. {
  72. // default identity hash - works for most primitive values
  73. return ((UINT)(ULONG_PTR)key) >> 4;
  74. }
  75. struct CPlex // warning variable length structure
  76. {
  77. CPlex* pNext;
  78. // BYTE data[maxNum*elementSize];
  79. void* data() { return this+1; }
  80. static CPlex* PASCAL Create(CPlex*& head, UINT nMax, UINT cbElement);
  81. // like 'calloc' but no zero fill
  82. // may throw memory exceptions
  83. void FreeDataChain(); // free this one and links
  84. };
  85. /////////////////////////////////////////////////////////////////////////////
  86. // CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>
  87. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  88. class CMap
  89. {
  90. public:
  91. CMap(int nBlockSize = default_block_size);
  92. ~CMap();
  93. INT_PTR GetCount() const;
  94. BOOL Lookup(ARG_KEY key, VALUE& rValue) const;
  95. VALUE& operator[](ARG_KEY key);
  96. void SetAt(ARG_KEY key, ARG_VALUE newValue);
  97. BOOL RemoveKey(ARG_KEY key);
  98. void RemoveAll();
  99. POSITION GetStartPosition() const;
  100. void GetNextAssoc(POSITION& rNextPosition, KEY& rKey, VALUE& rValue) const;
  101. void InitHashTable(UINT hashSize, BOOL bAllocNow = TRUE);
  102. private:
  103. // Association
  104. struct CAssoc {
  105. CAssoc* pNext;
  106. UINT nHashValue; // needed for efficient iteration
  107. KEY key;
  108. VALUE value;
  109. };
  110. static const int default_block_size = 10;
  111. private:
  112. CAssoc* NewAssoc();
  113. void FreeAssoc(CAssoc*);
  114. CAssoc* GetAssocAt(ARG_KEY, UINT&) const;
  115. private:
  116. CAssoc** m_pHashTable;
  117. UINT m_nHashTableSize;
  118. INT_PTR m_nCount;
  119. CAssoc* m_pFreeList;
  120. struct CPlex* m_pBlocks;
  121. int m_nBlockSize;
  122. };
  123. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  124. INT_PTR
  125. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetCount(
  126. ) const
  127. {
  128. return m_nCount;
  129. }
  130. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  131. void
  132. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::SetAt(
  133. ARG_KEY key,
  134. ARG_VALUE newValue
  135. )
  136. {
  137. (*this)[key] = newValue;
  138. }
  139. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  140. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CMap(
  141. int nBlockSize
  142. )
  143. {
  144. ASSERT(nBlockSize > 0);
  145. if (nBlockSize <= 0)
  146. nBlockSize = default_block_size;
  147. m_pHashTable = NULL;
  148. m_nHashTableSize = 17; // default size
  149. m_nCount = 0;
  150. m_pFreeList = NULL;
  151. m_pBlocks = NULL;
  152. m_nBlockSize = nBlockSize;
  153. }
  154. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  155. void
  156. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::InitHashTable(
  157. UINT nHashSize,
  158. BOOL bAllocNow
  159. )
  160. {
  161. ASSERT(m_nCount == 0);
  162. ASSERT(nHashSize > 0);
  163. if (m_pHashTable != NULL) {
  164. // free hash table
  165. delete[] m_pHashTable;
  166. m_pHashTable = NULL;
  167. }
  168. if (bAllocNow) {
  169. m_pHashTable = new CAssoc* [nHashSize];
  170. if (! m_pHashTable)
  171. return;
  172. memset(m_pHashTable, 0, sizeof(CAssoc*) * nHashSize);
  173. }
  174. m_nHashTableSize = nHashSize;
  175. }
  176. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  177. void
  178. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::RemoveAll(
  179. )
  180. {
  181. if (m_pHashTable != NULL) {
  182. // destroy elements (values and keys)
  183. for (UINT nHash = 0; nHash < m_nHashTableSize; nHash++) {
  184. CAssoc* pAssoc;
  185. for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext) {
  186. DestructElements<VALUE>(&pAssoc->value, 1);
  187. DestructElements<KEY>(&pAssoc->key, 1);
  188. }
  189. }
  190. }
  191. // free hash table
  192. delete[] m_pHashTable;
  193. m_pHashTable = NULL;
  194. m_nCount = 0;
  195. m_pFreeList = NULL;
  196. m_pBlocks->FreeDataChain();
  197. m_pBlocks = NULL;
  198. }
  199. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  200. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::~CMap(
  201. )
  202. {
  203. RemoveAll();
  204. ASSERT(m_nCount == 0);
  205. }
  206. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  207. typename CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CAssoc*
  208. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::NewAssoc(
  209. )
  210. {
  211. if (m_pFreeList == NULL) {
  212. // add another block
  213. CPlex* newBlock = CPlex::Create(m_pBlocks, m_nBlockSize, sizeof(CMap::CAssoc));
  214. // chain them into free list;
  215. CMap::CAssoc* pAssoc = (CMap::CAssoc*) newBlock->data();
  216. // free in reverse order to make it easier to debug
  217. pAssoc += m_nBlockSize - 1;
  218. for (int i = m_nBlockSize-1; i >= 0; i--, pAssoc--) {
  219. pAssoc->pNext = m_pFreeList;
  220. m_pFreeList = pAssoc;
  221. }
  222. }
  223. ASSERT(m_pFreeList != NULL); // we must have something
  224. CMap::CAssoc* pAssoc = m_pFreeList;
  225. m_pFreeList = m_pFreeList->pNext;
  226. m_nCount++;
  227. ASSERT(m_nCount > 0); // make sure we don't overflow
  228. ConstructElements<KEY>(&pAssoc->key, 1);
  229. ConstructElements<VALUE>(&pAssoc->value, 1); // special construct values
  230. return pAssoc;
  231. }
  232. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  233. void
  234. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::FreeAssoc(
  235. CAssoc* pAssoc
  236. )
  237. {
  238. DestructElements<VALUE>(&pAssoc->value, 1);
  239. DestructElements<KEY>(&pAssoc->key, 1);
  240. pAssoc->pNext = m_pFreeList;
  241. m_pFreeList = pAssoc;
  242. m_nCount--;
  243. ASSERT(m_nCount >= 0); // make sure we don't underflow
  244. // if no more elements, cleanup completely
  245. if (m_nCount == 0)
  246. RemoveAll();
  247. }
  248. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  249. typename CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CAssoc*
  250. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetAssocAt(
  251. ARG_KEY key,
  252. UINT& nHash
  253. ) const
  254. {
  255. nHash = HashKey<ARG_KEY>(key) % m_nHashTableSize;
  256. if (m_pHashTable == NULL)
  257. return NULL;
  258. // see if it exists
  259. CAssoc* pAssoc;
  260. for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext) {
  261. if (CompareElements(&pAssoc->key, &key))
  262. return pAssoc;
  263. }
  264. return NULL;
  265. }
  266. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  267. BOOL
  268. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Lookup(
  269. ARG_KEY key,
  270. VALUE& rValue
  271. ) const
  272. {
  273. UINT nHash;
  274. CAssoc* pAssoc = GetAssocAt(key, nHash);
  275. if (pAssoc == NULL)
  276. return FALSE; // not in map
  277. rValue = pAssoc->value;
  278. return TRUE;
  279. }
  280. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  281. VALUE&
  282. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::operator[](
  283. ARG_KEY key
  284. )
  285. {
  286. UINT nHash;
  287. CAssoc* pAssoc;
  288. if ((pAssoc = GetAssocAt(key, nHash)) == NULL) {
  289. if (m_pHashTable == NULL)
  290. InitHashTable(m_nHashTableSize);
  291. // it doesn't exist, add a new Association
  292. pAssoc = NewAssoc();
  293. pAssoc->nHashValue = nHash;
  294. pAssoc->key = key;
  295. // 'pAssoc->value' is a constructed object, nothing more
  296. // put into hash table
  297. pAssoc->pNext = m_pHashTable[nHash];
  298. m_pHashTable[nHash] = pAssoc;
  299. }
  300. return pAssoc->value; // return new reference
  301. }
  302. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  303. BOOL
  304. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::RemoveKey(
  305. ARG_KEY key
  306. )
  307. {
  308. if (m_pHashTable == NULL)
  309. return FALSE; // nothing in the table
  310. CAssoc** ppAssocPrev;
  311. ppAssocPrev = &m_pHashTable[HashKey<ARG_KEY>(key) % m_nHashTableSize];
  312. CAssoc* pAssoc;
  313. for (pAssoc = *ppAssocPrev; pAssoc != NULL; pAssoc = pAssoc->pNext) {
  314. if (CompareElements(&pAssoc->key, &key)) {
  315. // remove it
  316. *ppAssocPrev = pAssoc->pNext; // remove from list
  317. FreeAssoc(pAssoc);
  318. return TRUE;
  319. }
  320. ppAssocPrev = &pAssoc->pNext;
  321. }
  322. return FALSE; // not found
  323. }
  324. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  325. POSITION
  326. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetStartPosition(
  327. ) const
  328. {
  329. return (m_nCount == 0) ? NULL : BEFORE_START_POSITION;
  330. }
  331. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  332. void
  333. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetNextAssoc(
  334. POSITION& rNextPosition,
  335. KEY& rKey,
  336. VALUE& rValue
  337. ) const
  338. {
  339. ASSERT(m_pHashTable != NULL); // never call on empty map
  340. CAssoc* pAssocRet = (CAssoc*)rNextPosition;
  341. ASSERT(pAssocRet != NULL);
  342. if (pAssocRet == (CAssoc*) BEFORE_START_POSITION) {
  343. // find the first association
  344. for (UINT nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
  345. if ((pAssocRet = m_pHashTable[nBucket]) != NULL)
  346. break;
  347. ASSERT(pAssocRet != NULL); // must find something
  348. }
  349. // find next association
  350. CAssoc* pAssocNext;
  351. if ((pAssocNext = pAssocRet->pNext) == NULL) {
  352. // go to next bucket
  353. for (UINT nBucket = pAssocRet->nHashValue + 1; nBucket < m_nHashTableSize; nBucket++)
  354. if ((pAssocNext = m_pHashTable[nBucket]) != NULL)
  355. break;
  356. }
  357. rNextPosition = (POSITION) pAssocNext;
  358. // fill in return data
  359. rKey = pAssocRet->key;
  360. rValue = pAssocRet->value;
  361. }
  362. /////////////////////////////////////////////////////////////////////////////
  363. // CArray<TYPE, ARG_TYPE>
  364. template<class TYPE, class ARG_TYPE>
  365. class CArray
  366. {
  367. public:
  368. CArray();
  369. ~CArray();
  370. INT_PTR GetSize() const;
  371. BOOL SetSize(INT_PTR nNewSize, INT_PTR nGrowBy = -1);
  372. void RemoveAll();
  373. TYPE GetAt(INT_PTR nIndex) const;
  374. void SetAt(INT_PTR nIndex, ARG_TYPE newElement);
  375. const TYPE* GetData() const;
  376. TYPE* GetData();
  377. void SetAtGrow(INT_PTR nIndex, ARG_TYPE newElement);
  378. INT_PTR Add(ARG_TYPE newElement);
  379. void RemoveAt(int nIndex, int nCount = 1);
  380. private:
  381. TYPE* m_pData; // the actual array of data
  382. INT_PTR m_nSize; // # of elements (upperBound - 1)
  383. INT_PTR m_nMaxSize; // max allocated
  384. INT_PTR m_nGrowBy; // grow amount
  385. };
  386. template<class TYPE, class ARG_TYPE>
  387. CArray<TYPE, ARG_TYPE>::CArray(
  388. )
  389. {
  390. m_pData = NULL;
  391. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  392. }
  393. template<class TYPE, class ARG_TYPE>
  394. CArray<TYPE, ARG_TYPE>::~CArray(
  395. )
  396. {
  397. if (m_pData != NULL) {
  398. DestructElements<TYPE>(m_pData, m_nSize);
  399. delete[] (BYTE*)m_pData;
  400. }
  401. }
  402. template<class TYPE, class ARG_TYPE>
  403. INT_PTR
  404. CArray<TYPE, ARG_TYPE>::GetSize(
  405. ) const
  406. {
  407. return m_nSize;
  408. }
  409. template<class TYPE, class ARG_TYPE>
  410. BOOL
  411. CArray<TYPE, ARG_TYPE>::SetSize(
  412. INT_PTR nNewSize,
  413. INT_PTR nGrowBy
  414. )
  415. {
  416. if (nNewSize < 0)
  417. return FALSE;
  418. if ((nGrowBy == 0) || (nGrowBy < -1))
  419. return FALSE;
  420. if (nGrowBy != -1)
  421. m_nGrowBy = nGrowBy; // set new size
  422. if (nNewSize == 0) {
  423. // shrink to nothing
  424. if (m_pData != NULL) {
  425. DestructElements<TYPE>(m_pData, m_nSize);
  426. delete[] (BYTE*)m_pData;
  427. m_pData = NULL;
  428. }
  429. m_nSize = m_nMaxSize = 0;
  430. }
  431. else if (m_pData == NULL) {
  432. // create one with exact size
  433. m_pData = (TYPE*) new BYTE[(size_t)nNewSize * sizeof(TYPE)];
  434. if (! m_pData)
  435. return FALSE;
  436. ConstructElements<TYPE>(m_pData, nNewSize);
  437. m_nSize = m_nMaxSize = nNewSize;
  438. }
  439. else if (nNewSize <= m_nMaxSize) {
  440. // it fits
  441. if (nNewSize > m_nSize) {
  442. // initialize the new elements
  443. ConstructElements<TYPE>(&m_pData[m_nSize], nNewSize-m_nSize);
  444. }
  445. else if (m_nSize > nNewSize) {
  446. // destroy the old elements
  447. DestructElements<TYPE>(&m_pData[nNewSize], m_nSize-nNewSize);
  448. }
  449. m_nSize = nNewSize;
  450. }
  451. else {
  452. // otherwise, grow array
  453. INT_PTR nTempGrowBy = m_nGrowBy;
  454. if (nTempGrowBy == 0) {
  455. // heuristically determine growth when nTempGrowBy == 0
  456. // (this avoids heap fragmentation in many situations)
  457. nTempGrowBy = m_nSize / 8;
  458. nTempGrowBy = (nTempGrowBy < 4) ? 4 : ((nTempGrowBy > 1024) ? 1024 : nTempGrowBy);
  459. }
  460. INT_PTR nNewMax;
  461. if (nNewSize < m_nMaxSize + nTempGrowBy)
  462. nNewMax = m_nMaxSize + nTempGrowBy; // granularity
  463. else
  464. nNewMax = nNewSize; // no slush
  465. ASSERT(nNewMax >= m_nMaxSize); // no wrap around
  466. TYPE* pNewData = (TYPE*) new BYTE[(size_t)nNewMax * sizeof(TYPE)];
  467. if (! pNewData)
  468. return FALSE;
  469. // copy new data from old
  470. memcpy(pNewData, m_pData, (size_t)m_nSize * sizeof(TYPE));
  471. // construct remaining elements
  472. ASSERT(nNewSize > m_nSize);
  473. ConstructElements<TYPE>(&pNewData[m_nSize], nNewSize-m_nSize);
  474. // get rid of old stuff (note: no destructors called)
  475. delete[] (BYTE*)m_pData;
  476. m_pData = pNewData;
  477. m_nSize = nNewSize;
  478. m_nMaxSize = nNewMax;
  479. }
  480. return TRUE;
  481. }
  482. template<class TYPE, class ARG_TYPE>
  483. void
  484. CArray<TYPE, ARG_TYPE>::RemoveAll(
  485. )
  486. {
  487. SetSize(0);
  488. }
  489. template<class TYPE, class ARG_TYPE>
  490. TYPE
  491. CArray<TYPE, ARG_TYPE>::GetAt(
  492. INT_PTR nIndex
  493. ) const
  494. {
  495. ASSERT(nIndex >= 0 && nIndex < m_nSize);
  496. return m_pData[nIndex];
  497. }
  498. template<class TYPE, class ARG_TYPE>
  499. void
  500. CArray<TYPE, ARG_TYPE>::SetAt(
  501. INT_PTR nIndex,
  502. ARG_TYPE newElement
  503. )
  504. {
  505. ASSERT(nIndex >= 0 && nIndex < m_nSize);
  506. m_pData[nIndex] = newElement;
  507. }
  508. template<class TYPE, class ARG_TYPE>
  509. const TYPE*
  510. CArray<TYPE, ARG_TYPE>::GetData(
  511. ) const
  512. {
  513. return (const TYPE*)m_pData;
  514. }
  515. template<class TYPE, class ARG_TYPE>
  516. TYPE*
  517. CArray<TYPE, ARG_TYPE>::GetData(
  518. )
  519. {
  520. return (TYPE*)m_pData;
  521. }
  522. template<class TYPE, class ARG_TYPE>
  523. void
  524. CArray<TYPE, ARG_TYPE>::SetAtGrow(
  525. INT_PTR nIndex,
  526. ARG_TYPE newElement
  527. )
  528. {
  529. ASSERT(nIndex >= 0);
  530. if (nIndex >= m_nSize)
  531. if (! SetSize(nIndex+1))
  532. return;
  533. m_pData[nIndex] = newElement;
  534. }
  535. template<class TYPE, class ARG_TYPE>
  536. INT_PTR
  537. CArray<TYPE, ARG_TYPE>::Add(
  538. ARG_TYPE newElement
  539. )
  540. {
  541. INT_PTR nIndex = m_nSize;
  542. SetAtGrow(nIndex, newElement);
  543. return nIndex;
  544. }
  545. template<class TYPE, class ARG_TYPE>
  546. void
  547. CArray<TYPE, ARG_TYPE>::RemoveAt(
  548. int nIndex,
  549. int nCount
  550. )
  551. {
  552. // just remove a range
  553. INT_PTR nMoveCount = m_nSize - (nIndex + nCount);
  554. DestructElements<TYPE>(&m_pData[nIndex], nCount);
  555. if (nMoveCount)
  556. memmove(&m_pData[nIndex], &m_pData[nIndex + nCount],
  557. nMoveCount * sizeof(TYPE));
  558. m_nSize -= nCount;
  559. }
  560. /////////////////////////////////////////////////////////////////////////////
  561. // CFirstInFirstOut<TYPE, ARG_TYPE>
  562. template<class TYPE, class ARG_TYPE>
  563. class CFirstInFirstOut
  564. {
  565. public:
  566. CFirstInFirstOut();
  567. ~CFirstInFirstOut();
  568. INT_PTR GetSize() const;
  569. BOOL GetData(TYPE& data);
  570. VOID SetData(TYPE& data);
  571. void GrowBuffer(INT_PTR nGrowBy = 3);
  572. private:
  573. TYPE* m_pData; // the actual ring buffer of data
  574. INT_PTR m_nMaxSize; // max allocated
  575. INT_PTR m_In; // Index of First In of ring buffer
  576. INT_PTR m_Out; // Index of First Out of ring buffer
  577. };
  578. template<class TYPE, class ARG_TYPE>
  579. CFirstInFirstOut<TYPE, ARG_TYPE>::CFirstInFirstOut(
  580. )
  581. {
  582. m_pData = NULL;
  583. m_In = m_Out = 0;
  584. m_nMaxSize = 0;
  585. }
  586. template<class TYPE, class ARG_TYPE>
  587. CFirstInFirstOut<TYPE, ARG_TYPE>::~CFirstInFirstOut(
  588. )
  589. {
  590. if (m_pData != NULL) {
  591. DestructElements<TYPE>(m_pData, m_nMaxSize);
  592. delete[] (BYTE*)m_pData;
  593. }
  594. }
  595. template<class TYPE, class ARG_TYPE>
  596. INT_PTR
  597. CFirstInFirstOut<TYPE, ARG_TYPE>::GetSize(
  598. ) const
  599. {
  600. if (m_Out == m_In) {
  601. return 0; // no more data
  602. }
  603. else if (m_In > m_Out) {
  604. return (m_In - m_Out);
  605. }
  606. else {
  607. return (m_nMaxSize - m_Out) + m_In;
  608. }
  609. }
  610. template<class TYPE, class ARG_TYPE>
  611. BOOL
  612. CFirstInFirstOut<TYPE, ARG_TYPE>::GetData(
  613. TYPE& data
  614. )
  615. {
  616. if (m_Out == m_In) {
  617. return FALSE; // no more data
  618. }
  619. data = m_pData[m_Out++];
  620. if (m_Out == m_nMaxSize)
  621. m_Out = 0;
  622. return TRUE;
  623. }
  624. template<class TYPE, class ARG_TYPE>
  625. VOID
  626. CFirstInFirstOut<TYPE, ARG_TYPE>::SetData(
  627. TYPE& data
  628. )
  629. {
  630. if (m_nMaxSize == 0 || GetSize() >= m_nMaxSize - 1)
  631. GrowBuffer();
  632. m_pData[m_In++] = data;
  633. if (m_In == m_nMaxSize)
  634. m_In = 0;
  635. }
  636. template<class TYPE, class ARG_TYPE>
  637. void
  638. CFirstInFirstOut<TYPE, ARG_TYPE>::GrowBuffer(
  639. INT_PTR nGrowBy
  640. )
  641. {
  642. ASSERT(nGrowBy >= 0);
  643. if (m_pData == NULL) {
  644. // create one with exact size
  645. m_pData = (TYPE*) new BYTE[(size_t)nGrowBy * sizeof(TYPE)];
  646. if (! m_pData)
  647. return;
  648. ConstructElements<TYPE>(m_pData, nGrowBy);
  649. m_nMaxSize = nGrowBy;
  650. }
  651. else {
  652. // otherwise, grow ring buffer
  653. INT_PTR nNewMax = m_nMaxSize + nGrowBy;
  654. TYPE* pNewData = (TYPE*) new BYTE[(size_t)nNewMax * sizeof(TYPE)];
  655. if (! pNewData)
  656. return;
  657. // copy new data from old
  658. memcpy(pNewData, m_pData, (size_t)m_nMaxSize * sizeof(TYPE));
  659. // construct remaining elements
  660. ASSERT(nNewMax > m_nMaxSize);
  661. ConstructElements<TYPE>(&pNewData[m_nMaxSize], nGrowBy);
  662. if (m_Out > m_In) {
  663. // move data to new momory, if out data is remain into the tail of buffer.
  664. memcpy(&pNewData[m_Out+nGrowBy], &m_pData[m_Out], (size_t)(m_nMaxSize-m_Out) * sizeof(TYPE));
  665. m_Out += nGrowBy;
  666. }
  667. // get rid of old stuff (note: no destructors called)
  668. delete[] (BYTE*)m_pData;
  669. m_pData = pNewData;
  670. m_nMaxSize = nNewMax;
  671. }
  672. }
  673. /////////////////////////////////////////////////////////////////////////////
  674. // _Interface<T>
  675. //
  676. // Auto-interface classes
  677. //
  678. template <class T>
  679. class _Interface {
  680. public:
  681. _Interface(T* p = NULL)
  682. : m_p(p)
  683. {
  684. }
  685. virtual ~_Interface() = 0
  686. {
  687. }
  688. bool Valid() { return m_p != NULL; }
  689. bool Invalid() { return !Valid(); }
  690. operator void**() { return (void**)&m_p; }
  691. operator T*() { return m_p; }
  692. operator T**() { return &m_p; }
  693. T* operator->() { return m_p; }
  694. void Attach(T* ip)
  695. {
  696. ASSERT(ip);
  697. m_p = ip;
  698. }
  699. protected:
  700. T* m_p;
  701. private:
  702. // Do not allow to make a copy
  703. _Interface(_Interface<T>&);
  704. void operator=(_Interface<T>&);
  705. };
  706. /////////////////////////////////////////////////////////////////////////////
  707. // Interface_RefCnt<T>
  708. template <class T>
  709. class Interface_RefCnt : public _Interface<T> {
  710. public:
  711. Interface_RefCnt(T* p = NULL) : _Interface<T>(p)
  712. {
  713. if (m_p) {
  714. m_p->AddRef();
  715. }
  716. }
  717. virtual ~Interface_RefCnt()
  718. {
  719. if (m_p) {
  720. m_p->Release();
  721. }
  722. }
  723. private:
  724. // Do not allow to make a copy
  725. Interface_RefCnt(Interface_RefCnt<T>&);
  726. void operator=(Interface_RefCnt<T>&);
  727. };
  728. /////////////////////////////////////////////////////////////////////////////
  729. // Interface_Attach<T>
  730. //
  731. // The specialized class for auto-release
  732. //
  733. template <class T>
  734. class Interface_Attach : public Interface_RefCnt<T> {
  735. public:
  736. // Only the way to create an object of this type is
  737. // from the similar object.
  738. Interface_Attach(T* p) : Interface_RefCnt<T>(p) {}
  739. Interface_Attach(const Interface_Attach<T>& src) : Interface_RefCnt<T>(src.m_p) {}
  740. virtual ~Interface_Attach() {}
  741. // Since this class is extremely naive, get the pointer to
  742. // COM interface through the explicit member function.
  743. T* GetPtr() { return m_p; }
  744. public:
  745. // Do not allow to retrive a pointer
  746. operator T*();
  747. private:
  748. // Do not allow to make a copy
  749. // Interface_Attach(Interface_Attach<T>&);
  750. void operator=(Interface_Attach<T>&);
  751. };
  752. /////////////////////////////////////////////////////////////////////////////
  753. // Interface<T>
  754. //
  755. // The specialized class for auto-release without AddRef.
  756. //
  757. template <class T>
  758. class Interface : public Interface_RefCnt<T> {
  759. public:
  760. Interface() {};
  761. virtual ~Interface() {}
  762. operator T*() { return m_p; }
  763. private:
  764. // Do not allow to make a copy
  765. Interface(Interface<T>&);
  766. void operator=(Interface<T>&);
  767. };
  768. /////////////////////////////////////////////////////////////////////////////
  769. // Interface_Creator<T>
  770. //
  771. // This class should be used only by the creator of the series of
  772. // the objects.
  773. // The specialized class for auto-release without AddRef.
  774. //
  775. template <class T>
  776. class Interface_Creator : public Interface_RefCnt<T> {
  777. public:
  778. Interface_Creator() {};
  779. Interface_Creator(T* p)
  780. {
  781. Attach(p);
  782. }
  783. virtual ~Interface_Creator() {}
  784. bool Valid()
  785. {
  786. if (! Interface_RefCnt<T>::Valid())
  787. return false;
  788. else
  789. return m_p ? m_p->Valid() : false;
  790. }
  791. bool Invalid()
  792. {
  793. if (Interface_RefCnt<T>::Invalid())
  794. return true;
  795. else
  796. return m_p ? m_p->Invalid() : true;
  797. }
  798. private:
  799. // Do not allow to make a copy
  800. Interface_Creator(Interface_Creator<T>&);
  801. void operator=(Interface_Creator<T>&);
  802. };
  803. /////////////////////////////////////////////////////////////////////////////
  804. // Interface_TFSELECTION<>
  805. //
  806. // Specialized interface class for TFSELECTION
  807. // who has a COM pointer in it
  808. //
  809. class Interface_TFSELECTION : public _Interface<TF_SELECTION> {
  810. public:
  811. Interface_TFSELECTION()
  812. {
  813. Attach(&m_sel);
  814. m_p->range = NULL;
  815. }
  816. ~Interface_TFSELECTION()
  817. {
  818. if (m_p && m_p->range) {
  819. m_p->range->Release();
  820. }
  821. }
  822. operator TF_SELECTION*() { return m_p; }
  823. void Release()
  824. {
  825. ASSERT(m_p && m_p->range);
  826. m_p->range->Release();
  827. m_p = NULL;
  828. }
  829. TF_SELECTION m_sel;
  830. private:
  831. // Do not allow to make a copy
  832. Interface_TFSELECTION(Interface_TFSELECTION&);
  833. void operator=(Interface_TFSELECTION&);
  834. };
  835. /////////////////////////////////////////////////////////////////////////////
  836. // CEnumrateInterface<ENUM, CALLBACK>
  837. typedef enum {
  838. ENUM_FIND = 0,
  839. ENUM_CONTINUE, // DoEnumrate never return ENUM_CONTINUE
  840. ENUM_NOMOREDATA
  841. } ENUM_RET;
  842. template<class IF_ENUM, class IF_CALLBACK, class IF_ARG>
  843. class CEnumrateInterface
  844. {
  845. public:
  846. CEnumrateInterface(
  847. Interface<IF_ENUM>& Enum,
  848. ENUM_RET (*pCallback)(IF_CALLBACK* pObj, IF_ARG* Arg),
  849. IF_ARG* Arg = NULL
  850. ) : m_Enum(Enum), m_pfnCallback(pCallback), m_Arg(Arg) {};
  851. ENUM_RET DoEnumrate(void);
  852. private:
  853. Interface<IF_ENUM>& m_Enum;
  854. ENUM_RET (*m_pfnCallback)(IF_CALLBACK* pObj, IF_ARG* Arg);
  855. IF_ARG* m_Arg;
  856. };
  857. template<class IF_ENUM, class IF_CALLBACK, class IF_ARG>
  858. ENUM_RET
  859. CEnumrateInterface<IF_ENUM, IF_CALLBACK, IF_ARG>::DoEnumrate(
  860. void
  861. )
  862. {
  863. HRESULT hr;
  864. IF_CALLBACK* pObj;
  865. while ((hr = m_Enum->Next(1, &pObj, NULL)) == S_OK) {
  866. ENUM_RET ret = (*m_pfnCallback)(pObj, m_Arg);
  867. pObj->Release();
  868. if (ret == ENUM_FIND)
  869. return ret;
  870. }
  871. return ENUM_NOMOREDATA;
  872. }
  873. template<class IF_ENUM, class VAL_CALLBACK, class VAL_ARG>
  874. class CEnumrateValue
  875. {
  876. public:
  877. CEnumrateValue(
  878. Interface<IF_ENUM>& Enum,
  879. ENUM_RET (*pCallback)(VAL_CALLBACK Obj, VAL_ARG* Arg),
  880. VAL_ARG* Arg = NULL
  881. ) : m_Enum(Enum), m_pfnCallback(pCallback), m_Arg(Arg) {};
  882. ENUM_RET DoEnumrate(void);
  883. private:
  884. Interface<IF_ENUM>& m_Enum;
  885. ENUM_RET (*m_pfnCallback)(VAL_CALLBACK Obj, VAL_ARG* Arg);
  886. VAL_ARG* m_Arg;
  887. };
  888. template<class IF_ENUM, class VAL_CALLBACK, class VAL_ARG>
  889. ENUM_RET
  890. CEnumrateValue<IF_ENUM, VAL_CALLBACK, VAL_ARG>::DoEnumrate(
  891. void
  892. )
  893. {
  894. HRESULT hr;
  895. VAL_CALLBACK Obj;
  896. while ((hr = m_Enum->Next(1, &Obj, NULL)) == S_OK) {
  897. ENUM_RET ret = (*m_pfnCallback)(Obj, m_Arg);
  898. if (ret == ENUM_FIND)
  899. return ret;
  900. }
  901. return ENUM_NOMOREDATA;
  902. }
  903. /////////////////////////////////////////////////////////////////////////////
  904. // Alignment template for IA64 and x86
  905. //
  906. // On the assumption that Win32 (user32/gdi32) handle is 32bit length even IA64 platform.
  907. //
  908. template <class TYPE>
  909. class CAlignWinHandle
  910. {
  911. public:
  912. operator TYPE() { return (TYPE)ULongToPtr(dw); }
  913. TYPE operator -> () { return (TYPE)ULongToPtr(dw); }
  914. void operator = (TYPE a)
  915. {
  916. dw = (ULONG)(ULONG_PTR)(a);
  917. }
  918. protected:
  919. DWORD dw; // Alignment is always 32bit.
  920. };
  921. //
  922. // Exception HKL. User32 uses "IntToPtr".
  923. //
  924. class CAlignWinHKL : public CAlignWinHandle<HKL>
  925. {
  926. public:
  927. operator HKL() { return (HKL)IntToPtr(dw); }
  928. HKL operator -> () { return (HKL)IntToPtr(dw); }
  929. void operator = (HKL a)
  930. {
  931. dw = (ULONG)(ULONG_PTR)(a);
  932. }
  933. };
  934. template <class TYPE>
  935. union CAlignPointer
  936. {
  937. public:
  938. operator TYPE() { return h; }
  939. TYPE operator -> () { return h; }
  940. void operator = (TYPE a)
  941. {
  942. #ifndef _WIN64
  943. u = 0; // NULL out high dword.
  944. #endif
  945. h = a;
  946. }
  947. protected:
  948. TYPE h;
  949. private:
  950. __int64 u; // Alignment is always __int64.
  951. };
  952. template <class TYPE>
  953. struct CNativeOrWow64_WinHandle
  954. {
  955. public:
  956. TYPE GetHandle(BOOL _bOnWow64) { return ! _bOnWow64 ? _h : _h_wow6432; }
  957. TYPE SetHandle(BOOL _bOnWow64, TYPE a)
  958. {
  959. if ( ! _bOnWow64)
  960. _h = a;
  961. else
  962. _h_wow6432 = a;
  963. return a;
  964. }
  965. private:
  966. // Native system HHOOK
  967. CAlignWinHandle<TYPE> _h;
  968. // WOW6432 system HHOOK
  969. CAlignWinHandle<TYPE> _h_wow6432;
  970. };
  971. template <class TYPE>
  972. struct CNativeOrWow64_Pointer
  973. {
  974. public:
  975. TYPE GetPunk(BOOL _bOnWow64) { return ! _bOnWow64 ? _pv : _pv_wow6432; }
  976. TYPE SetPunk(BOOL _bOnWow64, TYPE a)
  977. {
  978. if ( ! _bOnWow64)
  979. _pv = a;
  980. else
  981. _pv_wow6432 = a;
  982. return a;
  983. }
  984. private:
  985. // Native system ITfLangBarEventSink
  986. CAlignPointer<TYPE> _pv;
  987. // WOW6432 system ITfLangBarEventSink
  988. CAlignPointer<TYPE> _pv_wow6432;
  989. };
  990. #endif // _TEMPLATE_H_