core/logic/CellArray.h
author David Anderson <dvander@alliedmods.net>
Thu Aug 08 22:02:42 2013 -0700 (2013-08-08)
changeset 3980 dc7dfcd855dc
parent 2726 c96f3fab8211
permissions -rw-r--r--
More Windows build fix.
dvander@2726
     1
/**
dvander@2726
     2
 * vim: set ts=4 :
dvander@2726
     3
 * =============================================================================
dvander@2726
     4
 * SourceMod
dvander@2726
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
dvander@2726
     6
 * =============================================================================
dvander@2726
     7
 *
dvander@2726
     8
 * This program is free software; you can redistribute it and/or modify it under
dvander@2726
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
dvander@2726
    10
 * Free Software Foundation.
dvander@2726
    11
 * 
dvander@2726
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
dvander@2726
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@2726
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
dvander@2726
    15
 * details.
dvander@2726
    16
 *
dvander@2726
    17
 * You should have received a copy of the GNU General Public License along with
dvander@2726
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@2726
    19
 *
dvander@2726
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
dvander@2726
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
dvander@2726
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
dvander@2726
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
dvander@2726
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
dvander@2726
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
dvander@2726
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
dvander@2726
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@2726
    28
 *
dvander@2726
    29
 * Version: $Id$
dvander@2726
    30
 */
dvander@2726
    31
dvander@2726
    32
#ifndef _INCLUDE_SOURCEMOD_CELLARRAY_H_
dvander@2726
    33
#define _INCLUDE_SOURCEMOD_CELLARRAY_H_
dvander@2726
    34
dvander@2726
    35
#include <stdlib.h>
dvander@2726
    36
#include <string.h>
dvander@2726
    37
dvander@2726
    38
extern HandleType_t htCellArray;
dvander@2726
    39
dvander@2726
    40
class CellArray
dvander@2726
    41
{
dvander@2726
    42
public:
dvander@2726
    43
	CellArray(size_t blocksize) : m_Data(NULL), m_BlockSize(blocksize), m_AllocSize(0), m_Size(0)
dvander@2726
    44
	{
dvander@2726
    45
	}
dvander@2726
    46
dvander@2726
    47
	~CellArray()
dvander@2726
    48
	{
dvander@2726
    49
		free(m_Data);
dvander@2726
    50
	}
dvander@2726
    51
dvander@2726
    52
	size_t size() const
dvander@2726
    53
	{
dvander@2726
    54
		return m_Size;
dvander@2726
    55
	}
dvander@2726
    56
dvander@2726
    57
	cell_t *push()
dvander@2726
    58
	{
dvander@2726
    59
		if (!GrowIfNeeded(1))
dvander@2726
    60
		{
dvander@2726
    61
			return NULL;
dvander@2726
    62
		}
dvander@2726
    63
		cell_t *arr = &m_Data[m_Size * m_BlockSize];
dvander@2726
    64
		m_Size++;
dvander@2726
    65
		return arr;
dvander@2726
    66
	}
dvander@2726
    67
dvander@2726
    68
	cell_t *at(size_t b) const
dvander@2726
    69
	{
dvander@2726
    70
		return &m_Data[b * m_BlockSize];
dvander@2726
    71
	}
dvander@2726
    72
dvander@2726
    73
	size_t blocksize() const
dvander@2726
    74
	{
dvander@2726
    75
		return m_BlockSize;
dvander@2726
    76
	}
dvander@2726
    77
dvander@2726
    78
	void clear()
dvander@2726
    79
	{
dvander@2726
    80
		m_Size = 0;
dvander@2726
    81
	}
dvander@2726
    82
dvander@2726
    83
	bool swap(size_t item1, size_t item2)
dvander@2726
    84
	{
dvander@2726
    85
		/* Make sure there is extra space available */
dvander@2726
    86
		if (!GrowIfNeeded(1))
dvander@2726
    87
		{
dvander@2726
    88
			return false;
dvander@2726
    89
		}
dvander@2726
    90
dvander@2726
    91
		cell_t *pri = at(item1);
dvander@2726
    92
		cell_t *alt = at(item2);
dvander@2726
    93
dvander@2726
    94
		/* Get our temporary array 1 after the limit */
dvander@2726
    95
		cell_t *temp = &m_Data[m_Size * m_BlockSize];
dvander@2726
    96
dvander@2726
    97
		memcpy(temp, pri, sizeof(cell_t) * m_BlockSize);
dvander@2726
    98
		memcpy(pri, alt, sizeof(cell_t) * m_BlockSize);
dvander@2726
    99
		memcpy(alt, temp, sizeof(cell_t) * m_BlockSize);
dvander@2726
   100
dvander@2726
   101
		return true;
dvander@2726
   102
	}
dvander@2726
   103
dvander@2726
   104
	void remove(size_t index)
dvander@2726
   105
	{
dvander@2726
   106
		/* If we're at the end, take the easy way out */
dvander@2726
   107
		if (index == m_Size - 1)
dvander@2726
   108
		{
dvander@2726
   109
			m_Size--;
dvander@2726
   110
			return;
dvander@2726
   111
		}
dvander@2726
   112
dvander@2726
   113
		/* Otherwise, it's time to move stuff! */
dvander@2726
   114
		size_t remaining_indexes = (m_Size - 1) - index;
dvander@2726
   115
		cell_t *src = at(index + 1);
dvander@2726
   116
		cell_t *dest = at(index);
dvander@2726
   117
		memmove(dest, src, sizeof(cell_t) * m_BlockSize * remaining_indexes);
dvander@2726
   118
dvander@2726
   119
		m_Size--;
dvander@2726
   120
	}
dvander@2726
   121
dvander@2726
   122
	cell_t *insert_at(size_t index)
dvander@2726
   123
	{
dvander@2726
   124
		/* Make sure it'll fit */
dvander@2726
   125
		if (!GrowIfNeeded(1))
dvander@2726
   126
		{
dvander@2726
   127
			return NULL;
dvander@2726
   128
		}
dvander@2726
   129
dvander@2726
   130
		/* move everything up */
dvander@2726
   131
		cell_t *src = at(index);
dvander@2726
   132
		cell_t *dst = at(index + 1);
dvander@2726
   133
		memmove(dst, src, sizeof(cell_t) * m_BlockSize * (m_Size-index));
dvander@2726
   134
dvander@2726
   135
		m_Size++;
dvander@2726
   136
dvander@2726
   137
		return src;
dvander@2726
   138
	}
dvander@2726
   139
dvander@2726
   140
	bool resize(size_t count)
dvander@2726
   141
	{
dvander@2726
   142
		if (count <= m_Size)
dvander@2726
   143
		{
dvander@2726
   144
			m_Size = count;
dvander@2726
   145
			return true;
dvander@2726
   146
		}
dvander@2726
   147
dvander@2726
   148
		if (!GrowIfNeeded(count - m_Size))
dvander@2726
   149
		{
dvander@2726
   150
			return false;
dvander@2726
   151
		}
dvander@2726
   152
dvander@2726
   153
		m_Size = count;
dvander@2726
   154
		return true;
dvander@2726
   155
	}
dvander@2726
   156
dvander@2726
   157
	CellArray *clone()
dvander@2726
   158
	{
dvander@2726
   159
		CellArray *array = new CellArray(m_BlockSize);
dvander@2726
   160
		array->m_AllocSize = m_AllocSize;
dvander@2726
   161
		array->m_Size = m_Size;
dvander@2726
   162
		array->m_Data = (cell_t *)malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize);
dvander@2726
   163
		memcpy(array->m_Data, m_Data, sizeof(cell_t) * m_BlockSize * m_Size);
dvander@2726
   164
		return array;
dvander@2726
   165
	}
dvander@2726
   166
dvander@2726
   167
	cell_t *base()
dvander@2726
   168
	{
dvander@2726
   169
		return m_Data;
dvander@2726
   170
	}
dvander@2726
   171
dvander@2726
   172
	size_t mem_usage()
dvander@2726
   173
	{
dvander@2726
   174
		return m_AllocSize * m_BlockSize * sizeof(cell_t);
dvander@2726
   175
	}
dvander@2726
   176
dvander@2726
   177
private:
dvander@2726
   178
	bool GrowIfNeeded(size_t count)
dvander@2726
   179
	{
dvander@2726
   180
		/* Shortcut out if we can store this */
dvander@2726
   181
		if (m_Size + count <= m_AllocSize)
dvander@2726
   182
		{
dvander@2726
   183
			return true;
dvander@2726
   184
		}
dvander@2726
   185
		/* Set a base allocation size of 8 items */
dvander@2726
   186
		if (!m_AllocSize)
dvander@2726
   187
		{
dvander@2726
   188
			m_AllocSize = 8;
dvander@2726
   189
		}
dvander@2726
   190
		/* If it's not enough, keep doubling */
dvander@2726
   191
		while (m_Size + count > m_AllocSize)
dvander@2726
   192
		{
dvander@2726
   193
			m_AllocSize *= 2;
dvander@2726
   194
		}
dvander@2726
   195
		/* finally, allocate the new block */
dvander@2726
   196
		if (m_Data)
dvander@2726
   197
		{
dvander@2726
   198
			m_Data = (cell_t *)realloc(m_Data, sizeof(cell_t) * m_BlockSize * m_AllocSize);
dvander@2726
   199
		} else {
dvander@2726
   200
			m_Data = (cell_t *)malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize);
dvander@2726
   201
		}
dvander@2726
   202
		return (m_Data != NULL);
dvander@2726
   203
	}
dvander@2726
   204
private:
dvander@2726
   205
	cell_t *m_Data;
dvander@2726
   206
	size_t m_BlockSize;
dvander@2726
   207
	size_t m_AllocSize;
dvander@2726
   208
	size_t m_Size;
dvander@2726
   209
};
dvander@2726
   210
dvander@2726
   211
#endif /* _INCLUDE_SOURCEMOD_CELLARRAY_H_ */
dvander@2726
   212