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

1.1       root        1: ////////////////////////////////////////////////////////////////////////////
                      2: // class CArray<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE> - an array 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 CArray : public CObject
                     22: {
                     23: #if IS_SERIAL
                     24:        DECLARE_SERIAL(CArray)
                     25: #else
                     26:        DECLARE_DYNAMIC(CArray)
                     27: #endif //!IS_SERIAL
                     28: public:
                     29: 
                     30: // Construction
                     31:        CArray();
                     32: 
                     33: // Attributes
                     34:        int     GetSize() const
                     35:                                { return m_nSize; }
                     36:        int     GetUpperBound() const
                     37:                                { return m_nSize-1; }
                     38:        void    SetSize(int nNewSize, int nGrowBy = -1);
                     39: 
                     40: // Operations
                     41:        // Clean up
                     42:        void    FreeExtra();
                     43:        void    RemoveAll()
                     44:                                { SetSize(0); }
                     45: 
                     46:        // Accessing elements
                     47:        TYPE    GetAt(int nIndex) const
                     48:                                { ASSERT(nIndex >= 0 && nIndex < m_nSize);
                     49:                                        return m_pData[nIndex]; }
                     50:        void    SetAt(int nIndex, ARG_TYPE newElement)
                     51:                                { ASSERT(nIndex >= 0 && nIndex < m_nSize);
                     52:                                        m_pData[nIndex] = newElement; }
                     53:        TYPE&   ElementAt(int nIndex)
                     54:                                { ASSERT(nIndex >= 0 && nIndex < m_nSize);
                     55:                                        return m_pData[nIndex]; }
                     56: 
                     57:        // Potentially growing the array
                     58:        void    SetAtGrow(int nIndex, ARG_TYPE newElement);
                     59:        int     Add(ARG_TYPE newElement)
                     60:                                { int nIndex = m_nSize;
                     61:                                        SetAtGrow(nIndex, newElement);
                     62:                                        return nIndex; }
                     63: 
                     64:        // overloaded operator helpers
                     65:        TYPE    operator[](int nIndex) const
                     66:                                { return GetAt(nIndex); }
                     67:        TYPE&   operator[](int nIndex)
                     68:                                { return ElementAt(nIndex); }
                     69: 
                     70:        // Operations that move elements around
                     71:        void    InsertAt(int nIndex, ARG_TYPE newElement, int nCount = 1);
                     72:        void    RemoveAt(int nIndex, int nCount = 1);
                     73:        void    InsertAt(int nStartIndex, CArray* pNewArray);
                     74: 
                     75: // Implementation
                     76: protected:
                     77:        TYPE*   m_pData;        // the actual array of data
                     78:        int     m_nSize;        // # of elements (upperBound - 1)
                     79:        int     m_nMaxSize;     // max allocated
                     80:        int     m_nGrowBy;      // grow amount
                     81: 
                     82: public:
                     83:        ~CArray();
                     84: #if IS_SERIAL
                     85:        void    Serialize(CArchive&);
                     86: #endif //IS_SERIAL
                     87: #ifdef _DEBUG
                     88:        void    Dump(CDumpContext&) const;
                     89:        void    AssertValid() const;
                     90: #endif
                     91: };
                     92: 
                     93: //$IMPLEMENT_TEMPLATE
                     94: 
                     95: /////////////////////////////////////////////////////////////////////////////
                     96: //
                     97: // Implementation of Array of TYPEs
                     98: //
                     99: /////////////////////////////////////////////////////////////////////////////
                    100: // NOTE: we allocate an array of 'm_nMaxSize' elements, but only
                    101: //  the current size 'm_nSize' contains properly constructed
                    102: //  objects.
                    103: 
                    104: #include "afxcoll.h"
                    105: #pragma hdrstop
                    106: 
                    107: #ifdef AFX_COLL_SEG
                    108: #pragma code_seg(AFX_COLL_SEG)
                    109: #endif
                    110: 
                    111: #include <limits.h>
                    112: #define SIZE_T_MAX  UINT_MAX            /* max size for a size_t */
                    113: 
                    114: #if IS_SERIAL
                    115: IMPLEMENT_SERIAL(CArray, CObject, 0);
                    116: #else
                    117: IMPLEMENT_DYNAMIC(CArray, CObject);
                    118: #endif //!IS_SERIAL
                    119: 
                    120: #ifdef _DEBUG
                    121: #undef THIS_FILE
                    122: static char BASED_CODE THIS_FILE[] = __FILE__;
                    123: #endif
                    124: 
                    125: #define new DEBUG_NEW
                    126: 
                    127: /////////////////////////////////////////////////////////////////////////////
                    128: 
                    129: #if HAS_CREATE
                    130: #include "elements.h"       // used for special creation
                    131: 
                    132: static void NEAR ConstructElements(register TYPE* pNewData, int nCount)
                    133: {
                    134:        ASSERT(nCount >= 0);
                    135: 
                    136:        while (nCount--)
                    137:        {
                    138:                ConstructElement(pNewData);
                    139:                pNewData++;
                    140:        }
                    141: }
                    142: 
                    143: static void NEAR DestructElements(register TYPE* pOldData, int nCount)
                    144: {
                    145:        ASSERT(nCount >= 0);
                    146: 
                    147:        while (nCount--)
                    148:        {
                    149:                pOldData->Empty();
                    150:                pOldData++;
                    151:        }
                    152: }
                    153: #endif //HAS_CREATE
                    154: 
                    155: /////////////////////////////////////////////////////////////////////////////
                    156: 
                    157: template<class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    158: CArray<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::CArray()
                    159: {
                    160:        m_pData = NULL;
                    161:        m_nSize = m_nMaxSize = m_nGrowBy = 0;
                    162: }
                    163: 
                    164: template<class TYPE, ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    165: CArray<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::~CArray()
                    166: {
                    167:        ASSERT_VALID(this);
                    168: 
                    169: #if HAS_CREATE
                    170:        DestructElements(m_pData, m_nSize);
                    171: #endif //HAS_CREATE
                    172:        delete [] (BYTE*)m_pData;
                    173: }
                    174: 
                    175: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    176: void CArray<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::SetSize(int nNewSize, int nGrowBy /* = -1 */)
                    177: {
                    178:        ASSERT_VALID(this);
                    179:        ASSERT(nNewSize >= 0);
                    180: 
                    181:        if (nGrowBy != -1)
                    182:                m_nGrowBy = nGrowBy;    // set new size
                    183: 
                    184:        if (nNewSize == 0)
                    185:        {
                    186:                // shrink to nothing
                    187: #if HAS_CREATE
                    188:                DestructElements(m_pData, m_nSize);
                    189: #endif //HAS_CREATE
                    190:                delete [] (BYTE*)m_pData;
                    191:                m_pData = NULL;
                    192:                m_nSize = m_nMaxSize = 0;
                    193:        }
                    194:        else if (m_pData == NULL)
                    195:        {
                    196:                // create one with exact size
                    197: #ifdef SIZE_T_MAX
                    198:                ASSERT((long)nNewSize * sizeof(TYPE) <= SIZE_T_MAX);    // no overflow
                    199: #endif
                    200:                m_pData = (TYPE*) new BYTE[nNewSize * sizeof(TYPE)];
                    201: #if HAS_CREATE
                    202:                ConstructElements(m_pData, nNewSize);
                    203: #else
                    204:                memset(m_pData, 0, nNewSize * sizeof(TYPE));        // zero fill
                    205: #endif
                    206:                m_nSize = m_nMaxSize = nNewSize;
                    207:        }
                    208:        else if (nNewSize <= m_nMaxSize)
                    209:        {
                    210:                // it fits
                    211:                if (nNewSize > m_nSize)
                    212:                {
                    213:                        // initialize the new elements
                    214: #if HAS_CREATE
                    215:                        ConstructElements(&m_pData[m_nSize], nNewSize-m_nSize);
                    216: #else
                    217:                        memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(TYPE));
                    218: #endif
                    219:                }
                    220: #if HAS_CREATE
                    221:                else if (m_nSize > nNewSize) // destroy the old elements
                    222:                        DestructElements(&m_pData[nNewSize], m_nSize-nNewSize);
                    223: #endif
                    224:                m_nSize = nNewSize;
                    225:        }
                    226:        else
                    227:        {
                    228:                // Otherwise grow array
                    229:                int nNewMax;
                    230:                if (nNewSize < m_nMaxSize + m_nGrowBy)
                    231:                        nNewMax = m_nMaxSize + m_nGrowBy;   // granularity
                    232:                else
                    233:                        nNewMax = nNewSize; // no slush
                    234: 
                    235: #ifdef SIZE_T_MAX
                    236:                ASSERT((long)nNewMax * sizeof(TYPE) <= SIZE_T_MAX); // no overflow
                    237: #endif
                    238:                TYPE* pNewData = (TYPE*) new BYTE[nNewMax * sizeof(TYPE)];
                    239: 
                    240:                // copy new data from old
                    241:                memcpy(pNewData, m_pData, m_nSize * sizeof(TYPE));
                    242: 
                    243:                // construct remaining elements
                    244:                ASSERT(nNewSize > m_nSize);
                    245: #if HAS_CREATE
                    246:                ConstructElements(&pNewData[m_nSize], nNewSize-m_nSize);
                    247: #else
                    248:                memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(TYPE));
                    249: #endif
                    250: 
                    251:                // get rid of old stuff (note: no destructors called)
                    252:                delete [] (BYTE*)m_pData;
                    253:                m_pData = pNewData;
                    254:                m_nSize = nNewSize;
                    255:                m_nMaxSize = nNewMax;
                    256:        }
                    257: }
                    258: 
                    259: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    260: void CArray<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::FreeExtra()
                    261: {
                    262:        ASSERT_VALID(this);
                    263: 
                    264:        if (m_nSize != m_nMaxSize)
                    265:        {
                    266:                // shrink to desired size
                    267: #ifdef SIZE_T_MAX
                    268:                ASSERT((long)m_nSize * sizeof(TYPE) <= SIZE_T_MAX); // no overflow
                    269: #endif
                    270:                TYPE* pNewData = (TYPE*) new BYTE[m_nSize * sizeof(TYPE)];
                    271:                // copy new data from old
                    272:                memcpy(pNewData, m_pData, m_nSize * sizeof(TYPE));
                    273: 
                    274:                // get rid of old stuff (note: no destructors called)
                    275:                delete [] (BYTE*)m_pData;
                    276:                m_pData = pNewData;
                    277:                m_nMaxSize = m_nSize;
                    278:        }
                    279: }
                    280: 
                    281: /////////////////////////////////////////////////////////////////////////////
                    282: 
                    283: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    284: void CArray<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::SetAtGrow(int nIndex, ARG_TYPE newElement)
                    285: {
                    286:        ASSERT(nIndex >= 0);
                    287:        if (nIndex >= m_nSize)
                    288:                SetSize(nIndex+1);
                    289:        m_pData[nIndex] = newElement;
                    290: }
                    291: 
                    292: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    293: void CArray<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::InsertAt(int nIndex, ARG_TYPE newElement, int nCount /*=1*/)
                    294: {
                    295:        ASSERT_VALID(this);
                    296:        ASSERT(nIndex >= 0);        // will expand to meet need
                    297:        ASSERT(nCount > 0);     // zero or negative size not allowed
                    298: 
                    299:        if (nIndex >= m_nSize)
                    300:        {
                    301:                // adding after the end of the array
                    302:                SetSize(nIndex + nCount);       // grow so nIndex is valid
                    303:        }
                    304:        else
                    305:        {
                    306:                // inserting in the middle of the array
                    307:                int nOldSize = m_nSize;
                    308:                SetSize(m_nSize + nCount); // grow it to new size
                    309:                // shift old data up to fill gap
                    310:                memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
                    311:                        (nOldSize-nIndex) * sizeof(TYPE));
                    312: 
                    313:                // re-init slots we copied from
                    314: #if HAS_CREATE
                    315:                ConstructElements(&m_pData[nIndex], nCount);
                    316: #else
                    317:                memset(&m_pData[nIndex], 0, nCount * sizeof(TYPE));
                    318: #endif
                    319:        }
                    320: 
                    321:        // insert new value in the gap
                    322:        ASSERT(nIndex + nCount <= m_nSize);
                    323:        while (nCount--)
                    324:                m_pData[nIndex++] = newElement;
                    325: }
                    326: 
                    327: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    328: void CArray<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::RemoveAt(int nIndex, int nCount /* = 1 */)
                    329: {
                    330:        ASSERT_VALID(this);
                    331:        ASSERT(nIndex >= 0);
                    332:        ASSERT(nCount >= 0);
                    333:        ASSERT(nIndex + nCount <= m_nSize);
                    334: 
                    335:        // just remove a range
                    336:        int nMoveCount = m_nSize - (nIndex + nCount);
                    337: #if HAS_CREATE
                    338:        DestructElements(&m_pData[nIndex], nCount);
                    339: #endif
                    340:        if (nMoveCount)
                    341:                memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
                    342:                        nMoveCount * sizeof(TYPE));
                    343:        m_nSize -= nCount;
                    344: }
                    345: 
                    346: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    347: void CArray<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::InsertAt(int nStartIndex, CArray* pNewArray)
                    348: {
                    349:        ASSERT_VALID(this);
                    350:        ASSERT(pNewArray != NULL);
                    351:        ASSERT(pNewArray->IsKindOf(RUNTIME_CLASS(CArray)));
                    352:        ASSERT_VALID(pNewArray);
                    353:        ASSERT(nStartIndex >= 0);
                    354: 
                    355:        if (pNewArray->GetSize() > 0)
                    356:        {
                    357:                InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
                    358:                for (int i = 0; i < pNewArray->GetSize(); i++)
                    359:                        SetAt(nStartIndex + i, pNewArray->GetAt(i));
                    360:        }
                    361: }
                    362: 
                    363: /////////////////////////////////////////////////////////////////////////////
                    364: // Serialization
                    365: 
                    366: template<class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    367: #if IS_SERIAL
                    368: void CArray<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::Serialize(CArchive& ar)
                    369: {
                    370:        ASSERT_VALID(this);
                    371: 
                    372:        CObject::Serialize(ar);
                    373: 
                    374:        if (ar.IsStoring())
                    375:        {
                    376:                ar << (WORD) m_nSize;
                    377:                for (int i = 0; i < m_nSize; i++)
                    378:                        ar << m_pData[i];
                    379:        }
                    380:        else
                    381:        {
                    382:                WORD    nOldSize;
                    383:                ar >> nOldSize;
                    384:                SetSize(nOldSize);
                    385: 
                    386:                for (int i = 0; i < m_nSize; i++)
                    387:                        ar >> m_pData[i];
                    388:        }
                    389: }
                    390: #endif //IS_SERIAL
                    391: 
                    392: /////////////////////////////////////////////////////////////////////////////
                    393: // Diagnostics
                    394: 
                    395: #ifdef _DEBUG
                    396: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    397: void CArray<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::Dump(CDumpContext& dc) const
                    398: {
                    399:        ASSERT_VALID(this);
                    400: 
                    401: #define MAKESTRING(x) #x
                    402:        dc << "a " MAKESTRING(CArray) " with " << m_nSize << " elements";
                    403: #undef MAKESTRING
                    404:        if (dc.GetDepth() > 0)
                    405:        {
                    406:                dc << "\n";
                    407:                for (int i = 0; i < m_nSize; i++)
                    408:                        dc << "\n\t[" << i << "] = " << m_pData[i];
                    409:        }
                    410: }
                    411: 
                    412: template <class TYPE, class ARG_TYPE, int IS_SERIAL, int HAS_CREATE>
                    413: void CArray<TYPE, ARG_TYPE, IS_SERIAL, HAS_CREATE>::AssertValid() const
                    414: {
                    415:        CObject::AssertValid();
                    416:        if (m_pData == NULL)
                    417:        {
                    418:                ASSERT(m_nSize == 0);
                    419:                ASSERT(m_nMaxSize == 0);
                    420:        }
                    421:        else
                    422:        {
                    423:                ASSERT(m_nSize <= m_nMaxSize);
                    424:        }
                    425: }
                    426: #endif //_DEBUG
                    427: 
                    428: /////////////////////////////////////////////////////////////////////////////
                    429: 

unix.superglobalmegacorp.com

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