home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1996 November
/
VPR9611B.ISO
/
vabasic
/
ntclnt.exe
/
DISK8
/
data.8
/
datab
/
INCLUDE
/
UNKNOWN.HH
< prev
next >
Wrap
Text File
|
1996-07-29
|
13KB
|
425 lines
/*------------------------------------------------------------------------
* $Source: /rcs/crcs/general/unknown.hh,v $
* $Date: 1996/07/26 02:44:28 $ $Revision: 1.17 $
*
* Copyright 1993, Visual Edge Software Ltd.
* -----------------------------------------
*
* ALL RIGHTS RESERVED. Permission to use, copy, modify, and
* distribute this software and its documentation for any purpose
* and without fee is hereby granted, provided that the above
* copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Visual Edge Software not be
* used in advertising or publicity pertaining to distribution of
* the software without specific, written prior permission. The year
* included in the notice is the year of the creation of the work.
*------------------------------------------------------------------------
* Framework for identified, queriable abstract interface classes.
*
* VeUnknown base of all identified interfaces.
* VePrimary base of object class that support identified interfaces.
* VeMixin base for mixins (abstract pluggable API's)
* VeDelegateMixin base for implementing mixins as subobjects.
*------------------------------------------------------------------------*/
#ifndef V_UNKNOWN_CLASS
#define V_UNKNOWN_CLASS
#include <assert.h>
#include <visedge.hh>
#include <dllclass.hh>
#include <vuuid.h>
#include <vatom.h>
#ifdef _MSC_VER
// Disable anoying warning about using 'this' as constructor argument
#pragma warning(disable:4355)
#endif
/*----------------------------------------------------------------
*
* The following macros are used to support the C++ object integration.
* They are used to specify the number of virtuals declared for a class
* and the first index of a class in the virtual table.
*
* VDECL_VIRTUALS_COUNT(n, cls, base)
* Given a class (cls), defines a function that returns the number (n)
* of virtual methods and a second function that returns the index of
* the first virtual method in the class virtual table. The base argument
* is required to get the superclass count of virtual methods.
*
* VDECL_VIRTUALS_INIT_COUNT(n, cls)
* Same as the above macro without the base class argument. Typically
* used to initialize cls as an upmost superclass.
*
* VSET_VIRTUALS_FIRST_INDEX(var, cls)
* Set A variable (var) with the index of the first virtual method in
* the class (cls) virtual table.
*
****************************** IMPORTANT ****************************
* Each time a virtual method is added or removed from a class,
* the number of virtuals has to be changed for this class.
*********************************************************************
*
*-------------------------------------------------------------------*/
#define VDECL_VIRTUALS_INIT_COUNT(n, cls) \
VFUNCDEF(int) VDecl##cls##VCount() \
{ \
return n; \
} \
VFUNCDEF(int) VGet##cls##FirstIndex() \
{ \
return 0; \
}
#define VDECL_VIRTUALS_COUNT(n, cls, base) \
VFUNCDEF(int) VDecl##cls##VCount() \
{ \
extern VDecl##base##VCount(); \
return n + VDecl##base##VCount(); \
} \
VFUNCDEF(int) VGet##cls##FirstIndex() \
{ \
extern VDecl##base##VCount(); \
return VDecl##base##VCount(); \
}
#define VSET_VIRTUALS_FIRST_INDEX(var, cls) \
{ \
extern int VGet##cls##FirstIndex(); \
var = VGet##cls##FirstIndex(); \
}
/*-------------------------------------------------------------------
* Each abstract mixin class is identified with unique key.
* The registration authority for these keys is the text file
* keys/MixIDs.txt
* in the common rcs tree.
*
* The constant for a class named 'VSomeMix' must be declared in
* the header where that class is declared. It takes the name
* 'kVSomeMixID'
*-------------------------------------------------------------------*/
typedef VTUniqueID VTMixinID;
#define VMixID VTMixinID
VCLASS VeMixin;
VCLASS VePrimary;
VCLASS VobMixinFactory;
/*------------------------------------------------------------------------
* VeUnknown is the base class that connects a primary base class
* with the mixin abstract classes.
*
* Things should inherit from VeUnknown in one of these ways:
* An independent instantiable class should derive from VePrimary
* An abstract interface class (a Mixin) should derive from VeMixin
*------------------------------------------------------------------------*/
class VeUnknown : public VeDllBasedClass
{
public:
virtual VOPERDECL ~VeUnknown();
/*--------------------------------------------------------
* Support for mixins; this is used from
* mixins to get back to the original controlling object.
*------------------------------------------------------*/
VVIRTUALDECL(VePrimary*) DoTheObject() = 0;
VePrimary *TheObject()
{
return DoTheObject();
}
};
/*------------------------------------------------------------------------
* VePrimary support structures
* These cannot be declared inside VePrimary due to bugs in the xlC compiler.
*------------------------------------------------------------------------*/
struct VTMixinItem
{
VTAtomP itsMixinID;
VeAtomRef itsItemName;
bool_t itsDeleteFlag;
VeMixin *itsMixin;
};
struct VTMixinBlock
{
int itsLength;
int itsAllocated;
VobMixinFactory *itsFactory;
VTMixinItem itsElements[1];
};
/*------------------------------------------------------------------------
* VDECLARE_BUILDMIX Macro
*
* The macro is used in header files to declare that BuildMix is being
* redefined in the class.
*------------------------------------------------------------------------*/
#define VDECLARE_BUILDMIX \
VVIRTUALDECL(VeMixin *) BuildMix( \
VMixID whichOne, \
VeAtomRef itemName, \
VobMixinFactory *useFactory, \
bool_t &deleteIt); \
/*------------------------------------------------------------------------
* Class VePrimary
*
* The base class for objects.
* Each instantiable object class that uses mixins derives from VePrimary.
*------------------------------------------------------------------------*/
class VePrimary : public VeUnknown
{
public:
VePrimary()
{
itsMixins = 0;
}
virtual VOPERDECL ~VePrimary();
VVIRTUALDECL(VePrimary*) DoTheObject();
VePrimary *TheObject()
{
return this;
}
/*-----------------------------------------------------
* When using a mixed-in interface on an object,
* always extract the mixin pointer using GetMix and
* operate on that, rather than using the object itself
* or casting it. This allows flexibility to the object
* implementor, who can later decide to implement
* mixins as sub-objects and delegate to them.
*-----------------------------------------------------*/
VVIRTUALDECL(VeMixin *) GetMix( VMixID whichOne,
VeAtomRef itemName);
VMETHODDECL(VeMixin *) GetLatestMix( VMixID whichOne,
VeAtomRef itemName);
VeMixin *GetLatestMix(VMixID whichOne)
{
return GetLatestMix(whichOne, VeAtomRef());
}
VeMixin *GetMix(VMixID whichOne)
{
return GetMix(whichOne, VeAtomRef());
}
VeMixin *GetMix( VeAtomRef whichOne,
VeAtomRef itemName)
{
VUUIDFROMATOM(localUUID, whichOne);
return GetMix(localUUID, itemName);
}
VeMixin *GetMix(VeAtomRef whichOne)
{
VUUIDFROMATOM(localUUID, whichOne);
return GetMix(localUUID, VeAtomRef());
}
VVIRTUALDECL(VobMixinFactory *) MixinFactory();
VDECLARE_BUILDMIX
VMETHODDECL(void) AddMix(
VMixID whichOne,
VeAtomRef itemName,
bool_t deleteIt,
VeMixin *newMixin);
VMETHODDECL(void) RemoveMix(
VeMixin *oldMixin);
VMETHODDECL(void) RemoveMix(
VMixID whichOne,
VeAtomRef itemName);
private:
void RemoveMix(int index);
VTMixinBlock *itsMixins;
};
/*------------------------------------------------------------------------
* VMI_UNKNOWN Macro
*
* The macro is used in classes which multiply inherit off of
* VeUnknown. The argument to the macro is the primary inheritance
* path base class.
*------------------------------------------------------------------------*/
#define VMI_UNKNOWN(base) \
VMI_ALLOCATION(base) \
\
VePrimary *TheObject() \
{ \
return (base *)this; \
} \
\
VINLINEDECL(VePrimary*) DoTheObject() \
{ \
return (base *)this; \
}
/*------------------------------------------------------------------------
* VDECLARE_GETMIX Macro
*
* The macro is used in header files to declare that GetMix is being
* redefined in the class.
*------------------------------------------------------------------------*/
#define VDECLARE_GETMIX \
VVIRTUALDECL(VeMixin *) GetMix( VMixID whichOne, \
VeAtomRef itemName); \
\
VeMixin *GetMix(VMixID whichOne) \
{ \
return GetMix(whichOne, VeAtomRef()); \
} \
\
VeMixin *GetMix( VeAtomRef whichOne, \
VeAtomRef itemName) \
{ \
VUUIDFROMATOM(localUUID, whichOne); \
return GetMix(localUUID, itemName); \
} \
\
VeMixin *GetMix(VeAtomRef whichOne) \
{ \
VUUIDFROMATOM(localUUID, whichOne); \
return GetMix(localUUID, VeAtomRef()); \
}
/*------------------------------------------------------------------------
* Class Mixin
*
* Mixin the base of all abstract mixin classes we define.
* It causes mixins to share the same VeUnknown protocol for
* querying for other attached mixins. The implementation
* of Unknown ensures that mixins attached as extra base classes
* will have access (through TheObject()->GetMix) to the same mixin
* set as the primary object.
*
* Mixins can be instantiated as secondary base classes attached
* to something first derived from either VePrimary or as standalone
* entities which are attached to the primary though the mixin factory
* or through the explicit use of VePrimary::AddMix. Note that if
* a Mixin is going to be inherited (instead of dynamically added)
* PutTheObject must be called on the mixin to set its primary.
*------------------------------------------------------------------------*/
class VeMixin : public VeUnknown
{
public:
VeMixin()
{
itsPrimary = 0;
}
VVIRTUALDECL(VePrimary*) DoTheObject();
VePrimary *TheObject()
{
if(itsPrimary)
return itsPrimary;
else
return itsPrimary = DoTheObject();
}
//=====================================================================
// PutTheObject is only to be called by creators of VMixins.
// Never arbitrarily call this method.
//---------------------------------------------------------------------
void PutTheObject(VePrimary *pPrimary)
{
if(!itsPrimary)
{
// Only set itsPrimary if it has not been
// set before -- mixins can't move
itsPrimary = pPrimary;
}
}
private:
VePrimary *itsPrimary;
};
/*------------------------------------------------------------------
* VeDelegateMixin is used to automatically set the "itsPrimary"
* of a VeMixin. Typical usage is to multiply inherit off
* both the VeMixin subclass and off VeDelegateMixin.
* The VeDelegateMixin constructor then forces the class to
* properly set the mixin's itsPrimary.
*------------------------------------------------------------------*/
class VeDelegateMixin
{
protected:
VeDelegateMixin( VePrimary* pPrimary,
VeMixin* theMixin)
{
theMixin->PutTheObject(pPrimary);
}
};
/*------------------------------------------------------------------------
* Writing GetMix Implementations
* ------------------------------
* Each abstract interface is identified by a VMixID constant.
* When GetMix receives such a constant, it must return one of:
*
* (TheAbstractClassName *) aSuitableImplementationPointer;
* or
* 0;
*
* Do -not- use any cast other than to the exact abstract base class,
* and -always- make that cast explicit.
*
* Using GetMix
* ------------
* Each call to GetMix takes the form
*
* (TheExactAbstractClassName *)
* pSomething->GetMix(kTheAbstractClassNameID);
*
* The result -must- be cast to the abstract class type denoted by the ID,
* not to any presumed base class or derived class.
* GetMix is called with an additonal argument, the class name, when
* the primary object has access to an association table (such as
* the MixinFactory) where mixin id and class name are associated
* with a particular mixin.
*
* (TheExactAbstractClassName *)
* pSomething->GetMix(kTheAbstractClassNameID, "classname");
*
*------------------------------------------------------------------------*/
#endif // V_UNKNOWN_CLASS