/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, 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 .
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtArray.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNUTILS_PRIVATE_PNUTARRAY_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtArray.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNUTILS_PRIVATE_PNUTARRAY_H
/****************************************************************************
*
* Macros
*
***/
#define ARRAY(type) TArray< type, TArrayCopyBits< type > >
#define ARRAYOBJ(type) TArray< type, TArrayCopyObject< type > >
#define FARRAY(type) TFArray< type, TArrayCopyBits< type > >
#define FARRAYOBJ(type) TFArray< type, TArrayCopyObject< type > >
#define SORTARRAYFIELD(type, keyType, field) TSortArray< type, TArrayCopyBits< type >, keyType, offsetof(type, field)>
#define SORTARRAYFIELDOBJ(type, keyType, field) TSortArray< type, TArrayCopyObject< type >, keyType, offsetof(type, field)>
#define SORTARRAYTYPE(type) TSortArray< type, TArrayCopyBits< type >, type, 0>
#define SORTARRAYTYPEOBJ(type) TSortArray< type, TArrayCopyObject< type >, type, 0>
#define ARR_MEMORY_FLAGS 0 /*| kMemIgnoreBlock*/
/****************************************************************************
*
* CBuffer
*
***/
template
class TBuffer {
protected:
T * m_data;
public:
inline TBuffer ();
inline TBuffer (unsigned count);
inline TBuffer (const void * source, unsigned count);
inline TBuffer (const TBuffer & source);
inline ~TBuffer ();
inline TBuffer & operator= (const TBuffer & source);
inline bool operator== (const TBuffer & source) const;
inline T & operator[] (unsigned index);
inline T operator[] (unsigned index) const;
inline void Attach (T * source, unsigned count);
inline unsigned Bytes () const;
inline void Clear ();
inline unsigned Count () const;
inline T * Detach ();
inline void Fill (byte value);
inline T * Ptr ();
inline const T * Ptr () const;
inline void Set (const T * source, unsigned count);
inline void SetBytes (unsigned bytes);
inline void SetCount (unsigned count);
inline void Zero ();
};
//===========================================================================
template
TBuffer::TBuffer () {
m_data = nil;
}
//===========================================================================
template
TBuffer::TBuffer (unsigned count) {
m_data = nil;
SetCount(count);
}
//===========================================================================
template
TBuffer::TBuffer (const void * source, unsigned count) {
m_data = nil;
SetCount(count);
memcpy(m_data, source, count * sizeof(T));
}
//===========================================================================
template
TBuffer::TBuffer (const TBuffer & source) {
m_data = nil;
unsigned bytes = source.Bytes();
SetBytes(bytes);
if (bytes)
memcpy(m_data, source.m_data, bytes);
}
//===========================================================================
template
TBuffer::~TBuffer () {
if (m_data)
FREEFLAGS(m_data, ARR_MEMORY_FLAGS);
}
//===========================================================================
template
TBuffer & TBuffer::operator= (const TBuffer & source) {
unsigned newBytes = source.Bytes();
if (newBytes != Bytes())
SetBytes(newBytes);
if (&source != this)
memcpy(m_data, source.m_data, newBytes);
return *this;
}
//===========================================================================
template
bool TBuffer::operator== (const TBuffer & source) const {
unsigned size = MemSize(m_data);
return (size == MemSize(source.m_data)) && !MemCmp(m_data, source.m_data, size);
}
//===========================================================================
template
T & TBuffer::operator[] (unsigned index) {
ASSERT(index < Count());
return m_data[index];
}
//===========================================================================
template
T TBuffer::operator[] (unsigned index) const {
ASSERT(index < Count());
return m_data[index];
}
//===========================================================================
template
void TBuffer::Attach (T * source, unsigned count) {
if (m_data)
FREEFLAGS(m_data, ARR_MEMORY_FLAGS);
m_data = source;
ASSERT(MemSize(source) >= count * sizeof(T));
}
//===========================================================================
template
unsigned TBuffer::Bytes () const {
return m_data ? MemSize(m_data) : 0;
}
//===========================================================================
template
void TBuffer::Clear () {
if (m_data) {
FREEFLAGS(m_data, ARR_MEMORY_FLAGS);
m_data = nil;
}
}
//===========================================================================
template
unsigned TBuffer::Count () const {
return m_data ? (MemSize(m_data) / sizeof(T)) : 0;
}
//===========================================================================
template
T * TBuffer::Detach () {
T * result = m_data;
m_data = nil;
return result;
}
//===========================================================================
template
void TBuffer::Fill (byte value) {
if (m_data)
MemSet(m_data, value, Bytes());
}
//===========================================================================
template
T * TBuffer::Ptr () {
return m_data;
}
//===========================================================================
template
const T * TBuffer::Ptr () const {
return m_data;
}
//===========================================================================
template
void TBuffer::Set (const T * source, unsigned count) {
SetCount(count);
memcpy(m_data, source, count * sizeof(T));
}
//===========================================================================
template
void TBuffer::SetBytes (unsigned bytes) {
if (bytes)
m_data = (T *)REALLOCFLAGS(m_data, bytes, ARR_MEMORY_FLAGS);
else if (m_data) {
FREEFLAGS(m_data, ARR_MEMORY_FLAGS);
m_data = nil;
}
}
//===========================================================================
template
void TBuffer::SetCount (unsigned count) {
SetBytes(count * sizeof(T));
}
//===========================================================================
template
void TBuffer::Zero () {
if (m_data)
MemZero(m_data, Bytes());
}
typedef TBuffer CBuffer;
/****************************************************************************
*
* CBaseArray
*
***/
class CBaseArray {
protected:
unsigned CalcAllocGrowth (unsigned newAlloc, unsigned oldAlloc, unsigned * chunkSize);
void * ReallocPtr (void * ptr, unsigned bytes);
};
/****************************************************************************
*
* TArrayCopyBits
*
***/
template
class TArrayCopyBits {
public:
inline static void Assign (T * dest, const T source[], unsigned count);
inline static void Construct (T * dest) { }
inline static void Construct (T * dest, unsigned count) { }
inline static void CopyConstruct (T * dest, const T & source);
inline static void CopyConstruct (T * dest, const T source[], unsigned count);
inline static void Destruct (T * dest) { }
inline static void Destruct (T * dest, unsigned count) { }
};
//===========================================================================
template
void TArrayCopyBits::Assign (T * dest, const T source[], unsigned count) {
MemMove(dest, source, count * sizeof(T));
}
//===========================================================================
template
void TArrayCopyBits::CopyConstruct (T * dest, const T & source) {
*dest = source;
}
//===========================================================================
template
void TArrayCopyBits::CopyConstruct (T * dest, const T source[], unsigned count) {
ASSERT((dest + count <= source) || (source + count <= dest));
memcpy(dest, source, count * sizeof(T));
}
/****************************************************************************
*
* TArrayCopyObject
*
***/
template
class TArrayCopyObject {
public:
inline static void Assign (T * dest, const T source[], unsigned count);
inline static void Construct (T * dest);
inline static void Construct (T * dest, unsigned count);
inline static void CopyConstruct (T * dest, const T & source);
inline static void CopyConstruct (T * dest, const T source[], unsigned count);
inline static void Destruct (T * dest);
inline static void Destruct (T * dest, unsigned count);
};
//===========================================================================
template
void TArrayCopyObject::Assign (T * dest, const T source[], unsigned count) {
if (dest > source)
for (unsigned loop = count; loop--; )
dest[loop] = source[loop];
else if (dest < source)
for (unsigned loop = 0; loop < count; ++loop)
dest[loop] = source[loop];
}
//===========================================================================
template
void TArrayCopyObject::Construct (T * dest) {
new(dest) T;
}
//===========================================================================
template
void TArrayCopyObject::Construct (T * dest, unsigned count) {
for (unsigned loop = 0; loop < count; ++loop)
new(&dest[loop]) T;
}
//===========================================================================
template
void TArrayCopyObject::CopyConstruct (T * dest, const T & source) {
new(dest) T(source);
}
//===========================================================================
template
void TArrayCopyObject::CopyConstruct (T * dest, const T source[], unsigned count) {
ASSERT((dest + count <= source) || (source + count <= dest));
for (unsigned loop = 0; loop < count; ++loop)
new(&dest[loop]) T(source[loop]);
}
//===========================================================================
template
void TArrayCopyObject::Destruct (T * dest) {
dest->~T();
}
//===========================================================================
template
void TArrayCopyObject::Destruct (T * dest, unsigned count) {
for (unsigned loop = count; loop--; )
dest[loop].~T();
}
/****************************************************************************
*
* TFArray
*
***/
template
class TFArray : protected CBaseArray {
protected:
T * m_data;
unsigned m_alloc;
unsigned m_count;
inline void AdjustSize (unsigned newAlloc, unsigned newCount);
public:
inline TFArray ();
inline TFArray (unsigned count);
inline TFArray (const T * source, unsigned count);
inline TFArray (const TFArray & source);
inline ~TFArray ();
inline TFArray & operator= (const TFArray & source);
inline bool operator== (const TFArray & source) const;
inline T & operator[] (unsigned index);
inline const T & operator[] (unsigned index) const;
inline void Attach (T * source, unsigned count);
inline void AttachTemp (T * source, unsigned count);
inline unsigned Bytes () const;
inline void Clear ();
inline unsigned Count () const;
inline T * Detach ();
inline void Fill (byte value);
inline T * Ptr ();
inline const T * Ptr () const;
inline void Set (const T * source, unsigned count);
inline void SetArray (const TFArray & source);
inline void SetCount (unsigned count);
inline T * Term ();
inline const T * Term () const;
inline T * Top ();
inline const T * Top () const;
inline void Zero ();
inline void ZeroCount ();
inline void ZeroRange (unsigned index, unsigned count);
};
//===========================================================================
template
TFArray::TFArray () {
m_alloc = 0;
m_count = 0;
m_data = nil;
}
//===========================================================================
template
TFArray::TFArray (unsigned count) {
m_alloc = m_count = count;
if (count) {
m_data = (T *)ALLOCFLAGS(count * sizeof(T), ARR_MEMORY_FLAGS);
C::Construct(m_data, count);
}
else
m_data = nil;
}
//===========================================================================
template
TFArray::TFArray (const T * source, unsigned count) {
m_alloc = m_count = count;
if (count) {
m_data = (T *)ALLOCFLAGS(count * sizeof(T), ARR_MEMORY_FLAGS);
C::CopyConstruct(m_data, source, count);
}
else
m_data = nil;
}
//===========================================================================
template
TFArray::TFArray (const TFArray & source) {
m_alloc = m_count = source.m_count;
if (m_count) {
m_data = (T *)ALLOCFLAGS(m_count * sizeof(T), ARR_MEMORY_FLAGS);
C::CopyConstruct(m_data, source.m_data, m_count);
}
else
m_data = nil;
}
//===========================================================================
template
TFArray::~TFArray () {
Clear();
}
//===========================================================================
template
TFArray & TFArray::operator= (const TFArray & source) {
if (&source == this)
return *this;
AdjustSize(source.m_count, 0);
C::CopyConstruct(m_data, source.m_data, source.m_count);
m_count = source.m_count;
return *this;
}
//===========================================================================
template
inline bool TFArray::operator== (const TFArray & source) const {
if (m_count != source.m_count)
return false;
for (unsigned index = 0; index < m_count; ++index)
if (!((*this)[index] == source[index]))
return false;
return true;
}
//===========================================================================
template
T & TFArray::operator[] (unsigned index) {
ASSERT(index < m_count);
return m_data[index];
}
//===========================================================================
template
const T & TFArray::operator[] (unsigned index) const {
ASSERT(index < m_count);
return m_data[index];
}
//===========================================================================
template
void TFArray::AdjustSize (unsigned newAlloc, unsigned newCount) {
// Destruct elements if the array is shrinking
if (m_count > newCount) {
C::Destruct(m_data + newCount, m_count - newCount);
m_count = newCount;
}
// Change the memory allocation size if necessary
if (m_alloc != newAlloc) {
T * newData = (T *)ReallocPtr(m_data, newAlloc * sizeof(T));
if (newData != m_data) {
C::CopyConstruct(newData, m_data, m_count);
C::Destruct(m_data, m_count);
if (m_data)
FREEFLAGS(m_data, ARR_MEMORY_FLAGS);
}
m_alloc = newAlloc;
m_data = newData;
}
// Construct elements if the array is growing
if (m_count < newCount) {
C::Construct(m_data + m_count, newCount - m_count);
m_count = newCount;
}
}
//===========================================================================
template
void TFArray::Attach (T * source, unsigned count) {
C::Destruct(m_data, m_count);
if (m_data)
FREEFLAGS(m_data, ARR_MEMORY_FLAGS);
m_data = source;
m_alloc = MemSize(source) / sizeof(T);
m_count = count;
ASSERT(m_alloc >= m_count);
}
//===========================================================================
template
void TFArray::AttachTemp (T * source, unsigned count) {
C::Destruct(m_data, m_count);
if (m_data)
FREEFLAGS(m_data, ARR_MEMORY_FLAGS);
m_data = source;
m_alloc = count;
m_count = count;
}
//===========================================================================
template
unsigned TFArray::Bytes () const {
return m_count * sizeof(T);
}
//===========================================================================
template
void TFArray::Clear () {
C::Destruct(m_data, m_count);
if (m_data)
FREEFLAGS(m_data, ARR_MEMORY_FLAGS);
m_data = nil;
m_alloc = m_count = 0;
}
//===========================================================================
template
unsigned TFArray::Count () const {
return m_count;
}
//===========================================================================
template
T * TFArray::Detach () {
T * result = m_data;
m_data = nil;
m_alloc = 0;
m_count = 0;
return result;
}
//===========================================================================
template
void TFArray::Fill (byte value) {
C::Destruct(m_data, m_count);
MemSet(m_data, value, m_count * sizeof(T));
C::Construct(m_data, m_count);
}
//===========================================================================
template
T * TFArray::Ptr () {
return m_data;
}
//===========================================================================
template
const T * TFArray::Ptr () const {
return m_data;
}
//===========================================================================
template
void TFArray::Set (const T * source, unsigned count) {
AdjustSize(count, 0);
C::CopyConstruct(m_data, source, count);
m_count = count;
}
//===========================================================================
template
void TFArray::SetArray (const TFArray & source) {
AdjustSize(source.m_count, 0);
C::CopyConstruct(m_data, source.m_data, source.m_count);
m_count = source.m_count;
}
//===========================================================================
template
void TFArray::SetCount (unsigned count) {
AdjustSize(count, count);
}
//===========================================================================
template
T * TFArray::Term () {
return m_data + m_count;
}
//===========================================================================
template
const T * TFArray::Term () const {
return m_data + m_count;
}
//===========================================================================
template
T * TFArray::Top () {
ASSERT(m_count);
return m_data + m_count - 1;
}
//===========================================================================
template
const T * TFArray::Top () const {
ASSERT(m_count);
return m_data + m_count - 1;
}
//===========================================================================
template
void TFArray::Zero () {
C::Destruct(m_data, m_count);
MemZero(m_data, m_count * sizeof(T));
C::Construct(m_data, m_count);
}
//===========================================================================
template
void TFArray::ZeroCount () {
C::Destruct(m_data, m_count);
m_count = 0;
}
//===========================================================================
template
void TFArray::ZeroRange (unsigned index, unsigned count) {
ASSERT(index + count <= m_count);
C::Destruct(m_data + index, count);
MemZero(m_data + index, count * sizeof(T));
C::Construct(m_data + index, count);
}
/****************************************************************************
*
* TArray
*
***/
template
class TArray : public TFArray {
private:
unsigned m_chunkSize;
inline void AdjustSizeChunked (unsigned newAlloc, unsigned newCount);
public:
inline TArray ();
inline TArray (const char file[], int line);
inline TArray (unsigned count);
inline TArray (const T * source, unsigned count);
inline TArray (const TArray & source);
inline TArray & operator= (const TArray & source);
inline unsigned Add (const T & source);
inline unsigned Add (const T * source, unsigned count);
inline unsigned AddArray (const TArray & source);
inline void Copy (unsigned destIndex, unsigned sourceIndex, unsigned count);
inline void DeleteOrdered (unsigned index);
inline void DeleteUnordered (unsigned index);
inline void GrowToCount (unsigned count, bool zero);
inline void GrowToFit (unsigned index, bool zero);
inline void ShrinkBy (unsigned count);
inline void Move (unsigned destIndex, unsigned sourceIndex, unsigned count);
inline T * New ();
inline T * New (unsigned count);
inline void Push (const T & source);
inline T Pop ();
inline void Reserve (unsigned additionalCount);
inline void Set (const T * source, unsigned count);
inline void SetChunkSize (unsigned chunkSize);
inline void SetCount (unsigned count);
inline void SetCountFewer (unsigned count);
inline void Trim ();
};
//===========================================================================
template
TArray::TArray () : TFArray() {
m_chunkSize = max(1, 256 / sizeof(T));
}
//===========================================================================
template
TArray::TArray (const char file[], int line) : TFArray(file, line) {
m_chunkSize = max(1, 256 / sizeof(T));
}
//===========================================================================
template
TArray::TArray (unsigned count) : TFArray(count) {
m_chunkSize = max(1, 256 / sizeof(T));
}
//===========================================================================
template
TArray::TArray (const T * source, unsigned count) : TFArray(source, count) {
m_chunkSize = max(1, 256 / sizeof(T));
}
//===========================================================================
template
TArray::TArray (const TArray & source) : TFArray(source) {
m_chunkSize = source.m_chunkSize;
}
//===========================================================================
template
TArray & TArray::operator= (const TArray & source) {
if (&source == this)
return *this;
m_chunkSize = source.m_chunkSize;
AdjustSize(max(m_alloc, source.m_count), 0);
C::CopyConstruct(m_data, source.m_data, source.m_count);
m_count = source.m_count;
return *this;
}
//===========================================================================
template
unsigned TArray::Add (const T & source) {
unsigned index = m_count;
Push(source);
return index;
}
//===========================================================================
template
unsigned TArray::Add (const T * source, unsigned count) {
unsigned index = m_count;
AdjustSizeChunked(m_count + count, m_count);
C::CopyConstruct(&m_data[m_count], source, count);
m_count += count;
return index;
}
//===========================================================================
template
unsigned TArray::AddArray (const TArray & source) {
unsigned index = m_count;
AdjustSizeChunked(m_count + source.m_count, m_count);
C::CopyConstruct(&m_data[m_count], source.m_data, source.m_count);
m_count += source.m_count;
return index;
}
//===========================================================================
template
void TArray::AdjustSizeChunked (unsigned newAlloc, unsigned newCount) {
// Disallow shrinking the allocation
if (newAlloc <= m_alloc)
newAlloc = m_alloc;
// Process growing the allocation
else
newAlloc = CalcAllocGrowth(newAlloc, m_alloc, &m_chunkSize);
// Perform the allocation
AdjustSize(newAlloc, newCount);
}
//===========================================================================
template
void TArray::Copy (unsigned destIndex, unsigned sourceIndex, unsigned count) {
// Copy the data to the destination
ASSERT(destIndex + count <= m_count);
ASSERT(sourceIndex + count <= m_count);
C::Assign(m_data + destIndex, m_data + sourceIndex, count);
}
//===========================================================================
template
void TArray::DeleteOrdered (unsigned index) {
ASSERT(index < m_count);
if (index + 1 < m_count)
C::Assign(&m_data[index], &m_data[index + 1], m_count - index - 1);
C::Destruct(&m_data[--m_count]);
}
//===========================================================================
template
void TArray::DeleteUnordered (unsigned index) {
ASSERT(index < m_count);
if (index + 1 < m_count)
C::Assign(&m_data[index], &m_data[m_count - 1], 1);
C::Destruct(&m_data[--m_count]);
}
//===========================================================================
template
void TArray::GrowToCount (unsigned count, bool zero) {
if (count <= m_count)
return;
AdjustSizeChunked(count, m_count);
if (zero)
memset(m_data + m_count, 0, (count - m_count) * sizeof(T));
C::Construct(m_data + m_count, count - m_count);
m_count = count;
}
//===========================================================================
template
void TArray::GrowToFit (unsigned index, bool zero) {
GrowToCount(index + 1, zero);
}
//===========================================================================
template
void TArray::ShrinkBy (unsigned count) {
ASSERT(count <= m_count);
C::Destruct(m_data + m_count - count, count);
m_count -= count;
}
//===========================================================================
template
void TArray::Move (unsigned destIndex, unsigned sourceIndex, unsigned count) {
// Copy the data to the destination
ASSERT(destIndex + count <= m_count);
ASSERT(sourceIndex + count <= m_count);
C::Assign(m_data + destIndex, m_data + sourceIndex, count);
// Remove it from the source
if (destIndex >= sourceIndex) {
C::Destruct(m_data + sourceIndex, min(count, destIndex - sourceIndex));
C::Construct(m_data + sourceIndex, min(count, destIndex - sourceIndex));
}
else {
unsigned overlap = (destIndex + count > sourceIndex) ? (destIndex + count - sourceIndex) : 0;
ASSERT(overlap <= count);
C::Destruct(m_data + sourceIndex + overlap, count - overlap);
C::Construct(m_data + sourceIndex + overlap, count - overlap);
}
}
//===========================================================================
template
T * TArray::New () {
AdjustSizeChunked(m_count + 1, m_count + 1);
return &m_data[m_count - 1];
}
//===========================================================================
template
T * TArray::New (unsigned count) {
AdjustSizeChunked(m_count + count, m_count + count);
return &m_data[m_count - count];
}
//===========================================================================
template
void TArray::Push (const T & source) {
AdjustSizeChunked(m_count + 1, m_count);
C::CopyConstruct(&m_data[m_count], source);
++m_count;
}
//===========================================================================
template
T TArray::Pop () {
ASSERT(m_count);
T result = m_data[--m_count];
C::Destruct(m_data + m_count);
return result;
}
//===========================================================================
template
void TArray::Reserve (unsigned additionalCount) {
AdjustSizeChunked(max(m_alloc, m_count + additionalCount), m_count);
}
//===========================================================================
template
void TArray::Set (const T * source, unsigned count) {
AdjustSizeChunked(count, 0);
C::CopyConstruct(m_data, source, count);
m_count = count;
}
//===========================================================================
template
void TArray::SetChunkSize (unsigned chunkSize) {
m_chunkSize = chunkSize;
}
//===========================================================================
template
void TArray::SetCount (unsigned count) {
AdjustSizeChunked(max(m_alloc, count), count);
}
//===========================================================================
template
void TArray::SetCountFewer (unsigned count) {
ASSERT(count <= m_count);
C::Destruct(m_data + count, m_count - count);
m_count = count;
}
//===========================================================================
template
void TArray::Trim () {
AdjustSize(m_count, m_count);
}
/****************************************************************************
*
* TSortArray
*
***/
template
class TSortArray : public TArray {
private:
inline static K & SortKey (T & rec) { return *(K *)((byte *)&rec + OFFSET); }
inline static const K & SortKey (const T & rec) { return *(const K *)((const byte *)&rec + OFFSET); }
public:
inline bool Delete (K sortKey);
inline T * Find (K sortKey) { unsigned index; return Find(sortKey, &index); }
inline T * Find (K sortKey, unsigned * index);
inline const T * Find (K sortKey) const { unsigned index; return Find(sortKey, &index); }
inline const T * Find (K sortKey, unsigned * index) const;
inline T * Insert (K sortKey, unsigned index);
inline void Sort ();
};
//===========================================================================
template
bool TSortArray::Delete (K sortKey) {
// Find the correct position for this key
unsigned index;
BSEARCH(T, Ptr(), Count(), (sortKey > SortKey(elem)), &index);
// Verify that an entry exists for this key
unsigned count = Count();
if ((index >= count) || (SortKey((*this)[index]) != sortKey))
return false;
// Delete the entry
DeleteOrdered(index);
return true;
}
//===========================================================================
template
T * TSortArray::Find (K sortKey, unsigned * index) {
// Find the correct position for this key
BSEARCH(T, Ptr(), Count(), (sortKey > SortKey(elem)), index);
if (*index >= Count())
return nil;
// Check whether the key is at that position
T & elem = (*this)[*index];
return (SortKey(elem) == sortKey) ? &elem : nil;
}
//===========================================================================
template
const T * TSortArray::Find (K sortKey, unsigned * index) const {
// Find the correct position for this key
BSEARCH(T, Ptr(), Count(), (sortKey > SortKey(elem)), index);
if (*index >= Count())
return nil;
// Check whether the key is at that position
const T & elem = (*this)[*index];
return (SortKey(elem) == sortKey) ? &elem : nil;
}
//===========================================================================
template
T * TSortArray::Insert (K sortKey, unsigned index) {
// Insert a new entry at this position
unsigned count = Count();
SetCount(count + 1);
if (index < count)
Move(index + 1, index, count - index);
// Fill in the new entry
T & elem = (*this)[index];
SortKey(elem) = sortKey;
return &elem;
}
//===========================================================================
template
void TSortArray::Sort () {
T * ptr = Ptr();
unsigned count = Count();
QSORT(
T,
ptr,
count,
SortKey(elem1) > SortKey(elem2)
);
}