home *** CD-ROM | disk | FTP | other *** search
/ Shareware Supreme Volume 6 #1 / swsii.zip / swsii / 099 / CL181.ZIP / CL.CPP next >
C/C++ Source or Header  |  1993-04-26  |  20KB  |  1,069 lines

  1. /*
  2.     cl.cpp -- Container Lite v 1.81
  3.     (C) Copyright 1993  John Webster Small
  4.     All rights reserved
  5. */
  6.  
  7. #include <string.h>
  8. #include <fstream.h>
  9. #include "cl.hpp"
  10.  
  11.  
  12. char memberStreamDelimiter = '\n';
  13.  
  14. void cl::init(unsigned flags, unsigned maxNodes,
  15.     unsigned limit, unsigned delta)
  16. {
  17.     curNode = first = nodes = 0U;
  18.     cmP = voidCmP0;
  19.  
  20. /*
  21.     The following relationships are maintained
  22.     during operation of a cl:
  23.  
  24.     1 <= delta <= lowLimit <= limit <= maxNodes
  25.         <= CL_MAXNODES
  26.     lowThreshold = lowLimit - delta;
  27. */
  28.  
  29.     if (maxNodes > CL_MAXNODES)
  30.         maxNodes = CL_MAXNODES;
  31.     if (limit > maxNodes)
  32.         limit = maxNodes;
  33.     if (delta > limit)
  34.         delta = limit;
  35.     if (!delta)  {
  36.         delta = 1;
  37.         if (limit < delta)
  38.             limit = delta;
  39.         if (maxNodes < limit)
  40.             maxNodes = limit;
  41.     }
  42.     if ((linkS = new void *[limit]) == (void **)0)
  43.     {
  44.         this->limit = lowLimit = lowThreshold
  45.             = this->delta = this->maxNodes
  46.             = this->flags = 0U;
  47.     }
  48.     else  {
  49.         this->limit = limit;
  50.         this->delta = delta;
  51.         this->maxNodes = maxNodes;
  52.         lowLimit = limit;
  53.         lowThreshold = lowLimit - delta;
  54.         this->flags = (flags | CL_SORTED);
  55.     }
  56. }
  57.  
  58. void cl::assign(cl& b)
  59. {
  60.     if (flags & CL_DDELETE)
  61.         allDel();
  62.     else
  63.         allRmv();
  64.     setDelta(1); setLimit(1); setMaxNodes(1);
  65.     setMaxNodes(b.MaxNodes());
  66.     setLimit(b.Limit());
  67.     setDelta(b.Delta());
  68.     resetFlags(CL_ALL_FLAGS);
  69.     setFlags(b.Flags());
  70.     setFlags(CL_DNEW | CL_DDELETE);
  71.     setCmP(b.CmP());
  72.     for (unsigned i = 0U; i < b.Nodes(); i++)
  73.         insQNew(b.atGet(i));
  74.     setCurNode(b.CurNode());
  75. }
  76.  
  77. void cl::destruct()
  78. {
  79.     if (flags & CL_DDELETE)
  80.         allDel();
  81.     else
  82.         allRmv();
  83.     if (linkS)  {
  84.         delete linkS;
  85.         linkS = (void **)0;
  86.     }
  87. }
  88.  
  89. int cl::put(ostream& os)
  90. {
  91.     if (!(os << maxNodes << endm << limit << endm
  92.         << delta << endm << nodes << endm
  93.         << curNode << endm << flags << endm
  94.         << cmP2ID(cmP) << endm))
  95.         return 0;
  96.     for (unsigned i = 0U; i < nodes; i++)
  97.         if (!Dput(os,atGet(i)))
  98.             return 0;
  99.     return 1;
  100. }
  101.  
  102. int cl::get(istream& is)
  103. {
  104.     unsigned maxNodes, limit, delta, nodes;
  105.     unsigned curNode, flags, cmPid;
  106.  
  107.     if (!(is >> maxNodes >> nextm >> limit >> nextm
  108.         >> delta >> nextm >> nodes >> nextm
  109.         >> curNode >> nextm >> flags >> nextm
  110.         >> cmPid >> nextm))
  111.         return 0;
  112.     flags |= CL_DDELETE;
  113.     //reloaded nodes are dynamic!
  114.     setMaxNodes(maxNodes);
  115.     setLimit(limit);
  116.     setDelta(delta);
  117.     setFlags(flags);
  118.     setCmP(ID2cmP(cmPid));
  119.     void * D;
  120.     for (unsigned i = 0U; i < nodes; i++)
  121.         if (!insQ(D=Dget(is)))
  122.             if (D)  {
  123.                 Ddelete(D);
  124.                 return 0;
  125.             }
  126.     setCurNode(curNode);
  127.     return 1;
  128. }
  129.  
  130. int cl::load(const char * filename)
  131. {
  132.     int ok = 0;
  133.     allClr();
  134.     if (filename)  {
  135.         ifstream is(filename);
  136.         if (is)  {
  137.             ok = get(is);
  138.             is.close();
  139.         }
  140.     }
  141.     return ok;
  142. }
  143.  
  144. int cl::save(const char * filename)
  145. {
  146.     int ok = 0;
  147.     if (Flags(CL_DSTORE))  {
  148.         ofstream os(filename);
  149.         if (os)  {
  150.             ok = put(os);
  151.             os.close();
  152.         }
  153.     }
  154.     return ok;
  155. }
  156.  
  157. void cl::vforEach(voidApplY B, va_list args)
  158. {
  159.     if (!linkS || !B || !nodes)
  160.         return;
  161.     for (unsigned i = 0U; i < nodes; i++)
  162.         (*B)(linkS[(first+i)%limit],args);
  163. }
  164.  
  165. cl::cl(void ** argv, unsigned argc,
  166.     unsigned flags)
  167. {
  168.    init(flags,CL_MAXNODES,argc,CL_DELTA);
  169.    if (maxNodes)
  170.     if (argv)
  171.         if (argc > 0U)
  172.             while (argc--)
  173.               (void) push(argv[argc]);
  174.         else
  175.             for (argc = 0U;
  176.                 insQ(argv[argc]);
  177.                 argc++)
  178.                 /* null stmt */;
  179. }
  180.  
  181. void ** cl::vector(void ** argv, unsigned argc)
  182. {
  183.     void ** V;
  184.  
  185.     if ((V = argv) == (void **)0)  {
  186.         if (!nodes)
  187.             return (void **)0;
  188.         if ((V = new void *[argc=nodes+1])
  189.             == (void **)0)
  190.             return (void **)0;
  191.     }
  192.     else if (argc) if (nodes > argc)
  193.         return (void **)0;
  194.     for (unsigned i = 0U; i < nodes; i++)
  195.         V[i] = atGet(i);
  196.     while (i < argc)
  197.         V[i++] = (void *)0;
  198.     return V;
  199. }
  200.  
  201. unsigned cl::setLimit(unsigned newLimit)
  202. {
  203.     void ** newLinkS;
  204.     unsigned i;
  205.  
  206.     if (newLimit < nodes)
  207.         newLimit = nodes;
  208.     else if (newLimit > maxNodes)
  209.         newLimit = maxNodes;
  210.     if (newLimit < delta)
  211.         newLimit = delta;
  212.     if (!linkS || !newLimit || newLimit == limit)
  213.         return 0U;
  214.     if ((newLinkS = new void *[newLimit])
  215.         == (void **)0)
  216.         return 0U;
  217.     if ((i = limit - first) > nodes)
  218.         i = nodes;
  219.     if (i)
  220.         memcpy(newLinkS,&linkS[first],
  221.             sizeof(linkS[0U])*i);
  222.     /* copy wrap around */
  223.     if (i < nodes)
  224.         memcpy(&newLinkS[i],linkS,
  225.             sizeof(linkS[0U])*(nodes-i));
  226.     if (newLimit > limit)
  227.         if (newLimit - delta > limit)
  228.             lowLimit = newLimit - delta;
  229.         else
  230.             lowLimit = limit;
  231.     else
  232.         if (newLimit - delta > delta)
  233.             lowLimit = newLimit - delta;
  234.         else
  235.             lowLimit = delta;
  236.     lowThreshold = lowLimit - delta;
  237.     delete linkS;
  238.     linkS = newLinkS;
  239.     limit = newLimit;
  240.     first = 0U;
  241.     return limit;
  242. }
  243.  
  244. unsigned cl::setDelta(unsigned newDelta)
  245. {
  246.     return ((newDelta && newDelta <= lowLimit)?
  247.         delta = newDelta : 0U);
  248. }
  249.  
  250. unsigned cl::setMaxNodes(unsigned newMaxNodes)
  251. {
  252.     return ((newMaxNodes >= limit)?
  253.         (maxNodes = (newMaxNodes
  254.         > CL_MAXNODES)? CL_MAXNODES
  255.         : newMaxNodes) : 0U);
  256. }
  257.  
  258. void * cl::atIns(unsigned n, void * D)
  259. {
  260.     void ** newLinkS;
  261.     unsigned newLimit, i;
  262.  
  263.     if (!linkS || !D)
  264.         return (void *)0;
  265.     if (nodes == limit)  {
  266.         if (limit == maxNodes)
  267.             return (void *)0;
  268.         newLimit = (maxNodes - delta > limit)?
  269.             limit + delta : maxNodes;
  270.         if ((newLinkS = new void *[newLimit])
  271.             == (void **)0)
  272.             return (void *)0;
  273.         if ((i = limit - first) > nodes)
  274.             i = nodes;
  275.         if (i)
  276.             memcpy(newLinkS,&linkS[first],
  277.                 sizeof(linkS[0U])*i);
  278.         /* copy wrap around */
  279.         if (i < nodes)
  280.             memcpy(&newLinkS[i],linkS,
  281.                 sizeof(linkS[0U])
  282.                     *(nodes-i));
  283.         /*
  284.             Compute next smaller linkS size
  285.             and threshold for shrinking.
  286.         */
  287.         lowLimit = limit;
  288.         lowThreshold = lowLimit - delta;
  289.         /* swap new for old */
  290.         delete linkS;
  291.         linkS = newLinkS;
  292.         limit = newLimit;
  293.         first = 0U;
  294.     }
  295.     if (!Dattach(D))
  296.         return (void *)0;
  297.     if (!n)  /* push */
  298.         linkS[first? --first
  299.             : (first = limit - 1)] = D;
  300.     else if (n >= nodes) /* insQ */
  301.         linkS[(first+(n=nodes))%limit] = D;
  302.     else  { /* insert interior */
  303.         i = (first + n) % limit;
  304.         if (i < first || !first)
  305.             /* move rear rightward */
  306.             memmove(&linkS[i+1],&linkS[i],
  307.                 sizeof(linkS[0U])
  308.                 * (nodes-n));
  309.         else  { /* move front leftward */
  310.             memmove(&linkS[first-1],
  311.                 &linkS[first],
  312.                 sizeof(linkS[0U])
  313.                 *(n));
  314.             first--;
  315.             i--;
  316.         }
  317.         linkS[i] = D;
  318.     }
  319.     nodes++;
  320.     if (n <= curNode)
  321.         curNode++;
  322.     flags &= ~CL_SORTED;
  323.     return D;
  324. }
  325.  
  326. void * cl::atInsNew(unsigned n, const void * D)
  327. {
  328.     void * cD;
  329.  
  330.     if (D && flags & CL_DNEW)
  331.         if ((cD = Dnew(D)) != (void *)0)
  332.             if (atIns(n,cD))  {
  333.                 flags |= CL_DNEWED;
  334.                 return cD;
  335.             }
  336.             else
  337.                 Ddelete(cD);
  338.     return (void *)0;
  339. }
  340.  
  341. void * cl::atRmv(unsigned n)
  342. {
  343.     void ** newLinkS;
  344.     unsigned newLimit, i;
  345.     void * D;
  346.  
  347.     if (!linkS || n >= nodes)
  348.         return (void *)0;
  349.     D = linkS[i=(first+n)%limit];
  350.     if (!n)  {  /* pop */
  351.         if (++first >= limit)
  352.             first = 0U;
  353.     }
  354.     else if (n != nodes-1)  /* del interior */
  355.         if (i < first) /* move tail leftward */
  356.             memmove(&linkS[i],&linkS[i+1],
  357.                 sizeof(linkS[0U])
  358.                 *(nodes-n-1));
  359.         else {  /* move head rightward */
  360.             memmove(&linkS[first+1],
  361.                 &linkS[first],
  362.                 sizeof(linkS[0U])*n);
  363.             first++;
  364.         }
  365.     if (--nodes == 0U)
  366.         flags |= CL_SORTED;
  367.     if (n < curNode)
  368.         curNode--;
  369.     else if (n == curNode)
  370.         curNode = nodes;
  371.     if (nodes < lowThreshold)  {
  372.         newLimit = lowLimit;
  373.         if ((newLinkS = new void *[newLimit])
  374.             != (void **)0)  {
  375.             if ((i = limit - first)
  376.                 > nodes)
  377.                 i = nodes;
  378.             if (i)
  379.                 memcpy(newLinkS,
  380.                   &linkS[first],
  381.                   sizeof(linkS[0U])*i);
  382.             /* copy wrap around */
  383.             if (i < nodes)
  384.                 memcpy(&newLinkS[i],
  385.                   linkS,
  386.                   sizeof(linkS[0U])
  387.                   *(nodes-i));
  388.         /*
  389.             Compute next smaller linkS
  390.             size and threshold for
  391.             shrinking.
  392.         */
  393.             if (lowLimit - delta > delta)
  394.                 lowLimit -= delta;
  395.             else
  396.                 lowLimit = delta;
  397.             lowThreshold =
  398.                 lowLimit - delta;
  399.             /* swap new for old */
  400.             delete linkS;
  401.             linkS = newLinkS;
  402.             limit = newLimit;
  403.             first = 0U;
  404.         }
  405.     }
  406.     Ddetach(D);
  407.     return D;
  408. }
  409.  
  410. void cl::allRmv()
  411. {
  412.     flags &= ~CL_DNEWED;
  413.     while (atRmv(0U)) /* null stmt */ ;
  414. }
  415.  
  416. int  cl::atDel(unsigned n)
  417. {
  418.     void * D;
  419.  
  420.     if (flags & CL_DDELETE)
  421.         if ((D = atRmv(n)) != (void *)0)  {
  422.             Ddelete(D);
  423.             return 1;
  424.         }
  425.     return 0;
  426. }
  427.  
  428. void * cl::atDelAsg(unsigned n, void * D)
  429. {
  430.     void * S;
  431.  
  432.     if (D && flags & CL_DASSIGN
  433.         && flags & CL_DDELETE)
  434.         if ((S = atGet(n)) != (void *)0)
  435.             if (D != S)  {
  436.               (flags &= ~CL_DREAD)
  437.                 |= CL_DREAD_DEL;
  438.               if (Dassign(D,S)) {
  439.                 (void) atDel(n);
  440.                 return D;
  441.               }
  442.             }
  443.     return (void *)0;
  444. }
  445.  
  446. int cl::allDel()
  447. {
  448.     void * D;
  449.  
  450.     if (flags & CL_DDELETE)  {
  451.         while ((D = atRmv(0U)) != (void *)0)
  452.             Ddelete(D);
  453.         return 1;
  454.     }
  455.     return 0;
  456. }
  457.  
  458. void cl::allClr()
  459. {
  460.     if (flags & CL_DDELETE)
  461.         allDel();
  462.     else
  463.         allRmv();
  464. }
  465.  
  466. void * cl::atPut(unsigned n, void * D)
  467. {
  468.     if (linkS && D && (n < nodes))  {
  469.         void *& N = linkS[(first+n)%limit];
  470.         if (D != N)  if (Dattach(D))  {
  471.             flags &= ~CL_SORTED;
  472.             Ddetach(N);
  473.             if (flags & CL_DDELETE)
  474.                 Ddelete(N);
  475.             return (N=D);
  476.         }
  477.     }
  478.     return (void *)0;
  479. }
  480.  
  481. void * cl::atPutNew(unsigned n, const void * D)
  482. {
  483.     void * oldD, * cD;
  484.  
  485.     if (!D || !(flags & CL_DNEW))
  486.         return (void *)0;
  487.     if ((oldD = atGet(n)) == (void *)0)
  488.         return (void *)0;
  489.     if (oldD == D)
  490.         return (void *)0;
  491.     if ((cD = Dnew(D)) != (void *)0)
  492.         if (atPut(n,cD))  {
  493.             flags |= CL_DNEWED;
  494.             return cD;
  495.         }
  496.         else
  497.             Ddelete(cD);
  498.     return (void *)0;
  499. }
  500.  
  501. void * cl::atPutAsg(unsigned n, const void * D)
  502. {
  503.     void * oldD;
  504.  
  505.     if (D && flags & CL_DASSIGN)
  506.         if ((oldD = atGet(n)) != (void *)0)
  507.             if (D != oldD)  {
  508.                 flags &= ~(CL_DREAD
  509.                   | CL_DREAD_DEL);
  510.                 return Dassign(oldD,D);
  511.             }
  512.     return (void *)0;
  513. }
  514.  
  515. void * cl::atGet(unsigned n)
  516. {
  517.     return ((linkS && (n < nodes))?
  518.         linkS[(first+n)%limit] : (void *)0);
  519. }
  520.  
  521. void * cl::atGetAsg(unsigned n, void * D)
  522. {
  523.     void * N;
  524.  
  525.     if (D && flags & CL_DASSIGN)
  526.         if ((N = atGet(n)) != (void *)0)
  527.             if (D != N)  {
  528.               (flags &= ~CL_DREAD_DEL)
  529.                 |= CL_DREAD;
  530.               return Dassign(D,N);
  531.             }
  532.     return (void *)0;
  533. }
  534.  
  535. void * cl::atXchg(unsigned n, void * D)
  536. {
  537.     if (linkS && D && (n < nodes))
  538.         if (Dattach(D))  {
  539.             flags &= ~CL_SORTED;
  540.             void *& N = linkS[(first+n)
  541.                 %limit];
  542.             void * oldD = N;
  543.             N = D;
  544.             Ddetach(oldD);
  545.             return oldD;
  546.         }
  547.     return (void *)0;
  548. }
  549.  
  550. unsigned cl::index(const void * D)
  551. {
  552.     unsigned i;
  553.  
  554.     if (linkS && D)
  555.         for (i = 0U; i < nodes; i++)
  556.             if (D == linkS[(first+i)
  557.                 %limit])
  558.                 return i;
  559.     return CL_NOTFOUND;
  560. }
  561.  
  562. unsigned cl::CurNode()
  563. {
  564.     return ((curNode < nodes)?
  565.         curNode : CL_NOTFOUND);
  566. }
  567.  
  568. int  cl::setCurNode(unsigned n)
  569. {
  570.     return ((curNode = ((n > nodes)? nodes : n))
  571.         < nodes);
  572. }
  573.  
  574. void * cl::ins(void * D)
  575. {
  576.     if (atIns(curNode+1,D))  {
  577.         if (++curNode >= nodes)
  578.             curNode = nodes - 1;
  579.         return D;
  580.     }
  581.     return (void *)0;
  582. }
  583.  
  584. void * cl::insNew(const void * D)
  585. {
  586.     void * cD;
  587.  
  588.     if (D && flags & CL_DNEW)
  589.         if ((cD = Dnew(D)) != (void *)0)
  590.             if (ins(cD))  {
  591.                 flags |= CL_DNEWED;
  592.                 return cD;
  593.             }
  594.             else
  595.                 Ddelete(cD);
  596.     return (void *)0;
  597. }
  598.  
  599. void * cl::rmv()
  600. {
  601.     void * D;
  602.     unsigned n;
  603.  
  604.     if ((D = atRmv(n=curNode)) != (void *)0)
  605.         if (n)
  606.             curNode = n - 1;
  607.         else
  608.             curNode = 0;
  609.     return D;
  610. }
  611.  
  612. int  cl::del()
  613. {
  614.     void * D;
  615.  
  616.     if (flags & CL_DDELETE)
  617.         if ((D = rmv()) != (void *)0)  {
  618.             Ddelete(D);
  619.             return 1;
  620.         }
  621.     return 0;
  622. }
  623.  
  624. void * cl::delAsg(void * D)
  625. {
  626.     void * S;
  627.  
  628.     if (D && flags & CL_DASSIGN
  629.         && flags & CL_DDELETE)
  630.         if ((S = atGet(curNode)) != (void *)0)
  631.             if (D != S)  {
  632.               (flags &= ~CL_DREAD)
  633.                 |= CL_DREAD_DEL;
  634.               if (Dassign(D,S)) {
  635.                 (void) del();
  636.                 return D;
  637.               }
  638.             }
  639.     return (void *)0;
  640. }
  641.  
  642. void * cl::next()
  643. {
  644.     if (linkS)  {
  645.         if (curNode >= nodes)
  646.             curNode = 0U;
  647.         else
  648.             curNode++;
  649.         if (curNode < nodes)
  650.             return linkS[(first+curNode)
  651.                 %limit];
  652.     }
  653.     return (void *)0;
  654. }
  655.  
  656. void * cl::nextAsg(void * D)
  657. {
  658.     unsigned oldCurNode = curNode;
  659.     void * S;
  660.  
  661.     if (D && flags & CL_DASSIGN)
  662.         if ((S = next()) != (void *)0)  {
  663.             if (D != S)  {
  664.               (flags &= ~CL_DREAD_DEL)
  665.                 |= CL_DREAD;
  666.               if (Dassign(D,S))
  667.                 return D;
  668.             }
  669.             curNode = oldCurNode;
  670.         }
  671.     return (void *)0;
  672. }
  673.  
  674. void * cl::prev()
  675. {
  676.     if (linkS)  {
  677.         if (curNode)  {
  678.             if (curNode > nodes)
  679.                 curNode = nodes;
  680.             curNode--;
  681.         }
  682.         else
  683.             curNode = nodes;
  684.         if (curNode < nodes)
  685.             return linkS[(first+curNode)
  686.                 %limit];
  687.     }
  688.     return (void *)0;
  689. }
  690.  
  691. void * cl::prevAsg(void * D)
  692. {
  693.     unsigned oldCurNode = curNode;
  694.     void * S;
  695.  
  696.     if (D && flags & CL_DASSIGN)
  697.         if ((S = prev()) != (void *)0)  {
  698.             if (D != S)  {
  699.               (flags &= ~CL_DREAD_DEL)
  700.                 |= CL_DREAD;
  701.               if (Dassign(D,S))
  702.                 return D;
  703.             }
  704.             curNode = oldCurNode;
  705.         }
  706.     return (void *)0;
  707. }
  708.  
  709. int   cl::sort(voidCmP cmP)
  710. {
  711.     unsigned low, mid, high;
  712.     unsigned d;
  713.     void * D;
  714.  
  715. /*
  716.     The current node is always reset to undefined
  717.     regardless of the outcome of sort.
  718. */
  719.  
  720.     curNode = nodes;
  721.     if (!this->cmP)
  722.         this->cmP = DcmP(voidCmP0);
  723.     if (flags & CL_SORTED)  {
  724.         if (this->cmP == cmP || !cmP)
  725.             return 1;
  726.     }
  727.     else if (!this->cmP && !cmP)
  728.         return 0;
  729.     if (cmP)  {
  730.         this->cmP = cmP;
  731.         flags &= ~CL_SORTED;
  732.     }
  733.     if (!nodes)
  734.         return (int) (flags |= CL_SORTED);
  735.     if (!linkS)
  736.         return 0;
  737.     if (first)  {
  738.         /* form contiguous block at front */
  739.         d = (first + nodes) % limit;
  740.         if (d > first)
  741.             memmove(linkS,&linkS[first],
  742.                 sizeof(linkS[0U])*nodes);
  743.         else if (d < first)
  744.             memmove(&linkS[d],
  745.                 &linkS[first],
  746.                 sizeof(linkS[0U])
  747.                 *(limit-first));
  748.         /* else array is full/contiguous */
  749.         first = 0U;
  750.     }
  751.     for (high = d = 1; d < nodes; high = ++d)  {
  752.         low = 0U;
  753.         D = linkS[d];
  754.         while (low < high)  {
  755.             mid = low +
  756.                 ((high - low) >> 1);
  757.             if ((*this->cmP)(D,
  758.                 linkS[mid]) <= 0)
  759.                 high = mid;
  760.             else
  761.                 low = mid + 1;
  762.         }
  763.         if (high < d)  {
  764.             memmove(&linkS[high+1],
  765.                 &linkS[high],
  766.                 sizeof(linkS[0U])
  767.                 *(d-high));
  768.             linkS[high] = D;
  769.         }
  770.     }
  771.     return (int) (flags |= CL_SORTED);
  772. }
  773.  
  774. void * cl::insSort(void * D)
  775. {
  776.     unsigned low, mid, high;
  777.     void * ok;
  778.  
  779. /*
  780.     The current node is left undefined if
  781.     anything fails, otherwise it is set to the
  782.     newly inserted node.
  783. */
  784.  
  785.     curNode = nodes;
  786.     if (!cmP) if ((cmP = DcmP(voidCmP0))
  787.         == voidCmP0) return (void *)0;
  788.     if (!linkS || !D || nodes >= maxNodes)
  789.         return (void *)0;
  790.     if (!(flags & CL_SORTED))
  791.         if (!sort())
  792.             return (void *)0;
  793.     low = 0U;
  794.     high = nodes;
  795.     while (low < high)  {
  796.         mid = low + ((high - low) >> 1);
  797.         if ((*cmP)(D,
  798.             linkS[(first+mid)%limit]) <= 0)
  799.             high = mid;
  800.         else
  801.             low = mid + 1;
  802.     }
  803.     if ((ok = atIns(high,D)) != (void *)0)
  804.         curNode = high;
  805.     /*  atIns() resets sorted to zero  */
  806.     flags |= CL_SORTED;
  807.     return ok;
  808. }
  809.  
  810. void * cl::insSortNew(const void * D)
  811. {
  812.     void * cD;
  813.  
  814.     if (D && flags & CL_DNEW)
  815.         if ((cD = Dnew(D)) != (void *)0)
  816.             if (insSort(cD))  {
  817.                 flags |= CL_DNEWED;
  818.                 return cD;
  819.             }
  820.             else
  821.                 Ddelete(cD);
  822.     return (void *)0;
  823. }
  824.  
  825. void * cl::insUnique(void * D)
  826. {
  827.     if (!findFirst(D))
  828.         return insSort(D);
  829.     return (void *)0;
  830. }
  831.  
  832. void * cl::insUniqueNew(const void * D)
  833. {
  834.     if (!findFirst(D))
  835.         return insSortNew(D);
  836.     return (void *)0;
  837. }
  838.  
  839. void * cl::findFirst(const void * K)
  840. {
  841.     unsigned low, mid, high;
  842.     void * D;
  843.  
  844. /*
  845.     The current node is left undefined if
  846.     anything fails, otherwise it is set to the
  847.     newly found node.
  848. */
  849.  
  850.     curNode = nodes;
  851.     if (!cmP) if ((cmP = DcmP(voidCmP0))
  852.         == voidCmP0) return (void *) 0;
  853.     if (!linkS || !K || !nodes)
  854.         return (void *)0;
  855.     if (flags & CL_SORTED)  {
  856.         low = 0U;
  857.         high = nodes;
  858.         while (low < high)  {
  859.             mid = low +
  860.                 ((high - low) >> 1);
  861.             if ((*cmP)(K,linkS[(first+mid)
  862.                 %limit]) <= 0)
  863.                 high = mid;
  864.             else
  865.                 low = mid + 1;
  866.         }
  867.         if (high < nodes)
  868.             if (!(*cmP)(K,D=linkS[(first+
  869.                 high)%limit]))  {
  870.                 curNode = high;
  871.                 return D;
  872.             }
  873.     }
  874.     else  {  /*  linear search!  */
  875.         while ((D = next()) != (void *)0)
  876.             if (!(*cmP)(K,D))
  877.                 return D;
  878.     }
  879.     return (void *)0;
  880. }
  881.  
  882. void * cl::findNext(const void * K)
  883. {
  884.  
  885. /*
  886.     For sorted cls you must first call
  887.     findFirst() to insure consistent results!
  888. */
  889.  
  890.     void * D;
  891.  
  892. /*
  893.     The current node is left undefined if
  894.     anything fails, otherwise it is set to the
  895.     newly found node.
  896. */
  897.  
  898.     if (!cmP)
  899.         cmP = DcmP(voidCmP0);
  900.     if (!linkS || !K || !cmP)  {
  901.         curNode = nodes;
  902.         return (void *)0;
  903.     }
  904.     while ((D = next()) != (void *)0)
  905.         if (!(*cmP)(K,D))
  906.             return D;
  907.         else if (flags & CL_SORTED)  {
  908.             curNode = nodes;
  909.             break; /*  Look no further!  */
  910.         }
  911.     return (void *)0;
  912. }
  913.  
  914. void * cl::findLast(const void * K)
  915. {
  916.     unsigned low, mid, high;
  917.     void * D;
  918.  
  919. /*
  920.     The current node is left undefined if
  921.     anything fails, otherwise it is set to the
  922.     newly found node.
  923. */
  924.  
  925.     curNode = nodes;
  926.     if (!cmP) if ((cmP = DcmP(voidCmP0))
  927.         == voidCmP0) return (void *)0;
  928.     if (!linkS || !K || !nodes)
  929.         return (void *)0;
  930.     if (flags & CL_SORTED)  {
  931.         low = 0U;
  932.         high = nodes;
  933.         while (low < high)  {
  934.             mid = low +
  935.                 ((high - low) >> 1);
  936.             if ((*cmP)(K,linkS[(first+mid)
  937.                 %limit]) < 0)
  938.                 high = mid;
  939.             else
  940.                 low = mid + 1;
  941.         }
  942.         if (high < nodes)
  943.             if (!(*cmP)(K,D=linkS[(first+
  944.                 high)%limit]))  {
  945.                 curNode = high;
  946.                 return D;
  947.             }
  948.     }
  949.     else  {  /*  linear search!  */
  950.         while ((D = prev()) != (void *)0)
  951.             if (!(*cmP)(K,D))
  952.                 return D;
  953.     }
  954.     return (void *)0;
  955. }
  956.  
  957. void * cl::findPrev(const void * K)
  958. {
  959.  
  960. /*
  961.     For sorted cls you must first call
  962.     findLast() to insure consistent results!
  963. */
  964.  
  965.     void * D;
  966.  
  967. /*
  968.     The current node is left undefined if
  969.     anything fails, otherwise it is set to the
  970.     newly found node.
  971. */
  972.  
  973.     if (!cmP)
  974.         cmP = DcmP(voidCmP0);
  975.     if (!linkS || !K || !cmP)  {
  976.         curNode = nodes;
  977.         return (void *)0;
  978.     }
  979.     while ((D = prev()) != (void *)0)
  980.         if (!(*cmP)(K,D))
  981.             return D;
  982.         else if (flags & CL_SORTED)  {
  983.             curNode = nodes;
  984.             break; /*  Look no further!  */
  985.         }
  986.     return (void *)0;
  987. }
  988.  
  989. unsigned cl::findAll(const void * K)
  990. {
  991.     unsigned count = 0U;
  992.  
  993.     /*  The current node is left undefined.  */
  994.  
  995.     if (findFirst(K))
  996.         do {
  997.             count++;
  998.         } while (findNext(K));
  999.     return count;
  1000. }
  1001.  
  1002.  
  1003.  
  1004. struct GenericFnCRecord  {
  1005.     GenericFnC fnC;
  1006.     unsigned id;
  1007.     GenericFnCRecord(GenericFnC fnC, unsigned id)
  1008.         { this->fnC = fnC; this->id = id; }
  1009.     ~GenericFnCRecord()  {}
  1010. };
  1011.  
  1012. typedef struct GenericFnCRecord * GenericFnCR;
  1013. #define GenericFnCR0  ((GenericFnCR)0)
  1014.  
  1015. int FunctionRegistry::regFnC(GenericFnC fnC,
  1016.     unsigned id)
  1017. {
  1018.     unsigned i;
  1019.  
  1020.     if (!fnC && !id)  // NULL's id is 0
  1021.         return 1;
  1022.     if ((!fnC && id) || (fnC && !id))
  1023.         return 0;
  1024.     for (i = 0U; i < Nodes(); i++)
  1025.         if (((GenericFnCR)atGet(i))->id
  1026.             == id)
  1027.             break;
  1028.     if (i < Nodes())
  1029.             return 0;
  1030.     GenericFnCR R = new GenericFnCRecord(fnC,id);
  1031.     if (!R)
  1032.         return 0;
  1033.     else if (!insQ((void *)R))  {
  1034.         delete R;
  1035.         return 0;
  1036.     }
  1037.     return 1;
  1038. }
  1039.  
  1040. unsigned FunctionRegistry::fnC_2_ID(GenericFnC fnC)
  1041. {
  1042.     GenericFnCR R;
  1043.     unsigned i;
  1044.  
  1045.     if (!fnC)
  1046.         return 0U;
  1047.     for (i = 0U; (R = (GenericFnCR) atGet(i))
  1048.         != GenericFnCR0; i++)
  1049.         if (R->fnC == fnC)
  1050.             return R->id;
  1051.     return 0U;
  1052. }
  1053.  
  1054. GenericFnC FunctionRegistry::ID_2_fnC(unsigned id)
  1055. {
  1056.     GenericFnCR R;
  1057.     unsigned i;
  1058.  
  1059.     if (!id)
  1060.         return GenericFnC0;
  1061.     for (i = 0U; (R = (GenericFnCR) atGet(i))
  1062.         != GenericFnCR0; i++)
  1063.         if (R->id == id)
  1064.             return R->fnC;
  1065.     return GenericFnC0;
  1066. }
  1067.  
  1068. FunctionRegistry fnCv;
  1069.