home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c017 / 34.ddi / CSTRM.ZIP / BINDER.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-27  |  21.9 KB  |  1,130 lines

  1. /*
  2.  
  3.     binder.cpp
  4.     8-27-91
  5.     Loose Data Binder
  6.  
  7.     Copyright 1991
  8.     John W. Small
  9.     All rights reserved
  10.  
  11.     PSW / Power SoftWare
  12.     P.O. Box 10072
  13.     McLean, Virginia 22102 8072 USA
  14.  
  15.     John Small
  16.     Voice: (703) 759-3838
  17.     CIS: 73757,2233
  18.  
  19. */
  20.  
  21.  
  22. #include <string.h>
  23. #include <binder.hpp>
  24.  
  25. int Streamable::debug = 0;
  26. int Streamable::refDebug = 0;
  27.  
  28. void Streamable::lserror(const char *msg, unsigned id)
  29. {
  30.     if (debug)
  31.         cerr << "Class id: " << setw(6) << id
  32.             <<  "   stream error - "
  33.             << msg << endl;
  34. }
  35.  
  36. void Streamable::serror(const char *msg)
  37. {
  38.     if (debug)
  39.         cerr << endl 
  40.             <<"Class id: " << setw(6) << id
  41.             << "    &instance:   "
  42.             << (void *) this << endl
  43.             <<  "Stream error - "
  44.             << msg << endl << endl;
  45. }
  46.  
  47. void Streamable::swarn(const char *msg)
  48. {
  49.     if (debug)
  50.         cerr << endl
  51.             << "Class id: " << setw(6) << id
  52.             << "    &instance:   "
  53.             << (void *) this << endl
  54.             <<  "Stream warning - "
  55.             << msg << endl;
  56. }
  57.  
  58.  
  59. #pragma argsused
  60. StreamablE Streamable::load(istream& is,
  61.     StreamablE InstancE)
  62.     { return InstancE; }
  63.  
  64. char Streamable::memberTermChar = '\n';
  65.  
  66. #pragma argsused
  67. Streamable::Streamable(StreamableClassRegistry& dummy,
  68.     unsigned id)
  69. {
  70.     this->id = id;
  71.     streamed = refCount = 0;
  72.     spos = 0L;
  73. }
  74.  
  75. void Streamable::registerClass(unsigned id,
  76.         StreamablE (*loader)(istream& is,
  77.         StreamablE InstancE))
  78. {
  79.     SCRegistry.registerClass(id,loader);
  80. }
  81.  
  82. void Streamable::restream()
  83.     { streamed = 0; spos = 0L; }
  84.  
  85. unsigned Streamable::unlink()
  86. {
  87.     if (refDebug)
  88.         cerr << endl
  89.             << "Class id: " << setw(6) << id
  90.             << "    &instance:   "
  91.             << (void *) this << endl
  92.             <<  "Unlinking, starting refCount: "
  93.             << refCount << endl;
  94.     return (refCount? refCount-- : refCount);
  95. }
  96.  
  97. StreamablE Streamable::link()
  98. {
  99.     refCount++;
  100.     if (refDebug)
  101.         cerr << endl
  102.             << "Class id: " << setw(6) << id
  103.             << "    &instance:   "
  104.             << (void *) this << endl
  105.             <<  "Adding link, new refCount: "
  106.             << refCount << endl;
  107.     return this;
  108. }
  109.  
  110.  
  111. ostream& endm(ostream& os)
  112. {
  113.     return os << Streamable::memberTermChar
  114.         << flush;
  115. }
  116.  
  117. istream& nextm(istream& is)
  118. {
  119.     is.get();
  120.     return is;
  121. }
  122.  
  123.  
  124. void Binder::construct(unsigned flags, unsigned maxNodes,
  125.     unsigned limit, unsigned delta)
  126. {
  127.     curNode = first = nodes = 0;
  128.     comparE = BDRcomparE0;
  129.  
  130. /*
  131.     The following relationships are maintained
  132.     during operation of a binder:
  133.  
  134.     1 <= delta <= lowLimit <= limit <= maxNodes
  135.         <= BDR_MAXNODES
  136.     lowThreshold = lowLimit - delta;
  137. */
  138.  
  139.     if (maxNodes > BDR_MAXNODES)
  140.         maxNodes = BDR_MAXNODES;
  141.     if (limit > maxNodes)
  142.         limit = maxNodes;
  143.     if (delta > limit)
  144.         delta = limit;
  145.     if (!delta)  {
  146.         delta = 1;
  147.         if (limit < delta)
  148.             limit = delta;
  149.         if (maxNodes < limit)
  150.             maxNodes = limit;
  151.     }
  152.     if ((linkS = new voiD[limit]) == voiDV0)
  153.         this->limit = lowLimit = lowThreshold
  154.             = this->delta = this->maxNodes
  155.             = this->flags = 0;
  156.     else  {
  157.         this->limit = limit;
  158.         this->delta = delta;
  159.         this->maxNodes = maxNodes;
  160.         lowLimit = limit;
  161.         lowThreshold = lowLimit - delta;
  162.         flags |= SORTED;
  163.         this->flags = flags;
  164.     }
  165. }
  166.  
  167. int Binder::Dfree(voiD D)
  168. {
  169.     if (D)  {
  170.         if (flags & STREAMABLE_NODES)  {
  171.             if (!((StreamablE)D)->unlink())
  172.                 delete (StreamablE) D;
  173.         }
  174.         else
  175.             delete D;
  176.         return 1;
  177.     }
  178.     else
  179.         return 0;
  180. }
  181.  
  182. void Binder::Dstore(ostream& os, const voiD D)
  183. {
  184.     if (D && (flags & STREAMABLE_NODES))
  185.         os << (StreamablE) D;
  186.     else
  187.         swarn("don't know how to store "
  188.             "binder node ");
  189. }
  190.  
  191. voiD Binder::Dload(istream& is)
  192. {
  193.     StreamablE InstancE = StreamablE0;
  194.  
  195.     if (flags & STREAMABLE_NODES)
  196.         is >> InstancE;
  197.     else
  198.         swarn("don't know how to load "
  199.             "binder node ");
  200.     return (voiD) InstancE;
  201. }
  202.  
  203.  
  204. voiD Binder::DinsQ(voiD D)
  205.     { return insQ(D); }
  206.  
  207.  
  208. ostream& Binder::store(ostream& os)
  209. {
  210.     unsigned i;
  211.  
  212.     os << maxNodes << endm << limit << endm
  213.         << delta << endm << nodes << endm
  214.         << curNode << endm << flags << endm
  215.         << FncPtrToID((GenericFnC)comparE) << endm;
  216.     if (!os)
  217.         serror("unable to store Binder ");
  218.     else for (i = 0; i < nodes; i++)
  219.         Dstore(os,atGet(i));
  220.     return os;
  221. }
  222.  
  223. StreamablE Binder::load(istream& is, StreamablE InstancE)
  224. {
  225.     unsigned i, maxNodes, limit, delta, nodes, curNode;
  226.     unsigned flags;
  227.     unsigned comparEID;
  228.  
  229.     is >> maxNodes >> nextm >> limit >> nextm
  230.         >> delta >> nextm >> nodes >> nextm
  231.         >> curNode >> nextm >> flags >> nextm
  232.         >> comparEID >> nextm;
  233.     if (!is)  {
  234.         lserror("unable to load binder header data",
  235.             CLASS_ID);
  236.         return StreamablE0;
  237.     }
  238.     if (!InstancE) if ((InstancE = (StreamablE)
  239.         new Binder(UNIQUE_STREAMABLE))
  240.         == StreamablE0)  {
  241.         lserror("unable to construct binder for"
  242.             " loading ",CLASS_ID);
  243.         return StreamablE0;
  244.     }
  245.     ((BindeR)InstancE)->construct(flags,maxNodes,
  246.         limit,delta);
  247.     for (i = 0; i < nodes; i++)
  248.         ((BindeR)InstancE)->DinsQ(((BindeR)InstancE)
  249.             ->Dload(is));
  250.     ((BindeR)InstancE)->setCurNode(curNode);
  251.     ((BindeR)InstancE)->flags = flags;
  252.     ((BindeR)InstancE)->setComparE((BDRcomparE)
  253.         IDtoFncPtr(comparEID));
  254.     return InstancE;
  255. }
  256.  
  257. void Binder::restream()
  258. {
  259.     Streamable::restream();
  260.     if (flags & STREAMABLE_NODES)
  261.         for (unsigned i = 0; i < nodes; i++)
  262.             ((StreamablE)atGet(i))->restream();
  263. }
  264.  
  265. Binder::Binder(voiDV argv, int argc, unsigned flags)
  266.     : Streamable(UNIQUE_STREAMABLE,CLASS_ID)
  267. {
  268.     construct(flags,BDR_MAXNODES,argc,BDR_DELTA);
  269.     if (argv) if (argc > 0)
  270.         while (argc--)
  271.             push(argv[argc]);
  272.     else
  273.         for (argc = 0; insQ(argv[argc]); argc++);
  274. }
  275.  
  276. voiDV Binder::vector()
  277. {
  278.     voiDV V = voiDV0;
  279.  
  280.     if (nodes) if ((V = new voiD[nodes+1]) != voiDV0)  {
  281.         for (unsigned i = 0; i < nodes; i++)
  282.             V[i] = atGet(i);
  283.         V[i] = voiD0;
  284.     }
  285.     return V;
  286. }
  287.  
  288. Binder::~Binder()
  289. {
  290.     if (flags & (ALL_FREE_DESTRUCT | STREAMABLE_NODES))
  291.         allFree();
  292.     else
  293.         allDel();
  294.     delete linkS;
  295. }
  296.  
  297. unsigned Binder::setLimit(unsigned newLimit)
  298. {
  299.     voiDV newLinkS;
  300.     unsigned i;
  301.  
  302.     if (newLimit < nodes)
  303.         newLimit = nodes;
  304.     else if (newLimit > maxNodes)
  305.         newLimit = maxNodes;
  306.     if (newLimit < delta)
  307.         newLimit = delta;
  308.     if (!linkS || !newLimit || newLimit == limit)
  309.         return 0;
  310.     if ((newLinkS = new voiD[newLimit]) == voiDV0)
  311.         return 0;
  312.     if ((i = limit - first) > nodes)
  313.         i = nodes;
  314.     memcpy(newLinkS,&linkS[first],sizeof(linkS[0])*i);
  315.     /* copy wrap around */
  316.     if (i < nodes)
  317.         memcpy(&newLinkS[i],linkS,
  318.             sizeof(linkS[0])*(nodes-i));
  319.     if (newLimit > limit)
  320.         if (newLimit - delta > limit)
  321.             lowLimit = newLimit - delta;
  322.         else
  323.             lowLimit = limit;
  324.     else
  325.         if (newLimit - delta > delta)
  326.             lowLimit = newLimit - delta;
  327.         else
  328.             lowLimit = delta;
  329.     lowThreshold = lowLimit - delta;
  330.     delete linkS;
  331.     linkS = newLinkS;
  332.     limit = newLimit;
  333.     first = 0;
  334.     return limit;
  335. }
  336.  
  337. unsigned Binder::setDelta(unsigned newDelta)
  338. {
  339.     return ((newDelta && newDelta <= lowLimit)?
  340.         delta = newDelta : 0);
  341. }
  342.  
  343. unsigned Binder::setMaxNodes(unsigned newMaxNodes)
  344. {
  345.     return ((newMaxNodes >= limit)?
  346.         (maxNodes = (newMaxNodes
  347.         > BDR_MAXNODES)? BDR_MAXNODES
  348.         : newMaxNodes) : 0);
  349. }
  350.  
  351. voiD Binder::atIns(unsigned n, const voiD D)
  352. {
  353.     voiDV newLinkS;
  354.     unsigned newLimit, i;
  355.  
  356.     if (!linkS || !D)
  357.         return voiD0;
  358.     if (nodes == limit)  {
  359.         if (limit == maxNodes)
  360.             return voiD0;
  361.         newLimit = (maxNodes - delta > limit)?
  362.             limit + delta : maxNodes;
  363.         if ((newLinkS = new voiD[newLimit]) 
  364.             == voiDV0) return voiD0;
  365.         if ((i = limit - first) > nodes)
  366.             i = nodes;
  367.         memcpy(newLinkS,&linkS[first],
  368.             sizeof(linkS[0])*i);
  369.         /* copy wrap around */
  370.         if (i < nodes)
  371.             memcpy(&newLinkS[i],linkS,
  372.                 sizeof(linkS[0])*(nodes-i));
  373.         /*
  374.             Compute next smaller linkS size
  375.             and threshold for shrinking.
  376.         */
  377.         lowLimit = limit;
  378.         lowThreshold = lowLimit - delta;
  379.         /* swap new for old */
  380.         delete linkS;
  381.         linkS = newLinkS;
  382.         limit = newLimit;
  383.         first = 0;
  384.     }
  385.     if (!n)  /* push */
  386.         linkS[first? --first
  387.             : (first = limit - 1)] = D;
  388.     else if (n >= nodes) /* insQ */
  389.         linkS[(first+(n=nodes))%limit] = D;
  390.     else  { /* insert interior */ 
  391.         i = (first + n) % limit;
  392.         if (i < first || !first)
  393.             /* move rear rightward */
  394.             memmove(&linkS[i+1],&linkS[i],
  395.                 sizeof(linkS[0])
  396.                 * (nodes-n));
  397.         else /* move front leftward */
  398.             memmove(&linkS[--first],&linkS[--i],
  399.                 sizeof(linkS[0])*(n+1));
  400.         linkS[i] = D;
  401.     }
  402.     nodes++;
  403.     if (n <= curNode)
  404.         curNode++;
  405.     flags &= ~SORTED;
  406.     return D;
  407. }
  408.  
  409. voiD Binder::atDel(unsigned n)
  410. {
  411.     voiDV newLinkS;
  412.     unsigned newLimit, i;
  413.     voiD D;
  414.  
  415.     if (!linkS || n >= nodes)
  416.         return voiD0;
  417.     D = linkS[(first+n)%limit];
  418.     if (!n)  {  /* pop */
  419.         if (++first >= limit)
  420.             first = 0;
  421.     }
  422.     else if (n != nodes-1)  {  /* del interior */
  423.         /* move front rightward */
  424.         memmove(&linkS[first+1],&linkS[first],
  425.             sizeof(linkS[0])*n);
  426.         first++;
  427.     }
  428.     if (--nodes == 0)
  429.         flags |= SORTED;
  430.     if (n < curNode)
  431.         curNode--;
  432.     else if (n == curNode)
  433.         curNode = nodes;
  434.     if (nodes < lowThreshold)  {
  435.         newLimit = lowLimit;
  436.         if ((newLinkS = new voiD[newLimit]) 
  437.             == voiDV0) return voiD0;
  438.         if ((i = limit - first) > nodes)
  439.             i = nodes;
  440.         memcpy(newLinkS,&linkS[first],
  441.             sizeof(linkS[0])*i);
  442.         /* copy wrap around */
  443.         if (i < nodes)
  444.             memcpy(&newLinkS[i],linkS,
  445.                 sizeof(linkS[0])*(nodes-i));
  446.         /*
  447.             Compute next smaller linkS size
  448.             and threshold for shrinking.
  449.         */
  450.         if (lowLimit - delta > delta)
  451.             lowLimit -= delta;
  452.         else
  453.             lowLimit = delta;
  454.         lowThreshold = lowLimit - delta;
  455.         /* swap new for old */
  456.         delete linkS;
  457.         linkS = newLinkS;
  458.         limit = newLimit;
  459.         first = 0;
  460.     }
  461.     return D;
  462. }
  463.  
  464. int Binder::allDel()
  465. {
  466.     if (!linkS)
  467.         return 0;
  468.     while (atDel(0))
  469.         /* null statement */;
  470.     return 1;
  471. }
  472.  
  473. int Binder::allFree()
  474. {
  475.     if (!linkS)
  476.         return 0;
  477.     while (atFree(0))
  478.         /* null statement */;
  479.     return 1;
  480. }
  481.  
  482. voiD Binder::atPut(unsigned n, const voiD D)
  483. {
  484.     return ((linkS && D && (n < nodes))?
  485.         flags &= ~SORTED,
  486.         linkS[(first+n)%limit] = D
  487.         : voiD0);
  488. }
  489.  
  490. voiD Binder::atGet(unsigned n)
  491. {
  492.     return ((linkS && (n < nodes))?
  493.         linkS[(first+n)%limit] : voiD0);
  494. }
  495.  
  496. voiD Binder::at(unsigned n, const voiD D)
  497. {
  498.     voiD oldD;
  499.     
  500.     if ((oldD = atGet(n)) != voiD0)
  501.         if (D)  {
  502.             linkS[(first+n)%limit] = D;
  503.             flags &= ~SORTED;
  504.         }
  505.     return oldD;
  506. }
  507.  
  508. unsigned Binder::index(const voiD D)
  509. {
  510.     unsigned i;
  511.  
  512.     if (linkS && D)
  513.         for (i = 0; i < nodes; i++)
  514.             if (D == linkS[(first+i)%limit])
  515.                 return i;
  516.     return BDR_NOTFOUND;
  517. }
  518.  
  519. int Binder::forEach(BDRforEachBlocK B, voiD M, voiD A)
  520. {
  521.     unsigned i;
  522.  
  523.     if (!linkS || !B || !nodes)
  524.         return 0;
  525.     for (i = 0; i < nodes; i++)
  526.         (*B)(linkS[(first+i)%limit],M,A);
  527.     return 1;
  528. }
  529.  
  530. unsigned Binder::firstThat(BDRdetectBlocK B, voiD M)
  531. {
  532.     unsigned i;
  533.  
  534.     if (linkS && B)
  535.         for (i = 0; i < nodes; i++)
  536.             if ((*B)(linkS[(first+i)%limit],M))
  537.                 return i;
  538.     return BDR_NOTFOUND;
  539. }
  540.  
  541. unsigned Binder::lastThat(BDRdetectBlocK B, voiD M)
  542. {
  543.     unsigned i;
  544.  
  545.     if (linkS && B && nodes)
  546.         for (i = nodes; i--; /* no reinit */)
  547.             if ((*B)(linkS[(first+i)%limit],M))
  548.                 return i;
  549.     return BDR_NOTFOUND;
  550. }
  551.  
  552. int Binder::collect(BDRcollectBlocK B, BindeR R,
  553.     voiD M, voiD A)
  554. {
  555.     unsigned i;
  556.  
  557.     if (!linkS || !B || !R)
  558.         return 0;
  559.     for (i = 0; i < nodes; i++)
  560.         (*B)(linkS[(first+i)%limit],R,M,A);
  561.     return 1;
  562. }
  563.  
  564.  
  565. /*  FlexList like primitives:  */
  566.  
  567. unsigned Binder::CurNode()
  568. {
  569.     return ((curNode < nodes)?
  570.         curNode : BDR_NOTFOUND);
  571. }
  572.  
  573. int  Binder::setCurNode(unsigned n)
  574. {
  575.     return ((curNode = ((n > nodes)? nodes : n))
  576.         < nodes);
  577. }
  578.  
  579. Binder& Binder::operator<<(Binder& (*manipulator)
  580.         (Binder& B))
  581. {
  582.     return (manipulator? (*manipulator)(*this)
  583.         : *this);
  584. }
  585.  
  586. voiD Binder::ins(const voiD D)
  587. {
  588.     if (atIns(curNode+1,D))  {
  589.         if (++curNode >= nodes)
  590.             curNode = nodes - 1;
  591.         return D;
  592.     }
  593.     return voiD0;
  594. }
  595.  
  596. voiD Binder::insSort(const voiD D)
  597. {
  598.     unsigned low, mid, high;
  599.     voiD ok;
  600.  
  601. /*
  602.     The current node is left undefined if
  603.     anything fails, otherwise it is set to the
  604.     newly inserted node.
  605. */
  606.  
  607.     curNode = nodes;
  608.     if (!linkS || !D || nodes >= maxNodes || !comparE)
  609.         return voiD0;
  610.     if (!(flags & SORTED))
  611.         if (!sort())
  612.             return voiD0;
  613.     low = 0;
  614.     high = nodes;
  615.     while (low < high)  {
  616.         mid = low + ((high - low) >> 1);
  617.         if ((*comparE)(D,
  618.             linkS[(first+mid)%limit]) <= 0)
  619.             high = mid;
  620.         else
  621.             low = mid + 1;
  622.     }
  623.     if ((ok = atIns(high,D)) != voiD0)
  624.         curNode = high;
  625.     /*  atIns() resets sorted to zero  */
  626.     flags |= SORTED;
  627.     return ok;
  628. }
  629.  
  630. voiD Binder::del()
  631. {
  632.     voiD D;
  633.     unsigned n;
  634.  
  635.     if ((D = atDel(n=curNode)) != voiD0)
  636.         if (n--)
  637.             curNode = n;
  638.     return D;
  639. }
  640.  
  641. voiD Binder::next()
  642.     if (linkS)  {
  643.         if (curNode >= nodes)
  644.             curNode = 0;
  645.         else
  646.             curNode++;
  647.         if (curNode < nodes)
  648.             return linkS[(first+curNode)%limit];
  649.     }
  650.     return voiD0;
  651. }
  652.  
  653. voiD Binder::prev()
  654.     if (linkS)  {
  655.         if (curNode)  {
  656.             if (curNode > nodes)
  657.                 curNode = nodes;
  658.             curNode--;
  659.         }
  660.         else
  661.             curNode = nodes;
  662.         if (curNode < nodes)
  663.             return linkS[(first+curNode)%limit];
  664.     }
  665.     return voiD0;
  666. }
  667.  
  668. voiD Binder::findFirst(const voiD K)
  669. {
  670.     unsigned low, mid, high;
  671.     voiD D;
  672.  
  673. /*
  674.     The current node is left undefined if
  675.     anything fails, otherwise it is set to the
  676.     newly found node.
  677. */
  678.  
  679.     curNode = nodes;
  680.     if (!linkS || !K || !comparE || !nodes)
  681.         return voiD0;
  682.     if (flags & SORTED)  {
  683.         low = 0;
  684.         high = nodes;
  685.         while (low < high)  {
  686.             mid = low + ((high - low) >> 1);
  687.             if ((*comparE)(K,linkS[(first+mid)
  688.                 %limit]) <= 0)
  689.                 high = mid;
  690.             else
  691.                 low = mid + 1;
  692.         }
  693.         if (high < nodes)
  694.             if (!(*comparE)(K,linkS[(first+
  695.                 high)%limit]))
  696.                 return linkS[(first+
  697.                 (curNode = high))%limit];
  698.     }
  699.     else  {  /*  linear search!  */
  700.         while ((D = next()) != voiD0)
  701.             if (!(*comparE)(K,D))
  702.                 return D;
  703.     }
  704.     return voiD0;
  705. }
  706.  
  707. voiD Binder::findNext(const voiD K)
  708. {
  709.  
  710. /*
  711.     For sorted binders you must first call findFirst()
  712.     to insure consistent results!
  713. */
  714.  
  715.     voiD D;
  716.  
  717. /*
  718.     The current node is left undefined if
  719.     anything fails, otherwise it is set to the
  720.     newly found node.
  721. */
  722.  
  723.     if (!linkS || !K || !comparE)  {
  724.         curNode = nodes;
  725.         return voiD0;
  726.     }
  727.     while ((D = next()) != voiD0)
  728.         if (!(*comparE)(K,D))
  729.             return D;
  730.         else if (flags & SORTED)  {
  731.             curNode = nodes;
  732.             break; /*  Look no further!  */
  733.         }
  734.     return voiD0;
  735. }
  736.  
  737. voiD Binder::findLast(const voiD K)
  738. {
  739.     unsigned low, mid, high;
  740.     voiD D;
  741.  
  742. /*
  743.     The current node is left undefined if
  744.     anything fails, otherwise it is set to the
  745.     newly found node.
  746. */
  747.  
  748.     curNode = nodes;
  749.     if (!linkS || !K || !comparE || !nodes)
  750.         return voiD0;
  751.     if (flags & SORTED)  {
  752.         low = 0;
  753.         high = nodes;
  754.         while (low < high)  {
  755.             mid = low + ((high - low) >> 1);
  756.             if ((*comparE)(K,linkS[(first+mid)
  757.                 %limit]) < 0)
  758.                 high = mid;
  759.             else
  760.                 low = mid + 1;
  761.         }
  762.         if (high < nodes)
  763.             if (!(*comparE)(K,linkS[(first+
  764.                 high)%limit]))
  765.                 return linkS[(first+
  766.                 (curNode = high))%limit];
  767.     }
  768.     else  {  /*  linear search!  */
  769.         while ((D = prev()) != voiD0)
  770.             if (!(*comparE)(K,D))
  771.                 return D;
  772.     }
  773.     return voiD0;
  774. }
  775.  
  776. voiD Binder::findPrev(const voiD K)
  777. {
  778.  
  779. /*
  780.     For sorted binders you must first call findLast()
  781.     to insure consistent results!
  782. */
  783.  
  784.     voiD D;
  785.  
  786. /*
  787.     The current node is left undefined if
  788.     anything fails, otherwise it is set to the
  789.     newly found node.
  790. */
  791.  
  792.     if (!linkS || !K || !comparE)  {
  793.         curNode = nodes;
  794.         return voiD0;
  795.     }
  796.     while ((D = prev()) != voiD0)
  797.         if (!(*comparE)(K,D))
  798.             return D;
  799.         else if (flags & SORTED)  {
  800.             curNode = nodes;
  801.             break; /*  Look no further!  */
  802.         }
  803.     return voiD0;
  804. }
  805.  
  806. int   Binder::sort(BDRcomparE comparE)
  807. {
  808.     unsigned low, mid, high;
  809.     unsigned d;
  810.     voiD D;
  811.  
  812. /*
  813.     The current node is always reset to undefined
  814.     regardless of the outcome of sort.
  815. */
  816.  
  817.     curNode = nodes;
  818.     if (flags & SORTED)  {
  819.         if (this->comparE == comparE || !comparE)
  820.             return 1;
  821.     }
  822.     else if (!this->comparE && !comparE)
  823.         return 0;
  824.     if (comparE)  {
  825.         this->comparE = comparE;
  826.         flags &= ~SORTED;
  827.     }
  828.     if (!nodes)
  829.         return (flags |= SORTED);
  830.     if (!linkS)
  831.         return 0;
  832.     if (first)  { /* form contiguous block at front */
  833.         d = (first + nodes) % limit;
  834.         if (d > first)
  835.             memmove(linkS,&linkS[first],
  836.                 sizeof(linkS[0])*nodes);
  837.         else if (d < first)
  838.             memmove(&linkS[d],&linkS[first],
  839.                 sizeof(linkS[0])
  840.                 *(limit-first));
  841.         /* else array is full/contiguous */
  842.         first = 0;
  843.     }
  844.     for (high = d = 1; d < nodes; high = ++d)  {
  845.         low = 0;
  846.         D = linkS[d];
  847.         while (low < high)  {
  848.             mid = low + ((high - low) >> 1);
  849.             if ((*this->comparE)(D,
  850.                 linkS[mid]) <= 0)
  851.                 high = mid;
  852.             else
  853.                 low = mid + 1;
  854.         }
  855.         if (high < d)  {
  856.             memmove(&linkS[high+1],&linkS[high],
  857.                 sizeof(linkS[0])*(d-high));
  858.             linkS[high] = D;
  859.         }
  860.     }
  861.     return (flags |= SORTED);
  862. }
  863.  
  864.  
  865.  
  866. StreamableClassRegistry SCRegistry;
  867.  
  868. int StreamableClassRegistry::debug;
  869.  
  870. void StreamableClassRegistry::error(char *msg, unsigned id)
  871. {
  872.     if (debug)
  873.         cerr
  874.         << "StreamClassRegistry error - "
  875.             << msg << id << endl;
  876. }
  877.  
  878. void StreamableClassRegistry::warn(char *msg, unsigned id)
  879. {
  880.     if (debug)
  881.         cerr
  882.         << "StreamClassRegistry warning - "
  883.         << msg << id << endl;
  884. }
  885.  
  886. void StreamableClassRegistry::registerClass(unsigned id,
  887.     StreamablE (*loader) (istream& is,
  888.     StreamablE InstancE))
  889. {
  890.     unsigned i;
  891.  
  892.     for (i = 0; i < ClassRecords.Nodes(); i++)
  893.         if (((SCRecorD)ClassRecords[i])->id
  894.             == id)
  895.             break;
  896.     if (i < ClassRecords.Nodes())
  897.         if (((SCRecorD)ClassRecords[i])->load
  898.             == loader)  {
  899.             warn("multiple registration of"
  900.                 " loader id: ",id);
  901.             return;
  902.         }
  903.         else  {
  904.             error("id conflict: ",id);
  905.             return;
  906.         }
  907.     SCRecorD R = new StreamableClassRecord(id,loader);
  908.     if (!R)
  909.         error("class record memory exhausted, id: ",
  910.             id);
  911.     else if (!ClassRecords.insQ(R))  {
  912.         error("class record can't be queued, id: ",
  913.             id);
  914.         delete R;
  915.     }
  916. }
  917.  
  918. void StreamableClassRegistry::forgetClasses()
  919. {
  920.     ClassRecords.allFree();
  921.     InstanceLinks.allDel();
  922. }
  923.  
  924. istream& StreamableClassRegistry::get(istream& is,
  925.     StreamablE& InstancE)
  926. {
  927.     unsigned id, streamed, i;
  928.     long spos;
  929.  
  930.     InstancE = StreamablE0;
  931.     if (!(is >> id >> nextm >> streamed >> nextm >>
  932.         spos >> nextm))
  933.         error("unable to read id, streamed, "
  934.             "spos ",0);
  935.     else if (streamed > 1)  {
  936.         // Link to previously loaded Instance
  937.         for (i = 0; i < InstanceLinks.Nodes(); i++)
  938.             if (((SCHRecorD)InstanceLinks[i])
  939.                 ->spos == spos)  {
  940.                 InstancE = ((SCHRecorD)
  941.                     InstanceLinks[i])
  942.                         ->InstancE;
  943.                 InstancE->link();
  944.                 break;
  945.             }
  946.         if (!InstancE)
  947.             error("unable to establish link to"
  948.                 " previously loaded class",
  949.                 id);
  950.     }
  951.     else  {  // load instance
  952.  
  953.  
  954. for (i = 0; i < ClassRecords.Nodes(); i++)
  955.     if (((SCRecorD)ClassRecords[i])->id == id)
  956.             break;
  957. if (i >= ClassRecords.Nodes())
  958.     error("attempted load of unknown class: ",id);
  959. else  {
  960.     if ((InstancE = (*((SCRecorD)
  961.         ClassRecords[i])->load)
  962.         (is,StreamablE0)) == StreamablE0)
  963.         error("unable to load class ",id);
  964.     else if (streamed == 1)  {
  965.         // 1st of many save in holding pen
  966.         SCHRecorD R = new
  967.             StreamableClassHoldingRecord
  968.                 (InstancE,spos);
  969.         if (!R)
  970.             error("class holding record"
  971.                 " memory exhausted,"
  972.                 " id: ",id);
  973.         else if (!InstanceLinks.insQ(R))  {
  974.             error("unable to hold class"
  975.                 " for multiple "
  976.                 "links ",id);
  977.             delete R;
  978.         }
  979.     }
  980. }
  981.  
  982.  
  983.  
  984.     }
  985.  
  986.     return is;
  987. }
  988.  
  989. ostream& StreamableClassRegistry::put(ostream& os,
  990.     StreamablE InstancE)
  991. {
  992.     unsigned id, i;
  993.     long tpos;
  994.  
  995.     if (!InstancE)
  996.         return os;
  997.     for (i = 0; i < ClassRecords.Nodes(); i++)
  998.         if (((SCRecorD)ClassRecords[i])->id
  999.             == InstancE->id)
  1000.             break;
  1001.     if (i >= ClassRecords.Nodes())  {
  1002.         error("attempted store of unknown class: ",
  1003.             InstancE->id);
  1004.         // Insert unknown class place holder
  1005.         os << ID_UnknownStreamable << endm;
  1006.         return os;
  1007.     }
  1008.     else  {
  1009.         if (!(os << InstancE->id << endm))
  1010.         {
  1011.             error("unable to insert id: ",
  1012.                 InstancE->id);
  1013.             return os;
  1014.         }
  1015.         if (!InstancE->spos)
  1016.             InstancE->spos = os.tellp();
  1017.         if (!(os << InstancE->streamed << endm
  1018.             << InstancE->spos << endm))
  1019.         {
  1020.             error("unable to insert streamed "
  1021.                 "and spos: ",InstancE->id);
  1022.             return os;
  1023.         }
  1024.         if (!InstancE->streamed)  {
  1025.             // first time - store instance!
  1026.             InstancE->store(os);
  1027.             InstancE->streamed = 2;
  1028.         }
  1029.         else
  1030.         {
  1031.             // go back to stored class and
  1032.             // indicate multiple links!
  1033.             tpos = os.tellp();
  1034.             os.seekp(InstancE->spos);
  1035.             os << "1";
  1036.             os.seekp(tpos);
  1037.         }
  1038.  
  1039.     }
  1040.     return os << flush;
  1041. }
  1042.  
  1043.  
  1044. StreamableFncPtrRegistry SFPRegistry;
  1045.  
  1046. int StreamableFncPtrRegistry::debug;
  1047.  
  1048. void StreamableFncPtrRegistry::error(char *msg, unsigned id)
  1049. {
  1050.     if (debug)
  1051.         cerr << "FncPtrRegistry error - "
  1052.             << msg << id << endl;
  1053. }
  1054.  
  1055. void StreamableFncPtrRegistry::warn(char *msg, unsigned id)
  1056. {
  1057.     if (debug)
  1058.         cerr << "FncPtrRegistry warning - "
  1059.             << msg << id << endl;
  1060.  
  1061. }
  1062.  
  1063. void StreamableFncPtrRegistry::registerFunction(unsigned id,
  1064.     GenericFnC fnC)
  1065. {
  1066.     unsigned i;
  1067.  
  1068.     for (i = 0; i < FncPtrRecords.Nodes(); i++)
  1069.         if (((SFPRecorD)FncPtrRecords[i])->id == id)
  1070.             break;
  1071.     if (i < FncPtrRecords.Nodes())
  1072.         if (((SFPRecorD)FncPtrRecords[i])->fnC
  1073.             == fnC)
  1074.         {
  1075.             warn("attempted multiple"
  1076.                 " registration"
  1077.                 " of function pointer: ",
  1078.                 id);
  1079.             return;
  1080.         }
  1081.         else {
  1082.             error("id conflict: ",id);
  1083.             return;
  1084.         }
  1085.     SFPRecorD R = new StreamableFncPtrRecord(id,fnC);
  1086.     if (!R)
  1087.         error("fncPtr memory exhausted, id: ",id);
  1088.     else if (!FncPtrRecords.insQ(R))  {
  1089.         error("fncPtr record can't be queued, id: ",
  1090.             id);
  1091.         delete R;
  1092.     }
  1093. }
  1094.  
  1095.  
  1096. GenericFnC StreamableFncPtrRegistry::FnC(unsigned id)
  1097. {
  1098.     unsigned i;
  1099.  
  1100.     for (i = 0; i < FncPtrRecords.Nodes(); i++)
  1101.         if (((SFPRecorD)FncPtrRecords[i])->id == id)
  1102.             break;
  1103.     if (i >= FncPtrRecords.Nodes())  {
  1104.         error("unknown fncPtr: ",id);
  1105.         return GenericFnC0;
  1106.     }
  1107.     else
  1108.         return ((SFPRecorD)FncPtrRecords[i])->fnC;
  1109. }
  1110.  
  1111. unsigned StreamableFncPtrRegistry::ID(GenericFnC fnC)
  1112. {
  1113.     unsigned i;
  1114.  
  1115.     for (i = 0; i < FncPtrRecords.Nodes(); i++)
  1116.         if (((SFPRecorD)FncPtrRecords[i])->fnC
  1117.             == fnC)
  1118.             break;
  1119.     if (i >= FncPtrRecords.Nodes())  {
  1120.         error("unknown fncPtr: ",
  1121.             ID_UnknownGenericFnC);
  1122.         return ID_UnknownGenericFnC;
  1123.     }
  1124.     else
  1125.         return ((SFPRecorD)FncPtrRecords[i])->id;
  1126. }
  1127.  
  1128.