home *** CD-ROM | disk | FTP | other *** search
- /*
-
- binder.cpp
- 8-27-91
- Loose Data Binder
-
- Copyright 1991
- John W. Small
- All rights reserved
-
- PSW / Power SoftWare
- P.O. Box 10072
- McLean, Virginia 22102 8072 USA
-
- John Small
- Voice: (703) 759-3838
- CIS: 73757,2233
-
- */
-
-
- #include <string.h>
- #include <binder.hpp>
-
- int Streamable::debug = 0;
- int Streamable::refDebug = 0;
-
- void Streamable::lserror(const char *msg, unsigned id)
- {
- if (debug)
- cerr << "Class id: " << setw(6) << id
- << " stream error - "
- << msg << endl;
- }
-
- void Streamable::serror(const char *msg)
- {
- if (debug)
- cerr << endl
- <<"Class id: " << setw(6) << id
- << " &instance: "
- << (void *) this << endl
- << "Stream error - "
- << msg << endl << endl;
- }
-
- void Streamable::swarn(const char *msg)
- {
- if (debug)
- cerr << endl
- << "Class id: " << setw(6) << id
- << " &instance: "
- << (void *) this << endl
- << "Stream warning - "
- << msg << endl;
- }
-
-
- #pragma argsused
- StreamablE Streamable::load(istream& is,
- StreamablE InstancE)
- { return InstancE; }
-
- char Streamable::memberTermChar = '\n';
-
- #pragma argsused
- Streamable::Streamable(StreamableClassRegistry& dummy,
- unsigned id)
- {
- this->id = id;
- streamed = refCount = 0;
- spos = 0L;
- }
-
- void Streamable::registerClass(unsigned id,
- StreamablE (*loader)(istream& is,
- StreamablE InstancE))
- {
- SCRegistry.registerClass(id,loader);
- }
-
- void Streamable::restream()
- { streamed = 0; spos = 0L; }
-
- unsigned Streamable::unlink()
- {
- if (refDebug)
- cerr << endl
- << "Class id: " << setw(6) << id
- << " &instance: "
- << (void *) this << endl
- << "Unlinking, starting refCount: "
- << refCount << endl;
- return (refCount? refCount-- : refCount);
- }
-
- StreamablE Streamable::link()
- {
- refCount++;
- if (refDebug)
- cerr << endl
- << "Class id: " << setw(6) << id
- << " &instance: "
- << (void *) this << endl
- << "Adding link, new refCount: "
- << refCount << endl;
- return this;
- }
-
-
- ostream& endm(ostream& os)
- {
- return os << Streamable::memberTermChar
- << flush;
- }
-
- istream& nextm(istream& is)
- {
- is.get();
- return is;
- }
-
-
- void Binder::construct(unsigned flags, unsigned maxNodes,
- unsigned limit, unsigned delta)
- {
- curNode = first = nodes = 0;
- comparE = BDRcomparE0;
-
- /*
- The following relationships are maintained
- during operation of a binder:
-
- 1 <= delta <= lowLimit <= limit <= maxNodes
- <= BDR_MAXNODES
- lowThreshold = lowLimit - delta;
- */
-
- if (maxNodes > BDR_MAXNODES)
- maxNodes = BDR_MAXNODES;
- if (limit > maxNodes)
- limit = maxNodes;
- if (delta > limit)
- delta = limit;
- if (!delta) {
- delta = 1;
- if (limit < delta)
- limit = delta;
- if (maxNodes < limit)
- maxNodes = limit;
- }
- if ((linkS = new voiD[limit]) == voiDV0)
- this->limit = lowLimit = lowThreshold
- = this->delta = this->maxNodes
- = this->flags = 0;
- else {
- this->limit = limit;
- this->delta = delta;
- this->maxNodes = maxNodes;
- lowLimit = limit;
- lowThreshold = lowLimit - delta;
- flags |= SORTED;
- this->flags = flags;
- }
- }
-
- int Binder::Dfree(voiD D)
- {
- if (D) {
- if (flags & STREAMABLE_NODES) {
- if (!((StreamablE)D)->unlink())
- delete (StreamablE) D;
- }
- else
- delete D;
- return 1;
- }
- else
- return 0;
- }
-
- void Binder::Dstore(ostream& os, const voiD D)
- {
- if (D && (flags & STREAMABLE_NODES))
- os << (StreamablE) D;
- else
- swarn("don't know how to store "
- "binder node ");
- }
-
- voiD Binder::Dload(istream& is)
- {
- StreamablE InstancE = StreamablE0;
-
- if (flags & STREAMABLE_NODES)
- is >> InstancE;
- else
- swarn("don't know how to load "
- "binder node ");
- return (voiD) InstancE;
- }
-
-
- voiD Binder::DinsQ(voiD D)
- { return insQ(D); }
-
-
- ostream& Binder::store(ostream& os)
- {
- unsigned i;
-
- os << maxNodes << endm << limit << endm
- << delta << endm << nodes << endm
- << curNode << endm << flags << endm
- << FncPtrToID((GenericFnC)comparE) << endm;
- if (!os)
- serror("unable to store Binder ");
- else for (i = 0; i < nodes; i++)
- Dstore(os,atGet(i));
- return os;
- }
-
- StreamablE Binder::load(istream& is, StreamablE InstancE)
- {
- unsigned i, maxNodes, limit, delta, nodes, curNode;
- unsigned flags;
- unsigned comparEID;
-
- is >> maxNodes >> nextm >> limit >> nextm
- >> delta >> nextm >> nodes >> nextm
- >> curNode >> nextm >> flags >> nextm
- >> comparEID >> nextm;
- if (!is) {
- lserror("unable to load binder header data",
- CLASS_ID);
- return StreamablE0;
- }
- if (!InstancE) if ((InstancE = (StreamablE)
- new Binder(UNIQUE_STREAMABLE))
- == StreamablE0) {
- lserror("unable to construct binder for"
- " loading ",CLASS_ID);
- return StreamablE0;
- }
- ((BindeR)InstancE)->construct(flags,maxNodes,
- limit,delta);
- for (i = 0; i < nodes; i++)
- ((BindeR)InstancE)->DinsQ(((BindeR)InstancE)
- ->Dload(is));
- ((BindeR)InstancE)->setCurNode(curNode);
- ((BindeR)InstancE)->flags = flags;
- ((BindeR)InstancE)->setComparE((BDRcomparE)
- IDtoFncPtr(comparEID));
- return InstancE;
- }
-
- void Binder::restream()
- {
- Streamable::restream();
- if (flags & STREAMABLE_NODES)
- for (unsigned i = 0; i < nodes; i++)
- ((StreamablE)atGet(i))->restream();
- }
-
- Binder::Binder(voiDV argv, int argc, unsigned flags)
- : Streamable(UNIQUE_STREAMABLE,CLASS_ID)
- {
- construct(flags,BDR_MAXNODES,argc,BDR_DELTA);
- if (argv) if (argc > 0)
- while (argc--)
- push(argv[argc]);
- else
- for (argc = 0; insQ(argv[argc]); argc++);
- }
-
- voiDV Binder::vector()
- {
- voiDV V = voiDV0;
-
- if (nodes) if ((V = new voiD[nodes+1]) != voiDV0) {
- for (unsigned i = 0; i < nodes; i++)
- V[i] = atGet(i);
- V[i] = voiD0;
- }
- return V;
- }
-
- Binder::~Binder()
- {
- if (flags & (ALL_FREE_DESTRUCT | STREAMABLE_NODES))
- allFree();
- else
- allDel();
- delete linkS;
- }
-
- unsigned Binder::setLimit(unsigned newLimit)
- {
- voiDV newLinkS;
- unsigned i;
-
- if (newLimit < nodes)
- newLimit = nodes;
- else if (newLimit > maxNodes)
- newLimit = maxNodes;
- if (newLimit < delta)
- newLimit = delta;
- if (!linkS || !newLimit || newLimit == limit)
- return 0;
- if ((newLinkS = new voiD[newLimit]) == voiDV0)
- return 0;
- if ((i = limit - first) > nodes)
- i = nodes;
- memcpy(newLinkS,&linkS[first],sizeof(linkS[0])*i);
- /* copy wrap around */
- if (i < nodes)
- memcpy(&newLinkS[i],linkS,
- sizeof(linkS[0])*(nodes-i));
- if (newLimit > limit)
- if (newLimit - delta > limit)
- lowLimit = newLimit - delta;
- else
- lowLimit = limit;
- else
- if (newLimit - delta > delta)
- lowLimit = newLimit - delta;
- else
- lowLimit = delta;
- lowThreshold = lowLimit - delta;
- delete linkS;
- linkS = newLinkS;
- limit = newLimit;
- first = 0;
- return limit;
- }
-
- unsigned Binder::setDelta(unsigned newDelta)
- {
- return ((newDelta && newDelta <= lowLimit)?
- delta = newDelta : 0);
- }
-
- unsigned Binder::setMaxNodes(unsigned newMaxNodes)
- {
- return ((newMaxNodes >= limit)?
- (maxNodes = (newMaxNodes
- > BDR_MAXNODES)? BDR_MAXNODES
- : newMaxNodes) : 0);
- }
-
- voiD Binder::atIns(unsigned n, const voiD D)
- {
- voiDV newLinkS;
- unsigned newLimit, i;
-
- if (!linkS || !D)
- return voiD0;
- if (nodes == limit) {
- if (limit == maxNodes)
- return voiD0;
- newLimit = (maxNodes - delta > limit)?
- limit + delta : maxNodes;
- if ((newLinkS = new voiD[newLimit])
- == voiDV0) return voiD0;
- if ((i = limit - first) > nodes)
- i = nodes;
- memcpy(newLinkS,&linkS[first],
- sizeof(linkS[0])*i);
- /* copy wrap around */
- if (i < nodes)
- memcpy(&newLinkS[i],linkS,
- sizeof(linkS[0])*(nodes-i));
- /*
- Compute next smaller linkS size
- and threshold for shrinking.
- */
- lowLimit = limit;
- lowThreshold = lowLimit - delta;
- /* swap new for old */
- delete linkS;
- linkS = newLinkS;
- limit = newLimit;
- first = 0;
- }
- if (!n) /* push */
- linkS[first? --first
- : (first = limit - 1)] = D;
- else if (n >= nodes) /* insQ */
- linkS[(first+(n=nodes))%limit] = D;
- else { /* insert interior */
- i = (first + n) % limit;
- if (i < first || !first)
- /* move rear rightward */
- memmove(&linkS[i+1],&linkS[i],
- sizeof(linkS[0])
- * (nodes-n));
- else /* move front leftward */
- memmove(&linkS[--first],&linkS[--i],
- sizeof(linkS[0])*(n+1));
- linkS[i] = D;
- }
- nodes++;
- if (n <= curNode)
- curNode++;
- flags &= ~SORTED;
- return D;
- }
-
- voiD Binder::atDel(unsigned n)
- {
- voiDV newLinkS;
- unsigned newLimit, i;
- voiD D;
-
- if (!linkS || n >= nodes)
- return voiD0;
- D = linkS[(first+n)%limit];
- if (!n) { /* pop */
- if (++first >= limit)
- first = 0;
- }
- else if (n != nodes-1) { /* del interior */
- /* move front rightward */
- memmove(&linkS[first+1],&linkS[first],
- sizeof(linkS[0])*n);
- first++;
- }
- if (--nodes == 0)
- flags |= SORTED;
- if (n < curNode)
- curNode--;
- else if (n == curNode)
- curNode = nodes;
- if (nodes < lowThreshold) {
- newLimit = lowLimit;
- if ((newLinkS = new voiD[newLimit])
- == voiDV0) return voiD0;
- if ((i = limit - first) > nodes)
- i = nodes;
- memcpy(newLinkS,&linkS[first],
- sizeof(linkS[0])*i);
- /* copy wrap around */
- if (i < nodes)
- memcpy(&newLinkS[i],linkS,
- sizeof(linkS[0])*(nodes-i));
- /*
- Compute next smaller linkS size
- and threshold for shrinking.
- */
- if (lowLimit - delta > delta)
- lowLimit -= delta;
- else
- lowLimit = delta;
- lowThreshold = lowLimit - delta;
- /* swap new for old */
- delete linkS;
- linkS = newLinkS;
- limit = newLimit;
- first = 0;
- }
- return D;
- }
-
- int Binder::allDel()
- {
- if (!linkS)
- return 0;
- while (atDel(0))
- /* null statement */;
- return 1;
- }
-
- int Binder::allFree()
- {
- if (!linkS)
- return 0;
- while (atFree(0))
- /* null statement */;
- return 1;
- }
-
- voiD Binder::atPut(unsigned n, const voiD D)
- {
- return ((linkS && D && (n < nodes))?
- flags &= ~SORTED,
- linkS[(first+n)%limit] = D
- : voiD0);
- }
-
- voiD Binder::atGet(unsigned n)
- {
- return ((linkS && (n < nodes))?
- linkS[(first+n)%limit] : voiD0);
- }
-
- voiD Binder::at(unsigned n, const voiD D)
- {
- voiD oldD;
-
- if ((oldD = atGet(n)) != voiD0)
- if (D) {
- linkS[(first+n)%limit] = D;
- flags &= ~SORTED;
- }
- return oldD;
- }
-
- unsigned Binder::index(const voiD D)
- {
- unsigned i;
-
- if (linkS && D)
- for (i = 0; i < nodes; i++)
- if (D == linkS[(first+i)%limit])
- return i;
- return BDR_NOTFOUND;
- }
-
- int Binder::forEach(BDRforEachBlocK B, voiD M, voiD A)
- {
- unsigned i;
-
- if (!linkS || !B || !nodes)
- return 0;
- for (i = 0; i < nodes; i++)
- (*B)(linkS[(first+i)%limit],M,A);
- return 1;
- }
-
- unsigned Binder::firstThat(BDRdetectBlocK B, voiD M)
- {
- unsigned i;
-
- if (linkS && B)
- for (i = 0; i < nodes; i++)
- if ((*B)(linkS[(first+i)%limit],M))
- return i;
- return BDR_NOTFOUND;
- }
-
- unsigned Binder::lastThat(BDRdetectBlocK B, voiD M)
- {
- unsigned i;
-
- if (linkS && B && nodes)
- for (i = nodes; i--; /* no reinit */)
- if ((*B)(linkS[(first+i)%limit],M))
- return i;
- return BDR_NOTFOUND;
- }
-
- int Binder::collect(BDRcollectBlocK B, BindeR R,
- voiD M, voiD A)
- {
- unsigned i;
-
- if (!linkS || !B || !R)
- return 0;
- for (i = 0; i < nodes; i++)
- (*B)(linkS[(first+i)%limit],R,M,A);
- return 1;
- }
-
-
- /* FlexList like primitives: */
-
- unsigned Binder::CurNode()
- {
- return ((curNode < nodes)?
- curNode : BDR_NOTFOUND);
- }
-
- int Binder::setCurNode(unsigned n)
- {
- return ((curNode = ((n > nodes)? nodes : n))
- < nodes);
- }
-
- Binder& Binder::operator<<(Binder& (*manipulator)
- (Binder& B))
- {
- return (manipulator? (*manipulator)(*this)
- : *this);
- }
-
- voiD Binder::ins(const voiD D)
- {
- if (atIns(curNode+1,D)) {
- if (++curNode >= nodes)
- curNode = nodes - 1;
- return D;
- }
- return voiD0;
- }
-
- voiD Binder::insSort(const voiD D)
- {
- unsigned low, mid, high;
- voiD ok;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly inserted node.
- */
-
- curNode = nodes;
- if (!linkS || !D || nodes >= maxNodes || !comparE)
- return voiD0;
- if (!(flags & SORTED))
- if (!sort())
- return voiD0;
- low = 0;
- high = nodes;
- while (low < high) {
- mid = low + ((high - low) >> 1);
- if ((*comparE)(D,
- linkS[(first+mid)%limit]) <= 0)
- high = mid;
- else
- low = mid + 1;
- }
- if ((ok = atIns(high,D)) != voiD0)
- curNode = high;
- /* atIns() resets sorted to zero */
- flags |= SORTED;
- return ok;
- }
-
- voiD Binder::del()
- {
- voiD D;
- unsigned n;
-
- if ((D = atDel(n=curNode)) != voiD0)
- if (n--)
- curNode = n;
- return D;
- }
-
- voiD Binder::next()
- {
- if (linkS) {
- if (curNode >= nodes)
- curNode = 0;
- else
- curNode++;
- if (curNode < nodes)
- return linkS[(first+curNode)%limit];
- }
- return voiD0;
- }
-
- voiD Binder::prev()
- {
- if (linkS) {
- if (curNode) {
- if (curNode > nodes)
- curNode = nodes;
- curNode--;
- }
- else
- curNode = nodes;
- if (curNode < nodes)
- return linkS[(first+curNode)%limit];
- }
- return voiD0;
- }
-
- voiD Binder::findFirst(const voiD K)
- {
- unsigned low, mid, high;
- voiD D;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly found node.
- */
-
- curNode = nodes;
- if (!linkS || !K || !comparE || !nodes)
- return voiD0;
- if (flags & SORTED) {
- low = 0;
- high = nodes;
- while (low < high) {
- mid = low + ((high - low) >> 1);
- if ((*comparE)(K,linkS[(first+mid)
- %limit]) <= 0)
- high = mid;
- else
- low = mid + 1;
- }
- if (high < nodes)
- if (!(*comparE)(K,linkS[(first+
- high)%limit]))
- return linkS[(first+
- (curNode = high))%limit];
- }
- else { /* linear search! */
- while ((D = next()) != voiD0)
- if (!(*comparE)(K,D))
- return D;
- }
- return voiD0;
- }
-
- voiD Binder::findNext(const voiD K)
- {
-
- /*
- For sorted binders you must first call findFirst()
- to insure consistent results!
- */
-
- voiD D;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly found node.
- */
-
- if (!linkS || !K || !comparE) {
- curNode = nodes;
- return voiD0;
- }
- while ((D = next()) != voiD0)
- if (!(*comparE)(K,D))
- return D;
- else if (flags & SORTED) {
- curNode = nodes;
- break; /* Look no further! */
- }
- return voiD0;
- }
-
- voiD Binder::findLast(const voiD K)
- {
- unsigned low, mid, high;
- voiD D;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly found node.
- */
-
- curNode = nodes;
- if (!linkS || !K || !comparE || !nodes)
- return voiD0;
- if (flags & SORTED) {
- low = 0;
- high = nodes;
- while (low < high) {
- mid = low + ((high - low) >> 1);
- if ((*comparE)(K,linkS[(first+mid)
- %limit]) < 0)
- high = mid;
- else
- low = mid + 1;
- }
- if (high < nodes)
- if (!(*comparE)(K,linkS[(first+
- high)%limit]))
- return linkS[(first+
- (curNode = high))%limit];
- }
- else { /* linear search! */
- while ((D = prev()) != voiD0)
- if (!(*comparE)(K,D))
- return D;
- }
- return voiD0;
- }
-
- voiD Binder::findPrev(const voiD K)
- {
-
- /*
- For sorted binders you must first call findLast()
- to insure consistent results!
- */
-
- voiD D;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly found node.
- */
-
- if (!linkS || !K || !comparE) {
- curNode = nodes;
- return voiD0;
- }
- while ((D = prev()) != voiD0)
- if (!(*comparE)(K,D))
- return D;
- else if (flags & SORTED) {
- curNode = nodes;
- break; /* Look no further! */
- }
- return voiD0;
- }
-
- int Binder::sort(BDRcomparE comparE)
- {
- unsigned low, mid, high;
- unsigned d;
- voiD D;
-
- /*
- The current node is always reset to undefined
- regardless of the outcome of sort.
- */
-
- curNode = nodes;
- if (flags & SORTED) {
- if (this->comparE == comparE || !comparE)
- return 1;
- }
- else if (!this->comparE && !comparE)
- return 0;
- if (comparE) {
- this->comparE = comparE;
- flags &= ~SORTED;
- }
- if (!nodes)
- return (flags |= SORTED);
- if (!linkS)
- return 0;
- if (first) { /* form contiguous block at front */
- d = (first + nodes) % limit;
- if (d > first)
- memmove(linkS,&linkS[first],
- sizeof(linkS[0])*nodes);
- else if (d < first)
- memmove(&linkS[d],&linkS[first],
- sizeof(linkS[0])
- *(limit-first));
- /* else array is full/contiguous */
- first = 0;
- }
- for (high = d = 1; d < nodes; high = ++d) {
- low = 0;
- D = linkS[d];
- while (low < high) {
- mid = low + ((high - low) >> 1);
- if ((*this->comparE)(D,
- linkS[mid]) <= 0)
- high = mid;
- else
- low = mid + 1;
- }
- if (high < d) {
- memmove(&linkS[high+1],&linkS[high],
- sizeof(linkS[0])*(d-high));
- linkS[high] = D;
- }
- }
- return (flags |= SORTED);
- }
-
-
-
- StreamableClassRegistry SCRegistry;
-
- int StreamableClassRegistry::debug;
-
- void StreamableClassRegistry::error(char *msg, unsigned id)
- {
- if (debug)
- cerr
- << "StreamClassRegistry error - "
- << msg << id << endl;
- }
-
- void StreamableClassRegistry::warn(char *msg, unsigned id)
- {
- if (debug)
- cerr
- << "StreamClassRegistry warning - "
- << msg << id << endl;
- }
-
- void StreamableClassRegistry::registerClass(unsigned id,
- StreamablE (*loader) (istream& is,
- StreamablE InstancE))
- {
- unsigned i;
-
- for (i = 0; i < ClassRecords.Nodes(); i++)
- if (((SCRecorD)ClassRecords[i])->id
- == id)
- break;
- if (i < ClassRecords.Nodes())
- if (((SCRecorD)ClassRecords[i])->load
- == loader) {
- warn("multiple registration of"
- " loader id: ",id);
- return;
- }
- else {
- error("id conflict: ",id);
- return;
- }
- SCRecorD R = new StreamableClassRecord(id,loader);
- if (!R)
- error("class record memory exhausted, id: ",
- id);
- else if (!ClassRecords.insQ(R)) {
- error("class record can't be queued, id: ",
- id);
- delete R;
- }
- }
-
- void StreamableClassRegistry::forgetClasses()
- {
- ClassRecords.allFree();
- InstanceLinks.allDel();
- }
-
- istream& StreamableClassRegistry::get(istream& is,
- StreamablE& InstancE)
- {
- unsigned id, streamed, i;
- long spos;
-
- InstancE = StreamablE0;
- if (!(is >> id >> nextm >> streamed >> nextm >>
- spos >> nextm))
- error("unable to read id, streamed, "
- "spos ",0);
- else if (streamed > 1) {
- // Link to previously loaded Instance
- for (i = 0; i < InstanceLinks.Nodes(); i++)
- if (((SCHRecorD)InstanceLinks[i])
- ->spos == spos) {
- InstancE = ((SCHRecorD)
- InstanceLinks[i])
- ->InstancE;
- InstancE->link();
- break;
- }
- if (!InstancE)
- error("unable to establish link to"
- " previously loaded class",
- id);
- }
- else { // load instance
-
-
- for (i = 0; i < ClassRecords.Nodes(); i++)
- if (((SCRecorD)ClassRecords[i])->id == id)
- break;
- if (i >= ClassRecords.Nodes())
- error("attempted load of unknown class: ",id);
- else {
- if ((InstancE = (*((SCRecorD)
- ClassRecords[i])->load)
- (is,StreamablE0)) == StreamablE0)
- error("unable to load class ",id);
- else if (streamed == 1) {
- // 1st of many save in holding pen
- SCHRecorD R = new
- StreamableClassHoldingRecord
- (InstancE,spos);
- if (!R)
- error("class holding record"
- " memory exhausted,"
- " id: ",id);
- else if (!InstanceLinks.insQ(R)) {
- error("unable to hold class"
- " for multiple "
- "links ",id);
- delete R;
- }
- }
- }
-
-
-
- }
-
- return is;
- }
-
- ostream& StreamableClassRegistry::put(ostream& os,
- StreamablE InstancE)
- {
- unsigned id, i;
- long tpos;
-
- if (!InstancE)
- return os;
- for (i = 0; i < ClassRecords.Nodes(); i++)
- if (((SCRecorD)ClassRecords[i])->id
- == InstancE->id)
- break;
- if (i >= ClassRecords.Nodes()) {
- error("attempted store of unknown class: ",
- InstancE->id);
- // Insert unknown class place holder
- os << ID_UnknownStreamable << endm;
- return os;
- }
- else {
- if (!(os << InstancE->id << endm))
- {
- error("unable to insert id: ",
- InstancE->id);
- return os;
- }
- if (!InstancE->spos)
- InstancE->spos = os.tellp();
- if (!(os << InstancE->streamed << endm
- << InstancE->spos << endm))
- {
- error("unable to insert streamed "
- "and spos: ",InstancE->id);
- return os;
- }
- if (!InstancE->streamed) {
- // first time - store instance!
- InstancE->store(os);
- InstancE->streamed = 2;
- }
- else
- {
- // go back to stored class and
- // indicate multiple links!
- tpos = os.tellp();
- os.seekp(InstancE->spos);
- os << "1";
- os.seekp(tpos);
- }
-
- }
- return os << flush;
- }
-
-
- StreamableFncPtrRegistry SFPRegistry;
-
- int StreamableFncPtrRegistry::debug;
-
- void StreamableFncPtrRegistry::error(char *msg, unsigned id)
- {
- if (debug)
- cerr << "FncPtrRegistry error - "
- << msg << id << endl;
- }
-
- void StreamableFncPtrRegistry::warn(char *msg, unsigned id)
- {
- if (debug)
- cerr << "FncPtrRegistry warning - "
- << msg << id << endl;
-
- }
-
- void StreamableFncPtrRegistry::registerFunction(unsigned id,
- GenericFnC fnC)
- {
- unsigned i;
-
- for (i = 0; i < FncPtrRecords.Nodes(); i++)
- if (((SFPRecorD)FncPtrRecords[i])->id == id)
- break;
- if (i < FncPtrRecords.Nodes())
- if (((SFPRecorD)FncPtrRecords[i])->fnC
- == fnC)
- {
- warn("attempted multiple"
- " registration"
- " of function pointer: ",
- id);
- return;
- }
- else {
- error("id conflict: ",id);
- return;
- }
- SFPRecorD R = new StreamableFncPtrRecord(id,fnC);
- if (!R)
- error("fncPtr memory exhausted, id: ",id);
- else if (!FncPtrRecords.insQ(R)) {
- error("fncPtr record can't be queued, id: ",
- id);
- delete R;
- }
- }
-
-
- GenericFnC StreamableFncPtrRegistry::FnC(unsigned id)
- {
- unsigned i;
-
- for (i = 0; i < FncPtrRecords.Nodes(); i++)
- if (((SFPRecorD)FncPtrRecords[i])->id == id)
- break;
- if (i >= FncPtrRecords.Nodes()) {
- error("unknown fncPtr: ",id);
- return GenericFnC0;
- }
- else
- return ((SFPRecorD)FncPtrRecords[i])->fnC;
- }
-
- unsigned StreamableFncPtrRegistry::ID(GenericFnC fnC)
- {
- unsigned i;
-
- for (i = 0; i < FncPtrRecords.Nodes(); i++)
- if (((SFPRecorD)FncPtrRecords[i])->fnC
- == fnC)
- break;
- if (i >= FncPtrRecords.Nodes()) {
- error("unknown fncPtr: ",
- ID_UnknownGenericFnC);
- return ID_UnknownGenericFnC;
- }
- else
- return ((SFPRecorD)FncPtrRecords[i])->id;
- }
-
-