Source code of Windows XP (NT5)
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.

773 lines
20 KiB

  1. #ifndef Array_hxx
  2. #define Array_hxx
  3. // File: Array.hxx
  4. // Description: Template Class definitions for dynamic array class.
  5. // Notes: Array class has the following features:
  6. // 1. The array can grow dynamically
  7. // 2. The class T must have = operator. When the = operator
  8. // of class T is invoked, it is guaranteed that the memory
  9. // pointed to by the lvalue of the assignment statement is
  10. // cleared to 0. Further, << operator is required for printing
  11. // the list and == operator is required locating or removing
  12. // the objects of class T.
  13. // History: Gopal (08/26/95) -- Creation.
  14. #include <string.h>
  15. #include <iostream.h>
  16. #define AFLAG_OUTOFMEMORY 1
  17. #define AFLAG_ISDIRTY 2
  18. #define ALLOCATED 0
  19. #define RESERVED -1
  20. #define NOFREEITEM -2
  21. typedef int BOOL;
  22. #define TRUE 1
  23. #define FALSE 0
  24. template <class T>
  25. class CArray
  26. {
  27. public:
  28. // Static constructor
  29. static CArray* CreateArray(const unsigned long ulStep=5,
  30. const unsigned long ulSlots=0) {
  31. return(new CArray(ulStep, ulSlots));
  32. }
  33. // Copy constructor
  34. CArray(const CArray& a);
  35. // Reference counting functions
  36. unsigned long AddRef() {
  37. return(++m_refs);
  38. }
  39. unsigned long Release();
  40. // New and Delete operators
  41. void* operator new(size_t size) {
  42. return PrivMemAlloc(size);
  43. };
  44. void operator delete(void *pv){
  45. PrivMemFree(pv);
  46. return;
  47. };
  48. // Functionality functions
  49. unsigned long Length() {
  50. return(m_ulLength);
  51. }
  52. void SetStepSize(unsigned long ulStep) {
  53. m_ulStepSize = ulStep;
  54. return;
  55. }
  56. unsigned long Reserve(const unsigned long ulSlots) {
  57. if(m_ulCurSize)
  58. return(0);
  59. m_ulResSlots = ulSlots;
  60. return(ulSlots);
  61. }
  62. unsigned long Locate(const T& givenitem);
  63. BOOL AddReservedItem(const T& item, const unsigned long ulSlot);
  64. unsigned long AddItem(const T& item);
  65. T* GetItem(const unsigned long index);
  66. BOOL DeleteItem(const unsigned long index);
  67. void DeleteAllItems(void);
  68. BOOL ShiftToEnd(unsigned long ulNode);
  69. void Reset(unsigned long& index, BOOL fEnumResSlots=TRUE) {
  70. if(fEnumResSlots)
  71. index = 0;
  72. else
  73. index = m_ulResSlots;
  74. return;
  75. }
  76. T* GetNext(unsigned long& ulIndex);
  77. T* GetPrev(unsigned long& ulIndex);
  78. BOOL IsOutOfMemory() {
  79. return(m_ulFlags | AFLAG_OUTOFMEMORY);
  80. }
  81. BOOL IsDirty() {
  82. return(m_ulFlags | AFLAG_ISDIRTY);
  83. }
  84. CArray& operator=(const CArray& a);
  85. friend ostream& operator<<(ostream& os, CArray<T>& l);
  86. void Dump();
  87. private:
  88. // Private data type
  89. struct ArrayNode {
  90. // Member variables
  91. T item;
  92. unsigned long next;
  93. unsigned long prev;
  94. };
  95. // Private constructor
  96. CArray(const unsigned long ulStep, const unsigned long ulSlots);
  97. // Private destructor
  98. ~CArray();
  99. // Private member variables
  100. unsigned long m_refs;
  101. unsigned long m_ulFlags;
  102. unsigned long m_ulStepSize;
  103. unsigned long m_ulCurSize;
  104. unsigned long m_ulLength;
  105. unsigned long m_ulResSlots;
  106. unsigned long m_ulHeadNode;
  107. unsigned long m_ulTailNode;
  108. int m_iFree;
  109. int* m_piAllocList;
  110. ArrayNode* m_pBuffer;
  111. void MakeCopy(const CArray& a);
  112. };
  113. template <class T>
  114. CArray<T>::CArray(const unsigned long ulStep, const unsigned long ulSlots)
  115. {
  116. m_refs = 1;
  117. m_ulFlags = 0;
  118. m_ulStepSize = ulStep;
  119. if(m_ulStepSize<1)
  120. m_ulStepSize = 1;
  121. m_ulCurSize = 0;
  122. m_ulLength = 0;
  123. m_ulResSlots = ulSlots;
  124. m_ulHeadNode = 0;
  125. m_ulTailNode = 0;
  126. m_iFree = NOFREEITEM;
  127. m_piAllocList = 0;
  128. m_pBuffer = 0;
  129. }
  130. template <class T>
  131. void CArray<T>::MakeCopy(const CArray<T>& a)
  132. {
  133. // Copy the StepSize
  134. m_ulStepSize = a.m_ulStepSize;
  135. m_ulResSlots = a.m_ulResSlots;
  136. // Allocate the memory for buffer and Allocation list
  137. if(a.m_ulLength>0) {
  138. m_pBuffer = (struct ArrayNode *) PrivMemAlloc(sizeof(ArrayNode)*a.m_ulCurSize);
  139. if(m_pBuffer) {
  140. m_piAllocList = (int *) PrivMemAlloc(sizeof(int)*a.m_ulCurSize);
  141. if(m_piAllocList) {
  142. // Memory allocation succeded.
  143. m_ulFlags = a.m_ulFlags;
  144. m_ulFlags &= ~AFLAG_OUTOFMEMORY;
  145. m_ulCurSize = a.m_ulCurSize;
  146. m_ulLength = 0;
  147. m_ulHeadNode = a.m_ulHeadNode;
  148. m_ulTailNode = a.m_ulTailNode;
  149. m_iFree = a.m_iFree;
  150. memset(m_pBuffer, 0, sizeof(ArrayNode)*m_ulCurSize);
  151. // Now copy the allocation list and the buffer
  152. for(int i=0; i<m_ulCurSize;i++) {
  153. m_piAllocList[i] = a.p_iAllocList[i];
  154. if(m_piAllocList[i]==ALLOCATED) {
  155. // Allocated buffer item. So, copy it
  156. m_pBuffer[i].item = a.m_pBuffer[i].item;
  157. m_pBuffer[i].next = a.m_pBuffer[i].next;
  158. m_pBuffer[i].prev = a.m_pBuffer[i].prev;
  159. m_ulLength++;
  160. }
  161. }
  162. Win4Assert(m_ulLength==a.m_ulLength);
  163. return;
  164. }
  165. // Memory allocation failure
  166. // Free the buffer allocated earlier
  167. PrivMemFree(m_pBuffer);
  168. }
  169. // Set m_Flags to indicate memory allocation failure
  170. // so that we will not try another allocation in future
  171. m_ulFlags = AFLAG_OUTOFMEMORY;
  172. }
  173. m_refs = 1;
  174. m_ulCurSize = 0;
  175. m_ulLength = 0;
  176. m_ulHeadNode = 0;
  177. m_ulTailNode = 0;
  178. m_iFree = NOFREEITEM;
  179. m_piAllocList = 0;
  180. m_pBuffer = 0;
  181. return;
  182. }
  183. template <class T>
  184. CArray<T>::CArray(const CArray<T>& a)
  185. {
  186. // Make a copy
  187. MakeCopy(a);
  188. return;
  189. }
  190. template <class T>
  191. CArray<T>::~CArray()
  192. {
  193. // Call the destructor for valid objects in the buffer
  194. if(m_pBuffer) {
  195. for(unsigned long i=0;i<m_ulCurSize;i++)
  196. if(m_piAllocList[i]==ALLOCATED)
  197. m_pBuffer[i].item.~T();
  198. // Free the allocated memory
  199. PrivMemFree(m_pBuffer);
  200. PrivMemFree(m_piAllocList);
  201. }
  202. return;
  203. }
  204. template <class T>
  205. unsigned long CArray<T>::Release()
  206. {
  207. if(--m_refs==0) {
  208. delete this;
  209. return(0);
  210. }
  211. return(m_refs);
  212. }
  213. template <class T>
  214. unsigned long CArray<T>::Locate(const T& GivenItem)
  215. {
  216. unsigned long i;
  217. if (m_pBuffer == NULL)
  218. return 0;
  219. // Search all the reserved and allocated items in the buffer
  220. for(i=0;i<m_ulResSlots;i++)
  221. if(m_piAllocList[i]==ALLOCATED && m_pBuffer[i].item==GivenItem)
  222. return(i+1);
  223. // Search rest of the nodes
  224. if(m_ulHeadNode) {
  225. i = m_ulHeadNode;
  226. while(i) {
  227. Win4Assert(m_piAllocList[i-1]==ALLOCATED);
  228. if(m_pBuffer[i-1].item==GivenItem)
  229. return(i);
  230. else
  231. i = m_pBuffer[i-1].next;
  232. }
  233. }
  234. return(0);
  235. }
  236. template <class T>
  237. BOOL CArray<T>::AddReservedItem(const T& item, const unsigned long ulSlot)
  238. {
  239. // Sanity check
  240. if(ulSlot<1 || ulSlot>m_ulResSlots)
  241. return(FALSE);
  242. // Check if buffer has been allocated
  243. if(!m_pBuffer && !(m_ulFlags & AFLAG_OUTOFMEMORY)) {
  244. unsigned long i, ulNewSize;
  245. ArrayNode* pNewBuffer;
  246. int* piNewAllocList;
  247. // Compute the new size
  248. ulNewSize = m_ulResSlots + m_ulStepSize;
  249. // Expand the buffer
  250. pNewBuffer = (ArrayNode *) PrivMemAlloc(sizeof(ArrayNode)*(ulNewSize));
  251. if(pNewBuffer) {
  252. piNewAllocList = (int *) PrivMemAlloc(sizeof(int)*(ulNewSize));
  253. if(piNewAllocList) {
  254. // Make the m_pBuffer and m_piAllocList point to the new
  255. // buffer and allocation list
  256. m_pBuffer = pNewBuffer;
  257. m_piAllocList = piNewAllocList;
  258. // Clear the memory in the buffer that is allocated now
  259. memset(&m_pBuffer[0], 0, sizeof(ArrayNode)*ulNewSize);
  260. // Reserve the desiresd number of slots
  261. for(i=0;i<m_ulResSlots;i++)
  262. m_piAllocList[i] = RESERVED;
  263. // Generate the free list
  264. for(i=m_ulResSlots;i<ulNewSize-1;i++)
  265. m_piAllocList[i] = i+2;
  266. m_piAllocList[ulNewSize-1] = NOFREEITEM;
  267. // Make m_iFree point to the first free item in the new buffer
  268. m_iFree = m_ulResSlots+1;
  269. // Update m_ulCurSize
  270. m_ulCurSize = ulNewSize;
  271. }
  272. else {
  273. PrivMemFree(pNewBuffer);
  274. m_ulFlags |= AFLAG_OUTOFMEMORY;
  275. }
  276. }
  277. else
  278. m_ulFlags |= AFLAG_OUTOFMEMORY;
  279. // If we could not expand the buffer, return FALSE
  280. if((m_ulFlags & AFLAG_OUTOFMEMORY))
  281. return(FALSE);
  282. }
  283. // If the reserved slot is occupied, delete the object
  284. if(m_piAllocList[ulSlot-1]==ALLOCATED) {
  285. m_pBuffer[ulSlot-1].item.~T();
  286. memset(&m_pBuffer[ulSlot-1], 0, sizeof(ArrayNode));
  287. }
  288. // Copy the item at the reserved
  289. m_pBuffer[ulSlot-1].item = item;
  290. // Update the allocation list and length
  291. if(m_piAllocList[ulSlot-1]==RESERVED) {
  292. m_piAllocList[ulSlot-1] = ALLOCATED;
  293. ++m_ulLength;
  294. }
  295. // Set the dirty Flag
  296. m_ulFlags |= AFLAG_ISDIRTY;
  297. return(TRUE);
  298. }
  299. template <class T>
  300. unsigned long CArray<T>::AddItem(const T& item)
  301. {
  302. unsigned long i;
  303. // Check if we have free item in the buffer
  304. if(m_iFree==NOFREEITEM && !(m_ulFlags & AFLAG_OUTOFMEMORY)) {
  305. // No free item in the buffer
  306. unsigned long ulNewSize;
  307. ArrayNode* pNewBuffer;
  308. int* piNewAllocList;
  309. // Compute the new size
  310. if(m_pBuffer)
  311. ulNewSize = m_ulCurSize + m_ulStepSize;
  312. else
  313. ulNewSize = m_ulResSlots + m_ulStepSize;
  314. // Expand the buffer
  315. pNewBuffer = (ArrayNode *) PrivMemAlloc(sizeof(ArrayNode)*(ulNewSize));
  316. if(pNewBuffer) {
  317. piNewAllocList = (int *) PrivMemAlloc(sizeof(int)*(ulNewSize));
  318. if(piNewAllocList) {
  319. if(m_pBuffer) {
  320. // Copy the existing buffer and allocation list
  321. memcpy(pNewBuffer, m_pBuffer, sizeof(ArrayNode)*m_ulCurSize);
  322. memcpy(piNewAllocList, m_piAllocList, sizeof(int)*m_ulCurSize);
  323. PrivMemFree(m_pBuffer);
  324. PrivMemFree(m_piAllocList);
  325. }
  326. else {
  327. // Reserve the desiresd number of slots
  328. for(i=0;i<m_ulResSlots;i++)
  329. piNewAllocList[i] = RESERVED;
  330. // Clear the memory in the reserved slots of the buffer
  331. memset(&pNewBuffer[0], 0, sizeof(ArrayNode)*m_ulResSlots);
  332. // Set current size to the number of reserved slots
  333. m_ulCurSize = m_ulResSlots;
  334. }
  335. // Make the m_pBuffer and m_piAllocList point to the new
  336. // buffer and allocation list
  337. m_pBuffer = pNewBuffer;
  338. m_piAllocList = piNewAllocList;
  339. // Clear the memory in the buffer that is allocated now
  340. memset(&m_pBuffer[m_ulCurSize], 0, sizeof(ArrayNode)*m_ulStepSize);
  341. // Generate the free list
  342. for(i=m_ulCurSize;i<ulNewSize-1;i++)
  343. m_piAllocList[i] = i+2;
  344. m_piAllocList[ulNewSize-1] = NOFREEITEM;
  345. // Make m_iFree point to the first free item in the new buffer
  346. m_iFree = m_ulCurSize+1;
  347. // Update m_ulCurSize
  348. m_ulCurSize = ulNewSize;
  349. }
  350. else {
  351. PrivMemFree(pNewBuffer);
  352. m_ulFlags |= AFLAG_OUTOFMEMORY;
  353. }
  354. }
  355. else
  356. m_ulFlags |= AFLAG_OUTOFMEMORY;
  357. }
  358. // If we could not expand the buffer, return 0
  359. if(m_iFree==NOFREEITEM)
  360. return 0;
  361. // Copy the item at the place pointed to by m_iFree
  362. m_pBuffer[m_iFree-1].item = item;
  363. m_pBuffer[m_iFree-1].next = 0;
  364. m_pBuffer[m_iFree-1].prev = m_ulTailNode;
  365. if(m_ulTailNode)
  366. m_pBuffer[m_ulTailNode-1].next = m_iFree;
  367. ++m_ulLength;
  368. // Update the m_ulHeadNode, m_ulTailNode, m_iFree and the allocation list
  369. if(!m_ulHeadNode)
  370. m_ulHeadNode = m_iFree;
  371. m_ulTailNode = m_iFree;
  372. i = m_iFree;
  373. m_iFree = m_piAllocList[i-1];
  374. m_piAllocList[i-1] = ALLOCATED;
  375. // Set the dirty Flag
  376. m_ulFlags |= AFLAG_ISDIRTY;
  377. return(i);
  378. }
  379. template <class T>
  380. T* CArray<T>::GetItem(const unsigned long index)
  381. {
  382. // Sanity checks
  383. if(index>m_ulCurSize || index<1)
  384. return(0);
  385. if(m_piAllocList[index-1]!=ALLOCATED)
  386. return(0);
  387. return(&m_pBuffer[index-1].item);
  388. }
  389. template <class T>
  390. BOOL CArray<T>::DeleteItem(const unsigned long index)
  391. {
  392. // Sanity checks
  393. if(index>m_ulCurSize || index<1)
  394. return(FALSE);
  395. if(m_piAllocList[index-1]!=ALLOCATED)
  396. return(FALSE);
  397. // Delete the object in the buffer
  398. m_pBuffer[index-1].item.~T();
  399. // Relink if index points to a normal item
  400. if(index>m_ulResSlots) {
  401. if(m_pBuffer[index-1].prev)
  402. m_pBuffer[m_pBuffer[index-1].prev-1].next = m_pBuffer[index-1].next;
  403. else {
  404. Win4Assert(m_ulHeadNode==index);
  405. m_ulHeadNode = m_pBuffer[index-1].next;
  406. }
  407. if(m_pBuffer[index-1].next)
  408. m_pBuffer[m_pBuffer[index-1].next-1].prev = m_pBuffer[index-1].prev;
  409. else {
  410. Win4Assert(m_ulTailNode==index);
  411. m_ulTailNode = m_pBuffer[index-1].prev;
  412. }
  413. }
  414. // Clear memory
  415. memset(&m_pBuffer[index-1], 0, sizeof(ArrayNode));
  416. --m_ulLength;
  417. if(index>m_ulResSlots) {
  418. // Update the free list
  419. m_piAllocList[index-1] = m_iFree;
  420. m_iFree = index;
  421. }
  422. else {
  423. // Revert slot to reserved
  424. m_piAllocList[index-1] = RESERVED;
  425. }
  426. return(TRUE);
  427. }
  428. template <class T>
  429. void CArray<T>::DeleteAllItems(void)
  430. {
  431. unsigned long i;
  432. // If we haven't even allocated a buffer yet,
  433. // just return.
  434. if (NULL == m_pBuffer)
  435. return;
  436. // Delete all objects in the buffer
  437. for(i=0;i<m_ulCurSize;i++)
  438. if(m_piAllocList[i]==ALLOCATED)
  439. m_pBuffer[i].item.~T();
  440. // Clear the memory in the buffer
  441. memset(&m_pBuffer[0], 0, sizeof(ArrayNode)*m_ulCurSize);
  442. // Update allocation list
  443. for(i=0;i<m_ulResSlots;i++)
  444. m_piAllocList[i] = RESERVED;
  445. // Update free list
  446. for(i=m_ulResSlots;i<m_ulCurSize-1;i++)
  447. m_piAllocList[i] = i+2;
  448. m_piAllocList[m_ulCurSize-1] = NOFREEITEM;
  449. m_iFree = m_ulResSlots+1;
  450. return;
  451. }
  452. template <class T>
  453. BOOL CArray<T>::ShiftToEnd(unsigned long ulNode)
  454. {
  455. // Sanity check
  456. if(ulNode<=m_ulResSlots || m_piAllocList[ulNode-1]!=ALLOCATED)
  457. return(FALSE);
  458. // Degenerate case
  459. if(!m_pBuffer[ulNode-1].next) {
  460. Win4Assert(ulNode==m_ulTailNode);
  461. return(TRUE);
  462. }
  463. // Fix link info
  464. m_pBuffer[m_ulTailNode-1].next = m_ulHeadNode;
  465. m_pBuffer[m_ulHeadNode-1].prev = m_ulTailNode;
  466. m_ulHeadNode = m_pBuffer[ulNode-1].next;
  467. m_pBuffer[m_ulHeadNode-1].prev = 0;
  468. m_ulTailNode = ulNode;
  469. m_pBuffer[m_ulTailNode-1].next = 0;
  470. return(TRUE);
  471. }
  472. template <class T>
  473. T* CArray<T>::GetNext(unsigned long& index)
  474. {
  475. // Sanity check
  476. if(index>m_ulCurSize)
  477. return(0);
  478. // Search for the next valid item in the buffer
  479. unsigned long i=index;
  480. // Search the reserved slots
  481. while(i<m_ulResSlots) {
  482. ++i;
  483. if(m_piAllocList[i-1]==ALLOCATED) {
  484. index = i;
  485. return(&m_pBuffer[i-1].item);
  486. }
  487. }
  488. // Skip to the next normal node
  489. if(i==m_ulResSlots)
  490. i = m_ulHeadNode;
  491. else {
  492. Win4Assert(m_piAllocList[i-1]==ALLOCATED);
  493. i = m_pBuffer[i-1].next;
  494. }
  495. if(i) {
  496. Win4Assert(m_piAllocList[i-1]==ALLOCATED);
  497. index = i;
  498. return(&m_pBuffer[i-1].item);
  499. }
  500. return 0;
  501. }
  502. template <class T>
  503. T* CArray<T>::GetPrev(unsigned long& index)
  504. {
  505. // Sanity check
  506. if(index<1)
  507. return 0;
  508. // Search for the previous valid item in the buffer
  509. unsigned long i=index;
  510. // Skip to the previous normal node
  511. if(i>m_ulResSlots) {
  512. Win4Assert(m_piAllocList[i-1]==ALLOCATED);
  513. i = m_pBuffer[i-1].prev;
  514. if(i) {
  515. Win4Assert(m_piAllocList[i-1]==ALLOCATED);
  516. index = i;
  517. return(&m_pBuffer[i-1].item);
  518. }
  519. else
  520. i = m_ulResSlots+1;
  521. }
  522. // Search the reserved slots
  523. while(i>1) {
  524. --i;
  525. if(m_piAllocList[i-1]==ALLOCATED) {
  526. index = i;
  527. return(&m_pBuffer[i-1].item);
  528. }
  529. }
  530. return 0;
  531. }
  532. template <class T>
  533. CArray<T>& CArray<T>::operator=(const CArray<T>& a)
  534. {
  535. // Check to see, if this a=a case
  536. if(this==&a)
  537. return(*this);
  538. // Self destroy
  539. CArray<T>::~CArray();
  540. // Now, make a copy
  541. MakeCopy(a);
  542. return(*this);
  543. }
  544. template <class T>
  545. ostream& operator<<(ostream& os, CArray<T>& a)
  546. {
  547. unsigned long i, index;
  548. a.Reset(index);
  549. os << "Length = " << a.m_ulLength <<
  550. " Current Size = " << a.m_ulCurSize << endl;
  551. if(a.m_ulLength) {
  552. os << '[';
  553. for(i=0;i<a.m_ulLength-1;i++)
  554. os << *(a.GetNext(index)) << ',';
  555. os << *(a.GetNext(index)) << ']' << endl;
  556. }
  557. else
  558. os << "[]" << endl;
  559. return(os);
  560. }
  561. template <class T>
  562. void CArray<T>::Dump()
  563. {
  564. unsigned long i;
  565. cerr << "Current Size = " << m_ulCurSize << endl;
  566. cerr << "HeadNode = " << m_ulHeadNode << endl;
  567. cerr << "TailNode = " << m_ulTailNode << endl;
  568. cerr << "FreeNode = " << m_iFree << endl;
  569. if(m_ulCurSize) {
  570. cerr << '[';
  571. for(i=0;i<m_ulCurSize-1;i++) {
  572. if(m_piAllocList[i]==ALLOCATED)
  573. cerr << '(' << m_pBuffer[i].item << ',' << m_pBuffer[i].prev << ','
  574. << m_pBuffer[i].next << "),";
  575. else
  576. cerr << '(' << "NULL," << m_pBuffer[i].prev << ','
  577. << m_pBuffer[i].next << "),";
  578. }
  579. if(m_piAllocList[m_ulCurSize-1]==ALLOCATED)
  580. cerr << '(' << m_pBuffer[m_ulCurSize-1].item << ','
  581. << m_pBuffer[m_ulCurSize-1].prev << ','
  582. << m_pBuffer[m_ulCurSize-1].next << ")]" << endl;
  583. else
  584. cerr << '(' << "NULL,"
  585. << m_pBuffer[m_ulCurSize-1].prev << ','
  586. << m_pBuffer[m_ulCurSize-1].next << ")]" << endl;
  587. cerr << '[';
  588. for(i=0;i<m_ulCurSize-1;i++)
  589. cerr << m_piAllocList[i] << ',';
  590. cerr << m_piAllocList[m_ulCurSize-1] << ']' << endl;
  591. }
  592. else
  593. cerr << "[]" << endl;
  594. return;
  595. }
  596. template <class T>
  597. class CInterfacePtr
  598. {
  599. public:
  600. // Default Constructor
  601. CInterfacePtr(T* a=NULL) {
  602. m_ptr = a;
  603. }
  604. // Copy constructor
  605. CInterfacePtr(const CInterfacePtr& a) {
  606. m_ptr = a.m_ptr;
  607. if(m_ptr)
  608. m_ptr->AddRef();
  609. }
  610. // Destructor
  611. ~CInterfacePtr() {
  612. if(m_ptr)
  613. m_ptr->Release();
  614. }
  615. // New and Delete operators
  616. void* operator new(size_t size) {
  617. return PrivMemAlloc(size);
  618. };
  619. void operator delete(void *pv){
  620. PrivMemFree(pv);
  621. return;
  622. };
  623. // Operators
  624. operator T*() {
  625. return(m_ptr);
  626. }
  627. T* operator->() {
  628. return(m_ptr);
  629. }
  630. T& operator*() {
  631. return(*m_ptr);
  632. }
  633. T& operator[](int i) {
  634. return(m_ptr[i]);
  635. }
  636. T** operator&() {
  637. return(&m_ptr);
  638. }
  639. const CInterfacePtr& operator=(T* a) {
  640. // Check for a=a case
  641. if(this->m_ptr==a)
  642. return(*this);
  643. // Self destroy
  644. CInterfacePtr<T>::~CInterfacePtr();
  645. m_ptr = a;
  646. if(m_ptr)
  647. m_ptr->AddRef();
  648. return(*this);
  649. }
  650. private:
  651. T* m_ptr;
  652. };
  653. #endif // Array_hxx