home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tlx501.zip / TEMPLATE / VBASE.CPP < prev    next >
C/C++ Source or Header  |  1996-07-02  |  18KB  |  562 lines

  1. /****************************************************************************
  2.     $Id: vbase.cpp 501.0 1995/03/07 12:27:02 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 TLVBase<T>.
  10.  
  11.     $Log: vbase.cpp $
  12.     Revision 501.0  1995/03/07 12:27:02  RON
  13.     Updated for TLX 5.01
  14.     Revision 1.7  1995/01/31 16:30:52  RON
  15.     Update for release 012
  16.     Added partial support for SunPro C++ compiler
  17.     Revision 1.6  1994/10/05  18:50:08  ron
  18.     Renamed TLx...() functions to tl...()
  19.  
  20.     Revision 1.5  1994/09/28  14:43:12  ron
  21.     Removed Macintosh-style #include references
  22.  
  23.     Revision 1.4  1994/09/27  20:27:46  ron
  24.     Changed path separator from / to \
  25.  
  26.     Revision 1.3  1994/09/26  15:36:56  ron
  27.     Changed include file references
  28.     Renamed SetSize() to Resize()
  29.  
  30.     Revision 1.2  1994/09/07  15:48:18  ron
  31.     Removed conditional code to cater for Borland C++ 4.0 delete[] bug;
  32.     clients are supposed to switch to Borland C++ 4.02
  33.  
  34.     Revision 1.1  1994/08/16  18:15:36  ron
  35.     Initial revision
  36.  
  37. ****************************************************************************/
  38.  
  39. #ifndef _TLX_VBASE_CPP
  40. #define _TLX_VBASE_CPP
  41.  
  42. //----- System headers
  43.  
  44. #ifndef __IOSTREAM_H
  45. #include <iostream.h>
  46. #endif
  47.  
  48. //----- Project headers
  49.  
  50. #ifndef _TLX_ARRAYS_H
  51. #include <tlx\501\arrays.h>
  52. #endif
  53. #ifndef _TLX_DEBUG_H
  54. #include <tlx\501\debug.h>
  55. #endif
  56. #ifndef _TLX_EXCEPT_H
  57. #include <tlx\501\except.h>
  58. #endif
  59. #ifndef _TLX_UTIL_H
  60. #include <tlx\501\util.h>    // For tlMin()
  61. #endif
  62.  
  63. /*---------------------------------------------------------------------------
  64.     Auxiliary functions
  65. ---------------------------------------------------------------------------*/
  66.  
  67. template<class T> int TLVBase<T>::DefaultCompare(const T &, const T &)
  68. {
  69.     return 0;
  70. }
  71.  
  72. template<class T> void TLVBase<T>::DefaultOutput(ostream &os, const T &t)
  73. {
  74.     os << t;
  75. }
  76.  
  77. /*---------------------------------------------------------------------------
  78.     TLVBase<T> static data members and runtime type info
  79.  
  80.     Note: if you use the Borland C++ compiler and get a "Conflicting type
  81.     modifiers" error message, then insert the following #pragma in the
  82.     source file that includes this file:
  83.  
  84.     #pragma option -Jgd
  85.  
  86.     The pragma should be inserted before the first reference to the TLVBase
  87.     template or one of its derivations; it is usually best to place it
  88.     at the start of the source file.
  89.  
  90.     This should solve the problem (which is a result of the fact that TLVBase
  91.     has a static data member). This problem is specific to the Borland
  92.     compiler and is regarded "as designed" rather than as a bug by its
  93.     developers.
  94. ---------------------------------------------------------------------------*/
  95.  
  96. #if defined (__BORLANDC__) //&& defined (__OS2__)
  97.     // Borland C++ for OS/2 bug fix
  98.     template<class T> char *TLVBase<T>::sPre      = "[";
  99.     template<class T> char *TLVBase<T>::sPreSep  = "";
  100.     template<class T> char *TLVBase<T>::sPostSep = ", ";
  101.     template<class T> char *TLVBase<T>::sPost      = "]";
  102. #elif defined(__SC__)
  103.     // Symantec C++ bug fix -- global data members are in TLX.CPP
  104. #else
  105.     template<class T> const char *TLVBase<T>::sPre     = "[";
  106.     template<class T> const char *TLVBase<T>::sPreSep  = "";
  107.     template<class T> const char *TLVBase<T>::sPostSep = ", ";
  108.     template<class T> const char *TLVBase<T>::sPost    = "]";
  109. #endif
  110.  
  111. /*-------------------------------------------------------------------------*/
  112.     template<class T> TLVBase<T>::TLVBase(size_t size)
  113.  
  114. /*  Constructor creating a vector of a given size.
  115. ---------------------------------------------------------------------------*/
  116. {
  117.     mSize    = 0;
  118.     mVect    = 0;
  119.     mCompare = DefaultCompare;
  120.     mOutF    = DefaultOutput;
  121.  
  122.     Resize(size);
  123. }
  124.  
  125. /*-------------------------------------------------------------------------*/
  126.     template<class T> TLVBase<T>::TLVBase(const T &t)
  127.  
  128. /*  Constructor creating a vector of a single element.
  129. ---------------------------------------------------------------------------*/
  130. {
  131.     mSize    = 0;
  132.     mVect    = 0;
  133.     mCompare = DefaultCompare;
  134.     mOutF    = DefaultOutput;
  135.  
  136.     Duplicate(&t, 1);
  137. }
  138.  
  139. /*-------------------------------------------------------------------------*/
  140.     template<class T> TLVBase<T>::TLVBase(const T *tptr, size_t sz)
  141.  
  142. /*  Constructor creating a vector from a C-style vector of given size.
  143. ---------------------------------------------------------------------------*/
  144. {
  145.     mSize    = 0;
  146.     mVect    = 0;
  147.     mCompare = DefaultCompare;
  148.     mOutF    = DefaultOutput;
  149.  
  150.     TLX_ASSERT_PTR(tptr);
  151.     Duplicate(tptr, sz);
  152. }
  153.  
  154. /*-------------------------------------------------------------------------*/
  155.     template<class T> TLVBase<T>::TLVBase(const TLVBase<T> &ar)
  156.  
  157. /*  Copy constructor.
  158. ---------------------------------------------------------------------------*/
  159. {
  160.     mSize    = 0;
  161.     mVect    = 0;
  162.     mCompare = DefaultCompare;
  163.     mOutF    = DefaultOutput;
  164.  
  165.     Duplicate(ar.mVect, ar.mSize);
  166. }
  167.  
  168. /*-------------------------------------------------------------------------*/
  169.     template<class T> TLVBase<T>::~TLVBase()
  170.  
  171. /*  Destructor. Discards data storage.
  172. ---------------------------------------------------------------------------*/
  173. {
  174.     delete [] mVect;
  175. }
  176.  
  177. /*-------------------------------------------------------------------------*/
  178.     template<class T> int TLVBase<T>::Compare(const TLVBase<T> &v) const
  179.  
  180. /*  Compares the current vector with another on an element by element base.
  181. ---------------------------------------------------------------------------*/
  182. {
  183.     iter_t i, j;
  184.     for (bool ok1 = IterFirst(i), ok2 = v.IterFirst(j); ok1 && ok2;
  185.          ok1 = IterNext(i), ok2 = v.IterNext(j))
  186.     {
  187.     int result = mCompare(operator[](i), v[j]);
  188.     if (result) return result;
  189.     }
  190.  
  191.     // Break ties on number of elements
  192.     return (int)Count() - (int)v.Count();
  193. }
  194.  
  195. /*-------------------------------------------------------------------------*/
  196.     template<class T> bool TLVBase<T>::Contains(const T &t) const
  197.  
  198. /*  Checks if a given value appears in the vector.
  199. ---------------------------------------------------------------------------*/
  200. {
  201.     return IsValidIndex(IndexOf(t));
  202. }
  203.  
  204. /*-------------------------------------------------------------------------*/
  205.     template<class T> void TLVBase<T>::DoAll(void (*f)(T &, va_list), ...)
  206.  
  207. /*  Applies a given function to all elements in the vector.
  208. ---------------------------------------------------------------------------*/
  209. {
  210.     va_list args;
  211.     va_start(args, f);
  212.     iter_t i;
  213.  
  214.     for (bool ok = IterFirst(i); ok; ok = IterNext(i))
  215.     f(operator [](i), args);
  216.  
  217.     va_end(args);
  218. }
  219.  
  220. /*-------------------------------------------------------------------------*/
  221.     template<class T>
  222.     void TLVBase<T>::DoAll(void (*f)(const T &, va_list), ...) const
  223.  
  224. /*  Applies a given function to all elements in the vector.
  225. ---------------------------------------------------------------------------*/
  226. {
  227.     va_list args;
  228.     va_start(args, f);
  229.     iter_t i;
  230.  
  231.     for (bool ok = IterFirst(i); ok; ok = IterNext(i))
  232.     f(operator [](i), args);
  233.  
  234.     va_end(args);
  235. }
  236.  
  237. /*-------------------------------------------------------------------------*/
  238.     template<class T>
  239.     index_t TLVBase<T>::DoWhile(bool (*f)(T &, va_list), ...)
  240.  
  241. /*  Applies a given function to elements in the vector while the function
  242.     returns nonzero. It returns the index of the element that first caused
  243.     the function to return zero.
  244. ---------------------------------------------------------------------------*/
  245. {
  246.     va_list args;
  247.     va_start(args, f);
  248.     iter_t i;
  249.  
  250.     for (bool ok = IterFirst(i); ok; ok = IterNext(i))
  251.     if (!f(operator [](i), args))
  252.         break;
  253.  
  254.     va_end(args);
  255.     return UnmapIndex(i.ix);
  256. }
  257.  
  258. /*-------------------------------------------------------------------------*/
  259.     template<class T>
  260.     index_t TLVBase<T>::DoWhile(bool (*f)(const T &, va_list), ...) const
  261.  
  262. /*  Applies a given function to elements in the vector while the function
  263.     returns nonzero. It returns the index of the element that first caused
  264.     the function to return zero.
  265. ---------------------------------------------------------------------------*/
  266. {
  267.     va_list args;
  268.     va_start(args, f);
  269.     iter_t i;
  270.  
  271.     for (bool ok = IterFirst(i); ok; ok = IterNext(i))
  272.     if (!f(operator [](i), args))
  273.         break;
  274.  
  275.     va_end(args);
  276.     return UnmapIndex(i.ix);
  277. }
  278.  
  279. /*-------------------------------------------------------------------------*/
  280.     template<class T>
  281.     index_t TLVBase<T>::DoUntil(bool (*f)(T &, va_list), ...)
  282.  
  283. /*  Applies a given function to elements in the vector until the function
  284.     returns nonzero. It returns the index of the element that first caused
  285.     the function to return nonzero.
  286. ---------------------------------------------------------------------------*/
  287. {
  288.     va_list args;
  289.     va_start(args, f);
  290.     iter_t i;
  291.  
  292.     for (bool ok = IterFirst(i); ok; ok = IterNext(i))
  293.     if (f(operator [](i), args))
  294.         break;
  295.  
  296.     va_end(args);
  297.     return UnmapIndex(i.ix);
  298. }
  299.  
  300. /*-------------------------------------------------------------------------*/
  301.     template<class T>
  302.     index_t TLVBase<T>::DoUntil(bool (*f)(const T &, va_list), ...) const
  303.  
  304. /*  Applies a given function to elements in the vector until the function
  305.     returns nonzero. It returns the index of the element that first caused
  306.     the function to return nonzero.
  307. ---------------------------------------------------------------------------*/
  308. {
  309.     va_list args;
  310.     va_start(args, f);
  311.     iter_t i;
  312.  
  313.     for (bool ok = IterFirst(i); ok; ok = IterNext(i))
  314.     if (f(operator [](i), args))
  315.         break;
  316.  
  317.     va_end(args);
  318.     return UnmapIndex(i.ix);
  319. }
  320.  
  321. /*-------------------------------------------------------------------------*/
  322.     template<class T> void TLVBase<T>::Duplicate(const T *ar, size_t sz)
  323.  
  324. /*  Makes the current vector a duplicate of the passed in C-style vector.
  325. ---------------------------------------------------------------------------*/
  326. {
  327.     if (mSize != sz)
  328.     {
  329.     delete [] mVect;
  330.     mVect = new T[mSize = sz];
  331.     }
  332.  
  333.     TLX_ASSERT(mVect != 0 || mSize == 0);
  334.  
  335.     T *dptr       = mVect;
  336.     const T *sptr = ar;
  337.  
  338.     for (size_t i = mSize; i; i--)
  339.     *dptr++ = *sptr++;
  340. }
  341.  
  342. /*-------------------------------------------------------------------------*/
  343.     template<class T> void TLVBase<T>::Fill(const T &t)
  344.  
  345. /*  Fills the entire vector with the given value.
  346. ---------------------------------------------------------------------------*/
  347. {
  348.     T *tptr = mVect;
  349.     for (size_t i = mSize; i; i--)
  350.     *tptr++ = t;
  351. }
  352.  
  353. /*-------------------------------------------------------------------------*/
  354.     template<class T> void TLVBase<T>::ExpandBy(size_t delta)
  355.  
  356. /*  Expands the size of the vector by the given amount.
  357. ---------------------------------------------------------------------------*/
  358. {
  359.     // Careful with size_t overflow
  360.     TLX_ASSERT(delta <= MaxSize() - mSize);
  361.     Resize(mSize + delta);
  362. }
  363.  
  364. /*-------------------------------------------------------------------------*/
  365.     template<class T> index_t TLVBase<T>::IndexOf(const T &t) const
  366.  
  367. /*  Returns the index of the (first occurrence of the) value in the vector.
  368. ---------------------------------------------------------------------------*/
  369. {
  370.     iter_t i;
  371.     for (bool ok = IterFirst(i); ok; ok = IterNext(i))
  372.     {
  373.     //if (mCompare(operator [](i), t) == 0)
  374.     if (operator[](i) == t)
  375.         break;
  376.     }
  377.     return UnmapIndex(i.ix);;
  378. }
  379.  
  380. /*-------------------------------------------------------------------------*/
  381.     template<class T> bool TLVBase<T>::IsValidIndex(index_t i) const
  382.  
  383. /*  Checks if the given index is valid for the vector, returning nonzero
  384.     if it is, else zero.
  385. ---------------------------------------------------------------------------*/
  386. {
  387.     return i >= Mini() && i <= Maxi();
  388. }
  389.  
  390. /*-------------------------------------------------------------------------*/
  391.     template<class T> bool TLVBase<T>::IterFirst(iter_t &i) const
  392.  
  393. /*  Initializes the iterator to address the first element of the vector.
  394.     Returns nonzero if the iterator is valid after the operation, else zero.
  395. ---------------------------------------------------------------------------*/
  396. {
  397.     return ((tSize)(i.ix = 0)) < mSize;
  398. }
  399.  
  400. #ifdef _MSC_VER
  401. #pragma optimize( "g", off )    // Code causes P2 internal compiler error
  402. #endif
  403.  
  404. /*-------------------------------------------------------------------------*/
  405.     template<class T> bool TLVBase<T>::IterLast(iter_t &i) const
  406.  
  407. /*  Initializes the iterator to address the last element of the vector.
  408.     Returns nonzero if the iterator is valid after the operation, else zero.
  409. ---------------------------------------------------------------------------*/
  410. {
  411.     return (i.ix = mSize - 1) >= 0;
  412. }
  413.  
  414. #ifdef _MSC_VER
  415. #pragma optimize( "", on )
  416. #endif
  417.  
  418. /*-------------------------------------------------------------------------*/
  419.     template<class T> bool TLVBase<T>::IterNext(iter_t &i) const
  420.  
  421. /*  Advances the iterator to address the next element of the vector.
  422.     Returns nonzero if the iterator is valid after the operation, else zero.
  423. ---------------------------------------------------------------------------*/
  424. {
  425.     return ((tSize)(++i.ix)) < mSize;
  426. }
  427.  
  428. /*-------------------------------------------------------------------------*/
  429.     template<class T> bool TLVBase<T>::IterPrev(iter_t &i) const
  430.  
  431. /*  Advances the iterator to address the previous element of the vector.
  432.     Returns nonzero if the iterator is valid after the operation, else zero.
  433. ---------------------------------------------------------------------------*/
  434. {
  435.     return --i.ix >= 0;
  436. }
  437.  
  438. /*-------------------------------------------------------------------------*/
  439.     template<class T> bool TLVBase<T>::OK() const
  440.  
  441. /*  Checks the class invariants, returning nonzero if all is well.
  442. ---------------------------------------------------------------------------*/
  443. {
  444.     return (mVect && mSize) || (!mVect && !mSize);
  445. }
  446.  
  447. /*-------------------------------------------------------------------------*/
  448.     template<class T> TLVBase<T> &TLVBase<T>::operator =(const T &t)
  449.  
  450. /*  Overloading of assignment operator that allows assignment of a single
  451.     element to the vector. The previous contents are lost.
  452. ---------------------------------------------------------------------------*/
  453. {
  454.     Duplicate(&t, 1);
  455.     return *this;
  456. }
  457.  
  458. /*-------------------------------------------------------------------------*/
  459.     template<class T>
  460.     TLVBase<T> &TLVBase<T>::operator =(const TLVBase<T> &ar)
  461.  
  462. /*  Overloading of the assignment operator.
  463. ---------------------------------------------------------------------------*/
  464. {
  465.     if (this != &ar) Duplicate(ar.mVect, ar.mSize);
  466.     return *this;
  467. }
  468.  
  469. /*-------------------------------------------------------------------------*/
  470.     template<class T> T &TLVBase<T>::operator [](index_t i)
  471.  
  472. /*  Returns reference to the indicated element in the vector. The access
  473.     is range checked and will throw a TLXIndex exception if the index is
  474.     out of range.
  475. ---------------------------------------------------------------------------*/
  476. {
  477.     if (!IsValidIndex(i))
  478.     THROW(TLXIndex(LOCUS, i));
  479.  
  480.     return mVect[MapIndex(i)];
  481. }
  482.  
  483. /*-------------------------------------------------------------------------*/
  484.     template<class T> const T &TLVBase<T>::operator [](index_t i) const
  485.  
  486. /*  Returns reference to the indicated element in the vector. The access
  487.     is range checked and will throw a TLXIndex exception if the index is
  488.     out of range.
  489. ---------------------------------------------------------------------------*/
  490. {
  491.     if (!IsValidIndex(i))
  492.     THROW(TLXIndex(LOCUS, i));
  493.  
  494.     return mVect[MapIndex(i)];
  495. }
  496.  
  497. /*-------------------------------------------------------------------------*/
  498.     template<class T> ostream &TLVBase<T>::PrintOn(ostream &os) const
  499.  
  500. /*  Prints the contents of the vector on the given stream. The vector is
  501.     preceded by a prefix; elements are surrounded by pre- and postfixes,
  502.     and the vector is concluded with a general postfix.
  503. ---------------------------------------------------------------------------*/
  504. {
  505.     iter_t i;
  506.  
  507.     if (sPre) os << sPre;
  508.     for (bool ok = IterFirst(i); ok; ok = IterNext(i))
  509.     {
  510.     if (sPreSep) os << sPreSep;
  511.     mOutF(os, operator[](i));
  512.     if (sPostSep) os << sPostSep;
  513.     }
  514.     if (sPost)
  515.         return os << sPost;
  516.     else
  517.     return os;
  518. }
  519.  
  520. /*-------------------------------------------------------------------------*/
  521.     template<class T> void TLVBase<T>::Resize(size_t newsize)
  522.  
  523. /*  Changes the allocated size of the vector. The elements common to the
  524.     old and the new vector sizes are left as is.
  525. ---------------------------------------------------------------------------*/
  526. {
  527.     if (newsize == mSize)
  528.         return;
  529.  
  530.     TLX_ASSERT(newsize <= MaxSize());
  531.  
  532.     if (newsize == 0)
  533.     {
  534.     delete [] mVect;
  535.     mVect = 0;
  536.     mSize = 0;
  537.     return;
  538.     }
  539.  
  540.     T *tmp = new T[newsize];
  541.     TLX_ASSERT_PTR(tmp);
  542.  
  543.     for (size_t i = 0, m = tlMin(newsize, mSize); i < m; i++)
  544.     tmp[i] = mVect[i];
  545.  
  546.     delete [] mVect;
  547.     mVect = tmp;
  548.     mSize = newsize;
  549. }
  550.  
  551. /*-------------------------------------------------------------------------*/
  552.     template<class T> void TLVBase<T>::ShrinkBy(size_t delta)
  553.  
  554. /*  Reduces the allocated size of the vector by the indicated amount.
  555. ---------------------------------------------------------------------------*/
  556. {
  557.     TLX_ASSERT(delta <= mSize);
  558.     Resize(mSize - delta);
  559. }
  560.  
  561. #endif    // _TLX_VBASE_CPP
  562.