Category : Files from Magazines
Archive   : DDJ9210.ZIP
Filename : PLUGS.ASC

 
Output of file : PLUGS.ASC contained in archive : DDJ9210.ZIP
_OBJECT-ORIENTED PROGRAM CONSTRUCTION_
by William Wong

[LISTING ONE]

//***** PLUGS.H -- by William G. Wong, Copyright (c) June 1992 *****

#if !defined(_PLUGS_H_)
#define _PLUGS_H_

// ---- Plug Class Definition Macros ----
// DECLARE_CONNECTION(abstractPlug1,base1,abstractPlug2,base2)
// DECLARE_PLUG(plug,abstractPlug)
// DECLARE_REDIRECTOR(redirector,abstractPlug)
//
// ---- Plug Class Implementation Macros ----
// IMPLEMENT_PLUG(plug)
// void plug::afterConnect () {}
// void plug::beforeDisconnect () {}
// IMPLEMENT_SIMPLE_PLUG(plug)
// IMPLEMENT_REDIRECTOR(redirector)
//
// ---- plugCheck alternate definition ----
// Define a check macro if you want to check for invalid access using ->.

#if !defined(plugCheck)
#define plugCheck(ptr)
#endif

// ---- Simple plug macro definitions ----
#define IMPLEMENT_SIMPLE_PLUG(c1,p1)\
IMPLEMENT_PLUG(c1,p1)\
void c1::afterConnect () {}\
void c1::beforeDisconnect () {}

#if !defined(NULL)
#define NULL ((void *)0)
#endif
#if !defined(FALSE)
#define FALSE 0
#endif
#if !defined(TRUE)
#define TRUE 1
#endif

#define DECLARE_CONNECTION(p1,b1,p2,b2)\
class p1##HiddenRedirector;\
class p2##HiddenRedirector;\
class p2;\
DECLARE_ABSTRACT_PLUG(p1,b1,p1##HiddenRedirector,p2)\
DECLARE_ABSTRACT_PLUG(p2,b2,p2##HiddenRedirector,p1)\
DECLARE_ABSTRACT_REDIRECTOR(p1##HiddenRedirector,p1)\
DECLARE_ABSTRACT_REDIRECTOR(p2##HiddenRedirector,p2)

#define DECLARE_ABSTRACT_PLUG(p1,b1,r1,p2)\
typedef r1 rd##p1 ;\
typedef p2 px##p1 ;\
class p1 : public b1\
{\
friend class r1;\
friend class p2;\
public:\
virtual ~p1 () {-- * this;}\
virtual int isRedirector () = 0 ;\
virtual int connected () = 0 ;\
virtual int usable () = 0 ;\
virtual void operator <= (px##p1 & newEnd) = 0 ;\
virtual px##p1 * operator -> () = 0 ;\
virtual px##p1 * operator - () = 0 ;\
virtual void operator -- () = 0 ;\
virtual void afterConnect () = 0 ;\
virtual void beforeDisconnect () = 0 ;\
virtual void addBefore ( px##p1 * inner, p1 * newEnd ) = 0 ;\
virtual void addAfter ( px##p1 * inner, p1 * newEnd ) = 0 ;\
virtual rd##p1 * getRedirector() = 0 ;\
virtual void setRedirector ( rd##p1 * newRedirector ) = 0 ;\
virtual p1 * connectedto ( px##p1 * newEnd ) = 0 ;\
virtual void disconnectedFree () = 0 ;\
virtual void disconnected () = 0 ;\
};

#define DECLARE_ABSTRACT_REDIRECTOR(r1,p1)\
class r1 : public p1\
{\
public:\
virtual p1 * operator = ( p1 * newPlug ) = 0 ;\
virtual void resetRedirection () = 0 ;\
};

#define DECLARE_PLUG(c1,p1)\
class c1 : public p1\
{\
public:\
c1 () {myPlug=NULL;myRedirector=NULL;}\
virtual ~c1 () {-- (* this);}\
virtual int isRedirector () {return TRUE;}\
virtual int connected () ;\
virtual int usable () ;\
virtual void operator <= (px##p1 & newEnd) ;\
virtual px##p1 * operator -> () ;\
virtual px##p1 * operator - () ;\
virtual void operator -- () ;\
virtual void addBefore ( px##p1 * inner, p1 * newEnd ) ;\
virtual void addAfter ( px##p1 * inner, p1 * newEnd ) ;\
virtual rd##p1 * getRedirector () ;\
virtual void setRedirector ( rd##p1 * newRedirector ) ;\
virtual p1 * connectedto ( px##p1 * newEnd ) ;\
virtual void disconnectedFree () ;\
virtual void disconnected () ;\
virtual void afterConnect () ;\
virtual void beforeDisconnect () ;\
rd##p1 * myRedirector ;\
px##p1 * myPlug ;\
};

#define DECLARE_REDIRECTOR(r1,p1)\
class r1 : public p1##HiddenRedirector\
{\
public:\
virtual p1 * operator = ( p1 * newPlug ) ;\
virtual void resetRedirection () ;\
r1 () {myPlug=NULL;myRedirector=NULL;}\
virtual ~r1 () {(* this) = NULL;}\
virtual int isRedirector () {return TRUE;}\
virtual int connected () ;\
virtual int usable () ;\
virtual void operator <= (px##p1 & newEnd) ;\
virtual px##p1 * operator -> () ;\
virtual px##p1 * operator - () ;\
virtual void operator -- () ;\
virtual void addBefore ( px##p1 * inner, p1 * newEnd ) ;\
virtual void addAfter ( px##p1 * inner, p1 * newEnd ) ;\
virtual rd##p1 * getRedirector() ;\
virtual void setRedirector ( rd##p1 * newRedirector ) ;\
virtual p1 * connectedto ( px##p1 * newEnd ) ;\
virtual void disconnectedFree () ;\
virtual void disconnected () ;\
virtual void afterConnect () ;\
virtual void beforeDisconnect () ;\
rd##p1 * myRedirector ;\
p1 * myPlug ;\
};

// ---- Implementation definitions ----
#define IMPLEMENT_PLUG(c1,p1)\
int c1::connected () {return myPlug != NULL;}\
int c1::usable () {return TRUE;}\
void c1::operator <= (px##p1 & newEnd)\
{\
if (myPlug != NULL)\
myPlug -> disconnectedFree () ;\
if ((& newEnd) != NULL)\
{\
myPlug = newEnd.connectedto ( this ) ;\
if (myPlug)\
{\
(*myPlug).afterConnect();\
(*this).afterConnect() ;\
}\
}\
}\
px##p1 * c1::operator -> () {return myPlug;}\
px##p1 * c1::operator - ()\
{\
px##p1 * prior = myPlug ;\
if ( prior != NULL )\
{\
beforeDisconnect();\
prior -> beforeDisconnect();\
disconnected () ;\
prior -> disconnected () ;\
}\
return prior ;\
}\
void c1::operator -- ()\
{\
px##p1 * prior = - (* this) ;\
if (prior) prior -> disconnectedFree () ;\
}\
void c1::addBefore ( px##p1 * inner, p1 * newEnd )\
{\
rd##p1 * oldRedirector = myRedirector ;\
addAfter ( inner, newEnd ) ;\
if (oldRedirector!=NULL)\
{\
oldRedirector -> resetRedirection () ;\
(* oldRedirector) = newEnd ;\
}\
}\
void c1::addAfter ( px##p1 * inner, p1 * newEnd )\
{\
if (myPlug && newEnd)\
(* newEnd) <= (* (- (* this))) ;\
(* this) <= (* inner) ;\
}\
rd##p1 * c1::getRedirector () {return myRedirector;}\
void c1::setRedirector ( rd##p1*newRedirector ) {myRedirector=newRedirector;}\
p1 * c1::connectedto ( px##p1 * newEnd )\
{\
if (myPlug)\
-- (* myPlug) ;\
myPlug = newEnd ;\
return this ;\
}\
void c1::disconnectedFree () {myPlug=NULL;}\
void c1::disconnected () {myPlug=NULL;}

// ---- Define for redirector methods -----
#define IMPLEMENT_REDIRECTOR(r1,p1)\
p1 * r1::operator = ( p1 * newPlug )\
{\
p1 * prior = myPlug ;\
resetRedirection () ;\
if (newPlug != NULL)\
{\
myPlug = newPlug ;\
newPlug -> setRedirector(this) ;\
}\
return prior ;\
}\
void r1::resetRedirection () {myPlug=NULL;}\
int r1::connected ()\
{ return (myPlug == NULL) ? FALSE : myPlug -> connected () ; }\
int r1::usable ()\
{ return (myPlug == NULL) ? FALSE : myPlug -> usable () ; }\
void r1::operator <= (px##p1 & newEnd)\
{if (myPlug) (* myPlug) <= newEnd ;}\
px##p1 * r1::operator -> ()\
{return (myPlug) ? myPlug -> operator -> () : NULL ;}\
px##p1 * r1::operator - ()\
{return (myPlug) ? - * myPlug : NULL ;}\
void r1::operator -- ()\
{if (myPlug) -- * myPlug ;}\
void r1::addBefore ( px##p1 * inner, p1 * newEnd )\
{\
if (myPlug)\
{\
myPlug -> setRedirector (NULL) ;\
(* myPlug).addBefore ( inner, newEnd ) ;\
}\
if (newEnd)\
newEnd -> setRedirector ( this ) ;\
myPlug = newEnd ;\
}\
void r1::addAfter ( px##p1 * inner, p1 * newEnd )\
{\
if (myPlug)\
(* myPlug).addAfter ( inner, newEnd ) ;\
}\
rd##p1 * r1::getRedirector () {return myRedirector;}\
void r1::setRedirector ( rd##p1 * newRedirector )\
{myRedirector=newRedirector;}\
p1 * r1::connectedto ( px##p1 * newEnd )\
{return (myPlug) ? (* myPlug).connectedto(newEnd) : NULL ;}\
void r1::disconnectedFree ()\
{if (myPlug) myPlug -> disconnectedFree();}\
void r1::disconnected ()\
{if (myPlug) myPlug -> disconnected();}\
void r1::afterConnect ()\
{if (myPlug) myPlug -> afterConnect();}\
void r1::beforeDisconnect ()\
{if (myPlug) myPlug -> beforeDisconnect();}

#endif

[LISTING TWO]

// *** PLUGS.CPP--Example of Use of Plugs by WIlliam G. Wong Copyright 1992 ***
// ****************************************************************

#include "plugs.h"

// ==== Class definitions ====
//
// These definitions are normally found in a header file.
//
// ---- Simple abstract plug that can link to objects link itself ----

class plugXBase // simple accessible class
{
public :
int plugXBaseCommonItem ;
} ;

class plugYBase {} ; // nothing provided here
// plug used to access plugXBase only

// ---- Declare plugs ----

DECLARE_CONNECTION(plugX,plugXBase,plugY,plugYBase)
DECLARE_PLUG(aPlugX,plugX)
DECLARE_PLUG(aPlugY,plugY)
DECLARE_REDIRECTOR(plugXRedirector,plugX)


// ---- Dynamic allocation example ----
//
// This pair of plug classes work like plugX except that a single
// plug creates a new object each time a connection is made. The
// plug object is freed when the connection is broken.
//
// Both <= and connectedto must be redefined because a connection
// will come through one or the other depending upon which side the
// multiPlugX object is when the initial connection is initiated.

class dynamicPlugX : public aPlugX
{
public:
void disconnectedFree () { delete this ; } ;
} ;

class multiPlugX : public aPlugX
{
public:
void operator <= ( plugY & newEnd )
{ newEnd <= * new dynamicPlugX ; }
plugX * connectedto ( plugY * newEnd )
{ return (* new dynamicPlugX).connectedto ( newEnd ) ; }
};

// ---- sample1 to sample2 connection ----
class sample1Base
{
public:
aPlugX x, y ;
} ;

class sample2Base {} ;

// ---- Declare plugs ----

DECLARE_CONNECTION(Sample1,sample1Base,Sample2,sample2Base)
DECLARE_PLUG(sample1,Sample1)
DECLARE_PLUG(sample2,Sample2)

// ---- A slightly more complex plug base ----
class myPlugBase
{
public:
int i ;
virtual void read ( int x ) { i = x ; } ;
virtual void write ( int x ) { i = x ; } ;

myPlugBase () { i = 1 ; } ;
} ;


// ---- Declare plugs ----
DECLARE_CONNECTION(MyPlug1,myPlugBase,MyPlug2,myPlugBase)
DECLARE_PLUG(myPlug1,MyPlug1)
DECLARE_PLUG(myPlug2,MyPlug2)


// ==== Implementation Definitions ====

IMPLEMENT_PLUG(aPlugX,plugX)
IMPLEMENT_PLUG(aPlugY,plugY)

void aPlugX::afterConnect ()
{
// initial connection code goes here
}

void aPlugX::beforeDisconnect ()
{
// disconnect code goes here
}

void aPlugY::afterConnect ()
{
// initial connection code goes here
}

void aPlugY::beforeDisconnect ()
{
// disconnect code goes here
}

IMPLEMENT_REDIRECTOR(plugXRedirector,plugX)


// ---- Implementation for simple plugs ----
//
// Generates null afterConnect and beforeDisconnect functions.

IMPLEMENT_SIMPLE_PLUG(sample1,Sample1)
IMPLEMENT_SIMPLE_PLUG(sample2,Sample2)


// ---- Implementat plugs ----
//
// myPlug1a and myPlug1b redifine methods from the base class.

IMPLEMENT_SIMPLE_PLUG(myPlug1,MyPlug1)
IMPLEMENT_SIMPLE_PLUG(myPlug2,MyPlug2)

class myPlug1a : public myPlug1
{
public :
int i1 ;
virtual void write ( int x ) { i1 = x ; } ;
} ;


class myPlug2a : public myPlug2
{
public :
int i2 ;
virtual void write ( int x ) { i2 = x ; } ;
} ;


// ==== Sample program ====

void test ( myPlug1 & pp1 )
{
aPlugX x1, x2, x3 ;
plugX * ppx ;
plugXRedirector rx1, rx2 ;
aPlugY y1, y2, y3 ;
sample1 s1 ;
sample2 s2 ;
myPlug1a p1 ;
myPlug2a p2 ;
multiPlugX mpx ;

// ---- General connections ----
x1 <= y1 ; // connect x1 and y1
y1 <= x2 ; // disconnect x1
// connect y1 and x2
s1 <= s2 ; // connect types must match

// ---- Compound linkages ----
s2 -> x <= y1 ; // linking s1.x to y1
s2 -> y <= y2 ; // linking s2.y to y2


// ---- Redirector examples ----
rx1 = & x1 ; // setup redirector
rx1 <= y1 ; // connect x1 to y1 through r1
y1 -> plugXBaseCommonItem = 1 ;
// access item at other end
rx1.addBefore ( & y2, & x3 ) ;// rx1 redirects x3, x1 connected to y2
// and x3 is attached to y1
rx2 = & x3 ; // setup a different redirector type
rx2 <= y2 ; // connects y2 to x3 through r2
rx2 = NULL ; // reset redirector

// ---- Multiplug examples ----
// This generates two new objects and deletes them when they are
// no longer of use. Note how pp is used to keep around a reference
// to (mp<=a) (the one created for a) which is later used to link to c.

mpx <= y1 ; // y1 connected to new object
mpx <= y2 ; // y2 connected to different object

ppx = - y1 ; // disconnect but keep around object

(* ppx ) <= y3 ; // link object to y3

-- x2 ; // free up the other end of x2

ppx = - y3 ; // - disconnects and returns pointer
-- * ppx ; // -- * frees result


// ---- Plugs with different variables or methods ----
p1 <= p2 ;

p1 -> read ( p1 -> i ) ; // using read and i from p2

pp1 <= p2 ; // connects pp1 to p2
// disconnects p1

// ---- Explicit disconnects ----
-- s2 ; // forced disconnect
-- s1 ;

if (x1.connected()) // determine if connection exists
-- x1 ;
// ---- Implicit disconnects for locally defined objects ----
}
// ------------main()--------
void main ()
{
myPlug1a p1 ;

test ( p1 ) ;
}
================================================================







  3 Responses to “Category : Files from Magazines
Archive   : DDJ9210.ZIP
Filename : PLUGS.ASC

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/