home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tlx501.zip / SRC / VPVECTOR.CPP < prev    next >
C/C++ Source or Header  |  1996-07-08  |  15KB  |  426 lines

  1. /****************************************************************************
  2.     $Id: vpvector.cpp 501.0 1995/03/07 12:26:28 RON Exp $
  3.  
  4.     Copyright (c) 1991-95 Tarma Software Research. All rights reserved.
  5.  
  6.     Project:    Tarma Library for C++ V5.0
  7.     Author:    Ron van der Wal
  8.  
  9.     Implementation of class TLVPVector. Class TLVPVector maintains a vector
  10.     of (void *). In order to allow easy resizes and such, we use the malloc()
  11.     family for memory allocations. (The pointers don't have constructors
  12.     or destructors anyway.)
  13.  
  14.     $Log: vpvector.cpp $
  15.     Revision 501.0  1995/03/07 12:26:28  RON
  16.     Updated for TLX 5.01
  17.     Revision 1.9  1995/01/31 16:30:36  RON
  18.     Update for release 012
  19.     Added partial support for SunPro C++ compiler
  20.     Revision 1.8  1995/01/06  15:58:59  ron
  21.     Corrected Revision keyword
  22.  
  23.     Revision 1.7  1994/11/16  15:46:22  ron
  24.     Added module info; rearranged #include directives
  25.  
  26.     Revision 1.6  1994/09/28  14:48:07  ron
  27.     Removed Macintosh-style #include references
  28.  
  29.     Revision 1.5  1994/09/27  20:23:37  ron
  30.     Changed path separator from / to \
  31.  
  32.     Revision 1.4  1994/09/26  15:52:12  ron
  33.     Renamed SetSize() to Resize()
  34.  
  35.     Revision 1.3  1994/09/07  15:46:17  ron
  36.     Small formatting changes
  37.  
  38.     Revision 1.2  1994/09/06  14:10:31  ron
  39.     Adapted to changes in tlx.h
  40.  
  41.     Revision 1.1  1994/08/16  18:13:25  ron
  42.     Initial revision
  43.  
  44. ****************************************************************************/
  45.  
  46. #include <tlx\501\_build.h>
  47.  
  48. TLX_MODULE_INFO("$Revision: 501.0 $");
  49.  
  50. #include <stdlib.h>        // For malloc() etc.
  51. #include <string.h>        // For memcpy() etc.
  52. #include <tlx\501\except.h>
  53. #include <tlx\501\vparrays.h>    // Class declaration
  54.  
  55. /*---------------------------------------------------------------------------
  56.     We assume throughout that NULL pointers are represented as an all zero
  57.     bit pattern. On platforms where this is not the case, we must adjust
  58.     our implementation. For now, just verify that NULL is all zeroes.
  59. ---------------------------------------------------------------------------*/
  60.  
  61. #ifndef _NULL_IS_0
  62. #error NULL pointers are nonzero; contact Tarma Software Research.
  63. #endif
  64.  
  65. /*-------------------------------------------------------------------------*/
  66.     TLVPVector::TLVPVector(size_t aSize)
  67.  
  68. /*  Constructor to create a vector with a specified size; also doubles
  69.     as the default constructor, creating an empty vector.
  70. ---------------------------------------------------------------------------*/
  71. : mVector(0), mSize(0), mOwner(false), mDeleteFunc(DefaultDelete)
  72. {
  73.     Copy(aSize);
  74.     TLX_ASSERT(Size() == aSize);
  75. }
  76.  
  77. /*-------------------------------------------------------------------------*/
  78.     TLVPVector::TLVPVector(void *aPtr)
  79.  
  80. /*  Constructor creating a vector of 1 element.
  81. ---------------------------------------------------------------------------*/
  82. : mVector(0), mSize(0), mOwner(false), mDeleteFunc(DefaultDelete)
  83. {
  84.     Copy(1, &aPtr);
  85.     TLX_ASSERT(Size() == 1);
  86. }
  87.  
  88. /*-------------------------------------------------------------------------*/
  89.     TLVPVector::TLVPVector(void **aVector, size_t aSize)
  90.  
  91. /*  Constructor creating a copy of C-style vector with the given size.
  92. ---------------------------------------------------------------------------*/
  93. : mVector(0), mSize(0), mOwner(false), mDeleteFunc(DefaultDelete)
  94. {
  95.     Copy(aSize, aVector);
  96.     TLX_ASSERT(Size() == aSize);
  97. }
  98.  
  99. /*-------------------------------------------------------------------------*/
  100.     TLVPVector::TLVPVector(const TLVPVector &aVector)
  101.  
  102. /*  Copy constructor.
  103. ---------------------------------------------------------------------------*/
  104. : mVector(0), mSize(0), mOwner(false), mDeleteFunc(DefaultDelete)
  105. {
  106.     Copy(aVector.mSize, aVector.mVector);
  107.     TLX_ASSERT(Size() == aVector.Size());
  108. }
  109.  
  110. /*-------------------------------------------------------------------------*/
  111.     TLVPVector::~TLVPVector()
  112.  
  113. /*  Destructor. Discards the vector storage.
  114. ---------------------------------------------------------------------------*/
  115. {
  116.     TLX_ASSERT(mVector != 0 || mSize == 0);
  117.  
  118.     // Destroy pointed to objects, if we are the owner. Because we use a
  119.     // deletion function pointer, we can still invoke the correct deletion
  120.     // operation (it isn't a virtual function).
  121.  
  122.     if (IsOwner())
  123.         RemoveAll();
  124.  
  125.     if (mVector)
  126.     {
  127.         free(mVector);
  128.     mVector = 0;
  129.     }
  130. }
  131.  
  132. /*-------------------------------------------------------------------------*/
  133.     bool TLVPVector::BecomeOwner(bool aFlag)
  134.  
  135. /*  Sets or resets the owner status of the vector. If the vector is owner
  136.     of the pointed to objects, it will delete them if necessary.
  137. ---------------------------------------------------------------------------*/
  138. {
  139.     bool oldOwner = mOwner;
  140.     mOwner = aFlag;
  141.     return oldOwner;
  142. }
  143.  
  144. /*-------------------------------------------------------------------------*/
  145.     void TLVPVector::Copy(size_t aSize, void **aVector)
  146.  
  147. /*  Helper function for the constructors and assignment operators.
  148.     Resizes the vector to match the indicated size, then copies the
  149.     contents of the (void *) vector (if any) to the current instance.
  150.  
  151.     Returns nonzero if successful, else zero.
  152. ---------------------------------------------------------------------------*/
  153. {
  154.     TLX_ASSERT(mVector == 0 || aVector != mVector);
  155.  
  156.     Resize(aSize);
  157.     TLX_ASSERT(aSize == mSize);
  158.  
  159.     // Before we copy the pointers, we must make sure that any
  160.     // currently pointed to objects are destroyed if we own them.
  161.  
  162.     if (IsOwner())
  163.     RemoveAll();        // To destroy pointed to objects
  164.     if (aVector)
  165.     memcpy(mVector, aVector, mSize * sizeof(void *));
  166. }
  167.  
  168. /*-------------------------------------------------------------------------*/
  169.     int TLVPVector::DefaultCompare(const void *aPtr1, const void *aPtr2)
  170.  
  171. /*  Default comparison function for (void *). The pointer values themselves
  172.     are compared, rather than the pointed to objects.
  173.  
  174.     Return value:
  175.  
  176.     < 0 if aPtr1 is less than aPtr2
  177.     = 0 if aPtr1 is equal to aPtr2
  178.     > 0 if aPtr1 is greater than aPtr2
  179. ---------------------------------------------------------------------------*/
  180. {
  181.     ptrdiff_t diff = (const char *)aPtr1 - (const char *)aPtr2;
  182.     return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
  183. }
  184.  
  185. /*-------------------------------------------------------------------------*/
  186.     void TLVPVector::DefaultDelete(void *aPtr)
  187.  
  188. /*  Default deletion function for (void *). The function applies operator
  189.     delete to the pointer.
  190. ---------------------------------------------------------------------------*/
  191. {
  192.     delete aPtr;
  193. }
  194.  
  195. /*-------------------------------------------------------------------------*/
  196.     void TLVPVector::RemoveAll()
  197.  
  198. /*  Clears all pointers in the vector by setting them to 0. If we are owner
  199.     of the pointed to objects, they are destroyed as well.
  200. ---------------------------------------------------------------------------*/
  201. {
  202.     TLX_ASSERT(mVector != 0 || mSize == 0);
  203.  
  204.     if (IsOwner())
  205.     {
  206.     for (index_t i = 0; (tSize)i < mSize; i++)
  207.         if (mVector[i])
  208.         DeletePtr(mVector[i]);
  209.     }
  210.     memset(mVector, 0, mSize * sizeof(void *));
  211. }
  212.  
  213. /*-------------------------------------------------------------------------*/
  214.     void TLVPVector::DeletePtr(void *aPtr)
  215.  
  216. /*  Deletes a single element by calling the current deletion function.
  217. ---------------------------------------------------------------------------*/
  218. {
  219.     TLX_ASSERT_PTR(mDeleteFunc);
  220.     (*mDeleteFunc)(aPtr);
  221. }
  222.  
  223. /*-------------------------------------------------------------------------*/
  224.     void TLVPVector::ExpandBy(size_t aDelta)
  225.  
  226. /*  Expands the size of the vector by a specified amount.
  227. ---------------------------------------------------------------------------*/
  228. {
  229.     // We must be careful to avoid unsigned integer wrap-around
  230.     TLX_ASSERT(mSize < (kMaxSize - aDelta));
  231.     Resize(mSize + aDelta);
  232. }
  233.  
  234. /*-------------------------------------------------------------------------*/
  235.     index_t TLVPVector::IndexOf(const void *aPtr) const
  236.  
  237. /*  Finds the index of a given pointer value. The function performs a
  238.     linear search. Only the first occurrence of the value is found (if any).
  239.  
  240.     The function returns the (first) index of the given pointer value, or
  241.     Maxi() + 1 if the pointer does not appear in the vector.
  242. ---------------------------------------------------------------------------*/
  243. {
  244.     index_t aIndex;
  245.     for (aIndex = 0; (tSize)aIndex < mSize; aIndex++)
  246.     if (mVector[aIndex] == aPtr)
  247.         break;
  248.  
  249.     return aIndex;
  250. }
  251.  
  252. /*-------------------------------------------------------------------------*/
  253.     bool TLVPVector::IsValidIndex(index_t aIndex) const
  254.  
  255. /*  Tests whether a given index is valid for the vector.
  256. ---------------------------------------------------------------------------*/
  257. {
  258.     return aIndex >= Mini() && aIndex <= Maxi();
  259. }
  260.  
  261. /*-------------------------------------------------------------------------*/
  262.     TLVPVector &TLVPVector::operator =(const TLVPVector &aVector)
  263.  
  264. /*  Overloading of assignment operator for class TLVPVector. Copies
  265.     the pointed to vector, rather than the vector pointer. The pointed
  266.     to objects are not copied. If the vector is owner of the objects, they
  267.     are deleted first. After the assignment, the vector is *not* the owner
  268.     of the new elements.
  269. ---------------------------------------------------------------------------*/
  270. {
  271.     if (this != &aVector)
  272.     {
  273.     Copy(aVector.mSize, aVector.mVector);
  274.  
  275.     // We cannot own the new objects
  276.     mOwner = false;
  277.     }
  278.     return *this;
  279. }
  280.  
  281. /*-------------------------------------------------------------------------*/
  282.     TLVPVector &TLVPVector::operator =(void *aPtr)
  283.  
  284. /*  Overloading of assignment operator that assigns a single (void *)
  285.     to the current instance. The vector is reduced to a single element
  286.     as a result of the assignment. The currently pointed to objects are
  287.     deleted if we are the owner of them. The owner status of the vector
  288.     is not changed by the assignment operation.
  289. ---------------------------------------------------------------------------*/
  290. {
  291.     Copy(1, &aPtr);
  292.     return *this;
  293. }
  294.  
  295. /*-------------------------------------------------------------------------*/
  296.     void *&TLVPVector::operator [](index_t aIndex)
  297.  
  298. /*  Overloading of the indexing operator for class TLVPVector. This version
  299.     performs range checking on the index, throwing an exception if the
  300.     index is out of range.
  301. ---------------------------------------------------------------------------*/
  302. {
  303.     if (!IsValidIndex(aIndex))
  304.     THROW(TLXIndex(LOCUS, aIndex));
  305.  
  306.     return mVector[aIndex];
  307. }
  308.  
  309. /*-------------------------------------------------------------------------*/
  310.     void *TLVPVector::operator [](index_t aIndex) const
  311.  
  312. /*  Overloading of the indexing operator for class TLVPVector. This version
  313.     performs range checking on the index, throwing an exception if the
  314.     index is out of range.
  315. ---------------------------------------------------------------------------*/
  316. {
  317.     if (!IsValidIndex(aIndex))
  318.     THROW(TLXIndex(LOCUS, aIndex));
  319.  
  320.     return mVector[aIndex];
  321. }
  322.  
  323. /*-------------------------------------------------------------------------*/
  324.     void *&TLVPVector::PeekAt(index_t aIndex)
  325.  
  326. /*  Returns a reference to the 'aIndex'th item in the vector.
  327. ---------------------------------------------------------------------------*/
  328. {
  329.     TLX_ASSERT(aIndex >= Mini());
  330.     TLX_ASSERT(aIndex <= Maxi());
  331.  
  332.     return mVector[aIndex];
  333. }
  334.  
  335. /*-------------------------------------------------------------------------*/
  336.     void *TLVPVector::PeekAt(index_t aIndex) const
  337.  
  338. /*  Returns the value of the 'aIndex'th item in the vector.
  339. ---------------------------------------------------------------------------*/
  340. {
  341.     TLX_ASSERT(aIndex >= Mini());
  342.     TLX_ASSERT(aIndex <= Maxi());
  343.  
  344.     return mVector[aIndex];
  345. }
  346.  
  347. /*-------------------------------------------------------------------------*/
  348.     tDeleteFunc TLVPVector::SetDelete(tDeleteFunc aFunc)
  349.  
  350. /*  Sets the deletion function pointer to the given function, while
  351.     returning the previous function pointer. If the new function pointer
  352.     is 0, the default deletion function is installed.
  353. ---------------------------------------------------------------------------*/
  354. {
  355.     tDeleteFunc oldf = mDeleteFunc;
  356.     mDeleteFunc = aFunc ? aFunc : DefaultDelete;
  357.     return oldf;
  358. }
  359.  
  360. /*-------------------------------------------------------------------------*/
  361.     void TLVPVector::Resize(size_t aSize)
  362.  
  363. /*  Adjusts the size of the vector. If the current size is equal to the
  364.     requested size, nothing happens. If it is larger, then the additional
  365.     elements will be initialized to zero. If it is smaller, the discarded
  366.     elements will be deleted if we are the owner. In all cases, the elements
  367.     common to the old and the new sizes remain unchanged.
  368. ---------------------------------------------------------------------------*/
  369. {
  370.     if (aSize == mSize)
  371.         return;
  372.  
  373.     TLX_ASSERT(aSize <= MaxSize());
  374.     TLX_ASSERT(mVector != 0 || mSize == 0);
  375.  
  376.     // If the new size is less than the old size, and we own the pointed
  377.     // to objects, we must delete the excess elements before the reallocation.
  378.  
  379.     if (aSize < mSize && IsOwner())
  380.     {
  381.     for (index_t i = aSize; (tSize)i < mSize; i++)
  382.         if (mVector[i])
  383.         {
  384.         DeletePtr(mVector[i]);
  385.         mVector[i] = 0;
  386.         }
  387.     }
  388.  
  389.     // We use the fact that realloc() will free an existing block if the new
  390.     // size is 0; also that it will work as malloc() when the old pointer
  391.     // was null.
  392.  
  393.     void **tmpvect = (void **) realloc(mVector, aSize * sizeof(void *));
  394.  
  395.     if (tmpvect)
  396.     {
  397.     // Reallocation succeeded. Zero out any new elements.
  398.     if (aSize > mSize)
  399.         memset(&tmpvect[mSize], 0, (aSize - mSize) * sizeof(void *));
  400.     }
  401.     else if (aSize == 0)
  402.     {
  403.     // Old vector is freed. No further action necessary.
  404.     }
  405.     else
  406.     {
  407.     // Failure to reallocate to a nonzero size.
  408.     THROW(TLXAlloc(LOCUS, aSize * sizeof(void *)));
  409.     }
  410.  
  411.     mVector = tmpvect;
  412.     mSize   = aSize;
  413.     TLX_ASSERT(mVector != 0 || mSize == 0);
  414. }
  415.  
  416. /*-------------------------------------------------------------------------*/
  417.     void TLVPVector::ShrinkBy(size_t aDelta)
  418.  
  419. /*  Reduces the size of the vector by a specified amount.
  420. ---------------------------------------------------------------------------*/
  421. {
  422.     TLX_ASSERT(aDelta <= mSize);
  423.     Resize(mSize - aDelta);
  424. }
  425.  
  426.