sourcemod/core/CellArray.h
David Anderson 8fa974961c initial import of adt array natives for amb576
--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401162
2007-07-24 01:18:28 +00:00

150 lines
3.1 KiB
C++

/**
* vim: set ts=4 :
* ===============================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* ===============================================================
*
* This file is not open source and may not be copied without explicit
* written permission of AlliedModders LLC. This file may not be redistributed
* in whole or significant part.
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
*
* Version: $Id$
*/
#include <malloc.h>
#include <string.h>
class CellArray
{
public:
CellArray(size_t blocksize) : m_Data(NULL), m_BlockSize(blocksize), m_AllocSize(0), m_Size(0)
{
}
~CellArray()
{
free(m_Data);
}
size_t size() const
{
return m_Size;
}
cell_t *push()
{
if (!GrowIfNeeded(1))
{
return NULL;
}
cell_t *arr = &m_Data[m_Size * m_BlockSize];
m_Size++;
return arr;
}
cell_t *at(size_t b) const
{
return &m_Data[b * m_BlockSize];
}
size_t blocksize() const
{
return m_BlockSize;
}
void clear()
{
m_Size = 0;
}
bool swap(size_t item1, size_t item2)
{
/* Make sure there is extra space available */
if (!GrowIfNeeded(1))
{
return false;
}
cell_t *pri = at(item1);
cell_t *alt = at(item2);
/* Get our temporary array 1 after the limit */
cell_t *temp = &m_Data[m_Size * m_BlockSize];
memcpy(temp, pri, sizeof(cell_t) * m_BlockSize);
memcpy(pri, alt, sizeof(cell_t) * m_BlockSize);
memcpy(alt, temp, sizeof(cell_t) * m_BlockSize);
return true;
}
void remove(size_t index)
{
/* If we're at the end, take the easy way out */
if (index == m_Size - 1)
{
m_Size--;
return;
}
/* Otherwise, it's time to move stuff! */
size_t remaining_indexes = (m_Size - 1) - index;
cell_t *src = at(index + 1);
cell_t *dest = at(index);
memmove(dest, src, sizeof(cell_t) * m_BlockSize * remaining_indexes);
m_Size--;
}
cell_t *insert_at(size_t index)
{
/* Make sure it'll fit */
if (!GrowIfNeeded(1))
{
return NULL;
}
/* move everything up */
cell_t *src = at(index);
cell_t *dst = at(index + 1);
memmove(dst, src, sizeof(cell_t) * m_BlockSize * m_Size);
m_Size++;
return src;
}
bool resize(size_t count)
{
if (count <= m_Size)
{
m_Size = count;
return true;
}
return GrowIfNeeded(m_Size - count);
}
private:
bool GrowIfNeeded(size_t count)
{
/* Shortcut out if we can store this */
if (m_Size + count <= m_AllocSize)
{
return true;
}
/* Set a base allocation size of 8 items */
if (!m_AllocSize)
{
m_AllocSize = 8;
}
/* If it's not enough, keep doubling */
while (m_Size + count > m_AllocSize)
{
m_AllocSize *= 2;
}
/* finally, allocate the new block */
if (m_Data)
{
m_Data = (cell_t *)realloc(m_Data, sizeof(cell_t) * m_BlockSize * m_AllocSize);
} else {
m_Data = (cell_t *)malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize);
}
return (m_Data != NULL);
}
private:
cell_t *m_Data;
size_t m_BlockSize;
size_t m_AllocSize;
size_t m_Size;
};