Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
566 lines
14 KiB
C++
566 lines
14 KiB
C++
//===========================================================================//
|
|
// File: schain.cc //
|
|
// Contents: Implementation details of safe chains //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 09/29/94 ECH Initial coding. //
|
|
// 11/01/94 JMA Made compatible with SGI CC, merged with iterator //
|
|
// 11/03/94 ECH Made compatible with BC4.0 //
|
|
// 11/05/94 JMA Made compatible with GNU C++ //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
|
|
// PROPRIETARY AND CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include "StuffHeaders.hpp"
|
|
|
|
//
|
|
//###########################################################################
|
|
// SCHAINLINK
|
|
//###########################################################################
|
|
//
|
|
|
|
MemoryBlock*
|
|
SafeChainLink::s_AllocatedMemory = NULL;
|
|
|
|
//
|
|
//###########################################################################
|
|
//###########################################################################
|
|
//
|
|
void
|
|
SafeChainLink::InitializeClass(size_t block_count)
|
|
{
|
|
Verify(!s_AllocatedMemory);
|
|
s_AllocatedMemory =
|
|
new MemoryBlock(
|
|
sizeof(SafeChainLink),
|
|
block_count,
|
|
block_count>>2,
|
|
"Stuff::SafeChainLink",
|
|
g_ConnectionEngineHeap
|
|
);
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
//###########################################################################
|
|
//
|
|
void
|
|
SafeChainLink::TerminateClass()
|
|
{
|
|
delete s_AllocatedMemory;
|
|
s_AllocatedMemory = NULL;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// SafeChainLink
|
|
//###########################################################################
|
|
//
|
|
SafeChainLink::SafeChainLink(
|
|
SafeChain *chain,
|
|
Plug *m_plug,
|
|
SafeChainLink *nextSafeChainLink,
|
|
SafeChainLink *prevSafeChainLink
|
|
):
|
|
Link(chain, m_plug)
|
|
{
|
|
//
|
|
//-------------------------
|
|
// Link into existing chain
|
|
//-------------------------
|
|
//
|
|
if ((m_nextSafeChainLink = nextSafeChainLink) != NULL)
|
|
{
|
|
Check_Object(m_nextSafeChainLink);
|
|
m_nextSafeChainLink->m_prevSafeChainLink = this;
|
|
}
|
|
if ((m_prevSafeChainLink = prevSafeChainLink) != NULL)
|
|
{
|
|
Check_Object(m_prevSafeChainLink);
|
|
m_prevSafeChainLink->m_nextSafeChainLink = this;
|
|
}
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// ~SafeChainLink
|
|
//###########################################################################
|
|
//
|
|
SafeChainLink::~SafeChainLink()
|
|
{
|
|
Check_Object(this);
|
|
SafeChain *chain = Cast_Object(SafeChain*, m_socket);
|
|
|
|
//
|
|
//---------------------------------------------
|
|
// Notify iterators that the link is going away
|
|
//---------------------------------------------
|
|
//
|
|
chain->SendIteratorMemo(PlugRemoved, this);
|
|
|
|
//
|
|
//---------------------------
|
|
// Remove from existing links
|
|
//---------------------------
|
|
//
|
|
if (m_prevSafeChainLink != NULL)
|
|
{
|
|
Check_Object(m_prevSafeChainLink);
|
|
m_prevSafeChainLink->m_nextSafeChainLink = m_nextSafeChainLink;
|
|
}
|
|
else
|
|
{
|
|
Check_Object(chain);
|
|
chain->m_head = m_nextSafeChainLink;
|
|
}
|
|
if (m_nextSafeChainLink != NULL)
|
|
{
|
|
Check_Object(m_nextSafeChainLink);
|
|
m_nextSafeChainLink->m_prevSafeChainLink = m_prevSafeChainLink;
|
|
}
|
|
else
|
|
{
|
|
Check_Object(chain);
|
|
chain->m_tail = m_prevSafeChainLink;
|
|
}
|
|
m_prevSafeChainLink = m_nextSafeChainLink = NULL;
|
|
|
|
//
|
|
//------------------------------------------
|
|
// Remove this link from any m_plug references
|
|
//------------------------------------------
|
|
//
|
|
ReleaseFromPlug();
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// TestInstance
|
|
//###########################################################################
|
|
//
|
|
void
|
|
SafeChainLink::TestInstance()
|
|
{
|
|
Link::TestInstance();
|
|
|
|
if (m_prevSafeChainLink != NULL)
|
|
{
|
|
Check_Signature(m_prevSafeChainLink);
|
|
}
|
|
if (m_nextSafeChainLink != NULL)
|
|
{
|
|
Check_Signature(m_nextSafeChainLink);
|
|
}
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// SCHAIN
|
|
//###########################################################################
|
|
//
|
|
|
|
//
|
|
//###########################################################################
|
|
// SafeChain
|
|
//###########################################################################
|
|
//
|
|
SafeChain::SafeChain(void *node)
|
|
{
|
|
m_head = NULL;
|
|
m_tail = NULL;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// ~SafeChain
|
|
//###########################################################################
|
|
//
|
|
SafeChain::~SafeChain()
|
|
{
|
|
Check_Object(this);
|
|
SafeChainLink *link = m_head;
|
|
while (link)
|
|
{
|
|
Check_Object(link);
|
|
SafeChainLink *next = link->m_nextSafeChainLink;
|
|
Check_Object(link);
|
|
delete link;
|
|
link = next;
|
|
}
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// TestInstance
|
|
//###########################################################################
|
|
//
|
|
void
|
|
SafeChain::TestInstance()
|
|
{
|
|
SafeSocket::TestInstance();
|
|
|
|
if (m_head != NULL)
|
|
{
|
|
Check_Object(m_head);
|
|
}
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// AddImplementation
|
|
//###########################################################################
|
|
//
|
|
void
|
|
SafeChain::AddPlug(Plug *m_plug)
|
|
{
|
|
Check_Object(this);
|
|
m_tail = new SafeChainLink(this, m_plug, NULL, m_tail);
|
|
Check_Object(m_tail);
|
|
if (m_head == NULL)
|
|
{
|
|
m_head = m_tail;
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// DeletePlugs
|
|
//#############################################################################
|
|
//
|
|
void
|
|
SafeChain::DeletePlugs()
|
|
{
|
|
SafeChainLink *link = m_head;
|
|
while (link)
|
|
{
|
|
Check_Object(link);
|
|
SafeChainLink *next = link->m_nextSafeChainLink;
|
|
Check_Object(link);
|
|
Check_Object(link->GetPlug());
|
|
delete link->GetPlug();
|
|
link = next;
|
|
}
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// GetSize
|
|
//###########################################################################
|
|
//
|
|
unsigned
|
|
SafeChain::GetSize()
|
|
{
|
|
Check_Object(this);
|
|
|
|
unsigned count = 0;
|
|
for (SafeChainLink *link=m_head; link != NULL; link = link->m_nextSafeChainLink)
|
|
{
|
|
Check_Object(link);
|
|
count++;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// GetNthImplementation
|
|
//###########################################################################
|
|
//
|
|
void*
|
|
SafeChain::GetNthItem(unsigned index)
|
|
{
|
|
Check_Object(this);
|
|
unsigned count = 0;
|
|
for (SafeChainLink *link=m_head; link != NULL; link = link->m_nextSafeChainLink)
|
|
{
|
|
Check_Object(link);
|
|
if (count == index)
|
|
return link->GetPlug();
|
|
count++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// IsEmpty
|
|
//#############################################################################
|
|
//
|
|
bool
|
|
SafeChain::IsEmpty()
|
|
{
|
|
Check_Object(this);
|
|
return (m_head == NULL);
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// InsertPlug
|
|
//###########################################################################
|
|
//
|
|
SafeChainLink*
|
|
SafeChain::InsertSafeChainLink(
|
|
Plug *m_plug,
|
|
SafeChainLink *link
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(link);
|
|
Check_Object(m_plug);
|
|
|
|
SafeChainLink *new_link =
|
|
new SafeChainLink(
|
|
this,
|
|
m_plug,
|
|
link,
|
|
link->m_prevSafeChainLink
|
|
);
|
|
Check_Object(new_link);
|
|
|
|
Check_Object(m_head);
|
|
if (m_head == link)
|
|
{
|
|
m_head = new_link;
|
|
}
|
|
return new_link;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// SafeChainIterator
|
|
//###########################################################################
|
|
//
|
|
SafeChainIterator::SafeChainIterator(
|
|
SafeChain *chain,
|
|
bool move_next_on_remove
|
|
):
|
|
SafeIterator(chain)
|
|
{
|
|
Check_Object(chain);
|
|
m_currentLink = chain->m_head;
|
|
m_moveNextOnRemove = move_next_on_remove;
|
|
}
|
|
|
|
SafeChainIterator::SafeChainIterator(const SafeChainIterator &iterator):
|
|
SafeIterator(Cast_Object(SafeChain*, iterator.m_socket))
|
|
{
|
|
Check_Object(&iterator);
|
|
m_currentLink = iterator.m_currentLink;
|
|
m_moveNextOnRemove = iterator.m_moveNextOnRemove;
|
|
}
|
|
|
|
SafeChainIterator::~SafeChainIterator()
|
|
{
|
|
Check_Object(this);
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// TestInstance
|
|
//###########################################################################
|
|
//
|
|
void
|
|
SafeChainIterator::TestInstance() const
|
|
{
|
|
SafeIterator::TestInstance();
|
|
|
|
if (m_currentLink != NULL)
|
|
{
|
|
Check_Object(m_currentLink);
|
|
}
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// First
|
|
//###########################################################################
|
|
//
|
|
Iterator&
|
|
SafeChainIterator::First()
|
|
{
|
|
Check_Object(this);
|
|
m_currentLink = Cast_Object(SafeChain*, m_socket)->m_head;
|
|
return *this;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// Last
|
|
//###########################################################################
|
|
//
|
|
Iterator&
|
|
SafeChainIterator::Last()
|
|
{
|
|
Check_Object(this);
|
|
m_currentLink = Cast_Object(SafeChain*, m_socket)->m_tail;
|
|
return *this;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// Next
|
|
//###########################################################################
|
|
//
|
|
Iterator&
|
|
SafeChainIterator::Next()
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(m_currentLink);
|
|
m_currentLink = m_currentLink->m_nextSafeChainLink;
|
|
return *this;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// Previous
|
|
//###########################################################################
|
|
//
|
|
Iterator&
|
|
SafeChainIterator::Previous()
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(m_currentLink);
|
|
m_currentLink = m_currentLink->m_prevSafeChainLink;
|
|
return *this;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// ReadAndNextItem
|
|
//###########################################################################
|
|
//
|
|
void*
|
|
SafeChainIterator::ReadAndNextItem()
|
|
{
|
|
Check_Object(this);
|
|
if (m_currentLink != NULL)
|
|
{
|
|
Plug *m_plug;
|
|
|
|
Check_Object(m_currentLink);
|
|
m_plug = m_currentLink->GetPlug();
|
|
m_currentLink = m_currentLink->m_nextSafeChainLink;
|
|
return m_plug;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// ReadAndPreviousItem
|
|
//###########################################################################
|
|
//
|
|
void*
|
|
SafeChainIterator::ReadAndPreviousItem()
|
|
{
|
|
Check_Object(this);
|
|
if (m_currentLink != NULL)
|
|
{
|
|
Plug *m_plug;
|
|
|
|
Check_Object(m_currentLink);
|
|
m_plug = m_currentLink->m_plug;
|
|
m_currentLink = m_currentLink->m_prevSafeChainLink;
|
|
return m_plug;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// GetCurrentItem
|
|
//###########################################################################
|
|
//
|
|
void*
|
|
SafeChainIterator::GetCurrentItem()
|
|
{
|
|
Check_Object(this);
|
|
if (m_currentLink != NULL)
|
|
{
|
|
Check_Object(m_currentLink);
|
|
return m_currentLink->GetPlug();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// GetNthImplementation
|
|
//###########################################################################
|
|
//
|
|
void*
|
|
SafeChainIterator::GetNthItem(unsigned index)
|
|
{
|
|
Check_Object(this);
|
|
unsigned count = 0;
|
|
for (
|
|
SafeChainLink *link=Cast_Object(SafeChain*, m_socket)->m_head;
|
|
link != NULL;
|
|
link = link->m_nextSafeChainLink
|
|
)
|
|
{
|
|
Check_Object(link);
|
|
if (count == index)
|
|
{
|
|
m_currentLink = link;
|
|
return link->GetPlug();
|
|
}
|
|
count++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// Remove
|
|
//###########################################################################
|
|
//
|
|
void
|
|
SafeChainIterator::Remove()
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(m_currentLink);
|
|
Check_Object(m_currentLink);
|
|
delete m_currentLink;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// InsertImplementation
|
|
//#############################################################################
|
|
//
|
|
void
|
|
SafeChainIterator::InsertPlug(Plug *m_plug)
|
|
{
|
|
Check_Object(this);
|
|
m_currentLink =
|
|
Cast_Object(SafeChain*, m_socket)->InsertSafeChainLink(m_plug, m_currentLink);
|
|
Check_Object(m_currentLink);
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
// ReceiveMemo
|
|
//###########################################################################
|
|
//
|
|
void
|
|
SafeChainIterator::ReceiveMemo(
|
|
IteratorMemo memo,
|
|
void *content
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
if (memo == PlugRemoved)
|
|
{
|
|
if (content == m_currentLink)
|
|
{
|
|
if (m_moveNextOnRemove)
|
|
Next();
|
|
else
|
|
Previous();
|
|
}
|
|
}
|
|
}
|