/* ** 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 : Library * * * * $Archive:: /G/wwlib/uarray.h $* * * * Author:: Greg Hjelstrom * * * * $Modtime:: 9/24/99 1:56p $* * * * $Revision:: 7 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * UniqueArrayClass::UniqueArrayClass -- constructor * * UniqueArrayClass::~UniqueArrayClass -- destructor * * UniqueArrayClass::Add -- Add an item to the array * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #ifndef UARRAY_H #define UARRAY_H #ifndef HASHCALC_H #include "hashcalc.h" #endif #ifndef VECTOR_H #include "vector.h" #endif /* ** UniqueArrayClass ** This template class can be used to generate an array of unique objects ** amongst a huge list of objects which may or may not be unique. However, ** in order to use the UniqueArrayClass, you will need to implement a ** HashCalculatorClass for the type you are using. ** ** Note that the UniqueArrayClass does *copies* of the objects you are ** giving it. It is meant to be used with relatively lightweight objects. */ template class UniqueArrayClass { public: UniqueArrayClass(int initialsize,int growthrate,HashCalculatorClass * hasher); ~UniqueArrayClass(void); int Add(const T & new_item); int Count(void) const { return Get_Unique_Count(); } int Get_Unique_Count(void) const { return UniqueItems.Count(); } const T & Get(int index) const { return UniqueItems[index].Item; } const T & operator [] (int index) const { return Get(index); } private: enum { NO_ITEM = 0xFFFFFFFF }; class HashItem { public: T Item; int NextHashIndex; bool operator == (const HashItem & that) { return ((Item == that.Item) && (NextHashIndex == that.NextHashIndex)); } bool operator != (const HashItem & that) { return !(*this == that); } }; // Dynamic Vector of the unique items: DynamicVectorClass UniqueItems; // Hash table: int HashTableSize; int * HashTable; // object which does the hashing for the type HashCalculatorClass * HashCalculator; friend class VectorClass; friend class DynamicVectorClass; }; /*********************************************************************************************** * UniqueArrayClass::UniqueArrayClass -- constructor * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 5/29/98 GTH : Created. * *=============================================================================================*/ template UniqueArrayClass::UniqueArrayClass(int initial_size,int growth_rate,HashCalculatorClass * hasher) : UniqueItems(initial_size), HashCalculator(hasher) { // set the growth rate. UniqueItems.Set_Growth_Step(growth_rate); // sizing and allocating the actual hash table int bits = HashCalculator->Num_Hash_Bits(); assert(bits > 0); assert(bits < 24); HashTableSize = 1<::~UniqueArrayClass -- destructor * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 5/29/98 GTH : Created. * *=============================================================================================*/ template UniqueArrayClass::~UniqueArrayClass(void) { if (HashTable != NULL) { delete[] HashTable; HashTable = NULL; } } /*********************************************************************************************** * UniqueArrayClass::Add -- Add an item to the array * * * * Only adds the item to the end of the array if another duplicate item is not found. Returns * * the array index of where the item is stored. * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 5/29/98 GTH : Created. * *=============================================================================================*/ template inline int UniqueArrayClass::Add(const T & new_item) { /* ** Use the hash table to quickly (hopefully :-) detect ** whether this item is already in the array */ int num_hash_vals; HashCalculator->Compute_Hash(new_item); num_hash_vals = HashCalculator->Num_Hash_Values(); unsigned int lasthash = 0xFFFFFFFF; unsigned int hash; for (int hidx = 0; hidx < num_hash_vals; hidx++) { hash = HashCalculator->Get_Hash_Value(hidx); if (hash != lasthash) { int test_item_index = HashTable[hash]; while (test_item_index != 0xFFFFFFFF) { if (HashCalculator->Items_Match(UniqueItems[test_item_index].Item,new_item)) { return test_item_index; } test_item_index = UniqueItems[test_item_index].NextHashIndex; } } lasthash = hash; } /* ** Ok, this is a new item so add it (copy it!) into the array */ int index = UniqueItems.Count(); int hash_index = HashCalculator->Get_Hash_Value(0); HashItem entry; entry.Item = new_item; entry.NextHashIndex = HashTable[hash_index]; HashTable[hash_index] = index; UniqueItems.Add(entry); return index; } #endif // UARRAY_H