/* ** 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