Annotation of mstools/mfc/src/archive.cpp, revision 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.