/* =========================================================================== 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 #pragma once #if defined(GAME_DLL) // // game dll specific defines // #include "../fgame/g_local.h" #define CONTAINER_Error gi.Error #define CONTAINER_DPrintf gi.DPrintf #define CONTAINER_WDPrintf(text) gi.DPrintf(text) #elif defined(CGAME_DLL) // // cgame dll specific defines // #include "../cgame/cg_local.h" #define CONTAINER_Error cgi.Error #define CONTAINER_DPrintf cgi.DPrintf #define CONTAINER_WDPrintf(text) cgi.DPrintf(text) #else // // client specific defines // #define CONTAINER_Error Com_Error #define CONTAINER_DPrintf Com_DPrintf #define CONTAINER_WDPrintf(text) Com_DPrintf(text) #endif class Archiver; template class Container { private: Type* objlist; int numobjects; int maxobjects; private: void Copy(const Container& container); public: Container(); Container(const Container& 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& operator=(const Container& container); }; template Container::Container() { objlist = NULL; numobjects = 0; maxobjects = 0; } template Container::Container(const Container& container) { objlist = NULL; Copy(container); } template Container::~Container() { FreeObjectList(); } template int Container::AddObject(const Type& obj) { if (!objlist) { Resize(10); } if (numobjects >= maxobjects) { Resize(numobjects * 2); } objlist[numobjects] = obj; numobjects++; return numobjects; } template int Container::AddUniqueObject(const Type& obj) { int index; index = IndexOfObject(obj); if (!index) { index = AddObject(obj); } return index; } template void Container::AddObjectAt(int index, const Type& obj) { if (index > maxobjects) { Resize(index); } if (index > numobjects) { numobjects = index; } SetObjectAt(index, obj); } template Type* Container::AddressOfObjectAt(int index) { if (index > maxobjects) { CONTAINER_Error( ERR_DROP, "Container::AddressOfObjectAt : index is greater than maxobjects"); } if (index > numobjects) { numobjects = index; } return &objlist[index - 1]; } /*template< class Type > void Container::Archive( Archiver &arc ) { }*/ template void Container::ClearObjectList(void) { if (objlist && numobjects) { delete[] objlist; if (maxobjects == 0) { objlist = NULL; return; } objlist = new Type[maxobjects]; numobjects = 0; } } template void Container::Fix(void) { if (!objlist || !numobjects) { return; } Type* newlist = new Type[numobjects]; int j = 0; for (int i = 0; i < numobjects; i++) { if (objlist[i] == NULL) { continue; } newlist[j] = objlist[i]; j++; } numobjects = j; delete[] objlist; objlist = newlist; if (!numobjects) { ClearObjectList(); } } template void Container::FreeObjectList(void) { if (objlist) { delete[] objlist; } objlist = NULL; numobjects = 0; maxobjects = 0; } template int Container::IndexOfObject(const Type& obj) { int i; if (!objlist) { return 0; } for (i = 0; i < numobjects; i++) { if (objlist[i] == obj) { return i + 1; } } return 0; } template void Container::InsertObjectAt(int index, const Type& obj) { 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; } } template int Container::MaxObjects(void) const { return maxobjects; } template int Container::NumObjects(void) const { return numobjects; } template Type& Container::ObjectAt(const size_t index) const { if ((index <= 0) || (index > numobjects)) { CONTAINER_Error(ERR_DROP, "Container::ObjectAt : index out of range"); } return objlist[index - 1]; } template bool Container::ObjectInList(const Type& obj) { if (!IndexOfObject(obj)) { return false; } return true; } template void Container::RemoveObjectAt(int index) { int i; if (!objlist) { return; } if ((index <= 0) || (index > numobjects)) { return; } i = index - 1; numobjects--; for (i = index - 1; i < numobjects; i++) { objlist[i] = objlist[i + 1]; } } template void Container::RemoveObject(const Type& obj) { int index; index = IndexOfObject(obj); assert(index); if (!index) { CONTAINER_WDPrintf("Container::RemoveObject : Object not in list\n"); return; } RemoveObjectAt(index); } template void Container::Reset() { objlist = NULL; numobjects = 0; maxobjects = 0; } template void Container::Resize(int maxelements) { 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; } } template void Container::SetObjectAt(int index, const Type& obj) { if (!objlist) { return; } if ((index <= 0) || (index > numobjects)) { CONTAINER_Error(ERR_DROP, "Container::SetObjectAt : index out of range"); } objlist[index - 1] = obj; } template void Container::Sort(int (*compare)(const void* elem1, const void* elem2)) { if (!objlist) { return; } qsort((void*)objlist, (size_t)numobjects, sizeof(Type), compare); } template Type& Container::operator[](const int index) const { return ObjectAt(index + 1); } template void Container::Copy(const Container& container) { int i; if (&container == this) { return; } FreeObjectList(); numobjects = container.numobjects; maxobjects = container.maxobjects; objlist = NULL; if (container.objlist == NULL || !container.maxobjects) { return; } Resize(maxobjects); if (!container.numobjects) { return; } for (i = 0; i < container.numobjects; i++) { objlist[i] = container.objlist[i]; } return; } template Container& Container::operator=(const Container& container) { Copy(container); return *this; }