amxmodx/amxmodx/trie_natives.h

215 lines
3.7 KiB
C
Raw Normal View History

2008-04-14 19:52:11 +00:00
#ifndef _TRIE_NATIVES_H_
#define _TRIE_NATIVES_H_
#include "amxmodx.h"
2014-05-03 11:22:48 +00:00
#include "sm_stringhashmap.h"
2008-04-14 19:52:11 +00:00
#include "CVector.h"
2014-05-03 11:22:48 +00:00
using namespace SourceMod;
2008-04-14 19:52:11 +00:00
2014-05-03 11:22:48 +00:00
enum EntryType
2008-04-14 19:52:11 +00:00
{
2014-05-03 11:22:48 +00:00
EntryType_Cell,
EntryType_CellArray,
EntryType_String,
};
2008-04-14 19:52:11 +00:00
2014-05-03 11:22:48 +00:00
class Entry
{
struct ArrayInfo
2008-04-14 19:52:11 +00:00
{
2014-05-03 11:22:48 +00:00
size_t length;
size_t maxbytes;
2008-04-14 19:52:11 +00:00
2014-05-03 11:22:48 +00:00
void *base() {
return this + 1;
2008-04-14 19:52:11 +00:00
}
2014-05-03 11:22:48 +00:00
};
2008-04-14 19:52:11 +00:00
public:
2014-05-03 11:22:48 +00:00
Entry()
: control_(0)
2008-04-14 19:52:11 +00:00
{
}
2014-05-03 11:22:48 +00:00
Entry(ke::Moveable<Entry> other)
2008-04-14 19:52:11 +00:00
{
2014-05-03 11:22:48 +00:00
control_ = other->control_;
data_ = other->data_;
other->control_ = 0;
2008-04-14 19:52:11 +00:00
}
2014-05-03 11:22:48 +00:00
~Entry()
2008-04-14 19:52:11 +00:00
{
2014-05-03 11:22:48 +00:00
free(raw());
}
2008-04-14 19:52:11 +00:00
2014-05-03 11:22:48 +00:00
void setCell(cell value) {
setType(EntryType_Cell);
data_ = value;
}
void setArray(cell *cells, size_t length) {
ArrayInfo *array = ensureArray(length * sizeof(cell));
array->length = length;
memcpy(array->base(), cells, length * sizeof(cell));
setTypeAndPointer(EntryType_CellArray, array);
}
void setString(const char *str) {
size_t length = strlen(str);
ArrayInfo *array = ensureArray(length + 1);
array->length = length;
strcpy((char *)array->base(), str);
setTypeAndPointer(EntryType_String, array);
2008-04-14 19:52:11 +00:00
}
2014-05-03 11:22:48 +00:00
size_t arrayLength() const {
assert(isArray());
2014-05-03 11:22:48 +00:00
return raw()->length;
}
cell *array() const {
assert(isArray());
2014-05-03 11:22:48 +00:00
return reinterpret_cast<cell *>(raw()->base());
}
char *chars() const {
assert(isString());
2014-05-03 11:22:48 +00:00
return reinterpret_cast<char *>(raw()->base());
}
cell cell_() const {
assert(isCell());
2014-05-03 11:22:48 +00:00
return data_;
}
2008-04-14 19:52:11 +00:00
2014-05-03 11:22:48 +00:00
bool isCell() const {
return type() == EntryType_Cell;
2008-04-14 19:52:11 +00:00
}
2014-05-03 11:22:48 +00:00
bool isArray() const {
return type() == EntryType_CellArray;
}
bool isString() const {
return type() == EntryType_String;
}
private:
Entry(const Entry &other) KE_DELETE;
ArrayInfo *ensureArray(size_t bytes) {
ArrayInfo *array = raw();
if (array && array->maxbytes >= bytes)
return array;
array = (ArrayInfo *)realloc(array, bytes + sizeof(ArrayInfo));
if (!array)
2008-04-14 19:52:11 +00:00
{
2014-05-03 11:22:48 +00:00
fprintf(stderr, "Out of memory!\n");
abort();
2008-04-14 19:52:11 +00:00
}
2014-05-03 11:22:48 +00:00
array->maxbytes = bytes;
return array;
2008-04-14 19:52:11 +00:00
}
2014-05-03 11:22:48 +00:00
// Pointer and type are overlaid, so we have some accessors.
ArrayInfo *raw() const {
return reinterpret_cast<ArrayInfo *>(control_ & ~uintptr_t(0x3));
2008-04-14 19:52:11 +00:00
}
2014-05-03 11:22:48 +00:00
void setType(EntryType aType) {
control_ = uintptr_t(raw()) | uintptr_t(aType);
assert(type() == aType);
2008-04-14 19:52:11 +00:00
}
2014-05-03 11:22:48 +00:00
void setTypeAndPointer(EntryType aType, ArrayInfo *ptr) {
// malloc() should guarantee 8-byte alignment at worst
assert((uintptr_t(ptr) & 0x3) == 0);
2014-05-03 11:22:48 +00:00
control_ = uintptr_t(ptr) | uintptr_t(aType);
assert(type() == aType);
2014-05-03 11:22:48 +00:00
}
EntryType type() const {
return (EntryType)(control_ & 0x3);
2008-04-14 19:52:11 +00:00
}
2014-05-03 11:22:48 +00:00
private:
// Contains the bits for the type, and an array pointer, if one is set.
uintptr_t control_;
// Contains data for cell-only entries.
cell data_;
};
2014-05-03 12:28:12 +00:00
struct CellTrie
2014-05-03 11:22:48 +00:00
{
StringHashMap<Entry> map;
2008-04-14 19:52:11 +00:00
};
2014-05-03 11:22:48 +00:00
template <typename T>
2008-04-14 19:52:11 +00:00
class TrieHandles
{
private:
2014-05-03 11:22:48 +00:00
CVector<T *> m_tries;
2008-04-14 19:52:11 +00:00
public:
TrieHandles() { }
~TrieHandles()
{
this->clear();
}
void clear()
{
for (size_t i = 0; i < m_tries.size(); i++)
{
if (m_tries[i] != NULL)
{
delete m_tries[i];
}
}
m_tries.clear();
}
2014-05-03 11:22:48 +00:00
T *lookup(int handle)
2008-04-14 19:52:11 +00:00
{
handle--;
if (handle < 0 || handle >= static_cast<int>(m_tries.size()))
{
return NULL;
}
return m_tries[handle];
}
int create()
{
for (size_t i = 0; i < m_tries.size(); i++)
{
if (m_tries[i] == NULL)
{
// reuse handle
2014-05-03 11:22:48 +00:00
m_tries[i] = new T;
2008-04-14 19:52:11 +00:00
return static_cast<int>(i) + 1;
}
}
2014-05-03 11:22:48 +00:00
m_tries.push_back(new T);
2008-04-14 19:52:11 +00:00
return m_tries.size();
}
bool destroy(int handle)
{
handle--;
if (handle < 0 || handle >= static_cast<int>(m_tries.size()))
{
return false;
}
if (m_tries[handle] == NULL)
{
return false;
}
delete m_tries[handle];
m_tries[handle] = NULL;
return true;
}
};
2014-05-03 11:22:48 +00:00
extern TrieHandles<CellTrie> g_TrieHandles;
2008-04-14 19:52:11 +00:00
extern AMX_NATIVE_INFO trie_Natives[];
#endif