home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
tlx501.zip
/
SRC
/
VPVECTOR.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-08
|
15KB
|
426 lines
/****************************************************************************
$Id: vpvector.cpp 501.0 1995/03/07 12:26:28 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 TLVPVector. Class TLVPVector maintains a vector
of (void *). In order to allow easy resizes and such, we use the malloc()
family for memory allocations. (The pointers don't have constructors
or destructors anyway.)
$Log: vpvector.cpp $
Revision 501.0 1995/03/07 12:26:28 RON
Updated for TLX 5.01
Revision 1.9 1995/01/31 16:30:36 RON
Update for release 012
Added partial support for SunPro C++ compiler
Revision 1.8 1995/01/06 15:58:59 ron
Corrected Revision keyword
Revision 1.7 1994/11/16 15:46:22 ron
Added module info; rearranged #include directives
Revision 1.6 1994/09/28 14:48:07 ron
Removed Macintosh-style #include references
Revision 1.5 1994/09/27 20:23:37 ron
Changed path separator from / to \
Revision 1.4 1994/09/26 15:52:12 ron
Renamed SetSize() to Resize()
Revision 1.3 1994/09/07 15:46:17 ron
Small formatting changes
Revision 1.2 1994/09/06 14:10:31 ron
Adapted to changes in tlx.h
Revision 1.1 1994/08/16 18:13:25 ron
Initial revision
****************************************************************************/
#include <tlx\501\_build.h>
TLX_MODULE_INFO("$Revision: 501.0 $");
#include <stdlib.h> // For malloc() etc.
#include <string.h> // For memcpy() etc.
#include <tlx\501\except.h>
#include <tlx\501\vparrays.h> // Class declaration
/*---------------------------------------------------------------------------
We assume throughout that NULL pointers are represented as an all zero
bit pattern. On platforms where this is not the case, we must adjust
our implementation. For now, just verify that NULL is all zeroes.
---------------------------------------------------------------------------*/
#ifndef _NULL_IS_0
#error NULL pointers are nonzero; contact Tarma Software Research.
#endif
/*-------------------------------------------------------------------------*/
TLVPVector::TLVPVector(size_t aSize)
/* Constructor to create a vector with a specified size; also doubles
as the default constructor, creating an empty vector.
---------------------------------------------------------------------------*/
: mVector(0), mSize(0), mOwner(false), mDeleteFunc(DefaultDelete)
{
Copy(aSize);
TLX_ASSERT(Size() == aSize);
}
/*-------------------------------------------------------------------------*/
TLVPVector::TLVPVector(void *aPtr)
/* Constructor creating a vector of 1 element.
---------------------------------------------------------------------------*/
: mVector(0), mSize(0), mOwner(false), mDeleteFunc(DefaultDelete)
{
Copy(1, &aPtr);
TLX_ASSERT(Size() == 1);
}
/*-------------------------------------------------------------------------*/
TLVPVector::TLVPVector(void **aVector, size_t aSize)
/* Constructor creating a copy of C-style vector with the given size.
---------------------------------------------------------------------------*/
: mVector(0), mSize(0), mOwner(false), mDeleteFunc(DefaultDelete)
{
Copy(aSize, aVector);
TLX_ASSERT(Size() == aSize);
}
/*-------------------------------------------------------------------------*/
TLVPVector::TLVPVector(const TLVPVector &aVector)
/* Copy constructor.
---------------------------------------------------------------------------*/
: mVector(0), mSize(0), mOwner(false), mDeleteFunc(DefaultDelete)
{
Copy(aVector.mSize, aVector.mVector);
TLX_ASSERT(Size() == aVector.Size());
}
/*-------------------------------------------------------------------------*/
TLVPVector::~TLVPVector()
/* Destructor. Discards the vector storage.
---------------------------------------------------------------------------*/
{
TLX_ASSERT(mVector != 0 || mSize == 0);
// Destroy pointed to objects, if we are the owner. Because we use a
// deletion function pointer, we can still invoke the correct deletion
// operation (it isn't a virtual function).
if (IsOwner())
RemoveAll();
if (mVector)
{
free(mVector);
mVector = 0;
}
}
/*-------------------------------------------------------------------------*/
bool TLVPVector::BecomeOwner(bool aFlag)
/* Sets or resets the owner status of the vector. If the vector is owner
of the pointed to objects, it will delete them if necessary.
---------------------------------------------------------------------------*/
{
bool oldOwner = mOwner;
mOwner = aFlag;
return oldOwner;
}
/*-------------------------------------------------------------------------*/
void TLVPVector::Copy(size_t aSize, void **aVector)
/* Helper function for the constructors and assignment operators.
Resizes the vector to match the indicated size, then copies the
contents of the (void *) vector (if any) to the current instance.
Returns nonzero if successful, else zero.
---------------------------------------------------------------------------*/
{
TLX_ASSERT(mVector == 0 || aVector != mVector);
Resize(aSize);
TLX_ASSERT(aSize == mSize);
// Before we copy the pointers, we must make sure that any
// currently pointed to objects are destroyed if we own them.
if (IsOwner())
RemoveAll(); // To destroy pointed to objects
if (aVector)
memcpy(mVector, aVector, mSize * sizeof(void *));
}
/*-------------------------------------------------------------------------*/
int TLVPVector::DefaultCompare(const void *aPtr1, const void *aPtr2)
/* Default comparison function for (void *). The pointer values themselves
are compared, rather than the pointed to objects.
Return value:
< 0 if aPtr1 is less than aPtr2
= 0 if aPtr1 is equal to aPtr2
> 0 if aPtr1 is greater than aPtr2
---------------------------------------------------------------------------*/
{
ptrdiff_t diff = (const char *)aPtr1 - (const char *)aPtr2;
return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
}
/*-------------------------------------------------------------------------*/
void TLVPVector::DefaultDelete(void *aPtr)
/* Default deletion function for (void *). The function applies operator
delete to the pointer.
---------------------------------------------------------------------------*/
{
delete aPtr;
}
/*-------------------------------------------------------------------------*/
void TLVPVector::RemoveAll()
/* Clears all pointers in the vector by setting them to 0. If we are owner
of the pointed to objects, they are destroyed as well.
---------------------------------------------------------------------------*/
{
TLX_ASSERT(mVector != 0 || mSize == 0);
if (IsOwner())
{
for (index_t i = 0; (tSize)i < mSize; i++)
if (mVector[i])
DeletePtr(mVector[i]);
}
memset(mVector, 0, mSize * sizeof(void *));
}
/*-------------------------------------------------------------------------*/
void TLVPVector::DeletePtr(void *aPtr)
/* Deletes a single element by calling the current deletion function.
---------------------------------------------------------------------------*/
{
TLX_ASSERT_PTR(mDeleteFunc);
(*mDeleteFunc)(aPtr);
}
/*-------------------------------------------------------------------------*/
void TLVPVector::ExpandBy(size_t aDelta)
/* Expands the size of the vector by a specified amount.
---------------------------------------------------------------------------*/
{
// We must be careful to avoid unsigned integer wrap-around
TLX_ASSERT(mSize < (kMaxSize - aDelta));
Resize(mSize + aDelta);
}
/*-------------------------------------------------------------------------*/
index_t TLVPVector::IndexOf(const void *aPtr) const
/* Finds the index of a given pointer value. The function performs a
linear search. Only the first occurrence of the value is found (if any).
The function returns the (first) index of the given pointer value, or
Maxi() + 1 if the pointer does not appear in the vector.
---------------------------------------------------------------------------*/
{
index_t aIndex;
for (aIndex = 0; (tSize)aIndex < mSize; aIndex++)
if (mVector[aIndex] == aPtr)
break;
return aIndex;
}
/*-------------------------------------------------------------------------*/
bool TLVPVector::IsValidIndex(index_t aIndex) const
/* Tests whether a given index is valid for the vector.
---------------------------------------------------------------------------*/
{
return aIndex >= Mini() && aIndex <= Maxi();
}
/*-------------------------------------------------------------------------*/
TLVPVector &TLVPVector::operator =(const TLVPVector &aVector)
/* Overloading of assignment operator for class TLVPVector. Copies
the pointed to vector, rather than the vector pointer. The pointed
to objects are not copied. If the vector is owner of the objects, they
are deleted first. After the assignment, the vector is *not* the owner
of the new elements.
---------------------------------------------------------------------------*/
{
if (this != &aVector)
{
Copy(aVector.mSize, aVector.mVector);
// We cannot own the new objects
mOwner = false;
}
return *this;
}
/*-------------------------------------------------------------------------*/
TLVPVector &TLVPVector::operator =(void *aPtr)
/* Overloading of assignment operator that assigns a single (void *)
to the current instance. The vector is reduced to a single element
as a result of the assignment. The currently pointed to objects are
deleted if we are the owner of them. The owner status of the vector
is not changed by the assignment operation.
---------------------------------------------------------------------------*/
{
Copy(1, &aPtr);
return *this;
}
/*-------------------------------------------------------------------------*/
void *&TLVPVector::operator [](index_t aIndex)
/* Overloading of the indexing operator for class TLVPVector. This version
performs range checking on the index, throwing an exception if the
index is out of range.
---------------------------------------------------------------------------*/
{
if (!IsValidIndex(aIndex))
THROW(TLXIndex(LOCUS, aIndex));
return mVector[aIndex];
}
/*-------------------------------------------------------------------------*/
void *TLVPVector::operator [](index_t aIndex) const
/* Overloading of the indexing operator for class TLVPVector. This version
performs range checking on the index, throwing an exception if the
index is out of range.
---------------------------------------------------------------------------*/
{
if (!IsValidIndex(aIndex))
THROW(TLXIndex(LOCUS, aIndex));
return mVector[aIndex];
}
/*-------------------------------------------------------------------------*/
void *&TLVPVector::PeekAt(index_t aIndex)
/* Returns a reference to the 'aIndex'th item in the vector.
---------------------------------------------------------------------------*/
{
TLX_ASSERT(aIndex >= Mini());
TLX_ASSERT(aIndex <= Maxi());
return mVector[aIndex];
}
/*-------------------------------------------------------------------------*/
void *TLVPVector::PeekAt(index_t aIndex) const
/* Returns the value of the 'aIndex'th item in the vector.
---------------------------------------------------------------------------*/
{
TLX_ASSERT(aIndex >= Mini());
TLX_ASSERT(aIndex <= Maxi());
return mVector[aIndex];
}
/*-------------------------------------------------------------------------*/
tDeleteFunc TLVPVector::SetDelete(tDeleteFunc aFunc)
/* Sets the deletion function pointer to the given function, while
returning the previous function pointer. If the new function pointer
is 0, the default deletion function is installed.
---------------------------------------------------------------------------*/
{
tDeleteFunc oldf = mDeleteFunc;
mDeleteFunc = aFunc ? aFunc : DefaultDelete;
return oldf;
}
/*-------------------------------------------------------------------------*/
void TLVPVector::Resize(size_t aSize)
/* Adjusts the size of the vector. If the current size is equal to the
requested size, nothing happens. If it is larger, then the additional
elements will be initialized to zero. If it is smaller, the discarded
elements will be deleted if we are the owner. In all cases, the elements
common to the old and the new sizes remain unchanged.
---------------------------------------------------------------------------*/
{
if (aSize == mSize)
return;
TLX_ASSERT(aSize <= MaxSize());
TLX_ASSERT(mVector != 0 || mSize == 0);
// If the new size is less than the old size, and we own the pointed
// to objects, we must delete the excess elements before the reallocation.
if (aSize < mSize && IsOwner())
{
for (index_t i = aSize; (tSize)i < mSize; i++)
if (mVector[i])
{
DeletePtr(mVector[i]);
mVector[i] = 0;
}
}
// We use the fact that realloc() will free an existing block if the new
// size is 0; also that it will work as malloc() when the old pointer
// was null.
void **tmpvect = (void **) realloc(mVector, aSize * sizeof(void *));
if (tmpvect)
{
// Reallocation succeeded. Zero out any new elements.
if (aSize > mSize)
memset(&tmpvect[mSize], 0, (aSize - mSize) * sizeof(void *));
}
else if (aSize == 0)
{
// Old vector is freed. No further action necessary.
}
else
{
// Failure to reallocate to a nonzero size.
THROW(TLXAlloc(LOCUS, aSize * sizeof(void *)));
}
mVector = tmpvect;
mSize = aSize;
TLX_ASSERT(mVector != 0 || mSize == 0);
}
/*-------------------------------------------------------------------------*/
void TLVPVector::ShrinkBy(size_t aDelta)
/* Reduces the size of the vector by a specified amount.
---------------------------------------------------------------------------*/
{
TLX_ASSERT(aDelta <= mSize);
Resize(mSize - aDelta);
}