home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #1
/
monster.zip
/
monster
/
PROG_C
/
CL187A.ZIP
/
PITEM.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-15
|
6KB
|
296 lines
/*
pitem.cpp -- Container Lite v 1.87a:
polymorphic items.
(C) Copyright 1994 John Webster Small
All rights reserved
*/
#include "pitem.h"
ostream& Streamable::insert(ostream& os)
{
if (os << ID() << endm)
(void) put(os);
return os;
}
StreamablE Streamable::extract(istream& is)
{
unsigned id;
if (!(is >> id >> nextm))
return StreamablE0;
StreamExtractoR extracT = ID2StreamExtracT(id);
return (extracT? (*extracT)(is) : StreamablE0);
}
#ifdef MUTUAL_DEBUG
void Mutual::mut_error(const char *msg, unsigned id,
unsigned refCount, unsigned streamCount,
long streamPos)
{
cerr << "mut error: " << msg
<< " - id: " << id << endl
<< " - refCount: " << refCount
<< " - streamCount: " << streamCount
<< " - streamPos: " << streamPos
<< endl;
}
#endif
ostream& Mutual::insert(ostream& os)
{
if (refCount <= streamCount)
mut_error("more stores attempted "
"than links",ID(),refCount,
streamCount,streamPos);
else {
streamCount++;
if (streamPos) { // already stored!
if (!(os << 0U << endm
<< streamPos << endm))
mut_error("unable to store "
"multiple reference ",
ID(),refCount,
streamCount,streamPos);
}
else { // Never store object at streamPos 0
if ((streamPos = os.tellp()) == 0L)
if (!(os << 0U << endm))
mut_error("unable to skip "
"streamPos 0",ID(),
refCount,streamCount,
streamPos);
else
streamPos = os.tellp();
if (!(os << ID() << endm)) {
streamPos = 0L;
mut_error("unable to "
"insert id",ID(),
refCount,streamCount,
streamPos);
}
else {
if (!(os << refCount << endm)){
streamPos = 0L;
mut_error("unable to store"
" refCount",ID(),
refCount,streamCount,
streamPos);
}
else if (!put(os))
streamPos = 0L;
}
}
}
return os << flush;
}
MutuaL Mutual::extract(istream& is)
{
unsigned id = 0U;
unsigned refCount = 0U;
long streamPos = 0L;
MutuaL thiS = MutuaL0;
if ((streamPos = is.tellg()) == 0L)
if (!(is >> id >> nextm)) {
mut_error("unable to skip "
"streamPos 0",id,
refCount,0,streamPos);
return MutuaL0;
}
else
streamPos = is.tellg();
if (!(is >> id >> nextm)) {
mut_error("unable to read id",id,
refCount,0,streamPos);
return MutuaL0;
}
if (id == 0U) {
// link to previously loaded Instance
if (!(is >> streamPos >> nextm)) {
mut_error("unable to read "
"streamPos",id,
refCount,0,streamPos);
return MutuaL0;
}
if ((thiS = MutualLink(streamPos))
== MutuaL0)
mut_error("unable to "
"establish link to "
"previously loaded "
"instance",id,refCount,
0,streamPos);
}
else { // load instance
if (!(is >> refCount >> nextm)) {
mut_error("unable to read "
"refCount",id,0,
0,streamPos);
return MutuaL0;
}
MutualStreamExtractoR extracT
= ID2MutualStreamExtracT(id);
thiS = (extracT? (*extracT)(is)
: MutuaL0);
if (!thiS)
mut_error("unable to extract "
"instance from stream",
id,refCount,0,streamPos);
else if (refCount > 1) {
// 1st of many
// - save in holding pen
MutualHold(thiS,refCount,
streamPos);
}
}
return thiS;
}
unsigned Mutual::restream()
{
unsigned underFlow = (streamPos?
refCount - streamCount : 0U);
streamCount = 0U;
streamPos = 0L;
#ifdef MUTUAL_DEBUG
if (underFlow)
mut_error("streamed less "
"than referenced",
ID(),refCount,
streamCount,streamPos);
#endif
return underFlow;
}
void Mutual::unlink(const void *P)
{
if (refCount) {
--refCount;
Streamable::unlink(P);
}
else
mut_error("excessive unlinking",
ID(),refCount,streamCount,
streamPos);
}
int Mutual::link(const void *P)
{
if (refCount >= UINT_MAX) {
mut_error("excessive linking",
ID(),refCount,streamCount,
streamPos);
return 0;
}
refCount++;
Streamable::link(P);
return 1;
}
ClassRegistry clasSv;
MutualHoldingPen instancEv;
struct MutualInstancERecord {
MutuaL instancE;
unsigned refCount, streamCount;
long streamPos;
MutualInstancERecord(MutuaL instancE,
unsigned refCount, long streamPos)
{
this->instancE = instancE;
this->refCount = refCount;
streamCount = 1;
this->streamPos = streamPos;
}
~MutualInstancERecord() {}
};
typedef struct MutualInstancERecord * MIRecorD;
#define MIRecorD0 ((MIRecorD)0)
#ifdef MUTUAL_DEBUG
void MutualHoldingPen::mhp_error(const char *msg,
unsigned id, unsigned refCount,
long streamPos)
{
cerr << "mut holdpen error: " << msg
<< " - id: " << id << endl
<< " - refCount: " << refCount
<< " - streamPos: " << streamPos
<< endl;
}
#endif
MutuaL MutualHoldingPen::link(long streamPos)
{
MutuaL instancE = MutuaL0;
MIRecorD R;
for (unsigned i = 0U; i < Nodes(); i++)
if ((R = (MIRecorD)atGet(i))
->streamPos == streamPos) {
// found saved instance!
instancE = R->instancE;
if (R->refCount
<= ++R->streamCount)
// discard when done!
atDel(i);
break;
}
#ifdef MUTUAL_DEBUG
if (!instancE)
mhp_error("unable to establish link "
"to previously loaded "
"Mutual instance",
0,0,streamPos);
#endif
return instancE;
}
void MutualHoldingPen::hold(MutuaL instancE,
unsigned refCount, long streamPos)
{
MIRecorD R;
CL_try_new
R = new MutualInstancERecord
(instancE,refCount,streamPos);
CL_catch_xalloc(R)
if (!insQ((void *)R)) {
mhp_error("unable to hold Mutual "
"instance for multiple "
"referencing",instancE->ID(),
instancE->RefCount(),
instancE->StreamPos());
if (R)
delete R;
}
}
unsigned MutualHoldingPen::restream()
{
unsigned underFlow = Nodes();
for (unsigned i = 0U; i < underFlow; i++) {
mhp_error("holding pen under-linked",
((MIRecorD)atGet(i))
->instancE->ID(),
((MIRecorD)atGet(i))
->refCount,
((MIRecorD)atGet(i))
->streamPos);
}
allDel();
return underFlow;
}