amxmodx/amxmodx/trie_natives.h

168 lines
3.4 KiB
C
Raw Normal View History

2014-08-04 08:36:20 +00:00
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
2008-04-14 19:52:11 +00:00
#ifndef _TRIE_NATIVES_H_
#define _TRIE_NATIVES_H_
#include "amxmodx.h"
#include <sm_stringhashmap.h>
#include <sm_memtable.h>
#include "natives_handles.h"
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-12-06 11:22:29 +00:00
Entry(Entry &&other)
2008-04-14 19:52:11 +00:00
{
2014-12-06 11:22:29 +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 21:21:56 +00:00
struct TrieSnapshot
{
TrieSnapshot()
: strings(128)
{ }
size_t mem_usage()
{
return length * sizeof(int) + strings.GetMemTable()->GetMemUsage();
}
size_t length;
ke::AutoArray<int> keys;
BaseStringTable strings;
};
extern Handle<CellTrie> TrieHandles;
extern Handle<TrieSnapshot> TrieSnapshotHandles;
2008-04-14 19:52:11 +00:00
extern AMX_NATIVE_INFO trie_Natives[];
#endif