1 #ifndef __ATLCOLL_H__ 2 #define __ATLCOLL_H__ 3 4 #pragma once 5 #include "atlbase.h" 6 #include "atlexcept.h" 7 8 // FIXME: We need to include <new> for placement new, but that would mean everyone using atl 9 // would also need to set the option 'WITH_STL'.. 10 // For now we just copy the definition here, under a guard.. 11 #ifndef _NEW 12 inline void* operator new (size_t size, void* ptr) noexcept { return ptr; } 13 inline void operator delete (void* ptr, void* voidptr2) noexcept { } 14 #endif 15 16 17 struct __POSITION 18 { 19 }; 20 typedef __POSITION* POSITION; 21 22 23 namespace ATL 24 { 25 26 class CAtlPlex 27 { 28 public: 29 CAtlPlex* m_Next; 30 31 #if (_AFX_PACKING >= 8) 32 DWORD dwReserved[1]; 33 #endif 34 35 static inline CAtlPlex* Create( 36 _Inout_ CAtlPlex*& Entry, 37 _In_ size_t MaxElements, 38 _In_ size_t ElementSize 39 ) 40 { 41 CAtlPlex* Block; 42 43 ATLASSERT(MaxElements > 0); 44 ATLASSERT(ElementSize > 0); 45 46 size_t BufferSize = sizeof(CAtlPlex) + (MaxElements * ElementSize); 47 48 void *Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize); 49 if (Buffer == NULL) return NULL; 50 51 Block = static_cast< CAtlPlex* >(Buffer); 52 Block->m_Next = Entry; 53 Entry = Block; 54 55 return Block; 56 } 57 58 void* GetData() 59 { 60 return (this + 1); 61 } 62 63 inline void Destroy() 64 { 65 CAtlPlex* Block; 66 CAtlPlex* Next; 67 68 Block = this; 69 while (Block != NULL) 70 { 71 Next = Block->m_Next; 72 HeapFree(GetProcessHeap(), 0, Block); 73 Block = Next; 74 } 75 } 76 }; 77 78 79 template<typename T> 80 class CElementTraitsBase 81 { 82 public: 83 typedef const T& INARGTYPE; 84 typedef T& OUTARGTYPE; 85 86 static void CopyElements( 87 _Out_writes_all_(NumElements) T* Dest, 88 _In_reads_(NumElements) const T* Source, 89 _In_ size_t NumElements) 90 { 91 for (size_t i = 0; i < NumElements; i++) 92 { 93 Dest[i] = Source[i]; 94 } 95 } 96 97 static void RelocateElements( 98 _Out_writes_all_(NumElements) T* Dest, 99 _In_reads_(NumElements) T* Source, 100 _In_ size_t NumElements) 101 { 102 // A simple memmove works for most of the types. 103 // You'll have to override this for types that have pointers to their 104 // own members. 105 106 #if defined(__GNUC__) && __GNUC__ >= 8 107 #pragma GCC diagnostic push 108 #pragma GCC diagnostic ignored "-Wclass-memaccess" 109 #endif 110 memmove(Dest, Source, NumElements * sizeof(T)); 111 #if defined(__GNUC__) && __GNUC__ >= 8 112 #pragma GCC diagnostic pop 113 #endif 114 } 115 }; 116 117 template<typename T> 118 class CDefaultCompareTraits 119 { 120 public: 121 static bool CompareElements( 122 _In_ const T& Val1, 123 _In_ const T& Val2) 124 { 125 return (Val1 == Val2); 126 } 127 128 static int CompareElementsOrdered( 129 _In_ const T& Val1, 130 _In_ const T& Val2) 131 { 132 if (Val1 < Val2) 133 { 134 return -1; 135 } 136 else if (Val1 > Val2) 137 { 138 return 1; 139 } 140 141 return 0; // equal 142 } 143 }; 144 145 template<typename T> 146 class CDefaultElementTraits : 147 public CElementTraitsBase<T>, 148 public CDefaultCompareTraits<T> 149 { 150 }; 151 152 153 template<typename T> 154 class CElementTraits : 155 public CDefaultElementTraits<T> 156 { 157 }; 158 159 160 template<typename T, class Allocator = CCRTAllocator> 161 class CHeapPtrElementTraits : 162 public CDefaultElementTraits< CHeapPtr<T, Allocator> > 163 { 164 public: 165 typedef CHeapPtr<T, Allocator>& INARGTYPE; 166 typedef T*& OUTARGTYPE; 167 }; 168 169 170 171 template<typename E, class ETraits = CElementTraits<E> > 172 class CAtlArray 173 { 174 public: 175 typedef typename ETraits::INARGTYPE INARGTYPE; 176 typedef typename ETraits::OUTARGTYPE OUTARGTYPE; 177 178 private: 179 E* m_pData; 180 size_t m_Size; 181 size_t m_AllocatedSize; 182 size_t m_GrowBy; 183 184 185 #pragma push_macro("new") 186 #undef new 187 188 void CreateItems(E* pData, size_t Size) 189 { 190 for (size_t n = 0; n < Size; ++n) 191 { 192 ::new (pData + n) E; 193 } 194 } 195 196 #pragma pop_macro("new") 197 198 void DestructItems(E* pData, size_t Size) 199 { 200 for (size_t n = 0; n < Size; ++n) 201 { 202 pData[n].~E(); 203 } 204 } 205 206 bool GrowAllocatedData(size_t nNewSize) 207 { 208 if (m_pData) 209 { 210 size_t addSize = m_GrowBy > 0 ? m_GrowBy : m_AllocatedSize / 2; 211 size_t allocSize = m_AllocatedSize + addSize; 212 if (allocSize < nNewSize) 213 allocSize = nNewSize; 214 215 E* pData = (E*)malloc(nNewSize * sizeof(E)); 216 217 if (pData == NULL) 218 { 219 return false; 220 } 221 222 // Copy the objects over (default implementation will just move them without calling anything 223 ETraits::RelocateElements(pData, m_pData, m_Size); 224 225 free(m_pData); 226 m_pData = pData; 227 m_AllocatedSize = nNewSize; 228 } 229 else 230 { 231 // We need to allocate a new buffer 232 size_t allocSize = m_GrowBy > nNewSize ? m_GrowBy : nNewSize; 233 m_pData = (E*)malloc(allocSize * sizeof(E)); 234 if (m_pData == NULL) 235 { 236 return false; 237 } 238 m_AllocatedSize = allocSize; 239 } 240 return true; 241 } 242 243 /* The CAtlArray class does not support construction by copy */ 244 private: 245 CAtlArray(_In_ const CAtlArray&); 246 CAtlArray& operator=(_In_ const CAtlArray&); 247 248 public: 249 CAtlArray(); 250 ~CAtlArray(); 251 252 size_t Add(INARGTYPE element); 253 size_t Add(); 254 255 bool SetCount(size_t nNewSize, int nGrowBy = - 1); 256 size_t GetCount() const; 257 258 E& operator[](size_t ielement); 259 const E& operator[](size_t ielement) const; 260 261 E& GetAt(size_t iElement); 262 const E& GetAt(size_t iElement) const; 263 264 E* GetData(); 265 const E* GetData() const; 266 267 268 //FIXME: Most of this class is missing! 269 }; 270 271 // 272 // CAtlArray public methods 273 // 274 275 template<typename E, class ETraits> 276 CAtlArray< E, ETraits >::CAtlArray() 277 : m_pData(NULL) 278 , m_Size(0) 279 , m_AllocatedSize(0) 280 , m_GrowBy(0) 281 { 282 } 283 284 template<typename E, class ETraits> 285 CAtlArray< E, ETraits >::~CAtlArray() 286 { 287 // Destroy all items 288 SetCount(0, -1); 289 } 290 291 #pragma push_macro("new") 292 #undef new 293 294 template<typename E, class ETraits> 295 size_t CAtlArray<E, ETraits>::Add(INARGTYPE element) 296 { 297 if (m_Size >= m_AllocatedSize) 298 { 299 if (!GrowAllocatedData(m_Size + 1)) 300 { 301 AtlThrow(E_OUTOFMEMORY); 302 } 303 } 304 305 ::new (m_pData + m_Size) E(element); 306 m_Size++; 307 308 return m_Size - 1; 309 } 310 311 #pragma pop_macro("new") 312 313 template<typename E, class ETraits> 314 size_t CAtlArray<E, ETraits>::Add() 315 { 316 if (!SetCount(m_Size + 1)) 317 { 318 AtlThrow(E_OUTOFMEMORY); 319 } 320 321 return m_Size - 1; 322 } 323 324 template<typename E, class ETraits> 325 bool CAtlArray<E, ETraits>::SetCount(size_t nNewSize, int nGrowBy /*= -1*/) 326 { 327 328 if (nGrowBy > -1) 329 { 330 m_GrowBy = (size_t)nGrowBy; 331 } 332 333 if (nNewSize == m_Size) 334 { 335 // Do nothing 336 } 337 else if (nNewSize == 0) 338 { 339 if (m_pData) 340 { 341 DestructItems(m_pData, m_Size); 342 m_pData = NULL; 343 } 344 m_Size = m_AllocatedSize = NULL; 345 } 346 else if (nNewSize < m_AllocatedSize) 347 { 348 if (nNewSize > m_Size) 349 { 350 CreateItems(m_pData + m_Size, nNewSize - m_Size); 351 } 352 else 353 { 354 DestructItems(m_pData + nNewSize, m_Size - nNewSize); 355 } 356 m_Size = nNewSize; 357 } 358 else 359 { 360 if (!GrowAllocatedData(nNewSize)) 361 { 362 return false; 363 } 364 365 CreateItems(m_pData + m_Size, nNewSize - m_Size); 366 m_Size = nNewSize; 367 } 368 369 return true; 370 } 371 372 template<typename E, class ETraits> 373 size_t CAtlArray<E, ETraits>::GetCount() const 374 { 375 return m_Size; 376 } 377 378 template<typename E, class ETraits> 379 E& CAtlArray<E, ETraits>::operator[](size_t iElement) 380 { 381 ATLASSERT(iElement < m_Size); 382 383 return m_pData[iElement]; 384 } 385 386 template<typename E, class ETraits> 387 const E& CAtlArray<E, ETraits>::operator[](size_t iElement) const 388 { 389 ATLASSERT(iElement < m_Size); 390 391 return m_pData[iElement]; 392 } 393 394 template<typename E, class ETraits> 395 E& CAtlArray<E, ETraits>::GetAt(size_t iElement) 396 { 397 ATLASSERT(iElement < m_Size); 398 399 return m_pData[iElement]; 400 } 401 402 template<typename E, class ETraits> 403 const E& CAtlArray<E, ETraits>::GetAt(size_t iElement) const 404 { 405 ATLASSERT(iElement < m_Size); 406 407 return m_pData[iElement]; 408 } 409 410 template<typename E, class ETraits> 411 E* CAtlArray<E, ETraits>::GetData() 412 { 413 return m_pData; 414 } 415 416 template<typename E, class ETraits> 417 const E* CAtlArray<E, ETraits>::GetData() const 418 { 419 return m_pData; 420 } 421 422 423 template<typename E, class ETraits = CElementTraits<E> > 424 class CAtlList 425 { 426 private: 427 typedef typename ETraits::INARGTYPE INARGTYPE; 428 429 private: 430 class CNode : public __POSITION 431 { 432 public: 433 CNode* m_Next; 434 CNode* m_Prev; 435 E m_Element; 436 437 public: 438 CNode(INARGTYPE Element) : 439 m_Element(Element) 440 { 441 } 442 443 /* The CNode class does not support construction by copy */ 444 private: 445 CNode(_In_ const CNode&); 446 CNode& operator=(_In_ const CNode&); 447 }; 448 449 private: 450 CAtlPlex* m_Blocks; 451 UINT m_BlockSize; 452 CNode* m_HeadNode; 453 CNode* m_TailNode; 454 CNode* m_FreeNode; 455 size_t m_NumElements; 456 457 /* The CAtlList class does not support construction by copy */ 458 private: 459 CAtlList(_In_ const CAtlList&); 460 CAtlList& operator=(_In_ const CAtlList&); 461 462 public: 463 CAtlList(_In_ UINT nBlockSize = 10); 464 ~CAtlList(); 465 466 size_t GetCount() const; 467 bool IsEmpty() const; 468 469 POSITION GetHeadPosition() const; 470 POSITION GetTailPosition() const; 471 472 E& GetNext(_Inout_ POSITION& pos); 473 const E& GetNext(_Inout_ POSITION& pos) const; 474 E& GetPrev(_Inout_ POSITION& pos); 475 const E& GetPrev(_Inout_ POSITION& pos) const; 476 477 E& GetAt(_In_ POSITION pos); 478 const E& GetAt(_In_ POSITION pos) const; 479 480 POSITION AddHead(INARGTYPE element); 481 POSITION AddTail(INARGTYPE element); 482 483 E RemoveHead(); 484 E RemoveTail(); 485 486 POSITION InsertBefore(_In_ POSITION pos, INARGTYPE element); 487 POSITION InsertAfter(_In_ POSITION pos, INARGTYPE element); 488 489 void RemoveAll(); 490 void RemoveAt(_In_ POSITION pos); 491 492 POSITION Find( 493 INARGTYPE element, 494 _In_opt_ POSITION posStartAfter = NULL) const; 495 POSITION FindIndex(_In_ size_t iElement) const; 496 497 void SwapElements(POSITION pos1, POSITION pos2); 498 499 private: 500 CNode* CreateNode( 501 INARGTYPE element, 502 _In_opt_ CNode* pPrev, 503 _In_opt_ CNode* pNext 504 ); 505 506 void FreeNode( 507 _Inout_ CNode* pNode 508 ); 509 510 CNode* GetFreeNode( 511 ); 512 513 }; 514 515 516 // 517 // CAtlist public methods 518 // 519 520 template<typename E, class ETraits> 521 CAtlList< E, ETraits >::CAtlList(_In_ UINT nBlockSize) : 522 m_Blocks(NULL), 523 m_BlockSize(nBlockSize), 524 m_HeadNode(NULL), 525 m_TailNode(NULL), 526 m_FreeNode(NULL), 527 m_NumElements(0) 528 { 529 ATLASSERT(nBlockSize > 0); 530 } 531 532 template<typename E, class ETraits> 533 CAtlList<E, ETraits >::~CAtlList(void) 534 { 535 RemoveAll(); 536 } 537 538 template<typename E, class ETraits> 539 inline size_t CAtlList< E, ETraits >::GetCount() const 540 { 541 return m_NumElements; 542 } 543 544 template<typename E, class ETraits> 545 inline bool CAtlList< E, ETraits >::IsEmpty() const 546 { 547 return (m_NumElements == 0); 548 } 549 550 template<typename E, class ETraits> 551 inline POSITION CAtlList<E, ETraits>::GetHeadPosition() const 552 { 553 return (POSITION)m_HeadNode; 554 } 555 556 template<typename E, class ETraits> 557 inline POSITION CAtlList<E, ETraits>::GetTailPosition() const 558 { 559 return (POSITION)m_TailNode; 560 } 561 562 template<typename E, class ETraits> 563 inline E& CAtlList< E, ETraits >::GetNext(_Inout_ POSITION& pos) 564 { 565 CNode* Node = (CNode*)pos; 566 pos = (POSITION)Node->m_Next; 567 return Node->m_Element; 568 } 569 570 template<typename E, class ETraits> 571 inline const E& CAtlList< E, ETraits >::GetNext(_Inout_ POSITION& pos) const 572 { 573 CNode* Node = (CNode*)pos; 574 pos = (POSITION)Node->m_Next; 575 return Node->m_Element; 576 } 577 578 template<typename E, class ETraits> 579 inline E& CAtlList< E, ETraits >::GetPrev(_Inout_ POSITION& pos) 580 { 581 CNode* Node = (CNode*)pos; 582 pos = (POSITION)Node->m_Prev; 583 return Node->m_Element; 584 } 585 586 template<typename E, class ETraits> 587 inline const E& CAtlList< E, ETraits >::GetPrev(_Inout_ POSITION& pos) const 588 { 589 CNode* Node = (CNode*)pos; 590 pos = (POSITION)Node->m_Prev; 591 return Node->m_Element; 592 } 593 594 template<typename E, class ETraits> 595 inline E& CAtlList< E, ETraits >::GetAt(_In_ POSITION pos) 596 { 597 CNode* Node = (CNode*)pos; 598 return Node->m_Element; 599 } 600 601 template<typename E, class ETraits> 602 inline const E& CAtlList< E, ETraits >::GetAt(_In_ POSITION pos) const 603 { 604 CNode* Node = (CNode*)pos; 605 return Node->m_Element; 606 } 607 608 template<typename E, class ETraits> 609 POSITION CAtlList<E, ETraits>::AddHead(INARGTYPE element) 610 { 611 CNode* Node = CreateNode(element, NULL, m_HeadNode); 612 if (m_HeadNode) 613 { 614 m_HeadNode->m_Prev = Node; 615 } 616 else 617 { 618 m_TailNode = Node; 619 } 620 m_HeadNode = Node; 621 622 return (POSITION)Node; 623 } 624 625 template<typename E, class ETraits> 626 POSITION CAtlList<E, ETraits>::AddTail(INARGTYPE element) 627 { 628 CNode* Node = CreateNode(element, m_TailNode, NULL); 629 if (m_TailNode) 630 { 631 m_TailNode->m_Next = Node; 632 } 633 else 634 { 635 m_HeadNode = Node; 636 } 637 m_TailNode = Node; 638 639 return (POSITION)Node; 640 } 641 642 template<typename E, class ETraits> 643 E CAtlList<E, ETraits>::RemoveHead() 644 { 645 CNode* Node = m_HeadNode; 646 E Element(Node->m_Element); 647 648 m_HeadNode = Node->m_Next; 649 if (m_HeadNode) 650 { 651 m_HeadNode->m_Prev = NULL; 652 } 653 else 654 { 655 m_TailNode = NULL; 656 } 657 FreeNode(Node); 658 659 return Element; 660 } 661 662 template<typename E, class ETraits> 663 E CAtlList<E, ETraits>::RemoveTail() 664 { 665 CNode* Node = m_TailNode; 666 E Element(Node->m_Element); 667 668 m_TailNode = Node->m_Prev; 669 if (m_TailNode) 670 { 671 m_TailNode->m_Next = NULL; 672 } 673 else 674 { 675 m_HeadNode = NULL; 676 } 677 FreeNode(Node); 678 679 return Element; 680 } 681 682 template<typename E, class ETraits> 683 POSITION CAtlList<E, ETraits >::InsertBefore(_In_ POSITION pos, _In_ INARGTYPE element) 684 { 685 if (pos == NULL) 686 return AddHead(element); 687 688 CNode* OldNode = (CNode*)pos; 689 CNode* Node = CreateNode(element, OldNode->m_Prev, OldNode); 690 691 if (OldNode->m_Prev != NULL) 692 { 693 OldNode->m_Prev->m_Next = Node; 694 } 695 else 696 { 697 m_HeadNode = Node; 698 } 699 OldNode->m_Prev = Node; 700 701 return (POSITION)Node; 702 } 703 704 template<typename E, class ETraits> 705 POSITION CAtlList<E, ETraits >::InsertAfter(_In_ POSITION pos, _In_ INARGTYPE element) 706 { 707 if (pos == NULL) 708 return AddTail(element); 709 710 CNode* OldNode = (CNode*)pos; 711 CNode* Node = CreateNode(element, OldNode, OldNode->m_Next); 712 713 if (OldNode->m_Next != NULL) 714 { 715 OldNode->m_Next->m_Prev = Node; 716 } 717 else 718 { 719 m_TailNode = Node; 720 } 721 OldNode->m_Next = Node; 722 723 return (POSITION)Node; 724 } 725 726 template<typename E, class ETraits> 727 void CAtlList<E, ETraits >::RemoveAll() 728 { 729 while (m_NumElements > 0) 730 { 731 CNode* Node = m_HeadNode; 732 m_HeadNode = m_HeadNode->m_Next; 733 FreeNode(Node); 734 } 735 736 m_HeadNode = NULL; 737 m_TailNode = NULL; 738 m_FreeNode = NULL; 739 740 if (m_Blocks) 741 { 742 m_Blocks->Destroy(); 743 m_Blocks = NULL; 744 } 745 } 746 747 template<typename E, class ETraits> 748 void CAtlList<E, ETraits >::RemoveAt(_In_ POSITION pos) 749 { 750 ATLASSERT(pos != NULL); 751 752 CNode* OldNode = (CNode*)pos; 753 if (OldNode == m_HeadNode) 754 { 755 m_HeadNode = OldNode->m_Next; 756 } 757 else 758 { 759 OldNode->m_Prev->m_Next = OldNode->m_Next; 760 } 761 if (OldNode == m_TailNode) 762 { 763 m_TailNode = OldNode->m_Prev; 764 } 765 else 766 { 767 OldNode->m_Next->m_Prev = OldNode->m_Prev; 768 } 769 FreeNode(OldNode); 770 } 771 772 template<typename E, class ETraits> 773 POSITION CAtlList< E, ETraits >::Find( 774 INARGTYPE element, 775 _In_opt_ POSITION posStartAfter) const 776 { 777 CNode* Node = (CNode*)posStartAfter; 778 if (Node == NULL) 779 { 780 Node = m_HeadNode; 781 } 782 else 783 { 784 Node = Node->m_Next; 785 } 786 787 for (; Node != NULL; Node = Node->m_Next) 788 { 789 if (ETraits::CompareElements(Node->m_Element, element)) 790 return (POSITION)Node; 791 } 792 793 return NULL; 794 } 795 796 template<typename E, class ETraits> 797 POSITION CAtlList< E, ETraits >::FindIndex(_In_ size_t iElement) const 798 { 799 if (iElement >= m_NumElements) 800 return NULL; 801 802 if (m_HeadNode == NULL) 803 return NULL; 804 805 CNode* Node = m_HeadNode; 806 for (size_t i = 0; i < iElement; i++) 807 { 808 Node = Node->m_Next; 809 } 810 811 return (POSITION)Node; 812 } 813 814 template<typename E, class ETraits> 815 void CAtlList< E, ETraits >::SwapElements(POSITION pos1, POSITION pos2) 816 { 817 if (pos1 == pos2) 818 return; 819 820 821 CNode *node1 = (CNode *)pos1; 822 CNode *node2 = (CNode *)pos2; 823 824 CNode *tmp = node1->m_Prev; 825 node1->m_Prev = node2->m_Prev; 826 node2->m_Prev = tmp; 827 828 if (node1->m_Prev) 829 node1->m_Prev->m_Next = node1; 830 else 831 m_HeadNode = node1; 832 833 if (node2->m_Prev) 834 node2->m_Prev->m_Next = node2; 835 else 836 m_HeadNode = node2; 837 838 tmp = node1->m_Next; 839 node1->m_Next = node2->m_Next; 840 node2->m_Next = tmp; 841 842 if (node1->m_Next) 843 node1->m_Next->m_Prev = node1; 844 else 845 m_TailNode = node1; 846 847 if (node2->m_Next) 848 node2->m_Next->m_Prev = node2; 849 else 850 m_TailNode = node2; 851 } 852 853 854 // 855 // CAtlist private methods 856 // 857 858 template<typename E, class ETraits> 859 typename CAtlList<E, ETraits>::CNode* CAtlList<E, ETraits>::CreateNode( 860 INARGTYPE element, 861 _In_opt_ CNode* Prev, 862 _In_opt_ CNode* Next 863 ) 864 { 865 GetFreeNode(); 866 867 CNode* NewNode = m_FreeNode; 868 CNode* NextFree = m_FreeNode->m_Next; 869 870 NewNode = new CNode(element); 871 872 m_FreeNode = NextFree; 873 NewNode->m_Prev = Prev; 874 NewNode->m_Next = Next; 875 m_NumElements++; 876 877 return NewNode; 878 } 879 880 template<typename E, class ETraits> 881 void CAtlList<E, ETraits>::FreeNode( 882 _Inout_ CNode* pNode 883 ) 884 { 885 pNode->~CNode(); 886 pNode->m_Next = m_FreeNode; 887 m_FreeNode = pNode; 888 889 m_NumElements--; 890 if (m_NumElements == 0) 891 { 892 RemoveAll(); 893 } 894 } 895 896 template<typename E, class ETraits> 897 typename CAtlList<E, ETraits>::CNode* CAtlList< E, ETraits>::GetFreeNode() 898 { 899 if (m_FreeNode) 900 { 901 return m_FreeNode; 902 } 903 904 CAtlPlex* Block = CAtlPlex::Create(m_Blocks, m_BlockSize, sizeof(CNode)); 905 if (Block == NULL) 906 { 907 AtlThrowImp(E_OUTOFMEMORY); 908 } 909 910 CNode* Node = (CNode*)Block->GetData(); 911 Node += (m_BlockSize - 1); 912 for (int i = m_BlockSize - 1; i >= 0; i--) 913 { 914 Node->m_Next = m_FreeNode; 915 m_FreeNode = Node; 916 Node--; 917 } 918 919 return m_FreeNode; 920 } 921 922 923 template<typename E, class Allocator = CCRTAllocator > 924 class CHeapPtrList : 925 public CAtlList<CHeapPtr<E, Allocator>, CHeapPtrElementTraits<E, Allocator> > 926 { 927 public: 928 CHeapPtrList(_In_ UINT nBlockSize = 10) : 929 CAtlList<CHeapPtr<E, Allocator>, CHeapPtrElementTraits<E, Allocator> >(nBlockSize) 930 { 931 } 932 933 private: 934 CHeapPtrList(const CHeapPtrList&); 935 CHeapPtrList& operator=(const CHeapPtrList*); 936 }; 937 938 939 } 940 941 #endif 942