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 >
Text File  |  1996-07-29  |  13KB  |  425 lines

  1. /*------------------------------------------------------------------------
  2.  * $Source: /rcs/crcs/general/unknown.hh,v $
  3.  * $Date: 1996/07/26 02:44:28 $                 $Revision: 1.17 $
  4.  *
  5.  * Copyright 1993, Visual Edge Software Ltd.
  6.  * -----------------------------------------
  7.  *
  8.  * ALL  RIGHTS  RESERVED.  Permission  to  use,  copy,  modify,  and
  9.  * distribute  this  software  and its documentation for any purpose
  10.  * and  without  fee  is  hereby  granted,  provided  that the above
  11.  * copyright  notice  appear  in  all  copies  and  that  both  that
  12.  * copyright  notice and this permission notice appear in supporting
  13.  * documentation,  and that  the name of Visual Edge Software not be
  14.  * used  in advertising  or publicity  pertaining to distribution of
  15.  * the software without specific, written prior permission. The year
  16.  * included in the notice is the year of the creation of the work.
  17.  *------------------------------------------------------------------------
  18.  * Framework for identified, queriable abstract interface classes.
  19.  *
  20.  * VeUnknown  base of all identified interfaces.
  21.  * VePrimary  base of object class that support identified interfaces.
  22.  * VeMixin    base for mixins (abstract pluggable API's)
  23.  * VeDelegateMixin  base for implementing mixins as subobjects.
  24.  *------------------------------------------------------------------------*/
  25.  
  26. #ifndef V_UNKNOWN_CLASS
  27. #define V_UNKNOWN_CLASS
  28.  
  29. #include <assert.h>
  30. #include <visedge.hh>
  31. #include <dllclass.hh>
  32. #include <vuuid.h>
  33. #include <vatom.h>
  34.  
  35. #ifdef _MSC_VER
  36. // Disable anoying warning about using 'this' as constructor argument
  37. #pragma warning(disable:4355)
  38. #endif
  39.  
  40. /*----------------------------------------------------------------
  41.  *
  42.  * The following macros are used to support the C++ object integration.
  43.  * They are used to specify the number of virtuals declared for a class
  44.  * and the first index of a class in the virtual table. 
  45.  *
  46.  * VDECL_VIRTUALS_COUNT(n, cls, base)
  47.  *    Given a class (cls), defines a function that returns the number (n) 
  48.  *    of virtual methods and a second function that returns the index of 
  49.  *    the first virtual method in the class virtual table. The base argument
  50.  *    is required to get the superclass count of virtual methods.
  51.  *
  52.  * VDECL_VIRTUALS_INIT_COUNT(n, cls)
  53.  *    Same as the above macro without the base class argument. Typically 
  54.  *    used to initialize cls as an upmost superclass.
  55.  *
  56.  * VSET_VIRTUALS_FIRST_INDEX(var, cls)
  57.  *    Set A variable (var) with the index of the first virtual method in 
  58.  *    the class (cls) virtual table. 
  59.  *
  60.  ****************************** IMPORTANT ****************************
  61.  *    Each time a virtual method is added or removed from a class, 
  62.  *    the number of virtuals has to be changed for this class. 
  63.  *********************************************************************
  64.  *
  65.  *-------------------------------------------------------------------*/
  66.  
  67. #define VDECL_VIRTUALS_INIT_COUNT(n, cls)    \
  68. VFUNCDEF(int) VDecl##cls##VCount()            \
  69. {                        \
  70.     return n;                \
  71. }                        \
  72. VFUNCDEF(int) VGet##cls##FirstIndex()            \
  73. {                        \
  74.     return 0;                \
  75. }
  76. #define VDECL_VIRTUALS_COUNT(n, cls, base)    \
  77. VFUNCDEF(int) VDecl##cls##VCount()            \
  78. {                        \
  79.     extern VDecl##base##VCount();        \
  80.     return n + VDecl##base##VCount();    \
  81. }                        \
  82. VFUNCDEF(int) VGet##cls##FirstIndex()            \
  83. {                        \
  84.     extern VDecl##base##VCount();        \
  85.     return VDecl##base##VCount();        \
  86. }
  87. #define VSET_VIRTUALS_FIRST_INDEX(var, cls)    \
  88. {                        \
  89.     extern int VGet##cls##FirstIndex();    \
  90.     var = VGet##cls##FirstIndex();        \
  91. }
  92.  
  93.  
  94. /*-------------------------------------------------------------------
  95.  * Each abstract mixin class is identified with unique key.
  96.  * The registration authority for these keys is the text file
  97.  *    keys/MixIDs.txt
  98.  * in the common rcs tree.
  99.  *
  100.  * The constant for a class named 'VSomeMix' must be declared in
  101.  * the header where that class is declared.  It takes the name
  102.  *     'kVSomeMixID'
  103.  *-------------------------------------------------------------------*/
  104.  
  105. typedef VTUniqueID VTMixinID;
  106.  
  107. #define VMixID    VTMixinID
  108.  
  109. VCLASS VeMixin;
  110. VCLASS VePrimary;
  111. VCLASS VobMixinFactory;
  112.  
  113. /*------------------------------------------------------------------------
  114.  * VeUnknown is the base class that connects a primary base class
  115.  * with the mixin abstract classes.  
  116.  *
  117.  * Things should inherit from VeUnknown in one of these ways:
  118.  *    An independent instantiable class should derive from VePrimary
  119.  *    An abstract interface class (a Mixin) should derive from VeMixin
  120.  *------------------------------------------------------------------------*/
  121.  
  122. class VeUnknown : public VeDllBasedClass
  123. {
  124.     public:
  125.     virtual VOPERDECL ~VeUnknown();
  126.  
  127.     /*--------------------------------------------------------
  128.      * Support for mixins; this is used from
  129.      * mixins to get back to the original controlling object.
  130.      *------------------------------------------------------*/
  131.  
  132.     VVIRTUALDECL(VePrimary*) DoTheObject() = 0;
  133.  
  134.     VePrimary *TheObject()
  135.     {
  136.         return DoTheObject();
  137.     }
  138. };
  139.  
  140. /*------------------------------------------------------------------------
  141.  * VePrimary support structures
  142.  * These cannot be declared inside VePrimary due to bugs in the xlC compiler.
  143.  *------------------------------------------------------------------------*/
  144.  
  145. struct VTMixinItem
  146. {
  147.     VTAtomP        itsMixinID;
  148.     VeAtomRef    itsItemName;
  149.     bool_t        itsDeleteFlag;
  150.     VeMixin        *itsMixin;
  151. };
  152.  
  153. struct VTMixinBlock
  154. {
  155.     int        itsLength;
  156.     int        itsAllocated;
  157.     VobMixinFactory    *itsFactory;
  158.     VTMixinItem    itsElements[1];
  159. };
  160.  
  161.  
  162. /*------------------------------------------------------------------------
  163.  * VDECLARE_BUILDMIX Macro
  164.  *
  165.  * The macro is used in header files to declare that BuildMix is being
  166.  * redefined in the class.
  167.  *------------------------------------------------------------------------*/
  168.  
  169. #define VDECLARE_BUILDMIX                        \
  170.     VVIRTUALDECL(VeMixin *) BuildMix(                \
  171.                     VMixID        whichOne,    \
  172.                     VeAtomRef    itemName,    \
  173.                     VobMixinFactory    *useFactory,    \
  174.                     bool_t        &deleteIt);    \
  175.  
  176.  
  177. /*------------------------------------------------------------------------
  178.  * Class VePrimary
  179.  *
  180.  * The base class for objects.  
  181.  * Each instantiable object class that uses mixins derives from VePrimary.
  182.  *------------------------------------------------------------------------*/
  183.  
  184. class VePrimary : public VeUnknown
  185. {
  186.     public:
  187.  
  188.     VePrimary()
  189.     {
  190.         itsMixins = 0;
  191.     }
  192.  
  193.     virtual VOPERDECL    ~VePrimary();
  194.  
  195.     VVIRTUALDECL(VePrimary*)        DoTheObject();
  196.  
  197.     VePrimary *TheObject()
  198.     {
  199.         return this;
  200.     }
  201.  
  202.     /*-----------------------------------------------------
  203.      * When using a mixed-in interface on an object,
  204.      * always extract the mixin pointer using GetMix and
  205.      * operate on that, rather than using the object itself
  206.      * or casting it.  This allows flexibility to the object
  207.      * implementor, who can later decide to implement
  208.      * mixins as sub-objects and delegate to them.
  209.      *-----------------------------------------------------*/
  210.  
  211.     VVIRTUALDECL(VeMixin *)    GetMix(        VMixID        whichOne,
  212.                         VeAtomRef    itemName);
  213.     VMETHODDECL(VeMixin *)    GetLatestMix(    VMixID        whichOne,
  214.                         VeAtomRef    itemName);
  215.  
  216.     VeMixin *GetLatestMix(VMixID whichOne)
  217.     {
  218.         return GetLatestMix(whichOne, VeAtomRef());
  219.     }
  220.  
  221.     VeMixin *GetMix(VMixID whichOne)
  222.     {
  223.         return GetMix(whichOne, VeAtomRef());
  224.     }
  225.  
  226.     VeMixin *GetMix(    VeAtomRef    whichOne,
  227.                 VeAtomRef    itemName)
  228.     {
  229.         VUUIDFROMATOM(localUUID, whichOne);
  230.         return GetMix(localUUID, itemName);
  231.     }
  232.  
  233.     VeMixin *GetMix(VeAtomRef whichOne)
  234.     {
  235.         VUUIDFROMATOM(localUUID, whichOne);
  236.         return GetMix(localUUID, VeAtomRef());
  237.     }
  238.  
  239.     VVIRTUALDECL(VobMixinFactory *)    MixinFactory();
  240.  
  241.     VDECLARE_BUILDMIX
  242.  
  243.     VMETHODDECL(void)        AddMix(
  244.                         VMixID        whichOne,
  245.                         VeAtomRef    itemName,
  246.                         bool_t        deleteIt,
  247.                         VeMixin        *newMixin);
  248.  
  249.     VMETHODDECL(void)        RemoveMix(
  250.                         VeMixin        *oldMixin);
  251.  
  252.     VMETHODDECL(void)        RemoveMix(
  253.                         VMixID        whichOne,
  254.                         VeAtomRef    itemName);
  255.  
  256.     private:
  257.  
  258.     void        RemoveMix(int index);
  259.  
  260.     VTMixinBlock    *itsMixins;
  261. };
  262.  
  263. /*------------------------------------------------------------------------
  264.  * VMI_UNKNOWN Macro
  265.  *
  266.  * The macro is used in classes which multiply inherit off of
  267.  * VeUnknown.  The argument to the macro is the primary inheritance
  268.  * path base class.
  269.  *------------------------------------------------------------------------*/
  270.  
  271. #define VMI_UNKNOWN(base)                        \
  272.     VMI_ALLOCATION(base)                        \
  273.                                     \
  274.     VePrimary *TheObject()                        \
  275.     {                                \
  276.         return (base *)this;                    \
  277.     }                                \
  278.                                     \
  279.     VINLINEDECL(VePrimary*)    DoTheObject()                \
  280.     {                                \
  281.         return (base *)this;                    \
  282.     }
  283.  
  284. /*------------------------------------------------------------------------
  285.  * VDECLARE_GETMIX Macro
  286.  *
  287.  * The macro is used in header files to declare that GetMix is being
  288.  * redefined in the class.
  289.  *------------------------------------------------------------------------*/
  290.  
  291. #define VDECLARE_GETMIX                            \
  292.     VVIRTUALDECL(VeMixin *)    GetMix(    VMixID        whichOne,    \
  293.                     VeAtomRef    itemName);    \
  294.                                     \
  295.     VeMixin *GetMix(VMixID whichOne)                \
  296.     {                                \
  297.         return GetMix(whichOne, VeAtomRef());            \
  298.     }                                \
  299.                                     \
  300.     VeMixin *GetMix(    VeAtomRef    whichOne,        \
  301.                 VeAtomRef    itemName)        \
  302.     {                                \
  303.         VUUIDFROMATOM(localUUID, whichOne);            \
  304.         return GetMix(localUUID, itemName);            \
  305.     }                                \
  306.                                     \
  307.     VeMixin *GetMix(VeAtomRef whichOne)                \
  308.     {                                \
  309.         VUUIDFROMATOM(localUUID, whichOne);            \
  310.         return GetMix(localUUID, VeAtomRef());            \
  311.     }
  312.  
  313.  
  314. /*------------------------------------------------------------------------
  315.  * Class Mixin
  316.  * 
  317.  * Mixin the base of all abstract mixin classes we define.
  318.  * It causes mixins to share the same VeUnknown protocol for
  319.  * querying for other attached mixins.  The implementation
  320.  * of Unknown ensures that mixins attached as extra base classes
  321.  * will have access (through TheObject()->GetMix) to the same mixin
  322.  * set as the primary object.
  323.  *
  324.  * Mixins can be instantiated as secondary base classes attached
  325.  * to something first derived from either VePrimary or as standalone
  326.  * entities which are attached to the primary though the mixin factory
  327.  * or through the explicit use of VePrimary::AddMix.  Note that if
  328.  * a Mixin is going to be inherited (instead of dynamically added)
  329.  * PutTheObject must be called on the mixin to set its primary.
  330.  *------------------------------------------------------------------------*/
  331.  
  332. class VeMixin : public VeUnknown 
  333. {
  334.     public:
  335.  
  336.     VeMixin()
  337.     {
  338.         itsPrimary = 0;
  339.     }
  340.  
  341.     VVIRTUALDECL(VePrimary*)    DoTheObject();
  342.  
  343.     VePrimary *TheObject()
  344.     {
  345.         if(itsPrimary)
  346.             return itsPrimary;
  347.         else
  348.             return itsPrimary = DoTheObject();
  349.     }
  350.  
  351.     //=====================================================================
  352.     // PutTheObject is only to be called by creators of VMixins.
  353.     // Never arbitrarily call this method.
  354.     //---------------------------------------------------------------------
  355.  
  356.     void PutTheObject(VePrimary *pPrimary)
  357.     {
  358.         if(!itsPrimary)
  359.         {
  360.             // Only set itsPrimary if it has not been
  361.             // set before -- mixins can't move
  362.  
  363.             itsPrimary = pPrimary;
  364.         }
  365.     }
  366.  
  367.     private:
  368.  
  369.     VePrimary     *itsPrimary;
  370. };
  371.  
  372. /*------------------------------------------------------------------
  373.  * VeDelegateMixin is used to automatically set the "itsPrimary"
  374.  * of a VeMixin.  Typical usage is to multiply inherit off
  375.  * both the VeMixin subclass and off VeDelegateMixin.
  376.  * The VeDelegateMixin constructor then forces the class to
  377.  * properly set the mixin's itsPrimary.
  378.  *------------------------------------------------------------------*/
  379.  
  380. class VeDelegateMixin
  381. {
  382.     protected:
  383.  
  384.     VeDelegateMixin(    VePrimary*    pPrimary,
  385.             VeMixin*        theMixin)
  386.     {
  387.         theMixin->PutTheObject(pPrimary);
  388.     }
  389. };
  390.  
  391. /*------------------------------------------------------------------------
  392.  * Writing GetMix Implementations
  393.  * ------------------------------
  394.  * Each abstract interface is identified by a VMixID constant.
  395.  * When GetMix receives such a constant, it must return one of:
  396.  *
  397.  *    (TheAbstractClassName *) aSuitableImplementationPointer;
  398.  * or 
  399.  *    0;
  400.  *
  401.  * Do -not- use any cast other than to the exact abstract base class,
  402.  * and -always- make that cast explicit.
  403.  *
  404.  * Using GetMix
  405.  * ------------
  406.  * Each call to GetMix takes the form
  407.  *
  408.  *    (TheExactAbstractClassName *) 
  409.  *        pSomething->GetMix(kTheAbstractClassNameID);
  410.  *
  411.  * The result -must- be cast to the abstract class type denoted by the ID,
  412.  * not to any presumed base class or derived class.
  413.  * GetMix is called with an additonal argument, the class name, when
  414.  * the primary object has access to an association table (such as
  415.  * the MixinFactory) where mixin id and class name are associated 
  416.  * with a particular mixin.
  417.  *
  418.  *    (TheExactAbstractClassName *) 
  419.  *        pSomething->GetMix(kTheAbstractClassNameID, "classname");
  420.  *
  421.  *------------------------------------------------------------------------*/
  422.  
  423. #endif     // V_UNKNOWN_CLASS
  424.  
  425.