home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / alloop.zip / ALLOOP.CPP next >
Text File  |  1994-05-01  |  30KB  |  721 lines

  1. //----------------------------------------------------------------------------//
  2. // (c) 1994 Larry Morley, All Rights Reserved.                                //
  3. // For non-commercial use only without express written permission of author.  //
  4. //----------------------------------------------------------------------------//
  5. //                                                                            //
  6. // My standard disclaimer, terms and conditions apply, and are available      //
  7. // upon request.  By using this information you agree to the aforementioned   //
  8. // terms and conditions.  Basically, they just cover my hide.                 //
  9. //                                                                            //
  10. // I can be reached at CompuServe 73670,563 or by mail at                     //
  11. //                                                                            //
  12. //    6909 Custer #2503                                                       //
  13. //    Plano, TX 75023                                                         //
  14. //                                                                            //
  15. // if you need licensing information for commercial use; or, if you have some //
  16. // feedback or code you've developed and would like to pass along and/or get  //
  17. // a critique on, or if you're having some trouble writing C++ apps.  Don't   //
  18. // hesitate to contact me.  I'll be of as much help as I can.                 //
  19. //                                                                            //
  20. // PLEASE send me your thoughts and comments.  Thanks.                        //
  21. // -Larry                                                                     //
  22. //----------------------------------------------------------------------------//
  23. // It's difficult to enter into a discussion on OOP without someone bringing  //
  24. // up SmallTalk. One of it's supposed selling points besides being OO by      //
  25. // nature over C++ is that EVERYTHING, including numbers, letters, etc. is    //
  26. // represented as an object.  A lot of folks don't realize it, but C++ has    //
  27. // the same capability.  I'm presenting here, for you, a way to program       //
  28. // C++ using almost only objects (one exception is the implementation of      //
  29. // the classes presented here).  The first, bottom most class is called       //
  30. // GenericObject.  It contains a value, a class name, the size of the         //
  31. // object (in aribtrary units - sizeof(char) is used in this implementation), //
  32. // a count of how many times the object's been referenced, and a field        //
  33. // of flags that can be set, cleared and tested.  The reference counters      //
  34. // are useful for several purposes; one is debugging, another is controlling  //
  35. // resource usage.                                                            //
  36. //                                                                            //
  37. // NOTE: The "void *" type of value is intended to be used as a catch-all     //
  38. //       value; i.e., pointers to structs, classes, etc.                      //
  39. //                                                                            //
  40. // The next class is "Integer".  These objects looka and function like "int"s //
  41. // to other functions, in expressions, etc. BUT are actually objects/         //
  42. //                                                                            //
  43. // One thing to note is that while this is a nice, solid object model I'm     //
  44. // incurring a large amount of overhead.  That's the OOP tradeoff sometimes;  //
  45. // the more object oriented and accurate your model, the more you accumulate  //
  46. // extra (extra in that it wouldn't be present using native types and         //
  47. // operators.  But, there's inarguably tremendous benefits in all areas of    //
  48. // the development process for reasonably pure OOP.  And, this implementaion  //
  49. // is as close to pure object oriented programming as you're ever going to    //
  50. // get.                                                                       //
  51. //----------------------------------------------------------------------------//
  52. //                                                                            //
  53. // Summary of GenericObject class methods:                                    //
  54. //                                                                            //
  55. // ***********************                                                    //
  56. // ***Protected Methods***                                                    //
  57. // ***********************                                                    //
  58. //                                                                            //
  59. // Object internal common initialization code:                                //
  60. //                                                                            //
  61. //    void          GlobalObjectInit()                                        //
  62. //                                                                            //
  63. // Bitmask manipulation routines:                                             //
  64. //                                                                            //
  65. // (1)   Turn a bit on; returns new flags.                                    //
  66. //          unsigned long SetBit  (unsigned long lMask)                       //
  67. // (2)   Test bit status (logical AND); returns zero or one                   //
  68. //          unsigned long TestBit (unsigned long lMask)                       //
  69. // (3)   Turn a bit off; returns new flags.                                   //
  70. //          unsigned long ClearBit(unsigned long lMask)                       //
  71. //                                                                            //
  72. // *************************                                                  //
  73. // ***   Public Methods  ***                                                  //
  74. // ***Class Contstructors***                                                  //
  75. // *************************                                                  //
  76. //                                                                            //
  77. // (1) Generic object, no type or size supplied.                              //
  78. //       GenericObject(void         )                                         //
  79. //                                                                            //
  80. // (2) Constructor for object with data type of "char"                        //
  81. //       GenericObject(char         )                                         //
  82. //                                                                            //
  83. // (3) Constructor for object with data type of "unsigned char"               //
  84. //       GenericObject(unsigned char)                                         //
  85. //                                                                            //
  86. // (4) Constructor for object with data type of "int"                         //
  87. //       GenericObject(int          )                                         //
  88. //                                                                            //
  89. // (5) Constructor for object with data type of "unsigned int"                //
  90. //       GenericObject(unsigned int )                                         //
  91. //                                                                            //
  92. // (6) Constructor for object with data type of "long"                        //
  93. //       GenericObject(long         )                                         //
  94. //                                                                            //
  95. // (7) Constructor for object with data type of "unsigned long"               //
  96. //       GenericObject(unsigned long)                                         //
  97. //                                                                            //
  98. // (8) Char pointer, no size given.  Size of object = physical size of        //
  99. //       pointer in SizeBasis units.                                          //
  100. //          GenericObject(char *       )                                      //
  101. //                                                                            //
  102. // (9) Char pointer, size supplied.  Size of object = supplied size.          //
  103. //       GenericObject(char *initialValue, int initialSize)                   //
  104. //                                                                            //
  105. // (10) Void pointer, no size given.  Size of object = physical size of       //
  106. //       pointer in SizeBasis units.                                          //
  107. //          GenericObject(void *       )                                      //
  108. //                                                                            //
  109. // (11) Void pointer, size supplied.  Size of object = supplied size.         //
  110. //       GenericObject(void *initialValue, int initialSize)                   //
  111. //                                                                            //
  112. // ***************************                                                //
  113. // ***Miscellaneous Methods***                                                //
  114. // ***************************                                                //
  115. //                                                                            //
  116. // (1) Return the name of the current class:                                  //
  117. //       char *GetClassName()                                                 //
  118. //                                                                            //
  119. //     Function doesn't need to be virtual as long as each derived            //
  120. //     class defines a protected data member "char *szClassName";             //
  121. //     the derived classes declaration is dominant.                           //
  122. //                                                                            //
  123. // (2) Increment object's reference count:                                    //
  124. //       int   ReferenceObject()                                              //
  125. //                                                                            //
  126. // (3) Decrement object's reference count:                                    //
  127. //       int   DeReferenceObject()                                            //
  128. //                                                                            //
  129. // (4) Get / Set Object Size:                                                 //
  130. //       int  &ObjectSize()                                                   //
  131. //                                                                            //
  132. // (5) Get / Set reference count:                                             //
  133. //       int &ReferenceCount()                                                //
  134. //                                                                            //
  135. // (6) Get / Set maximum reference count:                                     //
  136. //       int &MaxReferenceCount()                                             //
  137. //                                                                            //
  138. // ******************                                                         //
  139. // ***Value Method***                                                         //
  140. // ******************                                                         //
  141. //                                                                            //
  142. // Get Object's value in the form of a GenericDataType type:                  //
  143. //    GenericDataType &ObjectValue()                                          //
  144. //                                                                            //
  145. // **************************                                                 //
  146. // ***Conversion Functions***                                                 //
  147. // **************************                                                 //
  148. //                                                                            //
  149. // Provided here so derived classes don't need to define their own set        //
  150. // of conversions to intrinsic data types.                                    //
  151. //                                                                            //
  152. //   Conversion to "char":                                                    //
  153. //       operator char()                                                      //
  154. //                                                                            //
  155. //   Conversion to "unsigned char":                                           //
  156. //       operator unsigned char()                                             //
  157. //                                                                            //
  158. //   Conversion to "int":                                                     //
  159. //       operator int()                                                       //
  160. //                                                                            //
  161. //   Conversion to "unsigned int":                                            //
  162. //       operator unsigned int()                                              //
  163. //                                                                            //
  164. //   Conversion to "long":                                                    //
  165. //       operator long()                                                      //
  166. //                                                                            //
  167. //   Conversion to "unsigned long":                                           //
  168. //       operator unsigned long()                                             //
  169. //                                                                            //
  170. //   Conversion to "char *":                                                  //
  171. //       operator char *()                                                    //
  172. //                                                                            //
  173. //   Conversion to "void *" (See note above on use of the void * type):       //
  174. //       operator void *()                                                    //
  175. //                                                                            //
  176. //----------------------------------------------------------------------------//
  177. //                                                                            //
  178. //If you want to build the sample main(), remove the comment operator (//)
  179. //from the line below:
  180. #define __BUILD_SAMPLE__
  181.  
  182. //============================================================================//
  183. // Define what units to base object size on (sizeof(char) is used; under OS/2
  184. // it should be equivalent to bytes).
  185. #define SizeBasis (sizeof(char))
  186.  
  187. // Define a generic data type
  188. typedef union
  189. {
  190.    char          cValue;
  191.    unsigned char ucValue;
  192.    int           iValue;
  193.    unsigned int  uiValue;
  194.    long          lValue;
  195.    unsigned long ulValue;
  196.    char        * szValue;
  197.    void        * pvValue;  // Struct, class, etc.
  198. } GenericDataType;
  199.  
  200. //============================================================================//
  201. // Define a generic object class
  202. class GenericObject
  203. {
  204.  
  205.    protected:
  206.  
  207.       // Name of this class (text, set by
  208.       // common initialization routine)
  209.       char *szClassName;
  210.  
  211.  
  212.       // The object's value
  213.       GenericDataType objValue;
  214.  
  215.       //-------------------------------
  216.       // Flags with meanings
  217.       // defined elsewhere
  218.       unsigned long ulFlagBits;
  219.  
  220.       //-------------------------------
  221.       // Define the max number of times
  222.       // object can be referenced
  223.       // (0 -> no limit)
  224.       int iMaxReferenceCount;
  225.  
  226.       //-------------------------------
  227.       // Keep track of how many times
  228.       // the object's in use
  229.       int iReferenceCount;
  230.  
  231.       //-------------------------------
  232.       // Size of the object in
  233.       // "SizeBasis" units.  NOTE: In
  234.       // the cases where a constructor
  235.       // takes a pointer as an argument,
  236.       // without a specified size, the
  237.       // size IS THE SIZE OF THE
  238.       // POINTER, NOT the data it
  239.       // points to.  Beware.
  240.       int iObjectSize;
  241.  
  242.       //-------------------------------
  243.       // Common initialization routine
  244.       //    Do early on in constructor
  245.       //    so iMaxReferenceCount can
  246.       //    be set if desired (and
  247.       //    a constructor to set it
  248.       //    is provided).
  249.       void GlobalObjectInit()
  250.       {
  251.  
  252.          szClassName         = "Base_Generic_Object";
  253.  
  254.          ulFlagBits          = 0UL;
  255.          iReferenceCount     = 0;
  256.          iMaxReferenceCount  = 0;
  257.          iObjectSize         = 0;
  258.  
  259.          objValue.cValue     = (char)0;
  260.          objValue.ucValue    = (unsigned char)0;
  261.          objValue.iValue     = 0;
  262.          objValue.uiValue    = 0;
  263.          objValue.lValue     = 0L;
  264.          objValue.ulValue    = 0UL;
  265.          objValue.szValue    = (char *)0;
  266.          objValue.pvValue    = (void *)0;
  267.  
  268.          return;
  269.       }
  270.  
  271.       //-------------------------------
  272.       // Turn a bit on, off, or test it -
  273.       // keep these members protected to
  274.       // force derived classes to create
  275.       // a meaningful API.
  276.       unsigned long SetBit(unsigned long lMask)
  277.       {
  278.          return (ulFlagBits | lMask);
  279.       }
  280.  
  281.       //-------------------------------
  282.       // Test a bit in the bit flags
  283.       unsigned long TestBit(unsigned long lMask)
  284.       {
  285.          return (ulFlagBits & lMask);
  286.       }
  287.  
  288.       //-------------------------------
  289.       // Clear a bit in the bit flags
  290.       unsigned long ClearBit(unsigned long lMask)
  291.       {
  292.          return (ulFlagBits & (~lMask));
  293.       }
  294.  
  295.    //------------------------------------------------------
  296.  
  297.    public:
  298.  
  299.       //------------------------------------------
  300.       // Constructors:
  301.       // No initial type or value:
  302.       GenericObject()
  303.       {
  304.          // Do common initialization only
  305.          // (nothing else to do)
  306.          GlobalObjectInit();
  307.       }
  308.  
  309.       //------------------------------------------
  310.       // "char" object:
  311.       GenericObject(char         initialValue)
  312.       {
  313.          // Do common initialization
  314.          GlobalObjectInit();
  315.          // Specific initialization
  316.          objValue.cValue = initialValue;
  317.          // Set the object's size
  318.          iObjectSize = sizeof(initialValue) / SizeBasis;
  319.       }
  320.  
  321.       //------------------------------------------
  322.       // "unsigned char" object:
  323.       GenericObject(unsigned char initialValue)
  324.       {
  325.          GlobalObjectInit();
  326.          objValue.ucValue = initialValue;
  327.          iObjectSize = sizeof(initialValue) / SizeBasis;
  328.       }
  329.  
  330.       //------------------------------------------
  331.       // "int" object:
  332.       GenericObject(int initialValue          )
  333.       {
  334.          GlobalObjectInit();
  335.          objValue.iValue = initialValue;
  336.          iObjectSize = sizeof(initialValue) / SizeBasis;
  337.       }
  338.  
  339.       //------------------------------------------
  340.       // "unsigned int" object:
  341.       GenericObject(unsigned int  initialValue)
  342.       {
  343.          GlobalObjectInit();
  344.          objValue.uiValue = initialValue;
  345.          iObjectSize = sizeof(initialValue) / SizeBasis;
  346.       }
  347.  
  348.       //------------------------------------------
  349.       // "long" object:
  350.       GenericObject(long          initialValue)
  351.       {
  352.          GlobalObjectInit();
  353.          objValue.lValue = initialValue;
  354.          iObjectSize = sizeof(initialValue) / SizeBasis;
  355.       }
  356.  
  357.       //------------------------------------------
  358.       // "unsigned long" object:
  359.       GenericObject(unsigned long initialValue)
  360.       {
  361.          GlobalObjectInit();
  362.          objValue.ulValue = initialValue;
  363.          iObjectSize = sizeof(initialValue) / SizeBasis;
  364.       }
  365.  
  366.       //------------------------------------------
  367.       // "char *" object:
  368.       // NOTE: no actual copy of the "char *"
  369.       //       or string is made; the constructor
  370.       //       simply stores the address.
  371.       //       An actual copy can be made using
  372.       //       the value methods.
  373.       GenericObject(char *        initialValue)
  374.       {
  375.          GlobalObjectInit();
  376.          objValue.szValue = initialValue;
  377.          iObjectSize = sizeof(initialValue) / SizeBasis;
  378.       }
  379.  
  380.       //-----------------------------------------
  381.       // "char *" object with size specified:
  382.       GenericObject(char *initialValue, int initialSize)
  383.       {
  384.          GlobalObjectInit();
  385.          objValue.szValue = initialValue;
  386.          // Use supplied size
  387.          iObjectSize = initialSize;
  388.       }
  389.  
  390.       //-----------------------------------------
  391.       // "void *" object:
  392.       GenericObject(void *        initialValue)
  393.       {
  394.          GlobalObjectInit();
  395.          objValue.pvValue = initialValue;
  396.          iObjectSize = sizeof(initialValue) / SizeBasis;
  397.       }
  398.  
  399.       //-----------------------------------------
  400.       // "void *" object with size specified:
  401.       GenericObject(void *initialValue, int initialSize)
  402.       {
  403.          GlobalObjectInit();
  404.          objValue.pvValue = initialValue;
  405.          iObjectSize = initialSize;
  406.       }
  407.  
  408.       //-------------------------------
  409.       // Get the object's class name
  410.       char *GetClassName()
  411.       {
  412.          return szClassName;
  413.       }
  414.  
  415.       //-------------------------------
  416.       // If iMaxReferenceCount is non-zero,
  417.       // Increment reference count, return
  418.       // new count, or -1 if maximum count
  419.       // is exceeded; otherwise, just
  420.       // increment the reference count (no
  421.       // maximum limit).
  422.       int ReferenceObject()
  423.       {
  424.          if (iReferenceCount)
  425.             return (iReferenceCount < (iMaxReferenceCount-1)) ?
  426.                ++iReferenceCount
  427.             :
  428.                -1;
  429.          else
  430.             return ++iReferenceCount;
  431.       }
  432.  
  433.       //-------------------------------
  434.       // Decrement reference count,
  435.       // return new count or zero if
  436.       // no outstanding references
  437.       int DeReferenceObject()
  438.       {
  439.          return iReferenceCount ?
  440.             --iReferenceCount
  441.          :
  442.             0;
  443.       }
  444.  
  445.       //-------------------------------
  446.       // Return the object's size in
  447.       // whatever unit is being used
  448.       int &ObjectSize()
  449.       {
  450.          return iObjectSize;
  451.       }
  452.  
  453.       //-------------------------------
  454.       // Get / set reference count
  455.       int &ReferenceCount()
  456.       {
  457.          return iReferenceCount;
  458.       }
  459.  
  460.       //-------------------------------
  461.       // Get / set max reference count
  462.       int &MaxReferenceCount()
  463.       {
  464.          return iMaxReferenceCount;
  465.       }
  466.  
  467.       //-------------------------------
  468.       //  Value method - get or set
  469.       //  the object's value
  470.       GenericDataType &ObjectValue()
  471.       {
  472.          return objValue;
  473.       }
  474.  
  475.       //-------------------------------
  476.       // Conversion functions:
  477.       //    Convert object value to
  478.       //    an intrinsic data type.
  479.       //
  480.       // "char" object:
  481.       operator char()
  482.       {
  483.          return objValue.cValue;
  484.       }
  485.  
  486.       //-------------------------------
  487.       // "unsigned char" object:
  488.       operator unsigned char()
  489.       {
  490.          return objValue.ucValue;
  491.       }
  492.  
  493.       //-------------------------------
  494.       // "int" object:
  495.       operator int()
  496.       {
  497.          return objValue.uiValue;
  498.       }
  499.  
  500.       //-------------------------------
  501.       // "unsigned int" object:
  502.       operator unsigned int()
  503.       {
  504.          return objValue.uiValue;
  505.       }
  506.  
  507.       //-------------------------------
  508.       // "long" object:
  509.       operator long()
  510.       {
  511.          return objValue.lValue;
  512.       }
  513.  
  514.       //-------------------------------
  515.       // "unsigned long" object:
  516.       operator unsigned long()
  517.       {
  518.          return objValue.ulValue;
  519.       }
  520.  
  521.       //-------------------------------
  522.       // "char *" object:
  523.       operator char *()
  524.       {
  525.          return objValue.szValue;
  526.       }
  527.  
  528.       //-------------------------------
  529.       // "void *" object:
  530.       operator void *()
  531.       {
  532.          return objValue.pvValue;
  533.       }
  534.  
  535.    //------------------------------------------------------
  536.  
  537. };
  538.  
  539. //-----------------------------------------------------
  540. // Now, define a specific class; integers in this case.
  541.  
  542. class Integer : public GenericObject
  543. {
  544.  
  545.  
  546.    public:
  547.  
  548.       //-------------------------------
  549.       // Need a constructor for each
  550.       // integral type even though
  551.       // the parent class already
  552.       // has a set including them
  553.       //
  554.       // Constructors:
  555.       //
  556.       // No type, value, etc specified
  557.       Integer()                           : GenericObject() // Initialize
  558.       {                                                     // parent class
  559.          szClassName = "Integer_Class";                     // constructor
  560.       }
  561.  
  562.       //-------------------------------
  563.       // "char" object:
  564.       Integer(char initialValue)          : GenericObject(initialValue)
  565.       {
  566.          szClassName = "Integer_Class";
  567.       }
  568.  
  569.       //-------------------------------
  570.       // "unsigned char" object:
  571.       Integer(unsigned char initialValue) : GenericObject(initialValue)
  572.       {
  573.          szClassName = "Integer_Class";
  574.       }
  575.  
  576.       //-------------------------------
  577.       // "int" object:
  578.       Integer(int initialValue)           : GenericObject(initialValue)
  579.       {
  580.          szClassName = "Integer_Class";
  581.       }
  582.  
  583.       //-------------------------------
  584.       // "unsigned int" object:
  585.       Integer(unsigned int initialValue)  : GenericObject(initialValue)
  586.       {
  587.          szClassName = "Integer_Class";
  588.       }
  589.  
  590.       //-------------------------------
  591.       // "long" object:
  592.       Integer(long initialValue)          : GenericObject(initialValue)
  593.       {
  594.          szClassName = "Integer_Class";
  595.       }
  596.  
  597.       //-------------------------------
  598.       // "unsigned long" object
  599.       Integer(unsigned long initialValue) : GenericObject(initialValue)
  600.       {
  601.          szClassName = "Integer_Class";
  602.       }
  603.  
  604.       //-------------------------------
  605.       // Conversion functions are inher-
  606.       // ited from the parent class
  607.       //
  608.       //-------------------------------
  609.       // Overload the standard math
  610.       // operators - the compiler may
  611.       // not be able to tell which
  612.       // conversion function to apply;
  613.       // that process has to be done
  614.       // explicitly here.
  615.       //
  616.       // This is a round-about process;
  617.       // the argument to the operator is
  618.       // always an intrinsic data type
  619.       // BECAUSE of the conversion
  620.       // functions; the operators
  621.       // must be overloaded BECAUSE of
  622.       // the conversion functions.
  623.       //-------------------------------
  624.       // NOTE: There's no need to overload
  625.       // the assignment operator.  The
  626.       // compiler will pick an applicable
  627.       // constructor, called a "copy con-
  628.       // structor", create an interim
  629.       // class, and perform the assigment
  630.       // automatically.  You *can* provide
  631.       // your own copy constructor, but
  632.       // it's rare to need to do so.
  633.       //-------------------------------
  634.  
  635.       //-------------------------------
  636.       // Addition
  637.       operator+(int x)
  638.       {
  639.          return objValue.iValue + x;
  640.       }
  641.  
  642.       //-------------------------------
  643.       // Subtraction
  644.       operator-(int x)
  645.       {
  646.          return objValue.iValue - x;
  647.       }
  648.  
  649.       //-------------------------------
  650.       // Multiplication
  651.       operator*(int x)
  652.       {
  653.          return objValue.iValue * x;
  654.       }
  655.  
  656.       //-------------------------------
  657.       // Division
  658.       operator/(int x)
  659.       {
  660.          return objValue.iValue / x;
  661.       }
  662.  
  663.       //-------------------------------
  664.       // Modulus
  665.       operator%(int x)
  666.       {
  667.          return objValue.iValue % x;
  668.       }
  669.  
  670. };
  671.  
  672. //============================================================================//
  673. #ifdef __BUILD_SAMPLE__
  674.  
  675. #include <stdio.h>
  676.  
  677. int main(void);
  678.  
  679. int main()
  680. {
  681.    // Declare instances
  682.    Integer a,b;
  683.  
  684.    // Use the constructors
  685.    a = 50;
  686.    b = 25;
  687.  
  688.    // See what type they are
  689.    printf("a and b are of class %s and %s.\n",
  690.       a.GetClassName(),
  691.       b.GetClassName());
  692.  
  693.    // Use the overloaded operators and conversion functions
  694.    a = a + b;
  695.  
  696.    // Note that a *must* be explicitly typecast in calls
  697.    // to functions with variable argument lists.  Conversion
  698.    // is supplied only for the explicit parameters; in the
  699.    // case of printf(), the prototype is something
  700.    // (depending on your compiler; there might some minor
  701.    // differences, but nothing substantial) like this:
  702.    //
  703.    //          int printf(const char *,...);
  704.    //
  705.    // So, the compiler has no way to tell what conversion
  706.    // function to use.  What it ends up doing is
  707.    printf("The value of a is %d.\n",(int)a);
  708.  
  709.    // Try another operator and more conversions; b is 25, so b*5 should be 125.
  710.    b = b * 5;
  711.    printf("The value of b is %d.\n",(int)b);
  712.  
  713.    // All done
  714.    return 0;
  715.  
  716. }
  717.  
  718. #endif //(build sample)
  719.  
  720. //============================================================================//
  721.