amxmodx/amxmodx/datastructs.h

214 lines
4.0 KiB
C
Raw Normal View History

2014-08-04 03:36:20 -05:00
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#ifndef DATASTRUCTS_H
#define DATASTRUCTS_H
2014-07-25 00:25:31 +02:00
#include <am-vector.h>
2014-07-25 00:25:31 +02:00
class CellArray
{
public:
CellArray(size_t blocksize, size_t basesize = 0) : m_Data(NULL), m_BlockSize(blocksize), m_AllocSize(0), m_BaseSize(basesize > 0 ? basesize : 8), m_Size(0)
{
2014-07-25 00:25:31 +02:00
}
~CellArray()
{
2014-07-25 00:25:31 +02:00
free(m_Data);
}
size_t size() const
{
2014-07-25 00:25:31 +02:00
return m_Size;
}
cell *push()
{
2014-07-25 00:25:31 +02:00
if (!GrowIfNeeded(1))
{
2014-07-25 00:25:31 +02:00
return NULL;
}
2014-07-25 00:25:31 +02:00
cell *arr = &m_Data[m_Size * m_BlockSize];
m_Size++;
return arr;
}
cell *at(size_t b) const
{
2014-07-25 00:25:31 +02:00
return &m_Data[b * m_BlockSize];
}
size_t blocksize() const
{
2014-07-25 00:25:31 +02:00
return m_BlockSize;
}
2014-07-25 00:25:31 +02:00
void clear()
{
m_Size = 0;
}
2014-07-25 00:25:31 +02:00
bool swap(size_t item1, size_t item2)
{
2014-07-25 00:25:31 +02:00
/* Make sure there is extra space available */
if (!GrowIfNeeded(1))
{
2014-07-25 00:25:31 +02:00
return false;
}
2014-07-25 00:25:31 +02:00
cell *pri = at(item1);
cell *alt = at(item2);
2014-07-25 00:25:31 +02:00
/* Get our temporary array 1 after the limit */
cell *temp = &m_Data[m_Size * m_BlockSize];
2014-07-25 00:25:31 +02:00
memcpy(temp, pri, sizeof(cell)* m_BlockSize);
memcpy(pri, alt, sizeof(cell)* m_BlockSize);
memcpy(alt, temp, sizeof(cell)* m_BlockSize);
2014-07-25 00:25:31 +02:00
return true;
}
2014-07-25 00:25:31 +02:00
void remove(size_t index)
{
2014-07-25 00:25:31 +02:00
/* If we're at the end, take the easy way out */
if (index == m_Size - 1)
{
2014-07-25 00:25:31 +02:00
m_Size--;
return;
}
2014-07-25 00:25:31 +02:00
/* Otherwise, it's time to move stuff! */
size_t remaining_indexes = (m_Size - 1) - index;
cell *src = at(index + 1);
cell *dest = at(index);
memmove(dest, src, sizeof(cell)* m_BlockSize * remaining_indexes);
2014-07-25 00:25:31 +02:00
m_Size--;
}
cell *insert_at(size_t index)
{
2014-07-25 00:25:31 +02:00
/* Make sure it'll fit */
if (!GrowIfNeeded(1))
{
2014-07-25 00:25:31 +02:00
return NULL;
}
2014-07-25 00:25:31 +02:00
/* move everything up */
cell *src = at(index);
cell *dst = at(index + 1);
memmove(dst, src, sizeof(cell)* m_BlockSize * (m_Size - index));
2014-07-25 00:25:31 +02:00
m_Size++;
2014-07-25 00:25:31 +02:00
return src;
}
2014-07-25 00:25:31 +02:00
bool resize(size_t count)
{
2014-07-25 00:25:31 +02:00
if (count <= m_Size)
{
2014-07-25 00:25:31 +02:00
m_Size = count;
return true;
}
2014-07-25 00:25:31 +02:00
if (!GrowIfNeeded(count - m_Size))
{
return false;
}
2014-07-25 00:25:31 +02:00
m_Size = count;
return true;
}
2014-07-25 00:25:31 +02:00
CellArray *clone()
{
2014-07-25 00:25:31 +02:00
CellArray *array = new CellArray(m_BlockSize);
array->m_AllocSize = m_AllocSize;
array->m_Size = m_Size;
array->m_Data = (cell *)malloc(sizeof(cell)* m_BlockSize * m_AllocSize);
memcpy(array->m_Data, m_Data, sizeof(cell)* m_BlockSize * m_Size);
return array;
}
2014-07-25 00:25:31 +02:00
cell *base()
{
2014-07-25 00:25:31 +02:00
return m_Data;
}
2014-07-25 00:25:31 +02:00
size_t mem_usage()
{
2014-07-25 00:25:31 +02:00
return m_AllocSize * m_BlockSize * sizeof(cell);
}
private:
bool GrowIfNeeded(size_t count)
{
2014-07-25 00:25:31 +02:00
/* Shortcut out if we can store this */
if (m_Size + count <= m_AllocSize)
{
2014-07-25 00:25:31 +02:00
return true;
}
2014-07-25 00:25:31 +02:00
/* Set a base allocation size of 8 items */
if (!m_AllocSize)
{
m_AllocSize = m_BaseSize;
}
2014-07-25 00:25:31 +02:00
/* If it's not enough, keep doubling */
while (m_Size + count > m_AllocSize)
{
2014-07-25 00:25:31 +02:00
m_AllocSize *= 2;
}
2014-07-25 00:25:31 +02:00
/* finally, allocate the new block */
if (m_Data)
{
2014-07-25 00:25:31 +02:00
m_Data = (cell *)realloc(m_Data, sizeof(cell)* m_BlockSize * m_AllocSize);
}
2014-07-25 00:25:31 +02:00
else {
m_Data = (cell *)malloc(sizeof(cell)* m_BlockSize * m_AllocSize);
}
2014-07-25 00:25:31 +02:00
return (m_Data != NULL);
}
private:
cell *m_Data;
size_t m_BlockSize;
size_t m_AllocSize;
size_t m_BaseSize;
2014-07-25 00:25:31 +02:00
size_t m_Size;
};
2014-07-25 00:25:31 +02:00
extern ke::Vector<CellArray*> VectorHolder;
2014-07-25 00:25:31 +02:00
inline CellArray* HandleToVector(AMX* amx, int handle)
{
2014-07-25 00:25:31 +02:00
if (handle <= 0 || handle > (int)VectorHolder.length())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", handle);
return NULL;
}
2014-07-25 00:25:31 +02:00
CellArray* ret = VectorHolder[handle - 1];
if (ret == NULL)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", handle);
return NULL;
}
return ret;
}
#endif