openmohaa/code/qcommon/container.h

488 lines
9.7 KiB
C
Raw Normal View History

2016-03-27 11:49:47 +02:00
/*
===========================================================================
Copyright (C) 2008 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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 2 of the License,
or (at your option) any later version.
OpenMoHAA source code 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 OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// container.h: C++ Container
#ifndef __CONTAINER_H__
#define __CONTAINER_H__
#ifdef GAME_DLL
#ifdef WIN32
2023-02-04 19:56:06 +01:00
#define glbprintf(text) gi.Printf(text)
2016-03-27 11:49:47 +02:00
#else
2023-02-04 19:56:06 +01:00
#define glbprintf(text)
2016-03-27 11:49:47 +02:00
#endif
#elif defined CGAME_DLL
2023-02-04 19:56:06 +01:00
#define glbprintf(text) cgi.Printf(text)
2016-03-27 11:49:47 +02:00
#else
2023-02-04 19:56:06 +01:00
#define glbprintf(text) printf(text)
2016-03-27 11:49:47 +02:00
#endif
#ifdef _DEBUG
2023-02-04 19:56:06 +01:00
#define CONTAINER_Error(id, text) \
glbprintf(text); \
assert(0);
2016-03-27 11:49:47 +02:00
#else
2023-02-04 19:56:06 +01:00
#define CONTAINER_Error(id, text) throw(text) // gi.Error
2016-03-27 11:49:47 +02:00
#endif
2023-02-04 19:56:06 +01:00
#define CONTAINER_DPrintf(text) glbprintf(text)
#define CONTAINER_WDPrintf(text) glbprintf(text)
2016-03-27 11:49:47 +02:00
class Archiver;
2023-02-04 19:56:06 +01:00
template<class Type>
2016-03-27 11:49:47 +02:00
class Container
{
private:
2023-02-04 19:56:06 +01:00
Type* objlist;
int numobjects;
int maxobjects;
2016-03-27 11:49:47 +02:00
private:
2023-02-04 19:56:06 +01:00
void Copy(const Container<Type>& container);
2016-03-27 11:49:47 +02:00
public:
2023-02-04 19:56:06 +01:00
Container();
Container(const Container<Type>& container);
~Container();
void Archive(Archiver& arc);
void Archive(Archiver& arc, void (*ArchiveFunc)(Archiver& arc, Type* obj));
int AddObject(const Type& obj);
int AddUniqueObject(const Type& obj);
void AddObjectAt(int index, const Type& obj);
Type* AddressOfObjectAt(int index);
// void Archive( Archiver &arc );
void ClearObjectList(void);
void Fix(void);
void FreeObjectList(void);
int IndexOfObject(const Type& obj);
void InsertObjectAt(int index, const Type& obj);
int MaxObjects(void) const;
int NumObjects(void) const;
Type& ObjectAt(const size_t index) const;
bool ObjectInList(const Type& obj);
void RemoveObjectAt(int index);
void RemoveObject(const Type& obj);
void Reset(void);
void Resize(int maxelements);
void SetObjectAt(int index, const Type& obj);
void Sort(int (*compare)(const void* elem1, const void* elem2));
Type& operator[](const int index) const;
Container<Type>& operator=(const Container<Type>& container);
2016-03-27 11:49:47 +02:00
};
2023-02-04 19:56:06 +01:00
template<class Type>
2016-03-27 11:49:47 +02:00
Container<Type>::Container()
{
2023-02-04 19:56:06 +01:00
objlist = NULL;
numobjects = 0;
maxobjects = 0;
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
Container<Type>::Container(const Container<Type>& container)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
objlist = NULL;
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
Copy(container);
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
2016-03-27 11:49:47 +02:00
Container<Type>::~Container()
{
2023-02-04 19:56:06 +01:00
FreeObjectList();
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
int Container<Type>::AddObject(const Type& obj)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (!objlist) {
Resize(10);
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
if (numobjects >= maxobjects) {
Resize(numobjects * 2);
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
objlist[numobjects] = obj;
numobjects++;
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
return numobjects;
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
int Container<Type>::AddUniqueObject(const Type& obj)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
int index;
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
index = IndexOfObject(obj);
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
if (!index) {
index = AddObject(obj);
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
return index;
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
void Container<Type>::AddObjectAt(int index, const Type& obj)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (index > maxobjects) {
Resize(index);
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
if (index > numobjects) {
numobjects = index;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
SetObjectAt(index, obj);
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
Type* Container<Type>::AddressOfObjectAt(int index)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (index > maxobjects) {
CONTAINER_Error(
ERR_DROP,
"Container::AddressOfObjectAt : index is greater than maxobjects");
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
if (index > numobjects) {
numobjects = index;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
return &objlist[index - 1];
2016-03-27 11:49:47 +02:00
}
/*template< class Type >
void Container<Type>::Archive( Archiver &arc )
{
}*/
2023-02-04 19:56:06 +01:00
template<class Type>
void Container<Type>::ClearObjectList(void)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (objlist && numobjects) {
delete[] objlist;
if (maxobjects == 0) {
objlist = NULL;
return;
}
objlist = new Type[maxobjects];
numobjects = 0;
}
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
void Container<Type>::Fix(void)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (!objlist || !numobjects) {
return;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
Type* newlist = new Type[numobjects];
int j = 0;
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
for (int i = 0; i < numobjects; i++) {
if (objlist[i] == NULL) {
continue;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
newlist[j] = objlist[i];
j++;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
numobjects = j;
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
delete[] objlist;
objlist = newlist;
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
if (!numobjects) {
ClearObjectList();
}
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
void Container<Type>::FreeObjectList(void)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (objlist) {
delete[] objlist;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
objlist = NULL;
numobjects = 0;
maxobjects = 0;
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
int Container<Type>::IndexOfObject(const Type& obj)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
int i;
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
if (!objlist) {
return 0;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
for (i = 0; i < numobjects; i++) {
if (objlist[i] == obj) {
return i + 1;
}
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
return 0;
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
void Container<Type>::InsertObjectAt(int index, const Type& obj)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if ((index <= 0) || (index > numobjects + 1)) {
CONTAINER_Error(ERR_DROP,
"Container::InsertObjectAt : index out of range");
return;
}
numobjects++;
int arrayIndex = index - 1;
if (numobjects > maxobjects) {
maxobjects = numobjects;
if (!objlist) {
objlist = new Type[maxobjects];
objlist[arrayIndex] = obj;
return;
} else {
Type* temp = objlist;
if (maxobjects < numobjects) {
maxobjects = numobjects;
}
objlist = new Type[maxobjects];
int i;
for (i = arrayIndex - 1; i >= 0; i--) {
objlist[i] = temp[i];
}
objlist[arrayIndex] = obj;
for (i = numobjects - 1; i > arrayIndex; i--) {
objlist[i] = temp[i - 1];
}
delete[] temp;
}
} else {
for (int i = numobjects - 1; i > arrayIndex; i--) {
objlist[i] = objlist[i - 1];
}
objlist[arrayIndex] = obj;
}
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
int Container<Type>::MaxObjects(void) const
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
return maxobjects;
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
int Container<Type>::NumObjects(void) const
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
return numobjects;
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
Type& Container<Type>::ObjectAt(const size_t index) const
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if ((index <= 0) || (index > numobjects)) {
CONTAINER_Error(ERR_DROP, "Container::ObjectAt : index out of range");
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
return objlist[index - 1];
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
bool Container<Type>::ObjectInList(const Type& obj)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (!IndexOfObject(obj)) {
return false;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
return true;
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
void Container<Type>::RemoveObjectAt(int index)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
int i;
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
if (!objlist) {
return;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
if ((index <= 0) || (index > numobjects)) {
return;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
i = index - 1;
numobjects--;
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
for (i = index - 1; i < numobjects; i++) {
objlist[i] = objlist[i + 1];
}
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
void Container<Type>::RemoveObject(const Type& obj)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
int index;
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
index = IndexOfObject(obj);
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
assert(index);
if (!index) {
CONTAINER_WDPrintf("Container::RemoveObject : Object not in list\n");
return;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
RemoveObjectAt(index);
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
2016-03-27 11:49:47 +02:00
void Container<Type>::Reset()
{
2023-02-04 19:56:06 +01:00
objlist = NULL;
numobjects = 0;
maxobjects = 0;
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
void Container<Type>::Resize(int maxelements)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
Type* temp;
int i;
if (maxelements <= 0) {
FreeObjectList();
return;
}
if (!objlist) {
maxobjects = maxelements;
objlist = new Type[maxobjects];
} else {
temp = objlist;
maxobjects = maxelements;
if (maxobjects < numobjects) {
maxobjects = numobjects;
}
objlist = new Type[maxobjects];
for (i = 0; i < numobjects; i++) {
objlist[i] = temp[i];
}
delete[] temp;
}
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
void Container<Type>::SetObjectAt(int index, const Type& obj)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (!objlist) {
return;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
if ((index <= 0) || (index > numobjects)) {
CONTAINER_Error(ERR_DROP,
"Container::SetObjectAt : index out of range");
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
objlist[index - 1] = obj;
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
void Container<Type>::Sort(int (*compare)(const void* elem1, const void* elem2))
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (!objlist) {
return;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
qsort((void*)objlist, (size_t)numobjects, sizeof(Type), compare);
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
Type& Container<Type>::operator[](const int index) const
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
return ObjectAt(index + 1);
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
void Container<Type>::Copy(const Container<Type>& container)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
int i;
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
if (&container == this) {
return;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
FreeObjectList();
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
numobjects = container.numobjects;
maxobjects = container.maxobjects;
objlist = NULL;
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
if (container.objlist == NULL || !container.maxobjects) {
return;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
Resize(maxobjects);
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
if (!container.numobjects) {
return;
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
for (i = 0; i < container.numobjects; i++) {
objlist[i] = container.objlist[i];
}
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
return;
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
template<class Type>
Container<Type>& Container<Type>::operator=(const Container<Type>& container)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
Copy(container);
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
return *this;
2016-03-27 11:49:47 +02:00
}
#endif /* __CONTAINER_H__ */