|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.