Switch trie_natives off KTrie
This commit is contained in:
@@ -2,150 +2,145 @@
|
||||
#define _TRIE_NATIVES_H_
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "sm_trie_tpl.h"
|
||||
#include "sm_stringhashmap.h"
|
||||
#include <am-refcounting.h>
|
||||
#include "CVector.h"
|
||||
|
||||
#define TRIE_DATA_UNSET 0
|
||||
#define TRIE_DATA_CELL 1
|
||||
#define TRIE_DATA_STRING 2
|
||||
#define TRIE_DATA_ARRAY 3
|
||||
using namespace SourceMod;
|
||||
|
||||
#ifndef NDEBUG
|
||||
extern size_t trie_malloc_count;
|
||||
extern size_t trie_free_count;
|
||||
#endif
|
||||
|
||||
class TrieData
|
||||
enum EntryType
|
||||
{
|
||||
private:
|
||||
cell *m_data;
|
||||
cell m_cell;
|
||||
cell m_cellcount;
|
||||
int m_type;
|
||||
|
||||
void needCells(cell cellcount)
|
||||
{
|
||||
if (m_cellcount < cellcount)
|
||||
{
|
||||
if (m_data != NULL)
|
||||
{
|
||||
free(m_data);
|
||||
#ifndef NDEBUG
|
||||
trie_free_count++;
|
||||
#endif
|
||||
}
|
||||
size_t neededbytes = cellcount * sizeof(cell);
|
||||
m_data = static_cast<cell *>(malloc(neededbytes));
|
||||
|
||||
#ifndef NDEBUG
|
||||
trie_malloc_count++;
|
||||
#endif
|
||||
m_cellcount = cellcount;
|
||||
}
|
||||
}
|
||||
public:
|
||||
void freeCells()
|
||||
{
|
||||
if (m_data)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
trie_free_count++;
|
||||
#endif
|
||||
free(m_data);
|
||||
m_data = NULL;
|
||||
}
|
||||
m_cellcount = 0;
|
||||
}
|
||||
TrieData() : m_data(NULL), m_cell(0), m_cellcount(0), m_type(TRIE_DATA_UNSET) { }
|
||||
TrieData(const TrieData &src) : m_data(src.m_data),
|
||||
m_cell(src.m_cell),
|
||||
m_cellcount(src.m_cellcount),
|
||||
m_type(src.m_type) { }
|
||||
~TrieData() { }
|
||||
|
||||
int getType() { return m_type; }
|
||||
|
||||
void setCell(cell value)
|
||||
{
|
||||
freeCells();
|
||||
|
||||
m_cell = value;
|
||||
m_type = TRIE_DATA_CELL;
|
||||
}
|
||||
void setString(cell *value)
|
||||
{
|
||||
cell len = 0;
|
||||
|
||||
cell *p = value;
|
||||
|
||||
while (*p++ != 0)
|
||||
{
|
||||
len++;
|
||||
}
|
||||
len += 1; // zero terminator
|
||||
needCells(len);
|
||||
memcpy(m_data, value, sizeof(cell) * len);
|
||||
|
||||
m_type = TRIE_DATA_STRING;
|
||||
}
|
||||
void setArray(cell *value, cell size)
|
||||
{
|
||||
if (size <= 0)
|
||||
return;
|
||||
|
||||
needCells(size);
|
||||
memcpy(m_data, value, sizeof(cell) * size);
|
||||
|
||||
m_type = TRIE_DATA_ARRAY;
|
||||
}
|
||||
bool getCell(cell *out)
|
||||
{
|
||||
if (m_type == TRIE_DATA_CELL)
|
||||
{
|
||||
*out = m_cell;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool getString(cell *out, cell max)
|
||||
{
|
||||
if (m_type == TRIE_DATA_STRING && max >= 0)
|
||||
{
|
||||
int len = (max > m_cellcount) ? m_cellcount : max;
|
||||
memcpy(out, m_data, len * sizeof(cell));
|
||||
|
||||
/* Don't truncate a multi-byte character */
|
||||
if (m_data[len - 1] & 1 << 7)
|
||||
{
|
||||
len -= UTIL_CheckValidChar(m_data + len - 1);
|
||||
out[len] = '\0';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool getArray(cell *out, cell max)
|
||||
{
|
||||
if (m_type == TRIE_DATA_ARRAY && max >= 0)
|
||||
{
|
||||
memcpy(out, m_data, (max > m_cellcount ? m_cellcount : max) * sizeof(cell));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
freeCells();
|
||||
m_type = TRIE_DATA_UNSET;
|
||||
}
|
||||
EntryType_Cell,
|
||||
EntryType_CellArray,
|
||||
EntryType_String,
|
||||
};
|
||||
|
||||
class Entry
|
||||
{
|
||||
struct ArrayInfo
|
||||
{
|
||||
size_t length;
|
||||
size_t maxbytes;
|
||||
|
||||
void *base() {
|
||||
return this + 1;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
Entry()
|
||||
: control_(0)
|
||||
{
|
||||
}
|
||||
Entry(ke::Moveable<Entry> other)
|
||||
{
|
||||
control_ = other->control_;
|
||||
data_ = other->data_;
|
||||
other->control_ = 0;
|
||||
}
|
||||
~Entry()
|
||||
{
|
||||
free(raw());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
size_t arrayLength() const {
|
||||
//assert(isArray());
|
||||
return raw()->length;
|
||||
}
|
||||
cell *array() const {
|
||||
//assert(isArray());
|
||||
return reinterpret_cast<cell *>(raw()->base());
|
||||
}
|
||||
char *chars() const {
|
||||
//assert(isString());
|
||||
return reinterpret_cast<char *>(raw()->base());
|
||||
}
|
||||
cell cell_() const {
|
||||
//assert(isCell());
|
||||
return data_;
|
||||
}
|
||||
|
||||
bool isCell() const {
|
||||
return type() == EntryType_Cell;
|
||||
}
|
||||
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)
|
||||
{
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
abort();
|
||||
}
|
||||
array->maxbytes = bytes;
|
||||
return array;
|
||||
}
|
||||
|
||||
// Pointer and type are overlaid, so we have some accessors.
|
||||
ArrayInfo *raw() const {
|
||||
return reinterpret_cast<ArrayInfo *>(control_ & ~uintptr_t(0x3));
|
||||
}
|
||||
void setType(EntryType aType) {
|
||||
control_ = uintptr_t(raw()) | uintptr_t(aType);
|
||||
//assert(type() == aType);
|
||||
}
|
||||
void setTypeAndPointer(EntryType aType, ArrayInfo *ptr) {
|
||||
// malloc() should guarantee 8-byte alignment at worst
|
||||
//assert((uintptr_t(ptr) & 0x3) == 0);
|
||||
control_ = uintptr_t(ptr) | uintptr_t(aType);
|
||||
//assert(type() == aType);
|
||||
}
|
||||
EntryType type() const {
|
||||
return (EntryType)(control_ & 0x3);
|
||||
}
|
||||
|
||||
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_;
|
||||
};
|
||||
|
||||
struct CellTrie : public ke::Refcounted<CellTrie>
|
||||
{
|
||||
StringHashMap<Entry> map;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TrieHandles
|
||||
{
|
||||
private:
|
||||
CVector< KTrie< TrieData > *> m_tries;
|
||||
CVector<T *> m_tries;
|
||||
|
||||
public:
|
||||
TrieHandles() { }
|
||||
@@ -166,7 +161,7 @@ public:
|
||||
|
||||
m_tries.clear();
|
||||
}
|
||||
KTrie<TrieData> *lookup(int handle)
|
||||
T *lookup(int handle)
|
||||
{
|
||||
handle--;
|
||||
|
||||
@@ -184,12 +179,12 @@ public:
|
||||
if (m_tries[i] == NULL)
|
||||
{
|
||||
// reuse handle
|
||||
m_tries[i] = new KTrie<TrieData>;
|
||||
m_tries[i] = new T;
|
||||
|
||||
return static_cast<int>(i) + 1;
|
||||
}
|
||||
}
|
||||
m_tries.push_back(new KTrie<TrieData>);
|
||||
m_tries.push_back(new T);
|
||||
return m_tries.size();
|
||||
}
|
||||
bool destroy(int handle)
|
||||
@@ -213,7 +208,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
extern TrieHandles g_TrieHandles;
|
||||
extern TrieHandles<CellTrie> g_TrieHandles;
|
||||
extern AMX_NATIVE_INFO trie_Natives[];
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user