home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 19.ddi / MFC / SRC / ARCCORE.CP_ / ARCCORE.CP
Encoding:
Text File  |  1993-02-08  |  8.6 KB  |  351 lines

  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 and/or WinHelp documentation provided with the library. 
  8. // See these sources for detailed information regarding the 
  9. // Microsoft Foundation Classes product. 
  10.  
  11. #include "stdafx.h"
  12. #include <malloc.h>
  13.  
  14. #ifdef AFX_AUX_SEG
  15. #pragma code_seg(AFX_AUX_SEG)
  16. #endif
  17.  
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char BASED_CODE THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. #define new DEBUG_NEW
  24.  
  25. ////////////////////////////////////////////////////////////////////////////
  26. // Serialize member functions for low level classes put here
  27. // for code swapping improvements
  28.  
  29. // CString serialization code
  30. // String format: if < 255 chars: len:BYTE, characters in bytes
  31. //              if >= 255 characters: 0xff, len:WORD, characters in bytes
  32.  
  33. CArchive&
  34. AFXAPI operator<<(CArchive& ar, const CString& string)
  35. {
  36.     if (string.m_nDataLength < 255)
  37.     {
  38.         ar << (BYTE) string.m_nDataLength;
  39.     }
  40.     else
  41.     {
  42.         ar << (BYTE) 0xff;
  43.         ar << (WORD) string.m_nDataLength;
  44.     }
  45.     ar.Write(string.m_pchData, string.m_nDataLength);
  46.     return ar;
  47. }
  48.  
  49. CArchive&
  50. AFXAPI operator>>(CArchive& ar, CString& string)
  51. {
  52.     string.Empty();
  53.  
  54.     BYTE bLen;
  55.     ar >> bLen;
  56.  
  57.     WORD nNewLen;
  58.     if (bLen == 0xff)
  59.         // read word of length
  60.         ar >> nNewLen;
  61.     else
  62.         nNewLen = bLen;
  63.  
  64.     // read in as normal characters
  65.     if (nNewLen != 0)
  66.     {
  67.         string.AllocBuffer(nNewLen);
  68.         if (ar.Read(string.m_pchData, nNewLen) != nNewLen)
  69.             AfxThrowArchiveException(CArchiveException::endOfFile);
  70.     }
  71.     return ar;
  72. }
  73.  
  74. // Runtime class serialization code
  75. CRuntimeClass* PASCAL CRuntimeClass::Load(CArchive& ar, UINT* pwSchemaNum)
  76. {
  77.     WORD nLen;
  78.     char szClassName[64];
  79.     CRuntimeClass* pClass;
  80.  
  81.     ar >> (WORD&)(*pwSchemaNum) >> nLen;
  82.  
  83.     if (nLen >= sizeof(szClassName) || ar.Read(szClassName, nLen) != nLen)
  84.         return NULL;
  85.     szClassName[nLen] = '\0';
  86.  
  87. #ifndef _AFXDLL
  88.     for (pClass = pFirstClass; pClass != NULL; pClass = pClass->m_pNextClass)
  89.     {
  90.         if (lstrcmp(szClassName, pClass->m_lpszClassName) == 0)
  91.             return pClass;
  92.     }
  93. #else
  94.     // all registered CRuntimeClasses should be owned by the app or a DLL
  95.     ASSERT(CRuntimeClass::pFirstClass == NULL);
  96.  
  97.     // first walk through the app specific classes
  98.     for (pClass = _AfxGetAppData()->pFirstAppClass; pClass != NULL;
  99.         pClass = pClass->m_pNextClass)
  100.     {
  101.         if (lstrcmp(szClassName, pClass->m_lpszClassName) == 0)
  102.             return pClass;
  103.     }
  104.     // now walk through the classes in different DLLs
  105.     CDynLinkLibrary* pDLL;
  106.     for (pDLL = _AfxGetAppData()->pFirstDLL; pDLL != NULL;
  107.         pDLL = pDLL->m_pNextDLL)
  108.     {
  109.         for (pClass = pDLL->m_pFirstSharedClass; pClass != NULL;
  110.             pClass = pClass->m_pNextClass)
  111.         {
  112.             if (lstrcmp(szClassName, pClass->m_lpszClassName) == 0)
  113.                 return pClass;
  114.         }
  115.     }
  116. #endif //_AFXDLL
  117.  
  118.     return NULL; // not found
  119. }
  120.  
  121. void
  122. CRuntimeClass::Store(CArchive& ar)
  123.     // Stores a class ref
  124. {
  125.     WORD nLen = (WORD)lstrlen(m_lpszClassName);
  126.  
  127.     ar << (WORD)m_wSchema << nLen;
  128.     ar.Write(m_lpszClassName, nLen);
  129. }
  130.  
  131. ////////////////////////////////////////////////////////////////////////////
  132. ////////////////////////////////////////////////////////////////////////////
  133. // Archive object input/output
  134.  
  135.     // minimum buffer size
  136.     enum { nBufSizeMin = 128 };
  137.  
  138. ////////////////////////////////////////////////////////////////////////////
  139.  
  140. CArchive::CArchive(CFile* pFile, 
  141.         UINT nMode,
  142.         int nBufSize /* = 512 */,
  143.         void FAR* lpBuf /* = NULL */)
  144. {
  145.     ASSERT_VALID(pFile);
  146.  
  147.     m_nMode = nMode;
  148.  
  149.     // initialize the buffer.  minimum size is 128
  150.     m_lpBufStart = (BYTE FAR*)lpBuf;
  151.  
  152.     if (nBufSize < nBufSizeMin)
  153.     {
  154.         // force use of private buffer of minimum size
  155.         m_nBufSize = nBufSizeMin;
  156.         m_lpBufStart = NULL; 
  157.     }
  158.     else
  159.         m_nBufSize = nBufSize;
  160.  
  161.     if (m_lpBufStart == NULL)
  162.     {
  163.         m_lpBufStart = (BYTE FAR*)_fmalloc(m_nBufSize);
  164.         m_bUserBuf = FALSE;
  165.     }
  166.     else
  167.         m_bUserBuf = TRUE;
  168.  
  169.     ASSERT(m_lpBufStart != NULL);
  170.     ASSERT(AfxIsValidAddress(m_lpBufStart, m_nBufSize));
  171.  
  172.     m_lpBufMax = m_lpBufStart + m_nBufSize;
  173.     m_lpBufCur = (IsLoading()) ? m_lpBufMax : m_lpBufStart;
  174.     m_pFile = pFile;
  175.     m_pLoadArray = NULL;
  176.     ASSERT(m_pStoreMap == NULL);        // same as m_pLoadArray
  177. }
  178.  
  179. CArchive::~CArchive()
  180. {
  181.     ASSERT(AfxIsValidAddress(m_lpBufStart, (UINT)(m_lpBufMax - m_lpBufStart)));
  182.     ASSERT(AfxIsValidAddress(m_lpBufCur, (UINT)(m_lpBufMax - m_lpBufCur)));
  183.     ASSERT(m_lpBufStart != NULL);
  184.  
  185.     // Close makes m_pFile NULL.  If it is not NULL, we must Close the
  186.     // CArchive.
  187.     if (m_pFile != NULL && !(m_nMode & bNoFlushOnDelete))
  188.         Close();
  189.  
  190.     if (!m_bUserBuf)
  191.         _ffree(m_lpBufStart);
  192.  
  193.     // m_pStoreMap and m_pLoadArray are unioned, so we only need to delete one
  194.     ASSERT((CObject*)m_pStoreMap == (CObject*)m_pLoadArray);
  195.     delete (CObject*)m_pLoadArray;
  196. }
  197.  
  198. void
  199. CArchive::Close()
  200. {
  201.     ASSERT_VALID(m_pFile);
  202.  
  203.     Flush();
  204.     m_pFile = NULL;
  205. }
  206.  
  207. UINT
  208. CArchive::Read(void FAR* lpBuf, UINT nMax)
  209. {
  210.     ASSERT_VALID(m_pFile);
  211.     ASSERT(lpBuf != NULL);
  212.     ASSERT(m_lpBufStart != NULL);
  213.     ASSERT(m_lpBufCur != NULL);
  214.     ASSERT(AfxIsValidAddress(lpBuf, nMax));
  215.     ASSERT(AfxIsValidAddress(m_lpBufStart, (UINT)(m_lpBufMax - m_lpBufStart)));
  216.     ASSERT(AfxIsValidAddress(m_lpBufCur, (UINT)(m_lpBufMax - m_lpBufCur)));
  217.     ASSERT(IsLoading());
  218.  
  219.     if (nMax == 0)
  220.         return 0;
  221.  
  222.     UINT nRead = 0;
  223.     while (nMax > 0)
  224.     {
  225.         UINT nCopy = min(nMax, (UINT)(m_lpBufMax - m_lpBufCur));
  226.         _fmemcpy(lpBuf, m_lpBufCur, nCopy);
  227.         m_lpBufCur += nCopy;
  228.         lpBuf = ((BYTE FAR*)lpBuf) + nCopy;
  229.         nMax -= nCopy;
  230.         nRead += nCopy;
  231.         if (nMax != 0)
  232.         {
  233.             TRY
  234.             {
  235.                 FillBuffer(min(nMax, (UINT)m_nBufSize));
  236.             }
  237.             CATCH(CArchiveException, e)
  238.             {
  239.                 // Reached end of file
  240.                 if (e->m_cause != CArchiveException::endOfFile)
  241.                     THROW_LAST();
  242.  
  243.                 nCopy = (UINT)(m_lpBufMax - m_lpBufStart);
  244.                 _fmemcpy(lpBuf, m_lpBufCur, nCopy);
  245.                 return nRead + nCopy;
  246.             }
  247.             END_CATCH
  248.         }
  249.     }
  250.  
  251.     return nRead;
  252. }
  253.  
  254. void
  255. CArchive::Write(const void FAR* lpBuf, UINT nMax)
  256. {
  257.     ASSERT_VALID(m_pFile);
  258.     ASSERT(m_lpBufStart != NULL);
  259.     ASSERT(m_lpBufCur != NULL);
  260.     ASSERT(AfxIsValidAddress(lpBuf, nMax, FALSE));  // read-only access needed
  261.     ASSERT(AfxIsValidAddress(m_lpBufStart, (UINT)(m_lpBufMax - m_lpBufStart)));
  262.     ASSERT(AfxIsValidAddress(m_lpBufCur, (UINT)(m_lpBufMax - m_lpBufCur)));
  263.     ASSERT(IsStoring());
  264.  
  265.     while (nMax > 0)
  266.     {
  267.         UINT nCopy = min(nMax, (UINT)(m_lpBufMax - m_lpBufCur));
  268.         _fmemcpy(m_lpBufCur, lpBuf, nCopy);
  269.         m_lpBufCur += nCopy;
  270.         lpBuf = ((BYTE FAR*)lpBuf) + nCopy;
  271.         nMax -= nCopy;
  272.         if (nMax != 0)
  273.         {
  274.             // write out the current buffer to file
  275.             if (m_lpBufCur != m_lpBufStart)
  276.                 m_pFile->Write(m_lpBufStart, (UINT)(m_lpBufCur - m_lpBufStart));
  277.  
  278.             // restore buffer to initial state
  279.             m_lpBufCur = m_lpBufStart;
  280.         }
  281.     }
  282. }
  283.  
  284.  
  285. void
  286. CArchive::Flush()
  287. {
  288.     ASSERT(m_lpBufStart != NULL);
  289.     ASSERT(m_lpBufCur != NULL);
  290.     ASSERT_VALID(m_pFile);
  291.     ASSERT(m_lpBufStart != NULL);
  292.     ASSERT(m_lpBufCur != NULL);
  293.     ASSERT(AfxIsValidAddress(m_lpBufStart, (UINT)(m_lpBufMax - m_lpBufStart)));
  294.     ASSERT(AfxIsValidAddress(m_lpBufCur, (UINT)(m_lpBufMax - m_lpBufCur)));
  295.  
  296.     if (IsLoading())
  297.     {
  298.         // unget the characters in the buffer, seek back unused amount
  299.         m_pFile->Seek(-(m_lpBufMax - m_lpBufCur), CFile::current);
  300.         m_lpBufCur = m_lpBufMax;    // empty
  301.     }
  302.     else
  303.     {
  304.         // write out the current buffer to file
  305.         if (m_lpBufCur != m_lpBufStart)
  306.         {
  307.             m_pFile->Write(m_lpBufStart, (UINT)(m_lpBufCur - m_lpBufStart));
  308.             m_pFile->Flush();
  309.         }
  310.  
  311.         // restore buffer to initial state
  312.         m_lpBufCur = m_lpBufStart;
  313.     }
  314. }
  315.  
  316. void 
  317. CArchive::FillBuffer(UINT nBytesNeeded)
  318. {
  319.     ASSERT(IsLoading());
  320.     ASSERT_VALID(m_pFile);
  321.     ASSERT(m_lpBufStart != NULL);
  322.     ASSERT(m_lpBufCur != NULL);
  323.     ASSERT(nBytesNeeded > 0);
  324.     ASSERT(AfxIsValidAddress(m_lpBufStart, (UINT)(m_lpBufMax - m_lpBufStart)));
  325.     ASSERT(AfxIsValidAddress(m_lpBufCur, (UINT)(m_lpBufMax - m_lpBufCur)));
  326.  
  327.     // fill up the current buffer from file
  328.     if (m_lpBufCur > m_lpBufStart)
  329.     {
  330.         // there is at least some room to fill
  331.         UINT nUnused = 0; // bytes remaining in buffer
  332.         UINT nActual = 0; // bytes read from file
  333.  
  334.         if ((int)(nUnused = (UINT)(m_lpBufMax - m_lpBufCur)) > 0)
  335.         {
  336.             _fmemcpy(m_lpBufStart, m_lpBufCur,(size_t)(m_lpBufMax-m_lpBufCur)); 
  337.                    // copy unused
  338.         }
  339.  
  340.         nActual = m_pFile->Read(m_lpBufStart+nUnused, m_nBufSize-nUnused);
  341.  
  342.         m_lpBufCur = m_lpBufStart;
  343.         m_lpBufMax = m_lpBufStart + nUnused + nActual;
  344.  
  345.         if (nActual < nBytesNeeded)
  346.             // not enough data to fill request
  347.             AfxThrowArchiveException(CArchiveException::endOfFile);
  348.     }
  349. }
  350.  
  351.