Files
FC1/CryCommon/list2.h
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

414 lines
9.8 KiB
C++

////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: list2.h
// Version: v1.00
// Created: 28/5/2002 by Vladimir Kajalin
// Compilers: Visual Studio.NET
// Description: simple container, supports serialization
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#ifndef LIST_3DENGINE_H
#define LIST_3DENGINE_H
#include "platform.h"
#if defined(LINUX)
#include "ILog.h"
#include "ICryPak.h"
#else
#include <assert.h>
#endif
template <class T> class list2
{
T * m_pElements;
int m_nCount;
int m_nAllocatedCount;
public:
typedef T value_type;
int GetAllocatedMB() { return (m_nAllocatedCount*sizeof(T))/(1024*1024); }
int GetMemoryUsage() { return m_nAllocatedCount*sizeof(T);}
list2() { m_nCount=0; m_pElements=0; Reset(); }
~list2() { Reset(); }
void Free() { Reset(); }
void Reset()
{
if(m_pElements)
free (m_pElements);
m_pElements=0;
m_nCount=0;
m_nAllocatedCount= 0;
}
void Clear() { m_nCount=0; }
int Find(const T & p)
{
for(int i=0; i<m_nCount; i++)
if(p == (*this)[i])
return i;
return -1;;
}
inline void AddList(const list2<T> & lstAnother)
{
PreAllocate(m_nCount + lstAnother.Count());
memcpy(&m_pElements[m_nCount],&lstAnother.m_pElements[0],sizeof(m_pElements[0])*lstAnother.Count());
m_nCount += lstAnother.Count();
}
inline void AddList(T * pAnotherArray, int nAnotherCount)
{
PreAllocate(m_nCount + nAnotherCount);
memcpy(&m_pElements[m_nCount],pAnotherArray,sizeof(m_pElements[0])*nAnotherCount);
m_nCount += nAnotherCount;
}
inline void AddDebug(const char *p__FILE__, long n__LINE__, const T & p)
{
#ifdef _DEBUG
if( m_nCount >= m_nAllocatedCount )
{
assert(&p<m_pElements || &p>=(m_pElements+m_nAllocatedCount));
m_nAllocatedCount = m_nCount*2 + 8;
m_pElements = (T*)_realloc_dbg(m_pElements,m_nAllocatedCount*sizeof(T), _NORMAL_BLOCK, p__FILE__, n__LINE__);
assert(m_pElements);
}
memcpy(&m_pElements[m_nCount],&p,sizeof(m_pElements[m_nCount]));
m_nCount++;
#else
Add(p);
#endif
}
inline void Add(const T & p)
{
if( m_nCount >= m_nAllocatedCount )
{
assert(&p<m_pElements || &p>=(m_pElements+m_nAllocatedCount));
m_nAllocatedCount = m_nCount*2 + 8;
m_pElements = (T*)realloc(m_pElements,m_nAllocatedCount*sizeof(T));
assert(m_pElements);
}
memcpy(&m_pElements[m_nCount],&p,sizeof(m_pElements[m_nCount]));
m_nCount++;
}
void InsertBefore(const T & p, const unsigned int nBefore)
{
assert( nBefore>=0 && nBefore<=(unsigned int)m_nCount );
T tmp; Add(tmp); // add empty object to increase memory buffer
memmove(&(m_pElements[nBefore+1]), &(m_pElements[nBefore]), sizeof(T)*(m_nCount-nBefore-1));
m_pElements[nBefore] = p;
}
void PreAllocate(int elem_count, int nNewCount = 0)
{
if( elem_count > m_nAllocatedCount )
{
m_nAllocatedCount = elem_count;
T * new_elements = (T*)malloc(m_nAllocatedCount*sizeof(T));
assert(new_elements);
memset(new_elements, 0, sizeof(T)*m_nAllocatedCount);
memcpy(new_elements, m_pElements, sizeof(T)*m_nCount);
if(m_pElements)
free (m_pElements);
m_pElements = new_elements;
}
if(nNewCount)
m_nCount = nNewCount;
}
inline void Delete(const int nElemId, const int nElemCount = 1)
{
assert( nElemId >= 0 && nElemId+nElemCount <= m_nCount );
memcpy(&(m_pElements[nElemId]), &(m_pElements[nElemId+nElemCount]), sizeof(T)*(m_nCount-nElemId-nElemCount));
m_nCount-=nElemCount;
}
inline void DeleteFastUnsorted(const int nElemId, const int nElemCount = 1)
{
assert( nElemId >= 0 && nElemId+nElemCount <= m_nCount );
memcpy(&(m_pElements[nElemId]), &(m_pElements[m_nCount-nElemCount]), sizeof(T)*nElemCount);
m_nCount-=nElemCount;
}
inline bool Delete(const T & del)
{
bool bFound = false;
for( int i=0; i<Count(); i++ )
if(m_pElements[i] == del)
{
Delete(i);
i--;
bFound = true;
}
return bFound;
}
inline int Count() const { return m_nCount; }
inline unsigned int Size() const { return m_nCount; }
inline int IsEmpty() const { return m_nCount==0; }
inline T & operator [] (int i) const { assert( i>=0 && i<m_nCount ); return m_pElements[i]; }
inline T & GetAt (int i) const { assert( i>=0 && i<m_nCount ); return m_pElements[i]; }
inline T * Get (int i) const { assert( i>=0 && i<m_nCount ); return &m_pElements[i]; }
inline T * GetElements() { return m_pElements; }
inline T & Last() const { assert(m_nCount); return m_pElements[m_nCount-1]; }
inline void DeleteLast() { assert(m_nCount); m_nCount--; }
inline list2<T>& operator = (list2<T> & source_list)
{
Reset();
PreAllocate(source_list.Count()+2);
for(int i=0; i<source_list.Count(); i++)
Add(source_list[i]);
return *this;
}
bool operator == (const list2<T> & l)
{
if(Count() != l.Count())
return 0;
if(memcmp(m_pElements, l.m_pElements, m_nCount*sizeof(T))!=0)
return 0;
return 1;
}
bool operator != (const list2<T> & l)
{
return !(*this == l);
}
// Save/Load
void Save(const char * file_name)
{
FILE * f = fxopen(file_name, "wb");
if(f)
{
int size = sizeof(T);
fwrite(&size, 4, 1, f);
if(m_nCount)
fwrite(m_pElements, sizeof(T), m_nCount, f);
fclose(f);
}
}
void Load(const char * file_name, struct ICryPak *pPak)
{
Clear();
FILE * f;
f = pPak->FOpen(file_name, "rb");
if(!f)
return;
int size = 0;
pPak->FRead(&size, 4, 1, f);
while(!pPak->FEof(f) && sizeof(T)==size)
{
T tmp;
if(pPak->FRead(&tmp, 1, sizeof(T), f) == sizeof(T))
Add(tmp);
}
pPak->FClose(f);
}
// Save/Load
void SaveToBuffer(const unsigned char * pBuffer, int & nPos)
{
// copy size of element
int nSize = sizeof(T);
if(pBuffer)
memcpy((void*)&pBuffer[nPos],&nSize,4);
nPos+=4;
// copy count
if(pBuffer)
memcpy((void*)&pBuffer[nPos],&m_nCount,4);
nPos+=4;
// copy data
if(m_nCount)
{
if(pBuffer)
memcpy((void*)&pBuffer[nPos], m_pElements, sizeof(T)*m_nCount);
nPos += sizeof(T)*m_nCount;
}
}
void LoadFromBuffer(const unsigned char * pBuffer, int & nPos)
{
Reset();
// copy size of element
int nElemSize = 0;
memcpy(&nElemSize,(void*)&pBuffer[nPos],4);
assert(nElemSize == sizeof(T));
nPos+=4;
// copy count
int nNewCount=0;
memcpy((void*)&nNewCount,&pBuffer[nPos],4);
assert(nNewCount>=0 && nNewCount<1000000);
nPos+=4;
// copy data
if(nNewCount)
{
PreAllocate(nNewCount,nNewCount);
memcpy((void*)m_pElements, &pBuffer[nPos], sizeof(T)*nNewCount);
nPos += sizeof(T)*nNewCount;
}
}
// Sorting of objects
static int __cdecl Cmp_Ptrs1(const void* v1, const void* v2)
{
T* p1 = (T*)v1;
T* p2 = (T*)v2;
if(p1->m_fDistance > p2->m_fDistance)
return 1;
else if(p1->m_fDistance < p2->m_fDistance)
return -1;
return 0;
}
static int __cdecl Cmp_Ptrs2(const void* v1, const void* v2)
{
T* p1 = (T*)v1;
T* p2 = (T*)v2;
if(p1->m_fDistance > p2->m_fDistance)
return -1;
else if(p1->m_fDistance < p2->m_fDistance)
return 1;
return 0;
}
void SortByDistanceMember(bool front_to_back = true, int nSortOffSet = 0)
{
if(m_nCount-nSortOffSet > 1)
{
if(front_to_back)
qsort(&m_pElements[nSortOffSet], m_nCount-nSortOffSet, sizeof(T), Cmp_Ptrs1);
else
qsort(&m_pElements[nSortOffSet], m_nCount-nSortOffSet, sizeof(T), Cmp_Ptrs2);
}
}
// Sorting of pointers to objects
static int Cmp_Ptrs1_(const void* v1, const void* v2)
{
T p1 = *((T*)v1);
T p2 = *((T*)v2);
if(p1->m_fDistance > p2->m_fDistance)
return 1;
else if(p1->m_fDistance < p2->m_fDistance)
return -1;
return 0;
}
static int Cmp_Ptrs2_(const void* v1, const void* v2)
{
T p1 = *((T*)v1);
T p2 = *((T*)v2);
if(p1->m_fDistance > p2->m_fDistance)
return -1;
else if(p1->m_fDistance < p2->m_fDistance)
return 1;
return 0;
}
void SortByDistanceMember_(bool front_to_back = true)
{
if(front_to_back)
qsort(&m_pElements[0], m_nCount, sizeof(T), Cmp_Ptrs1_);
else
qsort(&m_pElements[0], m_nCount, sizeof(T), Cmp_Ptrs2_);
}
// STL convention driver routines to facilitate conversion from this class to optimized
// containers with standard, well-known and thus more convenient for some other (except
// the author) people naming conventions.
// All the routines mean the same as their counterparts in std::vector<T>.
bool empty() const
{
return IsEmpty() != 0;
}
void reserve (unsigned numElements)
{
PreAllocate ((int)numElements);
}
// C++ Standard Library makes new[] call instead of old-fashioned *alloc()
// this ensures the objects are constructed properly.
void resize (size_t numElements)
{
int nOldCount = m_nCount;
PreAllocate ((int)numElements, (int)numElements);
assert (numElements == size());
for (int nElement = nOldCount; nElement < m_nCount; ++nElement)
(*this)[nElement] = T();
}
void push_back (const T& rElement)
{
Add (rElement);
}
unsigned size ()const
{
return (unsigned)m_nCount;
}
unsigned capacity() const
{
return (unsigned)m_nAllocatedCount;
}
T* begin() {return m_pElements;}
T* end() {return m_pElements+m_nCount;}
const T* begin()const {return m_pElements;}
const T* end()const {return m_pElements+m_nCount;}
};
#endif // LIST_3DENGINE_H