Annotation of mstools/mfc/src/archive.cpp, revision 1.1.1.1

1.1       root        1: // This is a part of the Microsoft Foundation Classes C++ library. 
                      2: // Copyright (C) 1992 Microsoft Corporation 
                      3: // All rights reserved. 
                      4: //  
                      5: // This source code is only intended as a supplement to the 
                      6: // Microsoft Foundation Classes Reference and Microsoft 
                      7: // QuickHelp documentation provided with the library. 
                      8: // See these sources for detailed information regarding the 
                      9: // Microsoft Foundation Classes product. 
                     10: 
                     11: #include "afx.h"
                     12: #include "afxcoll.h"
                     13: #pragma hdrstop
                     14: 
                     15: #include <malloc.h>
                     16: 
                     17: #ifdef AFX_CORE_SEG
                     18: #pragma code_seg(AFX_CORE_SEG)
                     19: #endif
                     20: 
                     21: 
                     22: #ifndef min
                     23: #define min(a,b)        (((a) < (b)) ? (a) : (b))
                     24: #endif
                     25: 
                     26: #ifdef _DEBUG
                     27: #undef THIS_FILE
                     28: static char BASED_CODE THIS_FILE[] = __FILE__;
                     29: #endif
                     30: 
                     31: #define new DEBUG_NEW
                     32: 
                     33: ////////////////////////////////////////////////////////////////////////////
                     34: // Serialize member functions for low level classes put here
                     35: // for code swapping improvements
                     36: 
                     37: // CString serialization code
                     38: // String format: if < 255 chars: len:BYTE, characters in bytes
                     39: //              if >= 255 characters: 0xff, len:WORD, characters in bytes
                     40: 
                     41: CArchive&
                     42: operator <<(CArchive& ar, const CString& string)
                     43: {
                     44:        if (string.m_nDataLength < 255)
                     45:        {
                     46:                ar << (BYTE) string.m_nDataLength;
                     47:        }
                     48:        else
                     49:        {
                     50:                ar << (BYTE) 0xff;
                     51:                ar << (WORD) string.m_nDataLength;
                     52:        }
                     53:        ar.Write(string.m_pchData, string.m_nDataLength);
                     54:        return ar;
                     55: }
                     56: 
                     57: CArchive&
                     58: operator >>(CArchive& ar, CString& string)
                     59: {
                     60:        string.Empty();
                     61: 
                     62:        BYTE bLen;
                     63:        ar >> bLen;
                     64: 
                     65:        WORD nNewLen;
                     66:        if (bLen == 0xff)
                     67:                // read word of length
                     68:                ar >> nNewLen;
                     69:        else
                     70:                nNewLen = bLen;
                     71: 
                     72:        // read in as normal characters
                     73:        if (nNewLen != 0)
                     74:        {
                     75:                string.AllocBuffer(nNewLen);
                     76:                if (ar.Read(string.m_pchData, nNewLen) != nNewLen)
                     77:                        AfxThrowArchiveException(CArchiveException::endOfFile);
                     78:        }
                     79:        return ar;
                     80: }
                     81: 
                     82: // Runtime class serialization code
                     83: CRuntimeClass*
                     84: CRuntimeClass::Load(CArchive& ar, UINT* pwSchemaNum)
                     85: {
                     86:        WORD nLen;
                     87:        char szClassName[64];
                     88:        CRuntimeClass* pClass;
                     89: 
                     90:        ar >> (WORD&)(*pwSchemaNum) >> nLen;
                     91: 
                     92:        if (nLen >= sizeof(szClassName) || ar.Read(szClassName, nLen) != nLen)
                     93:                return NULL;
                     94:        szClassName[nLen] = '\0';
                     95: 
                     96:        for (pClass = pFirstClass; pClass != NULL; pClass = pClass->m_pNextClass)
                     97:        {
                     98:                if (strcmp(szClassName, pClass->m_pszClassName) == 0)
                     99:                        return pClass;
                    100:        }
                    101: 
                    102:        return NULL;
                    103: }
                    104: 
                    105: void
                    106: CRuntimeClass::Store(CArchive& ar)
                    107:        // Stores a class ref
                    108: {
                    109:        WORD nLen = (WORD)strlen(m_pszClassName);
                    110: 
                    111:        ar << (WORD)m_wSchema << nLen;
                    112:        ar.Write(m_pszClassName, nLen);
                    113: }
                    114: 
                    115: ////////////////////////////////////////////////////////////////////////////
                    116: ////////////////////////////////////////////////////////////////////////////
                    117: // Archive object input/output
                    118: 
                    119:        // amount to grow m_loadArray upon insert
                    120:        enum { nGrowSize = 10 };
                    121: 
                    122:        // minimum buffer size
                    123:        enum { nBufSizeMin = 128 };
                    124: 
                    125: ////////////////////////////////////////////////////////////////////////////
                    126: // Pointer mapping constants
                    127: #define wNullTag      ((WORD)0)
                    128: #define wNewClassTag  ((WORD)-1)
                    129: #define wOldClassTag  ((WORD)-32768) /* 0x8000 or the class index with this */
                    130: #define nMaxMapCount  ((WORD)32766)  /* 0x7FFE last valid mapCount */
                    131: 
                    132: 
                    133: // TRY/CATCH cannot be used with /Ox
                    134: #pragma optimize("elg", off)
                    135: 
                    136: CArchive::CArchive(CFile* pFile, 
                    137:                UINT nMode,
                    138:                int nBufSize /* = 512 */,
                    139:                void FAR* lpBuf /* = NULL */)
                    140: {
                    141:        ASSERT_VALID(pFile);
                    142: 
                    143:        m_nMode = nMode;
                    144: 
                    145:        // initialize the buffer.  minimum size is 128
                    146:        m_lpBufStart = (BYTE FAR*)lpBuf;
                    147: 
                    148:        if (nBufSize < nBufSizeMin)
                    149:        {
                    150:                // force use of private buffer of minimum size
                    151:                m_nBufSize = nBufSizeMin;
                    152:                m_lpBufStart = NULL; 
                    153:        }
                    154:        else
                    155:                m_nBufSize = nBufSize;
                    156: 
                    157:        if (m_lpBufStart == NULL)
                    158:        {
                    159:                m_lpBufStart = (BYTE FAR*)_fmalloc(m_nBufSize);
                    160:                m_bUserBuf = FALSE;
                    161:        }
                    162:        else
                    163:                m_bUserBuf = TRUE;
                    164: 
                    165:        ASSERT(m_lpBufStart != NULL);
                    166:        ASSERT(AfxIsValidAddress(m_lpBufStart, m_nBufSize));
                    167: 
                    168:        m_lpBufMax = m_lpBufStart + m_nBufSize;
                    169:        m_lpBufCur = (IsLoading()) ? m_lpBufMax : m_lpBufStart;
                    170:        m_pFile = pFile;
                    171: 
                    172:        // allocate the load/store map/array fail gracefully if OOM
                    173:        TRY
                    174:        {
                    175:                if (nMode == CArchive::load) 
                    176:                        m_pLoadArray = new CPtrArray;
                    177:                else
                    178:                        m_pStoreMap = new CMapPtrToWord;
                    179:        }
                    180:        CATCH(CMemoryException, e)
                    181:        {
                    182:                if (!m_bUserBuf)
                    183:                        _ffree(m_lpBufStart);
                    184:                THROW_LAST();
                    185:        }
                    186:        END_CATCH
                    187: 
                    188:        if (nMode == CArchive::load) 
                    189:        {
                    190:                ASSERT(IsLoading());
                    191:                ASSERT(nGrowSize > 0);
                    192:                m_pLoadArray->SetSize(nGrowSize, nGrowSize); 
                    193:                ASSERT(wNullTag == 0);
                    194:                m_pLoadArray->SetAt(wNullTag, NULL);
                    195:                m_nMapCount = 1;
                    196:        }
                    197:        else
                    198:        {
                    199:                ASSERT(IsStoring());
                    200: 
                    201:                m_pStoreMap->SetAt(NULL, wNullTag);
                    202:                m_nMapCount = 1;
                    203:        }
                    204: 
                    205: }
                    206: #pragma optimize("", on)
                    207: 
                    208: 
                    209: CArchive::~CArchive()
                    210: {
                    211:        ASSERT(AfxIsValidAddress(m_lpBufStart, (UINT)(m_lpBufMax - m_lpBufStart)));
                    212:        ASSERT(AfxIsValidAddress(m_lpBufCur, (UINT)(m_lpBufMax - m_lpBufCur)));
                    213:        ASSERT(m_lpBufStart != NULL);
                    214: 
                    215:        // Close makes m_pFile NULL.  If it is not NULL, we must Close the
                    216:        // CArchive.
                    217:        if (m_pFile)
                    218:                Close();
                    219: 
                    220:        if (!m_bUserBuf)
                    221:                _ffree(m_lpBufStart);
                    222: 
                    223:        if (m_nMode == CArchive::load)
                    224:                delete m_pLoadArray;
                    225:        else
                    226:                delete m_pStoreMap;
                    227: }
                    228: 
                    229: void
                    230: CArchive::Close()
                    231: {
                    232:        ASSERT_VALID(m_pFile);
                    233: 
                    234:        Flush();
                    235:        m_pFile = NULL;
                    236: }
                    237: 
                    238: void
                    239: CArchive::WriteObject(const CObject* cpOb)
                    240: {
                    241:        // object can be NULL
                    242:        ASSERT(IsStoring());    // proper direction
                    243:        ASSERT(m_lpBufStart != NULL);
                    244:        ASSERT(m_lpBufCur != NULL);
                    245: 
                    246:        CObject* pOb = (CObject*)cpOb;
                    247:        WORD nObIndex;
                    248: 
                    249:        ASSERT(sizeof(nObIndex) == 2);
                    250:        ASSERT(sizeof(wNullTag) == 2);
                    251:        ASSERT(sizeof(wNewClassTag) == 2);
                    252: 
                    253:        if (pOb == NULL)
                    254:                *this << wNullTag;
                    255:        else if (!(cpOb->IsSerializable()))
                    256:                AfxThrowNotSupportedException();
                    257:        else if ((nObIndex = (*m_pStoreMap)[pOb]) != 0) //ASSUME: initialized to 0 map
                    258:                *this << nObIndex;
                    259:        else
                    260:        {
                    261:                CRuntimeClass* pClassRef = pOb->GetRuntimeClass();
                    262:                WORD nClassIndex;
                    263: 
                    264:                // write out class id of pOb, with high bit set to indicate
                    265:                // new object follows
                    266: 
                    267:                // ASSUME: initialized to 0 map
                    268:                if ((nClassIndex = (*m_pStoreMap)[pClassRef]) != 0) 
                    269:                {
                    270:                        // previously seen class, write out the index tagged by high bit
                    271:                        *this << (WORD)(wOldClassTag | nClassIndex);
                    272:                }
                    273:                else
                    274:                {
                    275:                        // new class
                    276:                        *this << wNewClassTag;
                    277:                        pClassRef->Store(*this);
                    278: 
                    279:                        (*m_pStoreMap)[pClassRef] = (WORD) m_nMapCount++;
                    280:                        if (m_nMapCount > nMaxMapCount)
                    281:                                AfxThrowArchiveException(CArchiveException::badIndex);
                    282:                }
                    283:                // enter in stored object table and output
                    284:                (*m_pStoreMap)[pOb] = (WORD)m_nMapCount++;
                    285:                if (m_nMapCount > nMaxMapCount)
                    286:                        AfxThrowArchiveException(CArchiveException::badIndex);
                    287: 
                    288:                pOb->Serialize(*this);
                    289:        }
                    290: }
                    291: 
                    292: 
                    293: 
                    294: CObject*
                    295: CArchive::ReadObject(const CRuntimeClass* pClassRefRequested)
                    296: {
                    297:        ASSERT(pClassRefRequested == NULL || AfxIsValidAddress(pClassRefRequested, sizeof(struct CRuntimeClass)));
                    298:        ASSERT(IsLoading());    // proper direction
                    299:        ASSERT(wNullTag == 0);
                    300:        ASSERT(m_lpBufStart != NULL);
                    301:        ASSERT(m_lpBufCur != NULL);
                    302: 
                    303:        CRuntimeClass* pClassRef;
                    304:        WORD obTag;
                    305:        WORD wSchema;
                    306: 
                    307:        if (pClassRefRequested && (pClassRefRequested->m_wSchema == 0xFFFF))
                    308:                AfxThrowNotSupportedException();
                    309:                
                    310:        *this >> obTag;
                    311: 
                    312:        //NOTE: this relies on signed testing of the tag values
                    313:        if ((short)obTag >= (short)wNullTag)
                    314:        {
                    315:                if (obTag > (WORD)m_pLoadArray->GetUpperBound())
                    316:                        AfxThrowArchiveException(CArchiveException::badIndex);
                    317: 
                    318:                CObject* pOb = (CObject*)m_pLoadArray->GetAt(obTag);
                    319: 
                    320:                if (pOb != NULL && pClassRefRequested && !pOb->IsKindOf(pClassRefRequested))
                    321:                        AfxThrowArchiveException(CArchiveException::badClass);
                    322:                return pOb;
                    323:        }
                    324: 
                    325: 
                    326:        if (obTag == wNewClassTag)
                    327:        {
                    328:                // new object follows a new class id
                    329:                if (m_nMapCount > nMaxMapCount)
                    330:                        AfxThrowArchiveException(CArchiveException::badIndex);
                    331: 
                    332:                if ((pClassRef = CRuntimeClass::Load(*this, (UINT*)&wSchema)) == NULL)
                    333:                {
                    334:                        AfxThrowArchiveException(CArchiveException::badClass);
                    335:                        return NULL;
                    336:                }
                    337:                if (pClassRef->m_wSchema != wSchema)
                    338:                {
                    339:                        AfxThrowArchiveException(CArchiveException::badSchema);
                    340:                        return NULL;
                    341:                }
                    342:                m_pLoadArray->InsertAt(m_nMapCount++, pClassRef, 1);
                    343:                ASSERT(m_nMapCount < (UINT)0x7FFF);
                    344:        } 
                    345:        else
                    346:        {
                    347:                // existing class index in obTag followed by new object
                    348: 
                    349:                WORD nClassIndex = (WORD)(obTag & (WORD)~wOldClassTag);
                    350:                ASSERT(sizeof(nClassIndex) == 2);
                    351: 
                    352:                if (nClassIndex & 0x8000 || 
                    353:                                nClassIndex > (WORD)m_pLoadArray->GetUpperBound())
                    354:                        AfxThrowArchiveException(CArchiveException::badIndex);
                    355: 
                    356:                pClassRef = (CRuntimeClass*)m_pLoadArray->GetAt(nClassIndex);
                    357:        }
                    358: 
                    359:        // allocate a new object based on the class just acquired
                    360:        CObject* pOb = pClassRef->CreateObject();
                    361:        ASSERT(pOb != NULL);
                    362: 
                    363:        // Add to mapping array BEFORE de-serializing
                    364:        m_pLoadArray->InsertAt(m_nMapCount++, pOb, 1);
                    365: 
                    366:        pOb->Serialize(*this);
                    367: 
                    368:        ASSERT(pOb != NULL);
                    369:        if (pClassRefRequested && !pOb->IsKindOf(pClassRefRequested))
                    370:                AfxThrowArchiveException(CArchiveException::badClass);
                    371: 
                    372:        return pOb;
                    373: }
                    374: 
                    375: 
                    376: UINT
                    377: CArchive::Read(void FAR* lpBuf, UINT nMax)
                    378: {
                    379:        ASSERT_VALID(m_pFile);
                    380:        ASSERT(lpBuf != NULL);
                    381:        ASSERT(m_lpBufStart != NULL);
                    382:        ASSERT(m_lpBufCur != NULL);
                    383:        ASSERT(AfxIsValidAddress(lpBuf, nMax));
                    384:        ASSERT(AfxIsValidAddress(m_lpBufStart, (UINT)(m_lpBufMax - m_lpBufStart)));
                    385:        ASSERT(AfxIsValidAddress(m_lpBufCur, (UINT)(m_lpBufMax - m_lpBufCur)));
                    386:        ASSERT(IsLoading());
                    387: 
                    388:        register UINT nRead = 0;
                    389: 
                    390:        if (nMax == 0)
                    391:                return 0;
                    392: 
                    393:        while (nMax > 0)
                    394:        {
                    395:                UINT nCopy = min(nMax, (UINT)(m_lpBufMax - m_lpBufCur));
                    396:                _fmemcpy(lpBuf, m_lpBufCur, nCopy);
                    397:                m_lpBufCur += nCopy;
                    398:                lpBuf = ((BYTE FAR*)lpBuf) + nCopy;
                    399:                nMax -= nCopy;
                    400:                nRead += nCopy;
                    401:                if (nMax != 0)
                    402:                        FillBuffer(min(nMax, (UINT)m_nBufSize));
                    403:        }
                    404:        return nRead;
                    405: }
                    406: 
                    407: void
                    408: CArchive::Write(const void FAR* lpBuf, UINT nMax)
                    409: {
                    410:        ASSERT_VALID(m_pFile);
                    411:        ASSERT(m_lpBufStart != NULL);
                    412:        ASSERT(m_lpBufCur != NULL);
                    413:        ASSERT(AfxIsValidAddress(lpBuf, nMax));
                    414:        ASSERT(AfxIsValidAddress(m_lpBufStart, (UINT)(m_lpBufMax - m_lpBufStart)));
                    415:        ASSERT(AfxIsValidAddress(m_lpBufCur, (UINT)(m_lpBufMax - m_lpBufCur)));
                    416:        ASSERT(IsStoring());
                    417: 
                    418:        register void FAR* lpBufT = (void FAR*)lpBuf;
                    419: 
                    420:        while (nMax > 0)
                    421:        {
                    422:                UINT nCopy = min(nMax, (UINT)(m_lpBufMax - m_lpBufCur));
                    423:                _fmemcpy(m_lpBufCur, lpBufT, nCopy);
                    424:                m_lpBufCur += nCopy;
                    425:                lpBufT = ((BYTE FAR*)lpBufT) + nCopy;
                    426:                nMax -= nCopy;
                    427:                if (nMax != 0)
                    428:                {
                    429:                        // write out the current buffer to file
                    430:                        if (m_lpBufCur != m_lpBufStart)
                    431:                                m_pFile->Write(m_lpBufStart, m_lpBufCur - m_lpBufStart);
                    432: 
                    433:                        // restore buffer to initial state
                    434:                        m_lpBufCur = m_lpBufStart;
                    435:                }
                    436:        }
                    437: }
                    438: 
                    439: 
                    440: void
                    441: CArchive::Flush()
                    442: {
                    443:        ASSERT(m_lpBufStart != NULL);
                    444:        ASSERT(m_lpBufCur != NULL);
                    445:        ASSERT_VALID(m_pFile);
                    446:        ASSERT(m_lpBufStart != NULL);
                    447:        ASSERT(m_lpBufCur != NULL);
                    448:        ASSERT(AfxIsValidAddress(m_lpBufStart, (UINT)(m_lpBufMax - m_lpBufStart)));
                    449:        ASSERT(AfxIsValidAddress(m_lpBufCur, (UINT)(m_lpBufMax - m_lpBufCur)));
                    450: 
                    451:        if (IsLoading())
                    452:        {
                    453:                // unget the characters in the buffer, seek back unused amount
                    454:                m_pFile->Seek(-(m_lpBufMax - m_lpBufCur), CFile::current);
                    455:                m_lpBufCur = m_lpBufMax;    // empty
                    456:        }
                    457:        else
                    458:        {
                    459:                // write out the current buffer to file
                    460:                if (m_lpBufCur != m_lpBufStart)
                    461:                {
                    462:                        m_pFile->Write(m_lpBufStart, m_lpBufCur - m_lpBufStart);
                    463:                        m_pFile->Flush();
                    464:                }
                    465: 
                    466:                // restore buffer to initial state
                    467:                m_lpBufCur = m_lpBufStart;
                    468:        }
                    469: }
                    470: 
                    471: void 
                    472: CArchive::FillBuffer(UINT nBytesNeeded)
                    473: {
                    474:        ASSERT(IsLoading());
                    475:        ASSERT_VALID(m_pFile);
                    476:        ASSERT(m_lpBufStart != NULL);
                    477:        ASSERT(m_lpBufCur != NULL);
                    478:        ASSERT(nBytesNeeded > 0);
                    479:        ASSERT(AfxIsValidAddress(m_lpBufStart, (UINT)(m_lpBufMax - m_lpBufStart)));
                    480:        ASSERT(AfxIsValidAddress(m_lpBufCur, (UINT)(m_lpBufMax - m_lpBufCur)));
                    481: 
                    482: 
                    483:        // fill up the current buffer from file
                    484:        if (m_lpBufCur > m_lpBufStart)
                    485:        {
                    486:                // there is at least some room to fill
                    487:                UINT nUnused = 0; // bytes remaining in buffer
                    488:                UINT nActual = 0; // bytes read from file
                    489: 
                    490:                if ((nUnused = m_lpBufMax - m_lpBufCur) > 0)
                    491:                {
                    492:                        _fmemcpy(m_lpBufStart, m_lpBufCur, m_lpBufMax - m_lpBufCur);    // copy unused
                    493:                }
                    494: 
                    495:                nActual = m_pFile->Read(m_lpBufStart+nUnused, m_nBufSize-nUnused);
                    496: 
                    497:                if (nActual < nBytesNeeded)
                    498:                        // not enough data to fill request
                    499:                        AfxThrowArchiveException(CArchiveException::endOfFile);
                    500: 
                    501:                m_lpBufCur = m_lpBufStart;
                    502:                m_lpBufMax = m_lpBufStart + nUnused + nActual;
                    503:        }
                    504: }

unix.superglobalmegacorp.com

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