📄 mgcstream.cpp
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement. The various license agreements may be found at
// the Magic Software web site. This file is subject to the license
//
// RESTRICTED USE SOURCE CODE
// http://www.magic-software.com/License/restricted.pdf
#include "MgcObject.h"
#include "MgcStream.h"
const char MgcStream::ms_acVersion[MgcStream::VERSION_STRING_LENGTH] =
"Magic3D Version 1.00";
const unsigned int MgcStream::ms_uiTopLevelGrowBy = 8;
//----------------------------------------------------------------------------
MgcStream::MgcStream ()
:
m_aspkTopLevel(ms_uiTopLevelGrowBy),
m_kMap(32768)
{
m_pkFile = 0;
}
//----------------------------------------------------------------------------
MgcStream::~MgcStream ()
{
RemoveAll();
}
//----------------------------------------------------------------------------
bool MgcStream::Insert (MgcObject* pkObject)
{
if ( pkObject )
{
unsigned int uiQuantity = m_aspkTopLevel.GetQuantity();
unsigned int uiEmpty = uiQuantity;
for (unsigned int uiI = 0; uiI < uiQuantity; uiI++)
{
// find first available slot
if ( uiEmpty == uiQuantity && !m_aspkTopLevel[uiI] )
uiEmpty = uiI;
// check if object is already inserted
if ( pkObject == m_aspkTopLevel[uiI] )
return false;
}
if ( uiEmpty == uiQuantity )
{
// all slots filled, need to resize the array
uiQuantity += ms_uiTopLevelGrowBy;
m_aspkTopLevel.SetQuantity(uiQuantity,true);
}
m_aspkTopLevel[uiEmpty] = pkObject;
return true;
}
return false;
}
//----------------------------------------------------------------------------
void MgcStream::RemoveAll ()
{
unsigned int uiQuantity = m_aspkTopLevel.GetQuantity();
for (unsigned int uiI = 0; uiI < uiQuantity; uiI++)
m_aspkTopLevel[uiI] = 0;
}
//----------------------------------------------------------------------------
unsigned int MgcStream::GetObjectCount ()
{
unsigned int uiQuantity = m_aspkTopLevel.GetQuantity();
for (unsigned int uiI = 0; uiI < uiQuantity; uiI++)
{
if ( m_aspkTopLevel[uiI] == 0 )
return uiI;
}
return uiQuantity;
}
//----------------------------------------------------------------------------
MgcObject* MgcStream::GetObjectAt (unsigned int uiIndex) const
{
if ( uiIndex < m_aspkTopLevel.GetQuantity() )
return m_aspkTopLevel[uiIndex];
else
return 0;
}
//----------------------------------------------------------------------------
bool MgcStream::IsTopLevel (MgcObject* pkObject)
{
unsigned int uiQuantity = m_aspkTopLevel.GetQuantity();
for (unsigned int uiI = 0; uiI < uiQuantity; uiI++)
{
if ( pkObject == m_aspkTopLevel[uiI] )
return true;
}
return false;
}
//----------------------------------------------------------------------------
bool MgcStream::Load (const char* acFilename)
{
m_pkFile = fopen(acFilename,"rb");
if ( !m_pkFile )
return false;
// get the file version
char* acString = new char[VERSION_STRING_LENGTH];
fread(acString,sizeof(char),VERSION_STRING_LENGTH,m_pkFile);
if ( strcmp(acString,ms_acVersion) != 0 )
{
delete[] acString;
fclose(m_pkFile);
return false;
}
delete[] acString;
// clear out all previous top level objects
RemoveAll();
// load list of unique objects
MgcObject* pkObject;
while ( true )
{
// read "Top Level" or RTTI name
ReadString(acString);
if ( feof(m_pkFile) )
break;
bool bTopLevel = ( strcmp(acString,"Top Level") == 0 );
if ( bTopLevel )
{
// read RTTI name
delete[] acString;
ReadString(acString);
}
// get the factory function for the type of object about to be read
MgcString kString(acString);
MgcFactoryFunction oFactory;
bool bFound = MgcObject::ms_pkFactory->GetAt(kString,oFactory);
assert( bFound );
delete[] acString;
if ( !bFound )
{
// cannot find factory function
fclose(m_pkFile);
return false;
}
// load the object
pkObject = oFactory(*this);
// keep track of all top level objects for application use
if ( bTopLevel )
Insert(pkObject);
}
// link the objects
MgcObject* pkLinkID;
MgcStream::Link* pkLink;
bool bFound = m_kMap.GetFirst(pkLinkID,(void*&)pkLink);
while ( bFound )
{
pkObject = pkLink->GetObject();
pkObject->Link(*this,pkLink);
bFound = m_kMap.GetNext(pkLinkID,(void*&)pkLink);
}
// delete the stream link records
bFound = m_kMap.GetFirst(pkLinkID,(void*&)pkLink);
while ( bFound )
{
delete pkLink;
bFound = m_kMap.GetNext(pkLinkID,(void*&)pkLink);
}
m_kMap.RemoveAll();
return fclose(m_pkFile) == 0;
}
//----------------------------------------------------------------------------
bool MgcStream::Save (const char* acFilename)
{
m_pkFile = fopen(acFilename,"wb");
if ( !m_pkFile )
return false;
// file version
fwrite(ms_acVersion,sizeof(char),VERSION_STRING_LENGTH,m_pkFile);
// build list of unique objects
for (unsigned int uiI = 0; uiI < m_aspkTopLevel.GetQuantity(); uiI++)
{
if ( m_aspkTopLevel[uiI] )
m_aspkTopLevel[uiI]->Register(*this);
}
// save list of unique objects
MgcObject* pkObject;
MgcObject* pkDummy;
bool bFound = m_kMap.GetFirst(pkObject,(void*&)pkDummy);
while ( bFound )
{
if ( IsTopLevel(pkObject) )
WriteString("Top Level");
pkObject->Save(*this);
bFound = m_kMap.GetNext(pkObject,(void*&)pkDummy);
}
return fclose(m_pkFile) == 0;
}
//----------------------------------------------------------------------------
bool MgcStream::Load (char* acBuffer, int iSize)
{
// TO DO. implement
return false;
}
//----------------------------------------------------------------------------
bool MgcStream::Save (char*& racBuffer, int& riSize)
{
// TO DO. implement
return false;
}
//----------------------------------------------------------------------------
bool MgcStream::InsertInMap (MgcObject* pkKey, void* pvValue)
{
return m_kMap.SetAt(pkKey,pvValue);
}
//----------------------------------------------------------------------------
MgcObject* MgcStream::GetFromMap (MgcObject* pkLinkID)
{
Link* pkLink;
if ( m_kMap.GetAt(pkLinkID,(void*&)pkLink) )
return pkLink->GetObject();
else
return 0;
}
//----------------------------------------------------------------------------
void MgcStream::ReadString (char*& racString)
{
int iLength = 0;
fread(&iLength,sizeof(int),1,m_pkFile);
if ( iLength > 0 )
{
racString = new char[iLength+1];
fread(racString,sizeof(char),iLength,m_pkFile);
racString[iLength] = 0;
}
else
{
racString = 0;
}
}
//----------------------------------------------------------------------------
void MgcStream::WriteString (const char* acString)
{
int iLength;
if ( acString )
{
iLength = strlen(acString);
fwrite(&iLength,sizeof(int),1,m_pkFile);
fwrite(acString,sizeof(char),iLength,m_pkFile);
}
else
{
iLength = 0;
fwrite(&iLength,sizeof(int),1,m_pkFile);
}
}
//----------------------------------------------------------------------------
MgcStream::Link::Link (MgcObject* pkObject)
:
m_akLinkID(LINK_GROW_BY)
{
m_pkObject = pkObject;
m_uiQuantity = 0;
m_uiCurrent = 0;
}
//----------------------------------------------------------------------------
void MgcStream::Link::Add (MgcObject* pkLinkID)
{
unsigned int uiArrayQuantity = m_akLinkID.GetQuantity();
if ( m_uiQuantity >= uiArrayQuantity )
{
uiArrayQuantity += LINK_GROW_BY;
m_akLinkID.SetQuantity(uiArrayQuantity,true);
}
m_akLinkID[m_uiQuantity++] = pkLinkID;
}
//----------------------------------------------------------------------------
MgcObject* MgcStream::Link::GetObject ()
{
return m_pkObject;
}
//----------------------------------------------------------------------------
unsigned int MgcStream::Link::GetQuantity () const
{
return m_uiQuantity;
}
//----------------------------------------------------------------------------
MgcObject* MgcStream::Link::GetLinkID ()
{
assert( m_uiCurrent < m_uiQuantity );
return m_akLinkID[m_uiCurrent++];
}
//----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -