/* Copyright (C) 2010-2012 kaosu (qiupf2000@gmail.com)
* This file is part of the Interactive Text Hooker.
* Interactive Text Hooker 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 .
*/
#pragma once
template
class PointerTable
{
public:
PointerTable()
{
assert((default_size & (default_size - 1)) == 0);
size = default_size;
table = new T*[size];
used = 0;
next = 0;
memset(table, 0, size * sizeof(T*));
}
~PointerTable()
{
delete table;
}
T* Set(unsigned int number, T* ptr)
{
if (number >= size - 2)
{
unsigned int new_size = size;
while (number >= new_size - 2) new_size <<= 1;
Resize(new_size);
}
T* original = table[number + 1];
table[number + 1] = ptr;
if (ptr == 0) //Clear pointer.
{
if (number < next) next = number;
if (number == used - 1) //Last used position is cleared.
{
table[0] = (T*)1;
for (used--; table[used] == 0; used--);
}
}
else //Set pointer.
{
__assume(number < size - 2); //Otherwise a resize operation is invoked.
if (number == next)
{
next++; //Next position is occupied.
for (next++; table[next]; next++); //There is always a zero in the end.
next--; //next is zero based but the table start at one(zero is used as sentry).
}
if (number >= used) used = number + 1;
}
return original;
}
T* Get(unsigned int number)
{
number++;
if (number <= used) return table[number];
else return 0;
}
T* operator [](unsigned int number)
{
number++;
if (number <= used) return table[number];
else return 0;
}
void Append(T* ptr)
{
Set(next,ptr);
}
void Resize(unsigned int new_size)
{
assert(new_size > size);
assert((new_size & (new_size - 1)) == 0);
assert(new_size < 0x10000);
T** temp = new T*[new_size];
memcpy(temp, table, size * sizeof(T*));
memset(temp + size, 0, (new_size - size) * sizeof(T*));
delete table;
size = new_size;
table = temp;
}
void DeleteAll() //Release all pointers on demand.
{
T* p;
next = 0;
while (used)
{
p = table[used];
if (p) delete p;
table[used] = 0;
used--;
}
}
void Reset() //Reset without release pointers.
{
memset(table, 0, sizeof(T*) * (used + 1));
next = 0;
used = 0;
}
unsigned int size,next,used;
T** table;
};