/*==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 .
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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) { REF(dest); }
inline static void Construct (T * dest, unsigned count) { REF(dest); REF(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) { REF(dest); }
inline static void Destruct (T * dest, unsigned count) { REF(dest); REF(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) {
REF(dest);
dest->~T();
}
//===========================================================================
template
void TArrayCopyObject::Destruct (T * dest, unsigned count) {
REF(dest);
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)
);
}