/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see .
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWLib *
* *
* $Archive:: /Commando/Code/wwlib/simplevec.h $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 5/16/01 10:42a $*
* *
* $Revision:: 16 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* SimpleVecClass::SimpleVecClass -- Constructor *
* SimpleVecClass::~SimpleVecClass -- Destructor *
* SimpleVecClass::Resize -- resize the array *
* SimpleVecClass::Uninitialised_Grow -- upscale the array, don't copy contents *
* SimpleDynVecClass::~SimpleDynVecClass -- Destructor *
* SimpleDynVecClass::SimpleDynVecClass -- Constructor *
* SimpleDynVecClass::Resize -- Resize the array *
* SimpleDynVecClass::Add -- Add an item to the end of the array *
* SimpleDynVecClass::Delete -- Delete an item from the array *
* SimpleDynVecClass::Delete_Range -- delete several items from the array *
* SimpleDynVecClass::Delete_All -- delete all items from the array *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef SIMPLEVEC_H
#define SIMPLEVEC_H
#include "always.h"
#include
#include // for memmove
#if (_MSC_VER >= 1200)
#pragma warning (push)
#pragma warning (disable:4702) // disabling the "unreachable code" warning.
#endif
/**
** SimpleVecClass
** This is a template similar to VectorClass (found in Vector.h) except that it is designed
** specifically to work with data types that are "memcopy-able".
** DON'T USE THIS TEMPLATE IF YOUR CLASS REQUIRES A DESTRUCTOR!!!
*/
template class SimpleVecClass
{
public:
SimpleVecClass(int size = 0);
virtual ~SimpleVecClass(void);
T & operator[](int index) { assert(index < VectorMax); return(Vector[index]); }
T const & operator[](int index) const { assert(index < VectorMax); return(Vector[index]); }
int Length(void) const { return VectorMax; }
virtual bool Resize(int newsize);
virtual bool Uninitialised_Grow(int newsize);
void Zero_Memory(void) { if (Vector != NULL) { memset(Vector,0,VectorMax * sizeof(T)); } }
protected:
T * Vector;
int VectorMax;
};
/***********************************************************************************************
* SimpleVecClass::SimpleVecClass -- Constructor *
* *
* INPUT: *
* size - initial size of the vector *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/25/00 gth : Created. *
*=============================================================================================*/
template
inline SimpleVecClass::SimpleVecClass(int size) :
Vector(NULL),
VectorMax(0)
{
if (size > 0) {
Resize(size);
}
}
/***********************************************************************************************
* SimpleVecClass::~SimpleVecClass -- Destructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/25/00 gth : Created. *
*=============================================================================================*/
template
inline SimpleVecClass::~SimpleVecClass(void)
{
if (Vector != NULL) {
delete[] Vector;
Vector = NULL;
VectorMax = 0;
}
}
/***********************************************************************************************
* SimpleVecClass::Resize -- resize the array *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/25/00 gth : Created. *
*=============================================================================================*/
template
inline bool SimpleVecClass::Resize(int newsize)
{
if (newsize == VectorMax) {
return true;
}
if (newsize > 0) {
/*
** Allocate a new vector of the size specified. The default constructor
** will be called for every object in this vector.
*/
T * newptr = new T[newsize];
/*
** If there is an old vector, then it must be copied (as much as is feasible)
** to the new vector.
*/
if (Vector != NULL) {
/*
** Mem copy as much of the old vector into the new vector as possible.
*/
int copycount = (newsize < VectorMax) ? newsize : VectorMax;
memcpy(newptr,Vector,copycount * sizeof(T));
/*
** Delete the old vector.
*/
delete[] Vector;
Vector = NULL;
}
/*
** Assign the new vector data to this class.
*/
Vector = newptr;
VectorMax = newsize;
} else {
/*
** Delete entire vector and reset counts
*/
VectorMax = 0;
if (Vector != NULL) {
delete[] Vector;
Vector = NULL;
}
}
return true;
}
/***********************************************************************************************
* SimpleVecClass::Uninitialised_Grow -- resize the array if current array is too small. *
* Note that it the function doesn't copy the contents so if resising occurs (contents are *
* assumed uninitialised after the call). *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 6/6/00 jani : Created. *
*=============================================================================================*/
template
inline bool SimpleVecClass::Uninitialised_Grow(int newsize)
{
if (newsize <= VectorMax) {
return true;
}
if (newsize > 0) {
/*
** Allocate a new vector of the size specified. The default constructor
** will be called for every object in this vector.
*/
delete[] Vector;
Vector = new T[newsize];
VectorMax=newsize;
}
return true;
}
/**
** SimpleDynVecClass
** This is also a template designed to work with simple data types. It is designed to work
** just like DynamicVectorClass except that it assumes that the data type used can be
** legally mem-copied.
** DON'T USE THIS TEMPLATE IF YOUR CLASS REQUIRES A DESTRUCTOR!!!
**
** The automatic resizing behavior for this class is a little different than DynamicVectorClass.
** When the vector needs to be resized, it grows by 25% and if it ever shrinks to 75% usage,
** it resizes downwards. In addition, when adding objects, you can pass in a "next-size-hint"
** which is the minimum size the vector will need to be once you are done adding your set of
** objects. This will cause it to resize to at least that size if it needs to resize. Just
** leave the parameter at its default value for default behavior.
*/
template class SimpleDynVecClass : public SimpleVecClass
{
public:
SimpleDynVecClass(int size = 0);
virtual ~SimpleDynVecClass(void);
// Array-like access (does not grow)
int Count(void) const { return(ActiveCount); }
T & operator[](int index) { assert(index < ActiveCount); return(Vector[index]); }
T const & operator[](int index) const { assert(index < ActiveCount); return(Vector[index]); }
// Change maximum size of vector
virtual bool Resize(int newsize);
// Add object to vector (growing as necessary).
bool Add(T const & object,int new_size_hint = 0);
// Add room for multiple object to vector. Pointer to first slot added is returned.
T * Add_Multiple( int number_to_add );
// Delete objects from the vector
bool Delete(int index,bool allow_shrink = true);
bool Delete(T const & object,bool allow_shrink = true);
bool Delete_Range(int start,int count,bool allow_shrink = true);
void Delete_All(bool allow_shrink = true);
protected:
bool Grow(int new_size_hint);
bool Shrink(void);
int Find_Index(T const & object);
int ActiveCount;
};
/***********************************************************************************************
* SimpleDynVecClass::SimpleDynVecClass -- Constructor *
* *
* INPUT: *
* size - initial size of the allocated vector *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/25/00 gth : Created. *
*=============================================================================================*/
template
inline SimpleDynVecClass::SimpleDynVecClass(int size) :
SimpleVecClass(size),
ActiveCount(0)
{
}
/***********************************************************************************************
* SimpleDynVecClass::~SimpleDynVecClass -- Destructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/25/00 gth : Created. *
*=============================================================================================*/
template
inline SimpleDynVecClass::~SimpleDynVecClass(void)
{
if (Vector != NULL) {
delete[] Vector;
Vector = NULL;
}
}
/***********************************************************************************************
* SimpleDynVecClass::Resize -- Resize the array *
* *
* INPUT: *
* newsize - new desired size of the array *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/25/00 gth : Created. *
*=============================================================================================*/
template
inline bool SimpleDynVecClass::Resize(int newsize)
{
if (SimpleVecClass::Resize(newsize)) {
if (Length() < ActiveCount) ActiveCount = Length();
return(true);
}
return(false);
}
/***********************************************************************************************
* SimpleDynVecClass::Add -- Add an item to the end of the array *
* *
* INPUT: *
* object - object to add to the array *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/25/00 gth : Created. *
*=============================================================================================*/
template
inline bool SimpleDynVecClass::Add(T const & object,int new_size_hint)
{
if (ActiveCount >= VectorMax) {
/*
** We are out of space so tell the vector to grow
*/
if (!Grow(new_size_hint)) {
return false;
}
}
/*
** There is room for the new object now. Add it to the end of the object vector.
*/
(*this)[ActiveCount++] = object;
return true;
}
/***********************************************************************************************
* SimpleDynVecClass::Add_Multiple -- Add room for multiple object to vector. *
* *
* INPUT: number of object slots to add *
* *
* OUTPUT: pointer to first slot added is returned. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/25/01 bmg : Created. *
*=============================================================================================*/
template
inline T * SimpleDynVecClass::Add_Multiple( int number_to_add )
{
int index = ActiveCount;
ActiveCount += number_to_add;
if (ActiveCount >= VectorMax) {
/*
** We are out of space so tell the vector to grow
*/
Grow( ActiveCount );
}
return &Vector[index];
}
/***********************************************************************************************
* SimpleDynVecClass::Delete -- Delete an item from the array *
* *
* This causes the items below the specified index to be mem-moved up. *
* *
* INPUT: *
* index - index of the entry to delete *
* allow_shrink - should the vector be allowed to resize *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/25/00 gth : Created. *
*=============================================================================================*/
template
inline bool SimpleDynVecClass::Delete(int index,bool allow_shrink)
{
assert(index < ActiveCount);
/*
** If there are any objects past the index that was deleted, memcopy
** those objects to collapse the array. NOTE: again, this template
** cannot be used for classes that cannot be memcopied!!
*/
if (index < ActiveCount-1) {
memmove(&(Vector[index]),&(Vector[index+1]),(ActiveCount - index - 1) * sizeof(T));
}
ActiveCount--;
/*
** We deleted something so we may need to shrink
*/
if (allow_shrink) {
Shrink();
}
return true;
}
/***********************************************************************************************
* SimpleDynVecClass::Delete -- Remove the specified object from the vector. *
* *
* This routine will delete the object referenced from the vector. All objects in the *
* vector that follow the one deleted will be moved "down" to fill the hole. *
* *
* INPUT: object -- Reference to the object in this vector that is to be deleted. *
* allow_shrink -- should the vector be allowed to shrink if it is wasting space? *
* *
* OUTPUT: bool; Was the object deleted successfully? *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/10/1995 JLB : Created. *
*=============================================================================================*/
template
inline bool SimpleDynVecClass::Delete(T const & object,bool allow_shrink)
{
int id = Find_Index(object);
if (id != -1) {
return(Delete(id),allow_shrink);
}
return(false);
}
/***********************************************************************************************
* SimpleDynVecClass::Delete_Range -- delete several items from the array *
* *
* This causes the items below the specified index range to be mem-moved up. *
* *
* INPUT: *
* start - starting index to delete *
* count - number of entries to delete *
* allow_shrink - should the vector be allowed to shrink *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/25/00 gth : Created. *
*=============================================================================================*/
template
inline bool SimpleDynVecClass::Delete_Range(int start,int count,bool allow_shrink)
{
assert(start >= 0);
assert(start <= ActiveCount - count);
/*
** If there are any objects past the index that was deleted, memcopy
** those objects to collapse the array. NOTE: again, this template
** cannot be used for classes that cannot be memcopied!!
*/
if (start < ActiveCount - count) {
memmove(&(Vector[start]),&(Vector[start + count]),(ActiveCount - start - count) * sizeof(T));
}
ActiveCount -= count;
/*
** We deleted something so we may need to shrink
*/
if (allow_shrink) {
Shrink();
}
return true;
}
/***********************************************************************************************
* SimpleDynVecClass::Delete_All -- delete all items from the array *
* *
* Internally, this just resets the ActiveCount... *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/25/00 gth : Created. *
*=============================================================================================*/
template
inline void SimpleDynVecClass::Delete_All(bool allow_shrink)
{
ActiveCount = 0;
/*
** We deleted something so we may need to shrink
*/
if (allow_shrink) {
Shrink();
}
}
/***********************************************************************************************
* SimpleDynVecClass::Grow -- increase the size of the array *
* *
* Internally, this just resets the ActiveCount... *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/25/00 gth : Created. *
*=============================================================================================*/
template
inline bool SimpleDynVecClass::Grow(int new_size_hint)
{
/*
** Vector should grow to 25% bigger, grow at least 4 elements,
** and grow at least up to the user's new_size_hint
*/
int new_size = MAX(Length() + Length()/4,Length() + 4);
new_size = MAX(new_size,new_size_hint);
return Resize(new_size);
}
/***********************************************************************************************
* SimpleDynVecClass::Shrink -- reduce the size of the array *
* *
* Internally, this just resets the ActiveCount... *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/25/00 gth : Created. *
*=============================================================================================*/
template
inline bool SimpleDynVecClass::Shrink(void)
{
/*
** Shrink the array if it is wasting more than 25%
*/
if (ActiveCount < VectorMax/4) {
return Resize(ActiveCount);
}
return true;
}
/***********************************************************************************************
* SimpleDynVecClass::Find_Index -- Find matching value in the dynamic vector. *
* *
* Use this routine to find a matching object (by value) in the vector. Unlike the base *
* class ID function of similar name, this one restricts the scan to the current number *
* of valid objects. *
* *
* INPUT: object -- A reference to the object that a match is to be found in the *
* vector. *
* *
* OUTPUT: Returns with the index number of the object that is equivalent to the one *
* specified. If no equivalent object could be found then -1 is returned. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/13/1995 JLB : Created. *
*=============================================================================================*/
template
inline int SimpleDynVecClass::Find_Index(T const & object)
{
for (int index = 0; index < Count(); index++) {
if ((*this)[index] == object) return(index);
}
return(-1);
}
#if (_MSC_VER >= 1200)
#pragma warning (pop)
#endif
#endif // SIMPLEVEC_H