home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / CL187A.ZIP / PITEM.CPP < prev    next >
C/C++ Source or Header  |  1994-03-15  |  6KB  |  296 lines

  1. /*
  2.     pitem.cpp -- Container Lite v 1.87a:
  3.         polymorphic items.
  4.  
  5.     (C) Copyright 1994  John Webster Small
  6.     All rights reserved
  7. */
  8.  
  9.  
  10. #include "pitem.h"
  11.  
  12. ostream& Streamable::insert(ostream& os)
  13. {
  14.     if (os << ID() << endm)
  15.         (void) put(os);
  16.     return os;
  17. }
  18.  
  19. StreamablE Streamable::extract(istream& is)
  20. {
  21.     unsigned id;
  22.     if (!(is >> id >> nextm))
  23.         return StreamablE0;
  24.     StreamExtractoR extracT = ID2StreamExtracT(id);
  25.     return (extracT? (*extracT)(is) : StreamablE0);
  26. }
  27.  
  28.  
  29.  
  30. #ifdef MUTUAL_DEBUG
  31. void Mutual::mut_error(const char *msg, unsigned id,
  32.     unsigned refCount, unsigned streamCount,
  33.     long streamPos)
  34. {
  35.     cerr << "mut error: " << msg
  36.         << " - id: " << id << endl
  37.         << " - refCount: " << refCount
  38.         << " - streamCount: " << streamCount
  39.         << " - streamPos: " << streamPos
  40.         << endl;
  41. }
  42. #endif
  43.  
  44. ostream& Mutual::insert(ostream& os)
  45. {
  46.     if (refCount <= streamCount)
  47.         mut_error("more stores attempted "
  48.             "than links",ID(),refCount,
  49.             streamCount,streamPos);
  50.     else  {
  51.         streamCount++;
  52.         if (streamPos)  {  // already stored!
  53.         if (!(os << 0U << endm
  54.             << streamPos << endm))
  55.             mut_error("unable to store "
  56.                 "multiple reference ",
  57.                 ID(),refCount,
  58.                 streamCount,streamPos);
  59.         }
  60.         else { // Never store object at streamPos 0
  61.         if ((streamPos = os.tellp()) == 0L)
  62.             if (!(os << 0U << endm))
  63.                 mut_error("unable to skip "
  64.                 "streamPos 0",ID(),
  65.                 refCount,streamCount,
  66.                 streamPos);
  67.             else
  68.                 streamPos = os.tellp();
  69.         if (!(os << ID() << endm))  {
  70.             streamPos = 0L;
  71.             mut_error("unable to "
  72.                 "insert id",ID(),
  73.                 refCount,streamCount,
  74.                 streamPos);
  75.         }
  76.         else  {
  77.             if (!(os << refCount << endm)){
  78.                 streamPos = 0L;
  79.                 mut_error("unable to store"
  80.                 " refCount",ID(),
  81.                 refCount,streamCount,
  82.                 streamPos);
  83.             }
  84.             else if (!put(os))
  85.                 streamPos = 0L;
  86.         }
  87.         }
  88.     }
  89.     return os << flush;
  90. }
  91.  
  92. MutuaL Mutual::extract(istream& is)
  93. {
  94.     unsigned id = 0U;
  95.     unsigned refCount = 0U;
  96.     long streamPos = 0L;
  97.     MutuaL thiS = MutuaL0;
  98.  
  99.     if ((streamPos = is.tellg()) == 0L)
  100.         if (!(is >> id >> nextm))  {
  101.             mut_error("unable to skip "
  102.                 "streamPos 0",id,
  103.                 refCount,0,streamPos);
  104.             return MutuaL0;
  105.         }
  106.         else
  107.             streamPos = is.tellg();
  108.     if (!(is >> id >> nextm))  {
  109.         mut_error("unable to read id",id,
  110.             refCount,0,streamPos);
  111.         return MutuaL0;
  112.     }
  113.     if (id == 0U)  {
  114.         // link to previously loaded Instance
  115.         if (!(is >> streamPos >> nextm))  {
  116.             mut_error("unable to read "
  117.                 "streamPos",id,
  118.                 refCount,0,streamPos);
  119.             return MutuaL0;
  120.         }
  121.         if ((thiS = MutualLink(streamPos))
  122.             == MutuaL0)
  123.             mut_error("unable to "
  124.                 "establish link to "
  125.                 "previously loaded "
  126.                 "instance",id,refCount,
  127.                 0,streamPos);
  128.     }
  129.     else  {  // load instance
  130.         if (!(is >> refCount >> nextm))  {
  131.             mut_error("unable to read "
  132.                 "refCount",id,0,
  133.                 0,streamPos);
  134.             return MutuaL0;
  135.         }
  136.         MutualStreamExtractoR extracT 
  137.             = ID2MutualStreamExtracT(id);
  138.         thiS = (extracT? (*extracT)(is)
  139.             : MutuaL0);
  140.         if (!thiS)
  141.             mut_error("unable to extract "
  142.                 "instance from stream",
  143.                 id,refCount,0,streamPos);
  144.         else if (refCount > 1)  {
  145.             // 1st of many
  146.             // - save in holding pen
  147.             MutualHold(thiS,refCount,
  148.                 streamPos);
  149.         }
  150.     }
  151.     return thiS;
  152. }
  153.  
  154. unsigned Mutual::restream()
  155. {
  156.     unsigned underFlow = (streamPos?
  157.         refCount - streamCount : 0U);
  158.  
  159.     streamCount = 0U;
  160.     streamPos = 0L;
  161. #ifdef MUTUAL_DEBUG
  162.     if (underFlow)
  163.         mut_error("streamed less "
  164.             "than referenced",
  165.             ID(),refCount,
  166.             streamCount,streamPos);
  167. #endif
  168.     return underFlow;
  169. }
  170.  
  171. void Mutual::unlink(const void *P)
  172. {
  173.     if (refCount)  {
  174.         --refCount;
  175.         Streamable::unlink(P);
  176.     }
  177.     else
  178.         mut_error("excessive unlinking",
  179.             ID(),refCount,streamCount,
  180.             streamPos);
  181. }
  182.  
  183. int Mutual::link(const void *P)
  184. {
  185.     if (refCount >= UINT_MAX)  {
  186.         mut_error("excessive linking",
  187.             ID(),refCount,streamCount,
  188.             streamPos);
  189.         return 0;
  190.     }
  191.     refCount++;
  192.     Streamable::link(P);
  193.     return 1;
  194. }
  195.  
  196.  
  197. ClassRegistry clasSv;
  198.  
  199.  
  200. MutualHoldingPen instancEv;
  201.  
  202. struct MutualInstancERecord  {
  203.     MutuaL instancE;
  204.     unsigned refCount, streamCount;
  205.     long streamPos;
  206.     MutualInstancERecord(MutuaL instancE,
  207.         unsigned refCount, long streamPos)
  208.     {
  209.         this->instancE = instancE;
  210.         this->refCount = refCount;
  211.         streamCount = 1;
  212.         this->streamPos = streamPos;
  213.     }
  214.     ~MutualInstancERecord()  {}
  215. };
  216.  
  217. typedef struct MutualInstancERecord * MIRecorD;
  218. #define MIRecorD0  ((MIRecorD)0)
  219.  
  220. #ifdef MUTUAL_DEBUG
  221. void MutualHoldingPen::mhp_error(const char *msg,
  222.         unsigned id, unsigned refCount,
  223.         long streamPos)
  224. {
  225.     cerr << "mut holdpen error: " << msg
  226.         << " - id: " << id << endl
  227.         << " - refCount: " << refCount
  228.         << " - streamPos: " << streamPos
  229.         << endl;
  230. }
  231. #endif
  232.  
  233. MutuaL MutualHoldingPen::link(long streamPos)
  234. {
  235.     MutuaL instancE = MutuaL0;
  236.     MIRecorD R;
  237.  
  238.     for (unsigned i = 0U; i < Nodes(); i++)
  239.         if ((R = (MIRecorD)atGet(i))
  240.             ->streamPos == streamPos)  {
  241.             // found saved instance!
  242.             instancE = R->instancE;
  243.             if (R->refCount
  244.                 <= ++R->streamCount)
  245.                 // discard when done!
  246.                 atDel(i);
  247.             break;
  248.             }
  249. #ifdef MUTUAL_DEBUG
  250.     if (!instancE)
  251.         mhp_error("unable to establish link "
  252.             "to previously loaded "
  253.             "Mutual instance",
  254.             0,0,streamPos);
  255. #endif
  256.     return instancE;
  257. }
  258.  
  259.  
  260. void MutualHoldingPen::hold(MutuaL instancE,
  261.     unsigned refCount, long streamPos)
  262. {
  263.     MIRecorD R;
  264.     CL_try_new
  265.       R = new MutualInstancERecord
  266.         (instancE,refCount,streamPos);
  267.     CL_catch_xalloc(R)
  268.  
  269.     if (!insQ((void *)R))  {
  270.         mhp_error("unable to hold Mutual "
  271.             "instance for multiple "
  272.             "referencing",instancE->ID(),
  273.             instancE->RefCount(),
  274.             instancE->StreamPos());
  275.         if (R)
  276.             delete R;
  277.     }
  278. }
  279.  
  280. unsigned MutualHoldingPen::restream()
  281. {
  282.     unsigned underFlow = Nodes();
  283.  
  284.     for (unsigned i = 0U; i < underFlow; i++)  {
  285.         mhp_error("holding pen under-linked",
  286.             ((MIRecorD)atGet(i))
  287.                 ->instancE->ID(),
  288.             ((MIRecorD)atGet(i))
  289.                 ->refCount,
  290.             ((MIRecorD)atGet(i))
  291.                 ->streamPos);
  292.     }
  293.     allDel();
  294.     return underFlow;
  295. }
  296.