home *** CD-ROM | disk | FTP | other *** search
/ Shareware Supreme Volume 6 #1 / swsii.zip / swsii / 215 / DDJ9210.ZIP / PLUGS.ASC < prev    next >
Text File  |  1992-08-26  |  14KB  |  496 lines

  1. _OBJECT-ORIENTED PROGRAM CONSTRUCTION_
  2. by William Wong
  3.  
  4. [LISTING ONE]
  5.  
  6. //***** PLUGS.H -- by William G. Wong, Copyright (c) June 1992 *****
  7.  
  8. #if !defined(_PLUGS_H_)
  9. #define _PLUGS_H_
  10.  
  11. // ----  Plug Class Definition Macros  ----
  12. // DECLARE_CONNECTION(abstractPlug1,base1,abstractPlug2,base2)
  13. // DECLARE_PLUG(plug,abstractPlug)
  14. // DECLARE_REDIRECTOR(redirector,abstractPlug)
  15. //
  16. // ----  Plug Class Implementation Macros  ----
  17. // IMPLEMENT_PLUG(plug)
  18. //   void plug::afterConnect     () {}
  19. //   void plug::beforeDisconnect () {}
  20. // IMPLEMENT_SIMPLE_PLUG(plug)
  21. // IMPLEMENT_REDIRECTOR(redirector)
  22. //
  23. // ----  plugCheck alternate definition  ----
  24. // Define a check macro if you want to check for invalid access using ->.
  25.  
  26. #if !defined(plugCheck)
  27. #define plugCheck(ptr)
  28. #endif
  29.  
  30. // ----  Simple plug macro definitions  ----
  31. #define IMPLEMENT_SIMPLE_PLUG(c1,p1)\
  32. IMPLEMENT_PLUG(c1,p1)\
  33. void c1::afterConnect () {}\
  34. void c1::beforeDisconnect () {}
  35.  
  36. #if !defined(NULL)
  37. #define NULL ((void *)0)
  38. #endif
  39. #if !defined(FALSE)
  40. #define FALSE 0
  41. #endif
  42. #if !defined(TRUE)
  43. #define TRUE 1
  44. #endif
  45.  
  46. #define DECLARE_CONNECTION(p1,b1,p2,b2)\
  47. class p1##HiddenRedirector;\
  48. class p2##HiddenRedirector;\
  49. class p2;\
  50. DECLARE_ABSTRACT_PLUG(p1,b1,p1##HiddenRedirector,p2)\
  51. DECLARE_ABSTRACT_PLUG(p2,b2,p2##HiddenRedirector,p1)\
  52. DECLARE_ABSTRACT_REDIRECTOR(p1##HiddenRedirector,p1)\
  53. DECLARE_ABSTRACT_REDIRECTOR(p2##HiddenRedirector,p2)
  54.  
  55. #define DECLARE_ABSTRACT_PLUG(p1,b1,r1,p2)\
  56. typedef r1 rd##p1 ;\
  57. typedef p2 px##p1 ;\
  58. class p1 : public b1\
  59. {\
  60.  friend class r1;\
  61.  friend class p2;\
  62.  public:\
  63.   virtual ~p1                   () {-- * this;}\
  64.   virtual int  isRedirector     () = 0 ;\
  65.   virtual int  connected        () = 0 ;\
  66.   virtual int  usable           () = 0 ;\
  67.   virtual void operator <=      (px##p1 & newEnd) = 0 ;\
  68.   virtual px##p1 * operator ->  () = 0 ;\
  69.   virtual px##p1 * operator -   () = 0 ;\
  70.   virtual void operator --      () = 0 ;\
  71.   virtual void afterConnect     () = 0 ;\
  72.   virtual void beforeDisconnect () = 0 ;\
  73.   virtual void addBefore        ( px##p1 * inner, p1 * newEnd ) = 0 ;\
  74.   virtual void addAfter         ( px##p1 * inner, p1 * newEnd ) = 0 ;\
  75.   virtual rd##p1 * getRedirector() = 0 ;\
  76.   virtual void setRedirector    ( rd##p1 * newRedirector ) = 0 ;\
  77.   virtual p1 * connectedto      ( px##p1 * newEnd ) = 0 ;\
  78.   virtual void disconnectedFree () = 0 ;\
  79.   virtual void disconnected     () = 0 ;\
  80. };
  81.  
  82. #define DECLARE_ABSTRACT_REDIRECTOR(r1,p1)\
  83. class r1 : public p1\
  84. {\
  85.  public:\
  86.   virtual p1 * operator = ( p1 * newPlug ) = 0 ;\
  87.   virtual void resetRedirection () = 0 ;\
  88. };
  89.  
  90. #define DECLARE_PLUG(c1,p1)\
  91. class c1 : public p1\
  92. {\
  93.  public:\
  94.        c1                   () {myPlug=NULL;myRedirector=NULL;}\
  95.   virtual ~c1                   () {-- (* this);}\
  96.   virtual int  isRedirector     () {return TRUE;}\
  97.   virtual int  connected        () ;\
  98.   virtual int  usable           () ;\
  99.   virtual void operator <=      (px##p1 & newEnd) ;\
  100.   virtual px##p1 * operator ->  () ;\
  101.   virtual px##p1 * operator -   () ;\
  102.   virtual void operator --      () ;\
  103.   virtual void addBefore        ( px##p1 * inner, p1 * newEnd ) ;\
  104.   virtual void addAfter         ( px##p1 * inner, p1 * newEnd ) ;\
  105.   virtual rd##p1 * getRedirector () ;\
  106.   virtual void setRedirector    ( rd##p1 * newRedirector ) ;\
  107.   virtual p1 * connectedto      ( px##p1 * newEnd ) ;\
  108.   virtual void disconnectedFree () ;\
  109.   virtual void disconnected     () ;\
  110.   virtual void afterConnect     () ;\
  111.   virtual void beforeDisconnect () ;\
  112.   rd##p1 * myRedirector ;\
  113.   px##p1 * myPlug ;\
  114. };
  115.  
  116. #define DECLARE_REDIRECTOR(r1,p1)\
  117. class r1 : public p1##HiddenRedirector\
  118. {\
  119.  public:\
  120.   virtual p1 * operator =       ( p1 * newPlug ) ;\
  121.   virtual void resetRedirection () ;\
  122.        r1                   () {myPlug=NULL;myRedirector=NULL;}\
  123.   virtual ~r1                   () {(* this) = NULL;}\
  124.   virtual int  isRedirector     () {return TRUE;}\
  125.   virtual int  connected        () ;\
  126.   virtual int  usable           () ;\
  127.   virtual void operator <=      (px##p1 & newEnd) ;\
  128.   virtual px##p1 * operator ->  () ;\
  129.   virtual px##p1 * operator -   () ;\
  130.   virtual void operator --      () ;\
  131.   virtual void addBefore        ( px##p1 * inner, p1 * newEnd ) ;\
  132.   virtual void addAfter         ( px##p1 * inner, p1 * newEnd ) ;\
  133.   virtual rd##p1 * getRedirector() ;\
  134.   virtual void setRedirector    ( rd##p1 * newRedirector ) ;\
  135.   virtual p1 * connectedto      ( px##p1 * newEnd ) ;\
  136.   virtual void disconnectedFree () ;\
  137.   virtual void disconnected     () ;\
  138.   virtual void afterConnect     () ;\
  139.   virtual void beforeDisconnect () ;\
  140.   rd##p1 * myRedirector ;\
  141.   p1     * myPlug ;\
  142. };
  143.  
  144. // ----  Implementation definitions  ----
  145. #define IMPLEMENT_PLUG(c1,p1)\
  146. int  c1::connected   () {return myPlug != NULL;}\
  147. int  c1::usable      () {return TRUE;}\
  148. void c1::operator <= (px##p1 & newEnd)\
  149. {\
  150.   if (myPlug != NULL)\
  151.     myPlug -> disconnectedFree () ;\
  152.   if ((& newEnd) != NULL)\
  153.   {\
  154.     myPlug = newEnd.connectedto ( this ) ;\
  155.     if (myPlug)\
  156.     {\
  157.       (*myPlug).afterConnect();\
  158.       (*this).afterConnect() ;\
  159.     }\
  160.   }\
  161. }\
  162. px##p1 * c1::operator -> () {return myPlug;}\
  163. px##p1 * c1::operator -  ()\
  164. {\
  165.   px##p1 * prior = myPlug ;\
  166.   if ( prior != NULL )\
  167.   {\
  168.     beforeDisconnect();\
  169.     prior -> beforeDisconnect();\
  170.     disconnected () ;\
  171.     prior -> disconnected () ;\
  172.   }\
  173.   return prior ;\
  174. }\
  175. void c1::operator -- ()\
  176. {\
  177.   px##p1 * prior = - (* this) ;\
  178.   if (prior) prior -> disconnectedFree () ;\
  179. }\
  180. void c1::addBefore ( px##p1 * inner, p1 * newEnd )\
  181. {\
  182.   rd##p1 * oldRedirector = myRedirector ;\
  183.   addAfter ( inner, newEnd ) ;\
  184.   if (oldRedirector!=NULL)\
  185.   {\
  186.     oldRedirector -> resetRedirection () ;\
  187.     (* oldRedirector) = newEnd ;\
  188.   }\
  189. }\
  190. void c1::addAfter ( px##p1 * inner, p1 * newEnd )\
  191. {\
  192.   if (myPlug && newEnd)\
  193.     (* newEnd) <= (* (- (* this))) ;\
  194.   (* this) <= (* inner) ;\
  195. }\
  196. rd##p1 * c1::getRedirector () {return myRedirector;}\
  197. void c1::setRedirector ( rd##p1*newRedirector ) {myRedirector=newRedirector;}\
  198. p1 * c1::connectedto ( px##p1 * newEnd )\
  199. {\
  200.   if (myPlug)\
  201.     -- (* myPlug) ;\
  202.   myPlug = newEnd ;\
  203.   return this ;\
  204. }\
  205. void c1::disconnectedFree () {myPlug=NULL;}\
  206. void c1::disconnected     () {myPlug=NULL;}
  207.  
  208. // ----  Define for redirector methods  -----
  209. #define IMPLEMENT_REDIRECTOR(r1,p1)\
  210. p1 * r1::operator = ( p1 * newPlug )\
  211. {\
  212.   p1 * prior = myPlug ;\
  213.   resetRedirection () ;\
  214.   if (newPlug != NULL)\
  215.   {\
  216.     myPlug = newPlug ;\
  217.     newPlug -> setRedirector(this) ;\
  218.   }\
  219.   return prior ;\
  220. }\
  221. void r1::resetRedirection () {myPlug=NULL;}\
  222. int r1::connected ()\
  223.  { return (myPlug == NULL) ? FALSE : myPlug -> connected () ; }\
  224. int  r1::usable ()\
  225.  { return (myPlug == NULL) ? FALSE : myPlug -> usable () ; }\
  226. void r1::operator <= (px##p1 & newEnd)\
  227.  {if (myPlug) (* myPlug) <= newEnd ;}\
  228. px##p1 * r1::operator -> ()\
  229.  {return (myPlug) ? myPlug -> operator -> () : NULL ;}\
  230. px##p1 * r1::operator - ()\
  231.  {return (myPlug) ? - * myPlug : NULL ;}\
  232. void r1::operator -- ()\
  233.  {if (myPlug) -- * myPlug ;}\
  234. void r1::addBefore ( px##p1 * inner, p1 * newEnd )\
  235. {\
  236.   if (myPlug)\
  237.   {\
  238.     myPlug -> setRedirector (NULL) ;\
  239.     (* myPlug).addBefore ( inner, newEnd ) ;\
  240.   }\
  241.   if (newEnd)\
  242.     newEnd -> setRedirector ( this ) ;\
  243.    myPlug = newEnd ;\
  244. }\
  245. void r1::addAfter ( px##p1 * inner, p1 * newEnd )\
  246. {\
  247.   if (myPlug)\
  248.     (* myPlug).addAfter ( inner, newEnd ) ;\
  249. }\
  250. rd##p1 * r1::getRedirector () {return myRedirector;}\
  251. void r1::setRedirector ( rd##p1 * newRedirector )\
  252.  {myRedirector=newRedirector;}\
  253. p1 * r1::connectedto ( px##p1 * newEnd )\
  254.  {return (myPlug) ? (* myPlug).connectedto(newEnd) : NULL ;}\
  255. void r1::disconnectedFree ()\
  256.  {if (myPlug) myPlug -> disconnectedFree();}\
  257. void r1::disconnected     ()\
  258.  {if (myPlug) myPlug -> disconnected();}\
  259. void r1::afterConnect     ()\
  260.  {if (myPlug) myPlug -> afterConnect();}\
  261. void r1::beforeDisconnect ()\
  262.  {if (myPlug) myPlug -> beforeDisconnect();}
  263.  
  264. #endif
  265.  
  266. [LISTING TWO]
  267.  
  268. // *** PLUGS.CPP--Example of Use of Plugs by WIlliam G. Wong Copyright 1992 ***
  269. // ****************************************************************
  270.  
  271. #include "plugs.h"
  272.  
  273. // ====  Class definitions  ====
  274. //
  275. // These definitions are normally found in a header file.
  276. //
  277. // ----  Simple abstract plug that can link to objects link itself  ----
  278.  
  279. class plugXBase        // simple accessible class
  280. {
  281.   public :
  282.     int plugXBaseCommonItem ;
  283. } ;
  284.  
  285. class plugYBase {} ;    // nothing provided here
  286.             // plug used to access plugXBase only
  287.  
  288. // ----  Declare plugs  ----
  289.  
  290. DECLARE_CONNECTION(plugX,plugXBase,plugY,plugYBase)
  291. DECLARE_PLUG(aPlugX,plugX)
  292. DECLARE_PLUG(aPlugY,plugY)
  293. DECLARE_REDIRECTOR(plugXRedirector,plugX)
  294.  
  295.  
  296. // ----  Dynamic allocation example  ----
  297. //
  298. // This pair of plug classes work like plugX except that a single
  299. // plug creates a new object each time a connection is made. The
  300. // plug object is freed when the connection is broken.
  301. //
  302. // Both <= and connectedto must be redefined because a connection
  303. // will come through one or the other depending upon which side the
  304. // multiPlugX object is when the initial connection is initiated.
  305.  
  306. class dynamicPlugX : public aPlugX
  307. {
  308.   public:
  309.     void disconnectedFree () { delete this ; } ;
  310. } ;
  311.  
  312. class multiPlugX : public aPlugX
  313. {
  314.   public:
  315.     void operator <= ( plugY & newEnd )
  316.       { newEnd <= * new dynamicPlugX ; }
  317.     plugX * connectedto ( plugY * newEnd )
  318.       { return (* new dynamicPlugX).connectedto ( newEnd ) ; }
  319. };
  320.  
  321. // ----  sample1 to sample2 connection  ----
  322. class sample1Base
  323. {
  324.   public:
  325.     aPlugX x, y ;
  326. } ;
  327.  
  328. class sample2Base {} ;
  329.  
  330. // ----  Declare plugs  ----
  331.  
  332. DECLARE_CONNECTION(Sample1,sample1Base,Sample2,sample2Base)
  333. DECLARE_PLUG(sample1,Sample1)
  334. DECLARE_PLUG(sample2,Sample2)
  335.  
  336. // ----  A slightly more complex plug base  ----
  337. class myPlugBase
  338. {
  339.   public:
  340.     int i ;
  341.     virtual void read  ( int x ) { i = x ; } ;
  342.     virtual void write ( int x ) { i = x ; } ;
  343.  
  344.     myPlugBase () { i = 1 ; } ;
  345. } ;
  346.  
  347.  
  348. // ----  Declare plugs  ----
  349. DECLARE_CONNECTION(MyPlug1,myPlugBase,MyPlug2,myPlugBase)
  350. DECLARE_PLUG(myPlug1,MyPlug1)
  351. DECLARE_PLUG(myPlug2,MyPlug2)
  352.  
  353.  
  354. // ====  Implementation Definitions  ====
  355.  
  356. IMPLEMENT_PLUG(aPlugX,plugX)
  357. IMPLEMENT_PLUG(aPlugY,plugY)
  358.  
  359. void aPlugX::afterConnect ()
  360. {
  361.   // initial connection code goes here
  362. }
  363.  
  364. void aPlugX::beforeDisconnect ()
  365. {
  366.   // disconnect code goes here
  367. }
  368.  
  369. void aPlugY::afterConnect ()
  370. {
  371.   // initial connection code goes here
  372. }
  373.  
  374. void aPlugY::beforeDisconnect ()
  375. {
  376.   // disconnect code goes here
  377. }
  378.  
  379. IMPLEMENT_REDIRECTOR(plugXRedirector,plugX)
  380.  
  381.  
  382. // ----  Implementation for simple plugs  ----
  383. //
  384. // Generates null afterConnect and beforeDisconnect functions.
  385.  
  386. IMPLEMENT_SIMPLE_PLUG(sample1,Sample1)
  387. IMPLEMENT_SIMPLE_PLUG(sample2,Sample2)
  388.  
  389.  
  390. // ----  Implementat plugs  ----
  391. //
  392. // myPlug1a and myPlug1b redifine methods from the base class.
  393.  
  394. IMPLEMENT_SIMPLE_PLUG(myPlug1,MyPlug1)
  395. IMPLEMENT_SIMPLE_PLUG(myPlug2,MyPlug2)
  396.  
  397. class myPlug1a : public myPlug1
  398. {
  399.   public :
  400.     int i1 ;
  401.     virtual void write  ( int x ) { i1 = x ; } ;
  402. } ;
  403.  
  404.  
  405. class myPlug2a : public myPlug2
  406. {
  407.   public :
  408.     int i2 ;
  409.     virtual void write  ( int x ) { i2 = x ; } ;
  410. } ;
  411.  
  412.  
  413. // ====  Sample program  ====
  414.  
  415. void test ( myPlug1 & pp1 )
  416. {
  417.   aPlugX     x1, x2, x3 ;
  418.   plugX *    ppx ;
  419.   plugXRedirector rx1, rx2 ;
  420.   aPlugY     y1, y2, y3 ;
  421.   sample1    s1 ;
  422.   sample2    s2 ;
  423.   myPlug1a   p1 ;
  424.   myPlug2a   p2 ;
  425.   multiPlugX mpx ;
  426.  
  427.   // ----  General connections  ----
  428.   x1 <= y1 ;            // connect x1 and y1
  429.   y1 <= x2 ;            // disconnect x1
  430.                 // connect    y1 and x2
  431.   s1 <= s2 ;            // connect types must match
  432.  
  433.   // ----  Compound linkages  ----
  434.   s2 -> x <= y1 ;        // linking s1.x to y1
  435.   s2 -> y <= y2 ;        // linking s2.y to y2
  436.  
  437.  
  438.   // ----  Redirector examples  ----
  439.   rx1 = & x1 ;            // setup redirector
  440.   rx1 <= y1 ;            // connect x1 to y1 through r1
  441.   y1 -> plugXBaseCommonItem = 1 ;
  442.                 // access item at other end
  443.   rx1.addBefore ( & y2, & x3 ) ;// rx1 redirects x3, x1 connected to y2
  444.                 //  and x3 is attached to y1
  445.   rx2 = & x3 ;            // setup a different redirector type
  446.   rx2 <= y2 ;            // connects y2 to x3 through r2
  447.   rx2 = NULL ;            // reset redirector
  448.  
  449.   // ----  Multiplug examples  ----
  450.   // This generates two new objects and deletes them when they are
  451.   // no longer of use. Note how pp is used to keep around a reference
  452.   // to (mp<=a) (the one created for a) which is later used to link to c.
  453.  
  454.   mpx <= y1 ;            // y1 connected to new object
  455.   mpx <= y2 ;            // y2 connected to different object
  456.  
  457.   ppx = - y1 ;            // disconnect but keep around object
  458.  
  459.   (* ppx ) <= y3 ;        // link object to y3
  460.  
  461.   -- x2 ;                  // free up the other end of x2
  462.  
  463.   ppx = - y3 ;            // - disconnects and returns pointer
  464.   -- * ppx ;            // -- * frees result
  465.  
  466.  
  467.   // ----  Plugs with different variables or methods  ----
  468.   p1  <= p2 ;
  469.  
  470.   p1 -> read ( p1 -> i ) ;    // using read and i from p2
  471.  
  472.   pp1 <= p2 ;            // connects pp1 to p2
  473.                 // disconnects p1
  474.  
  475.   // ---- Explicit disconnects  ----
  476.   -- s2 ;            // forced disconnect
  477.   -- s1 ;
  478.  
  479.   if (x1.connected())        // determine if connection exists
  480.     -- x1 ;
  481.   // ---- Implicit disconnects for locally defined objects  ----
  482. }
  483. // ------------main()--------
  484. void main ()
  485. {
  486.   myPlug1a p1 ;
  487.  
  488.   test ( p1 ) ;
  489. }
  490. ================================================================
  491.  
  492.  
  493.  
  494.  
  495.  
  496.