WEB开发网
开发学院软件开发VC FMD开发文集 -- CArchive原理 阅读

FMD开发文集 -- CArchive原理

 2010-03-28 20:34:54 来源:WEB开发网   
核心提示:③运行时类信息的读写为了避免众多重复的同类对象写入重复的类信息,CArchive中使用CMap对象储存和检索类信息,FMD开发文集 -- CArchive原理(6),void CArchive::WriteClass(const CRuntimeClass* pClassRef){ASSERT(pClassRef !=

③运行时类信息的读写

为了避免众多重复的同类对象写入重复的类信息,CArchive中使用CMap对象储存和检索类信息。

void CArchive::WriteClass(const CRuntimeClass* pClassRef)
{
  ASSERT(pClassRef != NULL);
  ASSERT(IsStoring());  // proper direction
  if (pClassRef-> m_wSchema == 0xFFFF)
  {
    TRACE1("Warning: Cannot call WriteClass/WriteObject for %hs.
",
      pClassRef-> m_lpszClassName);
    AfxThrowNotSupportedException();
  }
  // make sure m_pStoreMap is initialized
  MapObject(NULL);
  // write out class id of pOb, with high bit set to indicate
  // new object follows
  // ASSUME: initialized to 0 map
  DWORD nClassIndex;
  if ((nClassIndex = (DWORD)(*m_pStoreMap)[(void*)pClassRef]) != 0)
  {
    // previously seen class, write out the index tagged by high bit
    if (nClassIndex < wBigObjectTag)
      *this << (WORD)(wClassTag | nClassIndex);
    else
    {
      *this << wBigObjectTag;
      *this << (dwBigClassTag | nClassIndex);
    }
  }
  else
  {
    // store new class
    *this << wNewClassTag;
    pClassRef-> Store(*this);
    // store new class reference in map, checking for overflow
    CheckCount();
    (*m_pStoreMap)[(void*)pClassRef] = (void*)m_nMapCount++;
  }
}
CRuntimeClass* CArchive::ReadClass(const CRuntimeClass* pClassRefRequested,
  UINT* pSchema, DWORD* pObTag)
{
  ASSERT(pClassRefRequested == NULL ||
    AfxIsValidAddress(pClassRefRequested, sizeof(CRuntimeClass), FALSE));
  ASSERT(IsLoading());  // proper direction
  if (pClassRefRequested != NULL && pClassRefRequested-> m_wSchema == 0xFFFF)
  {
    TRACE1("Warning: Cannot call ReadClass/ReadObject for %hs.
",
      pClassRefRequested-> m_lpszClassName);
    AfxThrowNotSupportedException();
  }
  // make sure m_pLoadArray is initialized
  MapObject(NULL);
  // read object tag - if prefixed by wBigObjectTag then DWORD tag follows
  DWORD obTag;
  WORD wTag;
  *this >> wTag;
  if (wTag == wBigObjectTag)
    *this >> obTag;
  else
    obTag = ((wTag & wClassTag) << 16) | (wTag & ~wClassTag);
  // check for object tag (throw exception if expecting class tag)
  if (!(obTag & dwBigClassTag))
  {
    if (pObTag == NULL)
      AfxThrowArchiveException(CArchiveException::badIndex, m_strFileName);
    *pObTag = obTag;
    return NULL;
  }
  CRuntimeClass* pClassRef;
  UINT nSchema;
  if (wTag == wNewClassTag)
  {
    // new object follows a new class id
    if ((pClassRef = CRuntimeClass::Load(*this, &nSchema)) == NULL)
      AfxThrowArchiveException(CArchiveException::badClass, m_strFileName);
    // check nSchema against the expected schema
    if ((pClassRef-> m_wSchema & ~VERSIONABLE_SCHEMA) != nSchema)
    {
      if (!(pClassRef-> m_wSchema & VERSIONABLE_SCHEMA))
      {
        // schema doesn''t match and not marked as VERSIONABLE_SCHEMA
        AfxThrowArchiveException(CArchiveException::badSchema,
          m_strFileName);
      }
      else
      {
        // they differ -- store the schema for later retrieval
        if (m_pSchemaMap == NULL)
          m_pSchemaMap = new CMapPtrToPtr;
        ASSERT_VALID(m_pSchemaMap);
        m_pSchemaMap-> SetAt(pClassRef, (void*)nSchema);
      }
    }
    CheckCount();
    m_pLoadArray-> InsertAt(m_nMapCount++, pClassRef);
  }
  else
  {
    // existing class index in obTag followed by new object
    DWORD nClassIndex = (obTag & ~dwBigClassTag);
    if (nClassIndex == 0 || nClassIndex > (DWORD)m_pLoadArray-> GetUpperBound())
      AfxThrowArchiveException(CArchiveException::badIndex,
        m_strFileName);
    pClassRef = (CRuntimeClass*)m_pLoadArray-> GetAt(nClassIndex);
    ASSERT(pClassRef != NULL);
    // determine schema stored against objects of this type
    void* pTemp;
    BOOL bFound = FALSE;
    nSchema = 0;
    if (m_pSchemaMap != NULL)
    {
      bFound = m_pSchemaMap-> Lookup( pClassRef, pTemp );
      if (bFound)
        nSchema = (UINT)pTemp;
    }
    if (!bFound)
      nSchema = pClassRef-> m_wSchema & ~VERSIONABLE_SCHEMA;
  }
  // check for correct derivation
  if (pClassRefRequested != NULL &&
    !pClassRef-> IsDerivedFrom(pClassRefRequested))
  {
    AfxThrowArchiveException(CArchiveException::badClass, m_strFileName);
  }
  // store nSchema for later examination
  if (pSchema != NULL)
    *pSchema = nSchema;
  else
    m_nObjectSchema = nSchema;
  // store obTag for later examination
  if (pObTag != NULL)
    *pObTag = obTag;
  // return the resulting CRuntimeClass*
  return pClassRef;
}

上一页  1 2 3 4 5 6 

Tags:FMD 开发 文集

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接