Annotation of mstools/mfc/samples/templdef/list.ctt, revision 1.1.1.1

1.1       root        1: /////////////////////////////////////////////////////////////////////////////
                      2: // class CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE> - a list containing 'TYPE' elements
                      3: // passed in parameters as ARG_TYPE
                      4: //
                      5: // This is a part of the Microsoft Foundation Classes C++ library.
                      6: // Copyright (C) 1992 Microsoft Corporation
                      7: // All rights reserved.
                      8: //
                      9: // This source code is only intended as a supplement to the
                     10: // Microsoft Foundation Classes Reference and Microsoft
                     11: // QuickHelp documentation provided with the library.
                     12: // See these sources for detailed information regarding the
                     13: // Microsoft Foundation Classes product.
                     14: /////////////////////////////////////////////////////////////////////////////
                     15: 
                     16: //$DECLARE_TEMPLATE
                     17: 
                     18: /////////////////////////////////////////////////////////////////////////////
                     19: 
                     20: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                     21: class CList : public CObject
                     22: {
                     23: #if IS_SERIAL
                     24:        DECLARE_SERIAL(CList)
                     25: #else
                     26:        DECLARE_DYNAMIC(CList)
                     27: #endif //!IS_SERIAL
                     28: 
                     29: protected:
                     30:        struct CNode
                     31:        {
                     32:                CNode*  pNext;
                     33:                CNode*  pPrev;
                     34:                TYPE    data;
                     35:        };
                     36: public:
                     37: 
                     38: // Construction
                     39:        CList(int nBlockSize=10);
                     40: 
                     41: // Attributes (head and tail)
                     42:        // count of elements
                     43:        int     GetCount() const
                     44:                                { return m_nCount; }
                     45:        BOOL    IsEmpty() const
                     46:                                { return m_nCount == 0; }
                     47: 
                     48:        // peek at head or tail
                     49:        TYPE&   GetHead()
                     50:                                { ASSERT(m_pNodeHead != NULL);
                     51:                                        return m_pNodeHead->data; }
                     52:        TYPE    GetHead() const
                     53:                                { ASSERT(m_pNodeHead != NULL);
                     54:                                        return m_pNodeHead->data; }
                     55:        TYPE&   GetTail()
                     56:                                { ASSERT(m_pNodeTail != NULL);
                     57:                                        return m_pNodeTail->data; }
                     58:        TYPE    GetTail() const
                     59:                                { ASSERT(m_pNodeTail != NULL);
                     60:                                        return m_pNodeTail->data; }
                     61: 
                     62: // Operations
                     63:        // get head or tail (and remove it) - don't call on empty list !
                     64:        TYPE    RemoveHead();
                     65:        TYPE    RemoveTail();
                     66: 
                     67:        // add before head or after tail
                     68:        POSITION AddHead(ARG_TYPE newElement);
                     69:        POSITION AddTail(ARG_TYPE newElement);
                     70: 
                     71:        // add another list of elements before head or after tail
                     72:        void    AddHead(CList* pNewList);
                     73:        void    AddTail(CList* pNewList);
                     74: 
                     75:        // remove all elements
                     76:        void    RemoveAll();
                     77: 
                     78:        // iteration
                     79:        POSITION GetHeadPosition() const
                     80:                                { return (POSITION) m_pNodeHead; }
                     81:        POSITION GetTailPosition() const
                     82:                                { return (POSITION) m_pNodeTail; }
                     83:        TYPE&   GetNext(POSITION& rPosition) // return *Position++
                     84:                                { CNode* pNode = (CNode*) rPosition;
                     85:                                        ASSERT(pNode != NULL);
                     86:                                        rPosition = (POSITION) pNode->pNext;
                     87:                                        return pNode->data; }
                     88:        TYPE    GetNext(POSITION& rPosition) const // return *Position++
                     89:                                { CNode* pNode = (CNode*) rPosition;
                     90:                                        ASSERT(pNode != NULL);
                     91:                                        rPosition = (POSITION) pNode->pNext;
                     92:                                        return pNode->data; }
                     93:        TYPE&   GetPrev(POSITION& rPosition) // return *Position--
                     94:                                { CNode* pNode = (CNode*) rPosition;
                     95:                                        ASSERT(pNode != NULL);
                     96:                                        rPosition = (POSITION) pNode->pPrev;
                     97:                                        return pNode->data; }
                     98:        TYPE    GetPrev(POSITION& rPosition) const // return *Position--
                     99:                                { CNode* pNode = (CNode*) rPosition;
                    100:                                        ASSERT(pNode != NULL);
                    101:                                        rPosition = (POSITION) pNode->pPrev;
                    102:                                        return pNode->data; }
                    103: 
                    104:        // getting/modifying an element at a given position
                    105:        TYPE&   GetAt(POSITION position)
                    106:                                { CNode* pNode = (CNode*) position;
                    107:                                        ASSERT(pNode != NULL);
                    108:                                        return pNode->data; }
                    109:        TYPE    GetAt(POSITION position) const
                    110:                                { CNode* pNode = (CNode*) position;
                    111:                                        ASSERT(pNode != NULL);
                    112:                                        return pNode->data; }
                    113:        void    SetAt(POSITION pos, ARG_TYPE newElement)
                    114:                                { CNode* pNode = (CNode*) pos;
                    115:                                        ASSERT(pNode != NULL);
                    116:                                        pNode->data = newElement; }
                    117:        void    RemoveAt(POSITION position);
                    118: 
                    119:        // inserting before or after a given position
                    120:        POSITION InsertBefore(POSITION position, ARG_TYPE newElement);
                    121:        POSITION InsertAfter(POSITION position, ARG_TYPE newElement);
                    122: 
                    123:        // helper functions (note: O(n) speed)
                    124:        POSITION Find(ARG_TYPE searchValue, POSITION startAfter = NULL) const;
                    125:                                                // defaults to starting at the HEAD
                    126:                                                // return NULL if not found
                    127:        POSITION FindIndex(int nIndex) const;
                    128:                                                // get the 'nIndex'th element (may return NULL)
                    129: 
                    130: // Implementation
                    131: protected:
                    132:        CNode*  m_pNodeHead;
                    133:        CNode*  m_pNodeTail;
                    134:        int     m_nCount;
                    135:        CNode*  m_pNodeFree;
                    136:        struct CPlex* m_pBlocks;
                    137:        int     m_nBlockSize;
                    138: 
                    139:        CNode*  NewNode(CNode*, CNode*);
                    140:        void    FreeNode(CNode*);
                    141: 
                    142: public:
                    143:        ~CList();
                    144: #if IS_SERIAL
                    145:        void    Serialize(CArchive&);
                    146: #endif //IS_SERIAL
                    147: #ifdef _DEBUG
                    148:        void    Dump(CDumpContext&) const;
                    149:        void    AssertValid() const;
                    150: #endif
                    151: };
                    152: 
                    153: //$IMPLEMENT_TEMPLATE
                    154: 
                    155: /////////////////////////////////////////////////////////////////////////////
                    156: //
                    157: // Implementation of List of TYPEs
                    158: //
                    159: /////////////////////////////////////////////////////////////////////////////
                    160: 
                    161: #include "afxcoll.h"
                    162: #pragma hdrstop
                    163: 
                    164: #include "plex.h"
                    165: 
                    166: #ifdef AFX_COLL_SEG
                    167: #pragma code_seg(AFX_COLL_SEG)
                    168: #endif
                    169: 
                    170: #if IS_SERIAL
                    171: IMPLEMENT_SERIAL(CList, CObject, 0);
                    172: #else
                    173: IMPLEMENT_DYNAMIC(CList, CObject);
                    174: #endif //!IS_SERIAL
                    175: 
                    176: #ifdef _DEBUG
                    177: #undef THIS_FILE
                    178: static char BASED_CODE THIS_FILE[] = __FILE__;
                    179: #endif
                    180: 
                    181: #if HAS_CREATE
                    182: #include "elements.h"       // used for special creation
                    183: #endif
                    184: 
                    185: /////////////////////////////////////////////////////////////////////////////
                    186: 
                    187: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    188: CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::CList(int nBlockSize)
                    189: {
                    190:        ASSERT(nBlockSize > 0);
                    191: 
                    192:        m_nCount = 0;
                    193:        m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
                    194:        m_pBlocks = NULL;
                    195:        m_nBlockSize = nBlockSize;
                    196: }
                    197: 
                    198: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    199: void CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::RemoveAll()
                    200: {
                    201:        ASSERT_VALID(this);
                    202: 
                    203:        // destroy elements
                    204: #if HAS_CREATE
                    205:        register CNode* pNode;
                    206:        for (pNode = m_pNodeHead; pNode != NULL; pNode = pNode->pNext)
                    207:                DestructElement(&pNode->data);
                    208: #endif
                    209: 
                    210:        m_nCount = 0;
                    211:        m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
                    212:        m_pBlocks->FreeDataChain();
                    213:        m_pBlocks = NULL;
                    214: }
                    215: 
                    216: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    217: CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::~CList()
                    218: {
                    219:        RemoveAll();
                    220:        ASSERT(m_nCount == 0);
                    221: }
                    222: 
                    223: /////////////////////////////////////////////////////////////////////////////
                    224: // Node helpers
                    225: /*
                    226:  * Implementation note: CNode's are stored in CPlex blocks and
                    227:  *  chained together. Free blocks are maintained in a singly linked list
                    228:  *  using the 'pNext' member of CNode with 'm_pNodeFree' as the head.
                    229:  *  Used blocks are maintained in a doubly linked list using both 'pNext'
                    230:  *  and 'pPrev' as links and 'm_pNodeHead' and 'm_pNodeTail'
                    231:  *   as the head/tail.
                    232:  *
                    233:  * We never free a CPlex block unless the List is destroyed or RemoveAll()
                    234:  *  is used - so the total number of CPlex blocks may grow large depending
                    235:  *  on the maximum past size of the list.
                    236:  */
                    237: 
                    238: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    239: CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::CNode*
                    240: CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::NewNode(CList::CNode* pPrev, CList::CNode* pNext)
                    241: {
                    242:        if (m_pNodeFree == NULL)
                    243:        {
                    244:                // add another block
                    245:                CPlex* pNewBlock = CPlex::Create(m_pBlocks, m_nBlockSize,
                    246:                                 sizeof(CNode));
                    247: 
                    248:                // chain them into free list
                    249:                CNode* pNode = (CNode*) pNewBlock->data();
                    250:                // free in reverse order to make it easier to debug
                    251:                pNode += m_nBlockSize - 1;
                    252:                for (int i = m_nBlockSize-1; i >= 0; i--, pNode--)
                    253:                {
                    254:                        pNode->pNext = m_pNodeFree;
                    255:                        m_pNodeFree = pNode;
                    256:                }
                    257:        }
                    258:        ASSERT(m_pNodeFree != NULL); // we must have something
                    259: 
                    260:        register CList::CNode* pNode = m_pNodeFree;
                    261:        m_pNodeFree = m_pNodeFree->pNext;
                    262:        pNode->pPrev = pPrev;
                    263:        pNode->pNext = pNext;
                    264:        m_nCount++;
                    265:        ASSERT(m_nCount > 0);       // make sure we don't overflow
                    266: 
                    267: #if HAS_CREATE
                    268:        ConstructElement(&pNode->data);
                    269: #else
                    270:        memset(&pNode->data, 0, sizeof(TYPE));          // zero fill
                    271: #endif
                    272:        return pNode;
                    273: }
                    274: 
                    275: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    276: void CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::FreeNode(CList::CNode* pNode)
                    277: {
                    278: #if HAS_CREATE
                    279:        DestructElement(&pNode->data);
                    280: #endif
                    281:        pNode->pNext = m_pNodeFree;
                    282:        m_pNodeFree = pNode;
                    283:        m_nCount--;
                    284:        ASSERT(m_nCount >= 0);      // make sure we don't underflow
                    285: }
                    286: 
                    287: /////////////////////////////////////////////////////////////////////////////
                    288: 
                    289: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    290: POSITION CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::AddHead(ARG_TYPE newElement)
                    291: {
                    292:        ASSERT_VALID(this);
                    293: 
                    294:        CNode* pNewNode = NewNode(NULL, m_pNodeHead);
                    295:        pNewNode->data = newElement;
                    296:        if (m_pNodeHead != NULL)
                    297:                m_pNodeHead->pPrev = pNewNode;
                    298:        else
                    299:                m_pNodeTail = pNewNode;
                    300:        m_pNodeHead = pNewNode;
                    301:        return (POSITION) pNewNode;
                    302: }
                    303: 
                    304: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    305: POSITION CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::AddTail(ARG_TYPE newElement)
                    306: {
                    307:        ASSERT_VALID(this);
                    308: 
                    309:        CNode* pNewNode = NewNode(m_pNodeTail, NULL);
                    310:        pNewNode->data = newElement;
                    311:        if (m_pNodeTail != NULL)
                    312:                m_pNodeTail->pNext = pNewNode;
                    313:        else
                    314:                m_pNodeHead = pNewNode;
                    315:        m_pNodeTail = pNewNode;
                    316:        return (POSITION) pNewNode;
                    317: }
                    318: 
                    319: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    320: void CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::AddHead(CList* pNewList)
                    321: {
                    322:        ASSERT_VALID(this);
                    323: 
                    324:        ASSERT(pNewList != NULL);
                    325:        ASSERT(pNewList->IsKindOf(RUNTIME_CLASS(CList)));
                    326:        ASSERT_VALID(pNewList);
                    327: 
                    328:        // add a list of same elements to head (maintain order)
                    329:        POSITION pos = pNewList->GetTailPosition();
                    330:        while (pos != NULL)
                    331:                AddHead(pNewList->GetPrev(pos));
                    332: }
                    333: 
                    334: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    335: void CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::AddTail(CList* pNewList)
                    336: {
                    337:        ASSERT_VALID(this);
                    338:        ASSERT(pNewList != NULL);
                    339:        ASSERT(pNewList->IsKindOf(RUNTIME_CLASS(CList)));
                    340:        ASSERT_VALID(pNewList);
                    341: 
                    342:        // add a list of same elements
                    343:        POSITION pos = pNewList->GetHeadPosition();
                    344:        while (pos)
                    345:                AddTail(pNewList->GetNext(pos));
                    346: }
                    347: 
                    348: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    349: TYPE CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::RemoveHead()
                    350: {
                    351:        ASSERT_VALID(this);
                    352:        ASSERT(m_pNodeHead != NULL);    // don't call on empty list !!!
                    353: 
                    354:        CNode* pOldNode = m_pNodeHead;
                    355:        ASSERT(pOldNode != NULL);
                    356:        TYPE returnValue = pOldNode->data;
                    357: 
                    358:        m_pNodeHead = pOldNode->pNext;
                    359:        if (m_pNodeHead != NULL)
                    360:                m_pNodeHead->pPrev = NULL;
                    361:        else
                    362:                m_pNodeTail = NULL;
                    363:        FreeNode(pOldNode);
                    364:        return returnValue;
                    365: }
                    366: 
                    367: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    368: TYPE CList<TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>::RemoveTail()
                    369: {
                    370:        ASSERT_VALID(this);
                    371:        ASSERT(m_pNodeTail != NULL);    // don't call on empty list !!!
                    372: 
                    373:        CNode* pOldNode = m_pNodeTail;
                    374:        ASSERT(pOldNode != NULL);
                    375:        TYPE returnValue = pOldNode->data;
                    376: 
                    377:        m_pNodeTail = pOldNode->pPrev;
                    378:        if (m_pNodeTail != NULL)
                    379:                m_pNodeTail->pNext = NULL;
                    380:        else
                    381:                m_pNodeHead = NULL;
                    382:        FreeNode(pOldNode);
                    383:        return returnValue;
                    384: }
                    385: 
                    386: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    387: POSITION CList<TYPE>::InsertBefore(POSITION position, ARG_TYPE newElement)
                    388: {
                    389:        ASSERT_VALID(this);
                    390: 
                    391:        if (position == NULL)
                    392:                return AddHead(newElement); // insert before nothing -> head of the list
                    393: 
                    394:        // Insert it before position
                    395:        CNode* pOldNode = (CNode*) position;
                    396:        CNode* pNewNode = NewNode(pOldNode->pPrev, pOldNode);
                    397:        pNewNode->data = newElement;
                    398: 
                    399:        if (pOldNode->pPrev != NULL)
                    400:        {
                    401:                pOldNode->pPrev->pNext = pNewNode;
                    402:        }
                    403:        else
                    404:        {
                    405:                ASSERT(pOldNode == m_pNodeHead);
                    406:                m_pNodeHead = pNewNode;
                    407:        }
                    408:        pOldNode->pPrev = pNewNode;
                    409:        return (POSITION) pNewNode;
                    410: }
                    411: 
                    412: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    413: POSITION CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::InsertAfter(POSITION position, ARG_TYPE newElement)
                    414: {
                    415:        ASSERT_VALID(this);
                    416: 
                    417:        if (position == NULL)
                    418:                return AddTail(newElement); // insert after nothing -> tail of the list
                    419: 
                    420:        // Insert it before position
                    421:        CNode* pOldNode = (CNode*) position;
                    422:        CNode* pNewNode = NewNode(pOldNode, pOldNode->pNext);
                    423:        pNewNode->data = newElement;
                    424: 
                    425:        if (pOldNode->pNext != NULL)
                    426:        {
                    427:                pOldNode->pNext->pPrev = pNewNode;
                    428:        }
                    429:        else
                    430:        {
                    431:                ASSERT(pOldNode == m_pNodeTail);
                    432:                m_pNodeTail = pNewNode;
                    433:        }
                    434:        pOldNode->pNext = pNewNode;
                    435:        return (POSITION) pNewNode;
                    436: }
                    437: 
                    438: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    439: void CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::RemoveAt(POSITION position)
                    440: {
                    441:        ASSERT_VALID(this);
                    442:        ASSERT(position != NULL);
                    443: 
                    444:        CNode* pOldNode = (CNode*) position;
                    445: 
                    446:        // remove pOldNode from list
                    447:        if (pOldNode == m_pNodeHead)
                    448:                m_pNodeHead = pOldNode->pNext;
                    449:        else
                    450:                pOldNode->pPrev->pNext = pOldNode->pNext;
                    451:        if (pOldNode == m_pNodeTail)
                    452:                m_pNodeTail = pOldNode->pPrev;
                    453:        else
                    454:                pOldNode->pNext->pPrev = pOldNode->pPrev;
                    455:        FreeNode(pOldNode);
                    456: }
                    457: 
                    458: 
                    459: /////////////////////////////////////////////////////////////////////////////
                    460: // slow operations
                    461: 
                    462: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    463: POSITION CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::FindIndex(int nIndex) const
                    464: {
                    465:        ASSERT_VALID(this);
                    466:        ASSERT(nIndex >= 0);
                    467: 
                    468:        if (nIndex >= m_nCount)
                    469:                return NULL;        // went too far
                    470: 
                    471:        register CNode* pNode = m_pNodeHead;
                    472:        while (nIndex--)
                    473:                pNode = pNode->pNext;
                    474:        return (POSITION) pNode;
                    475: }
                    476: 
                    477: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    478: POSITION CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::Find(ARG_TYPE searchValue, POSITION startAfter) const
                    479: {
                    480:        ASSERT_VALID(this);
                    481: 
                    482:        register CNode* pNode = (CNode*) startAfter;
                    483:        if (pNode == NULL)
                    484:                pNode = m_pNodeHead;        // start at head
                    485:        else
                    486:                pNode = pNode->pNext;       // start after the one specified
                    487: 
                    488:        for (; pNode != NULL; pNode = pNode->pNext)
                    489:                if (pNode->data == searchValue)
                    490:                        return (POSITION) pNode;
                    491:        return NULL;
                    492: }
                    493: 
                    494: /////////////////////////////////////////////////////////////////////////////
                    495: // Serialization
                    496: 
                    497: #if IS_SERIAL
                    498: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    499: void CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::Serialize(CArchive& ar)
                    500: {
                    501:        ASSERT_VALID(this);
                    502: 
                    503:        CObject::Serialize(ar);
                    504: 
                    505:        if (ar.IsStoring())
                    506:        {
                    507:                ar << (WORD) m_nCount;
                    508:                for (CNode* pNode = m_pNodeHead; pNode != NULL;
                    509:                  pNode = pNode->pNext)
                    510:                        ar << pNode->data;
                    511:        }
                    512:        else
                    513:        {
                    514:                WORD nNewCount;
                    515:                ar >> nNewCount;
                    516:                while (nNewCount--)
                    517:                {
                    518:                        TYPE newData;
                    519:                        ar >> newData;
                    520:                        AddTail(newData);
                    521:                }
                    522:        }
                    523: }
                    524: #endif //IS_SERIAL
                    525: 
                    526: /////////////////////////////////////////////////////////////////////////////
                    527: // Diagnostics
                    528: 
                    529: #ifdef _DEBUG
                    530: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    531: void CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::Dump(CDumpContext& dc) const
                    532: {
                    533:        ASSERT_VALID(this);
                    534: 
                    535: #define MAKESTRING(x) #x
                    536:        dc << "a " MAKESTRING(CList) " with " << m_nCount << " elements";
                    537: #undef MAKESTRING
                    538:        if (dc.GetDepth() > 0)
                    539:        {
                    540:                POSITION pos = GetHeadPosition();
                    541:                dc << "\n";
                    542: 
                    543:                while (pos != NULL)
                    544:                        dc << "\n\t" << GetNext(pos);
                    545:        }
                    546: }
                    547: 
                    548: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    549: void CList<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::AssertValid() const
                    550: {
                    551:        CObject::AssertValid();
                    552: 
                    553:        if (m_nCount == 0)
                    554:        {
                    555:                // empty list
                    556:                ASSERT(m_pNodeHead == NULL);
                    557:                ASSERT(m_pNodeTail == NULL);
                    558:        }
                    559:        else
                    560:        {
                    561:                // non-empty list
                    562:                ASSERT(m_pNodeHead != NULL);
                    563:                ASSERT(m_pNodeTail != NULL);
                    564:        }
                    565: }
                    566: #endif //_DEBUG
                    567: 
                    568: /////////////////////////////////////////////////////////////////////////////

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.