home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
tlx501.zip
/
TEMPLATE
/
VBASE.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-02
|
18KB
|
562 lines
/****************************************************************************
$Id: vbase.cpp 501.0 1995/03/07 12:27:02 RON Exp $
Copyright (c) 1991-95 Tarma Software Research. All rights reserved.
Project: Tarma Library for C++ V5.0
Author: Ron van der Wal
Implementation of class TLVBase<T>.
$Log: vbase.cpp $
Revision 501.0 1995/03/07 12:27:02 RON
Updated for TLX 5.01
Revision 1.7 1995/01/31 16:30:52 RON
Update for release 012
Added partial support for SunPro C++ compiler
Revision 1.6 1994/10/05 18:50:08 ron
Renamed TLx...() functions to tl...()
Revision 1.5 1994/09/28 14:43:12 ron
Removed Macintosh-style #include references
Revision 1.4 1994/09/27 20:27:46 ron
Changed path separator from / to \
Revision 1.3 1994/09/26 15:36:56 ron
Changed include file references
Renamed SetSize() to Resize()
Revision 1.2 1994/09/07 15:48:18 ron
Removed conditional code to cater for Borland C++ 4.0 delete[] bug;
clients are supposed to switch to Borland C++ 4.02
Revision 1.1 1994/08/16 18:15:36 ron
Initial revision
****************************************************************************/
#ifndef _TLX_VBASE_CPP
#define _TLX_VBASE_CPP
//----- System headers
#ifndef __IOSTREAM_H
#include <iostream.h>
#endif
//----- Project headers
#ifndef _TLX_ARRAYS_H
#include <tlx\501\arrays.h>
#endif
#ifndef _TLX_DEBUG_H
#include <tlx\501\debug.h>
#endif
#ifndef _TLX_EXCEPT_H
#include <tlx\501\except.h>
#endif
#ifndef _TLX_UTIL_H
#include <tlx\501\util.h> // For tlMin()
#endif
/*---------------------------------------------------------------------------
Auxiliary functions
---------------------------------------------------------------------------*/
template<class T> int TLVBase<T>::DefaultCompare(const T &, const T &)
{
return 0;
}
template<class T> void TLVBase<T>::DefaultOutput(ostream &os, const T &t)
{
os << t;
}
/*---------------------------------------------------------------------------
TLVBase<T> static data members and runtime type info
Note: if you use the Borland C++ compiler and get a "Conflicting type
modifiers" error message, then insert the following #pragma in the
source file that includes this file:
#pragma option -Jgd
The pragma should be inserted before the first reference to the TLVBase
template or one of its derivations; it is usually best to place it
at the start of the source file.
This should solve the problem (which is a result of the fact that TLVBase
has a static data member). This problem is specific to the Borland
compiler and is regarded "as designed" rather than as a bug by its
developers.
---------------------------------------------------------------------------*/
#if defined (__BORLANDC__) //&& defined (__OS2__)
// Borland C++ for OS/2 bug fix
template<class T> char *TLVBase<T>::sPre = "[";
template<class T> char *TLVBase<T>::sPreSep = "";
template<class T> char *TLVBase<T>::sPostSep = ", ";
template<class T> char *TLVBase<T>::sPost = "]";
#elif defined(__SC__)
// Symantec C++ bug fix -- global data members are in TLX.CPP
#else
template<class T> const char *TLVBase<T>::sPre = "[";
template<class T> const char *TLVBase<T>::sPreSep = "";
template<class T> const char *TLVBase<T>::sPostSep = ", ";
template<class T> const char *TLVBase<T>::sPost = "]";
#endif
/*-------------------------------------------------------------------------*/
template<class T> TLVBase<T>::TLVBase(size_t size)
/* Constructor creating a vector of a given size.
---------------------------------------------------------------------------*/
{
mSize = 0;
mVect = 0;
mCompare = DefaultCompare;
mOutF = DefaultOutput;
Resize(size);
}
/*-------------------------------------------------------------------------*/
template<class T> TLVBase<T>::TLVBase(const T &t)
/* Constructor creating a vector of a single element.
---------------------------------------------------------------------------*/
{
mSize = 0;
mVect = 0;
mCompare = DefaultCompare;
mOutF = DefaultOutput;
Duplicate(&t, 1);
}
/*-------------------------------------------------------------------------*/
template<class T> TLVBase<T>::TLVBase(const T *tptr, size_t sz)
/* Constructor creating a vector from a C-style vector of given size.
---------------------------------------------------------------------------*/
{
mSize = 0;
mVect = 0;
mCompare = DefaultCompare;
mOutF = DefaultOutput;
TLX_ASSERT_PTR(tptr);
Duplicate(tptr, sz);
}
/*-------------------------------------------------------------------------*/
template<class T> TLVBase<T>::TLVBase(const TLVBase<T> &ar)
/* Copy constructor.
---------------------------------------------------------------------------*/
{
mSize = 0;
mVect = 0;
mCompare = DefaultCompare;
mOutF = DefaultOutput;
Duplicate(ar.mVect, ar.mSize);
}
/*-------------------------------------------------------------------------*/
template<class T> TLVBase<T>::~TLVBase()
/* Destructor. Discards data storage.
---------------------------------------------------------------------------*/
{
delete [] mVect;
}
/*-------------------------------------------------------------------------*/
template<class T> int TLVBase<T>::Compare(const TLVBase<T> &v) const
/* Compares the current vector with another on an element by element base.
---------------------------------------------------------------------------*/
{
iter_t i, j;
for (bool ok1 = IterFirst(i), ok2 = v.IterFirst(j); ok1 && ok2;
ok1 = IterNext(i), ok2 = v.IterNext(j))
{
int result = mCompare(operator[](i), v[j]);
if (result) return result;
}
// Break ties on number of elements
return (int)Count() - (int)v.Count();
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLVBase<T>::Contains(const T &t) const
/* Checks if a given value appears in the vector.
---------------------------------------------------------------------------*/
{
return IsValidIndex(IndexOf(t));
}
/*-------------------------------------------------------------------------*/
template<class T> void TLVBase<T>::DoAll(void (*f)(T &, va_list), ...)
/* Applies a given function to all elements in the vector.
---------------------------------------------------------------------------*/
{
va_list args;
va_start(args, f);
iter_t i;
for (bool ok = IterFirst(i); ok; ok = IterNext(i))
f(operator [](i), args);
va_end(args);
}
/*-------------------------------------------------------------------------*/
template<class T>
void TLVBase<T>::DoAll(void (*f)(const T &, va_list), ...) const
/* Applies a given function to all elements in the vector.
---------------------------------------------------------------------------*/
{
va_list args;
va_start(args, f);
iter_t i;
for (bool ok = IterFirst(i); ok; ok = IterNext(i))
f(operator [](i), args);
va_end(args);
}
/*-------------------------------------------------------------------------*/
template<class T>
index_t TLVBase<T>::DoWhile(bool (*f)(T &, va_list), ...)
/* Applies a given function to elements in the vector while the function
returns nonzero. It returns the index of the element that first caused
the function to return zero.
---------------------------------------------------------------------------*/
{
va_list args;
va_start(args, f);
iter_t i;
for (bool ok = IterFirst(i); ok; ok = IterNext(i))
if (!f(operator [](i), args))
break;
va_end(args);
return UnmapIndex(i.ix);
}
/*-------------------------------------------------------------------------*/
template<class T>
index_t TLVBase<T>::DoWhile(bool (*f)(const T &, va_list), ...) const
/* Applies a given function to elements in the vector while the function
returns nonzero. It returns the index of the element that first caused
the function to return zero.
---------------------------------------------------------------------------*/
{
va_list args;
va_start(args, f);
iter_t i;
for (bool ok = IterFirst(i); ok; ok = IterNext(i))
if (!f(operator [](i), args))
break;
va_end(args);
return UnmapIndex(i.ix);
}
/*-------------------------------------------------------------------------*/
template<class T>
index_t TLVBase<T>::DoUntil(bool (*f)(T &, va_list), ...)
/* Applies a given function to elements in the vector until the function
returns nonzero. It returns the index of the element that first caused
the function to return nonzero.
---------------------------------------------------------------------------*/
{
va_list args;
va_start(args, f);
iter_t i;
for (bool ok = IterFirst(i); ok; ok = IterNext(i))
if (f(operator [](i), args))
break;
va_end(args);
return UnmapIndex(i.ix);
}
/*-------------------------------------------------------------------------*/
template<class T>
index_t TLVBase<T>::DoUntil(bool (*f)(const T &, va_list), ...) const
/* Applies a given function to elements in the vector until the function
returns nonzero. It returns the index of the element that first caused
the function to return nonzero.
---------------------------------------------------------------------------*/
{
va_list args;
va_start(args, f);
iter_t i;
for (bool ok = IterFirst(i); ok; ok = IterNext(i))
if (f(operator [](i), args))
break;
va_end(args);
return UnmapIndex(i.ix);
}
/*-------------------------------------------------------------------------*/
template<class T> void TLVBase<T>::Duplicate(const T *ar, size_t sz)
/* Makes the current vector a duplicate of the passed in C-style vector.
---------------------------------------------------------------------------*/
{
if (mSize != sz)
{
delete [] mVect;
mVect = new T[mSize = sz];
}
TLX_ASSERT(mVect != 0 || mSize == 0);
T *dptr = mVect;
const T *sptr = ar;
for (size_t i = mSize; i; i--)
*dptr++ = *sptr++;
}
/*-------------------------------------------------------------------------*/
template<class T> void TLVBase<T>::Fill(const T &t)
/* Fills the entire vector with the given value.
---------------------------------------------------------------------------*/
{
T *tptr = mVect;
for (size_t i = mSize; i; i--)
*tptr++ = t;
}
/*-------------------------------------------------------------------------*/
template<class T> void TLVBase<T>::ExpandBy(size_t delta)
/* Expands the size of the vector by the given amount.
---------------------------------------------------------------------------*/
{
// Careful with size_t overflow
TLX_ASSERT(delta <= MaxSize() - mSize);
Resize(mSize + delta);
}
/*-------------------------------------------------------------------------*/
template<class T> index_t TLVBase<T>::IndexOf(const T &t) const
/* Returns the index of the (first occurrence of the) value in the vector.
---------------------------------------------------------------------------*/
{
iter_t i;
for (bool ok = IterFirst(i); ok; ok = IterNext(i))
{
//if (mCompare(operator [](i), t) == 0)
if (operator[](i) == t)
break;
}
return UnmapIndex(i.ix);;
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLVBase<T>::IsValidIndex(index_t i) const
/* Checks if the given index is valid for the vector, returning nonzero
if it is, else zero.
---------------------------------------------------------------------------*/
{
return i >= Mini() && i <= Maxi();
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLVBase<T>::IterFirst(iter_t &i) const
/* Initializes the iterator to address the first element of the vector.
Returns nonzero if the iterator is valid after the operation, else zero.
---------------------------------------------------------------------------*/
{
return ((tSize)(i.ix = 0)) < mSize;
}
#ifdef _MSC_VER
#pragma optimize( "g", off ) // Code causes P2 internal compiler error
#endif
/*-------------------------------------------------------------------------*/
template<class T> bool TLVBase<T>::IterLast(iter_t &i) const
/* Initializes the iterator to address the last element of the vector.
Returns nonzero if the iterator is valid after the operation, else zero.
---------------------------------------------------------------------------*/
{
return (i.ix = mSize - 1) >= 0;
}
#ifdef _MSC_VER
#pragma optimize( "", on )
#endif
/*-------------------------------------------------------------------------*/
template<class T> bool TLVBase<T>::IterNext(iter_t &i) const
/* Advances the iterator to address the next element of the vector.
Returns nonzero if the iterator is valid after the operation, else zero.
---------------------------------------------------------------------------*/
{
return ((tSize)(++i.ix)) < mSize;
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLVBase<T>::IterPrev(iter_t &i) const
/* Advances the iterator to address the previous element of the vector.
Returns nonzero if the iterator is valid after the operation, else zero.
---------------------------------------------------------------------------*/
{
return --i.ix >= 0;
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLVBase<T>::OK() const
/* Checks the class invariants, returning nonzero if all is well.
---------------------------------------------------------------------------*/
{
return (mVect && mSize) || (!mVect && !mSize);
}
/*-------------------------------------------------------------------------*/
template<class T> TLVBase<T> &TLVBase<T>::operator =(const T &t)
/* Overloading of assignment operator that allows assignment of a single
element to the vector. The previous contents are lost.
---------------------------------------------------------------------------*/
{
Duplicate(&t, 1);
return *this;
}
/*-------------------------------------------------------------------------*/
template<class T>
TLVBase<T> &TLVBase<T>::operator =(const TLVBase<T> &ar)
/* Overloading of the assignment operator.
---------------------------------------------------------------------------*/
{
if (this != &ar) Duplicate(ar.mVect, ar.mSize);
return *this;
}
/*-------------------------------------------------------------------------*/
template<class T> T &TLVBase<T>::operator [](index_t i)
/* Returns reference to the indicated element in the vector. The access
is range checked and will throw a TLXIndex exception if the index is
out of range.
---------------------------------------------------------------------------*/
{
if (!IsValidIndex(i))
THROW(TLXIndex(LOCUS, i));
return mVect[MapIndex(i)];
}
/*-------------------------------------------------------------------------*/
template<class T> const T &TLVBase<T>::operator [](index_t i) const
/* Returns reference to the indicated element in the vector. The access
is range checked and will throw a TLXIndex exception if the index is
out of range.
---------------------------------------------------------------------------*/
{
if (!IsValidIndex(i))
THROW(TLXIndex(LOCUS, i));
return mVect[MapIndex(i)];
}
/*-------------------------------------------------------------------------*/
template<class T> ostream &TLVBase<T>::PrintOn(ostream &os) const
/* Prints the contents of the vector on the given stream. The vector is
preceded by a prefix; elements are surrounded by pre- and postfixes,
and the vector is concluded with a general postfix.
---------------------------------------------------------------------------*/
{
iter_t i;
if (sPre) os << sPre;
for (bool ok = IterFirst(i); ok; ok = IterNext(i))
{
if (sPreSep) os << sPreSep;
mOutF(os, operator[](i));
if (sPostSep) os << sPostSep;
}
if (sPost)
return os << sPost;
else
return os;
}
/*-------------------------------------------------------------------------*/
template<class T> void TLVBase<T>::Resize(size_t newsize)
/* Changes the allocated size of the vector. The elements common to the
old and the new vector sizes are left as is.
---------------------------------------------------------------------------*/
{
if (newsize == mSize)
return;
TLX_ASSERT(newsize <= MaxSize());
if (newsize == 0)
{
delete [] mVect;
mVect = 0;
mSize = 0;
return;
}
T *tmp = new T[newsize];
TLX_ASSERT_PTR(tmp);
for (size_t i = 0, m = tlMin(newsize, mSize); i < m; i++)
tmp[i] = mVect[i];
delete [] mVect;
mVect = tmp;
mSize = newsize;
}
/*-------------------------------------------------------------------------*/
template<class T> void TLVBase<T>::ShrinkBy(size_t delta)
/* Reduces the allocated size of the vector by the indicated amount.
---------------------------------------------------------------------------*/
{
TLX_ASSERT(delta <= mSize);
Resize(mSize - delta);
}
#endif // _TLX_VBASE_CPP