Added amb1600: trie natives
This commit is contained in:
parent
683f453b6f
commit
53ed817183
|
@ -20,7 +20,8 @@ OBJECTS = meta_api.cpp CFile.cpp CVault.cpp vault.cpp float.cpp file.cpp modules
|
||||||
amxxfile.cpp CLang.cpp md5.cpp emsg.cpp CForward.cpp CPlugin.cpp CModule.cpp \
|
amxxfile.cpp CLang.cpp md5.cpp emsg.cpp CForward.cpp CPlugin.cpp CModule.cpp \
|
||||||
CMenu.cpp util.cpp amx.cpp amxdbg.cpp natives.cpp newmenus.cpp debugger.cpp \
|
CMenu.cpp util.cpp amx.cpp amxdbg.cpp natives.cpp newmenus.cpp debugger.cpp \
|
||||||
optimizer.cpp format.cpp messages.cpp libraries.cpp vector.cpp sorting.cpp \
|
optimizer.cpp format.cpp messages.cpp libraries.cpp vector.cpp sorting.cpp \
|
||||||
amxmod_compat.cpp nongpl_matches.cpp CFlagManager.cpp datastructs.cpp
|
amxmod_compat.cpp nongpl_matches.cpp CFlagManager.cpp datastructs.cpp \
|
||||||
|
trie_natives.cpp
|
||||||
|
|
||||||
LINK = -lgcc -static-libgcc
|
LINK = -lgcc -static-libgcc
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
#include "datastructs.h"
|
#include "datastructs.h"
|
||||||
#include "CFlagManager.h"
|
#include "CFlagManager.h"
|
||||||
#include "svn_version.h"
|
#include "svn_version.h"
|
||||||
|
#include "trie_natives.h"
|
||||||
|
|
||||||
plugin_info_t Plugin_info =
|
plugin_info_t Plugin_info =
|
||||||
{
|
{
|
||||||
|
@ -412,6 +412,7 @@ int C_Spawn(edict_t *pent)
|
||||||
};
|
};
|
||||||
VectorHolder.clear();
|
VectorHolder.clear();
|
||||||
|
|
||||||
|
g_TrieHandles.clear();
|
||||||
char map_pluginsfile_path[256];
|
char map_pluginsfile_path[256];
|
||||||
char prefixed_map_pluginsfile[256];
|
char prefixed_map_pluginsfile[256];
|
||||||
char configs_dir[256];
|
char configs_dir[256];
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "libraries.h"
|
#include "libraries.h"
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
#include "amxmod_compat.h"
|
#include "amxmod_compat.h"
|
||||||
|
#include "trie_natives.h"
|
||||||
|
|
||||||
CList<CModule, const char*> g_modules;
|
CList<CModule, const char*> g_modules;
|
||||||
CList<CScript, AMX*> g_loadedscripts;
|
CList<CScript, AMX*> g_loadedscripts;
|
||||||
|
@ -579,6 +580,7 @@ int set_amxnatives(AMX* amx, char error[128])
|
||||||
amx_Register(amx, vector_Natives, -1);
|
amx_Register(amx, vector_Natives, -1);
|
||||||
amx_Register(amx, g_SortNatives, -1);
|
amx_Register(amx, g_SortNatives, -1);
|
||||||
amx_Register(amx, g_DataStructNatives, -1);
|
amx_Register(amx, g_DataStructNatives, -1);
|
||||||
|
amx_Register(amx, trie_Natives, -1);
|
||||||
|
|
||||||
if (amx->flags & AMX_FLAG_OLDFILE)
|
if (amx->flags & AMX_FLAG_OLDFILE)
|
||||||
{
|
{
|
||||||
|
|
316
amxmodx/trie_natives.cpp
Normal file
316
amxmodx/trie_natives.cpp
Normal file
|
@ -0,0 +1,316 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "amxmodx.h"
|
||||||
|
#include "sm_trie_tpl.h"
|
||||||
|
#include "trie_natives.h"
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
size_t trie_free_count = 0;
|
||||||
|
size_t trie_malloc_count = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TrieHandles g_TrieHandles;
|
||||||
|
typedef KTrie<TrieData> celltrie;
|
||||||
|
|
||||||
|
void triedata_dtor(TrieData *ptr)
|
||||||
|
{
|
||||||
|
ptr->freeCells();
|
||||||
|
}
|
||||||
|
// native Trie:TrieCreate();
|
||||||
|
static cell AMX_NATIVE_CALL TrieCreate(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
return static_cast<cell>(g_TrieHandles.create());
|
||||||
|
}
|
||||||
|
|
||||||
|
// native Trie::TrieClear(Trie:handle);
|
||||||
|
static cell AMX_NATIVE_CALL TrieClear(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
celltrie *t = g_TrieHandles.lookup(params[1]);
|
||||||
|
|
||||||
|
if (t == NULL)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid trie handle provided (%d)", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
t->run_destructor(triedata_dtor);
|
||||||
|
t->clear();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// native TrieSetCell(Trie:handle, const key[], any:value);
|
||||||
|
static cell AMX_NATIVE_CALL TrieSetCell(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
celltrie *t = g_TrieHandles.lookup(params[1]);
|
||||||
|
|
||||||
|
if (t == NULL)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid trie handle provided (%d)", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrieData *td = NULL;
|
||||||
|
int len;
|
||||||
|
const char *key = get_amxstring(amx, params[2], 0, len);
|
||||||
|
|
||||||
|
if ((td = t->retrieve(key)) == NULL)
|
||||||
|
{
|
||||||
|
TrieData dummy;
|
||||||
|
t->insert(key, dummy);
|
||||||
|
|
||||||
|
td = t->retrieve(key);
|
||||||
|
|
||||||
|
// should never, ever happen
|
||||||
|
if (td == NULL)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Couldn't KTrie::retrieve(), handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
td->setCell(params[3]);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// native TrieSetString(Trie:handle, const key[], const data[]);
|
||||||
|
static cell AMX_NATIVE_CALL TrieSetString(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
celltrie *t = g_TrieHandles.lookup(params[1]);
|
||||||
|
|
||||||
|
if (t == NULL)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid trie handle provided (%d)", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrieData *td = NULL;
|
||||||
|
int len;
|
||||||
|
const char *key = get_amxstring(amx, params[2], 0, len);
|
||||||
|
|
||||||
|
if ((td = t->retrieve(key)) == NULL)
|
||||||
|
{
|
||||||
|
TrieData dummy;
|
||||||
|
t->insert(key, dummy);
|
||||||
|
td = t->retrieve(key);
|
||||||
|
|
||||||
|
// should never, ever happen
|
||||||
|
if (td == NULL)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Couldn't KTrie::retrieve(), handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
td->setString(get_amxaddr(amx, params[3]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// native TrieSetArray(Trie:handle, const key[], const any:buffer[], buffsize)
|
||||||
|
static cell AMX_NATIVE_CALL TrieSetArray(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
celltrie *t = g_TrieHandles.lookup(params[2]);
|
||||||
|
|
||||||
|
if (t == NULL)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid trie handle provided (%d)", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrieData *td = NULL;
|
||||||
|
int len;
|
||||||
|
const char *key = get_amxstring(amx, params[2], 0, len);
|
||||||
|
|
||||||
|
if ((td = t->retrieve(key)) == NULL)
|
||||||
|
{
|
||||||
|
TrieData dummy;
|
||||||
|
t->insert(key, dummy);
|
||||||
|
td = t->retrieve(key);
|
||||||
|
|
||||||
|
// should never, ever happen
|
||||||
|
if (td == NULL)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Couldn't KTrie::retrieve(), handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
td->setArray(get_amxaddr(amx, params[3]), params[4]);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// native bool:TrieGetCell(Trie:handle, const key[], &any:value);
|
||||||
|
static cell AMX_NATIVE_CALL TrieGetCell(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
celltrie *t = g_TrieHandles.lookup(params[1]);
|
||||||
|
|
||||||
|
if (t == NULL)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid trie handle provided (%d)", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TrieData *td = NULL;
|
||||||
|
int len;
|
||||||
|
const char *key = get_amxstring(amx, params[2], 0, len);
|
||||||
|
|
||||||
|
if ((td = t->retrieve(key)) == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cell *ptr = get_amxaddr(amx, params[3]);
|
||||||
|
if (!td->getCell(ptr))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// native bool:TrieGetString(Trie:handle, const key[], buff[], len);
|
||||||
|
static cell AMX_NATIVE_CALL TrieGetString(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
celltrie *t = g_TrieHandles.lookup(params[1]);
|
||||||
|
|
||||||
|
if (t == NULL)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid trie handle provided (%d)", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TrieData *td = NULL;
|
||||||
|
int len;
|
||||||
|
const char *key = get_amxstring(amx, params[2], 0, len);
|
||||||
|
|
||||||
|
if ((td = t->retrieve(key)) == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cell *ptr = get_amxaddr(amx, params[3]);
|
||||||
|
if (!td->getString(ptr, params[4]))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// native bool:TrieGetArray(Trie:handle, const key[], any:buff[], len);
|
||||||
|
static cell AMX_NATIVE_CALL TrieGetArray(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
celltrie *t = g_TrieHandles.lookup(params[1]);
|
||||||
|
|
||||||
|
if (t == NULL)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid trie handle provided (%d)", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TrieData *td = NULL;
|
||||||
|
int len;
|
||||||
|
const char *key = get_amxstring(amx, params[2], 0, len);
|
||||||
|
|
||||||
|
if ((td = t->retrieve(key)) == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cell *ptr = get_amxaddr(amx, params[3]);
|
||||||
|
if (!td->getArray(ptr, params[4]))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// native bool:TrieKeyExists(Trie:handle, const key[]);
|
||||||
|
static cell AMX_NATIVE_CALL TrieKeyExists(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
celltrie *t = g_TrieHandles.lookup(params[1]);
|
||||||
|
|
||||||
|
if (t == NULL)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid trie handle provided (%d)", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int len;
|
||||||
|
const char *key = get_amxstring(amx, params[2], 0, len);
|
||||||
|
return t->retrieve(key) != NULL ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// native bool:TrieDeleteKey(Trie:handle, const key[]);
|
||||||
|
static cell AMX_NATIVE_CALL TrieDeleteKey(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
celltrie *t = g_TrieHandles.lookup(params[1]);
|
||||||
|
|
||||||
|
if (t == NULL)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid trie handle provided (%d)", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int len;
|
||||||
|
const char *key = get_amxstring(amx, params[2], 0, len);
|
||||||
|
TrieData *td = t->retrieve(key);
|
||||||
|
|
||||||
|
if (td != NULL)
|
||||||
|
{
|
||||||
|
td->freeCells();
|
||||||
|
}
|
||||||
|
return t->remove(key) ? 1 : 0;
|
||||||
|
}
|
||||||
|
//native TrieDestroy(&Trie:handle)
|
||||||
|
static cell AMX_NATIVE_CALL TrieDestroy(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
cell *ptr = get_amxaddr(amx, params[1]);
|
||||||
|
|
||||||
|
celltrie *t = g_TrieHandles.lookup(*ptr);
|
||||||
|
|
||||||
|
if (t == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
t->run_destructor(triedata_dtor);
|
||||||
|
if (g_TrieHandles.destroy(*ptr))
|
||||||
|
{
|
||||||
|
*ptr = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
#ifndef NDEBUG
|
||||||
|
static cell AMX_NATIVE_CALL TrieMallocCount(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
return trie_malloc_count;
|
||||||
|
}
|
||||||
|
static cell AMX_NATIVE_CALL TrieFreeCount(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
return trie_free_count;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
AMX_NATIVE_INFO trie_Natives[] =
|
||||||
|
{
|
||||||
|
{ "TrieCreate", TrieCreate },
|
||||||
|
{ "TrieClear", TrieClear },
|
||||||
|
|
||||||
|
{ "TrieSetCell", TrieSetCell },
|
||||||
|
{ "TrieSetString", TrieSetString },
|
||||||
|
{ "TrieSetArray", TrieSetArray },
|
||||||
|
|
||||||
|
{ "TrieGetCell", TrieGetCell },
|
||||||
|
{ "TrieGetString", TrieGetString },
|
||||||
|
{ "TrieGetArray", TrieGetArray },
|
||||||
|
|
||||||
|
{ "TrieDeleteKey", TrieDeleteKey },
|
||||||
|
{ "TrieKeyExists", TrieKeyExists },
|
||||||
|
{ "TrieDestroy", TrieDestroy },
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
{ "TrieMallocCount", TrieMallocCount },
|
||||||
|
{ "TrieFreeCount", TrieFreeCount },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
211
amxmodx/trie_natives.h
Normal file
211
amxmodx/trie_natives.h
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
#ifndef _TRIE_NATIVES_H_
|
||||||
|
#define _TRIE_NATIVES_H_
|
||||||
|
|
||||||
|
#include "amxmodx.h"
|
||||||
|
#include "sm_trie_tpl.h"
|
||||||
|
#include "CVector.h"
|
||||||
|
|
||||||
|
#define TRIE_DATA_UNSET 0
|
||||||
|
#define TRIE_DATA_CELL 1
|
||||||
|
#define TRIE_DATA_STRING 2
|
||||||
|
#define TRIE_DATA_ARRAY 3
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
extern size_t trie_malloc_count;
|
||||||
|
extern size_t trie_free_count;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class TrieData
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
memcpy(out, m_data, (max > m_cellcount ? m_cellcount : max) * sizeof(cell));
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TrieHandles
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
CVector< KTrie< TrieData > *> m_tries;
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
KTrie<TrieData> *lookup(int handle)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
m_tries[i] = new KTrie<TrieData>;
|
||||||
|
|
||||||
|
return static_cast<int>(i) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_tries.push_back(new KTrie<TrieData>);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern TrieHandles g_TrieHandles;
|
||||||
|
extern AMX_NATIVE_INFO trie_Natives[];
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sorting>
|
#include <sorting>
|
||||||
#include <cellarray>
|
#include <cellarray>
|
||||||
|
#include <celltrie>
|
||||||
#include <newmenus>
|
#include <newmenus>
|
||||||
|
|
||||||
/* Function is called just after server activation.
|
/* Function is called just after server activation.
|
||||||
|
|
26
plugins/include/celltrie.inc
Normal file
26
plugins/include/celltrie.inc
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#if defined _celltrie_included
|
||||||
|
#endinput
|
||||||
|
#endif
|
||||||
|
#define _celltrie_included
|
||||||
|
|
||||||
|
enum Trie
|
||||||
|
{
|
||||||
|
Invalid_Trie = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
native Trie:TrieCreate();
|
||||||
|
native TrieClear(Trie:handle);
|
||||||
|
|
||||||
|
native TrieSetCell(Trie:handle, const key[], any:value);
|
||||||
|
native TrieSetString(Trie:handle, const key[], const value[]);
|
||||||
|
native TrieSetArray(Trie:handle, const key[], const any:buffer[], size);
|
||||||
|
|
||||||
|
native bool:TrieGetCell(Trie:handle, const key[], &any:value);
|
||||||
|
native bool:TrieGetString(Trie:handle, const key[], output[], outputsize);
|
||||||
|
native bool:TrieGetArray(Trie:handle, const key[], any:output[], outputsize);
|
||||||
|
|
||||||
|
native bool:TrieDeleteKey(Trie:handle, const key[]);
|
||||||
|
native bool:TrieKeyExists(Trie:handle, const key[]);
|
||||||
|
native TrieDestroy(&Trie:handle);
|
||||||
|
|
|
@ -102,6 +102,9 @@ public arraytest1()
|
||||||
|
|
||||||
new Float:f;
|
new Float:f;
|
||||||
new Array:a=ArrayCreate(1);
|
new Array:a=ArrayCreate(1);
|
||||||
|
if (a == Invalid_Array)
|
||||||
|
{
|
||||||
|
}
|
||||||
for (new i=0; i<1000; i++)
|
for (new i=0; i<1000; i++)
|
||||||
{
|
{
|
||||||
f=float(i);
|
f=float(i);
|
||||||
|
|
169
plugins/testsuite/trietest.sma
Normal file
169
plugins/testsuite/trietest.sma
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
#include <amxmodx>
|
||||||
|
|
||||||
|
|
||||||
|
// These natives are only available in a debug build of amxmodx
|
||||||
|
native TrieFreeCount();
|
||||||
|
native TrieMallocCount();
|
||||||
|
|
||||||
|
new failcount = 0;
|
||||||
|
new passcount = 0;
|
||||||
|
public plugin_init()
|
||||||
|
{
|
||||||
|
register_plugin("Trie Test", AMXX_VERSION_STR, "AMXX Dev Team");
|
||||||
|
register_srvcmd("trietest", "trietest");
|
||||||
|
}
|
||||||
|
|
||||||
|
stock fail(const testname[])
|
||||||
|
{
|
||||||
|
server_print("[FAIL] %s", testname);
|
||||||
|
|
||||||
|
failcount++;
|
||||||
|
}
|
||||||
|
stock pass(const testname[])
|
||||||
|
{
|
||||||
|
server_print("[PASS] %s", testname);
|
||||||
|
|
||||||
|
passcount++;
|
||||||
|
}
|
||||||
|
stock done()
|
||||||
|
{
|
||||||
|
server_print("Finished. %d tests, %d failed", failcount + passcount, failcount);
|
||||||
|
}
|
||||||
|
stock check_frees()
|
||||||
|
{
|
||||||
|
if (TrieMallocCount() != TrieFreeCount())
|
||||||
|
fail("free count == malloc count");
|
||||||
|
|
||||||
|
else
|
||||||
|
pass("free count == malloc count");
|
||||||
|
|
||||||
|
server_print("malloc count: %d free count: %d", TrieMallocCount(), TrieFreeCount());
|
||||||
|
}
|
||||||
|
public trietest()
|
||||||
|
{
|
||||||
|
failcount = 0;
|
||||||
|
passcount = 0;
|
||||||
|
|
||||||
|
new bool:ok = true;
|
||||||
|
new Trie:t = TrieCreate();
|
||||||
|
|
||||||
|
new Trie:oldhandle = t; // Makes sure that the trie handle system recycles old handles
|
||||||
|
|
||||||
|
new key[32];
|
||||||
|
for (new i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
formatex(key, charsmax(key), "K%dK", i);
|
||||||
|
TrieSetCell(t, key, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (new i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
formatex(key, charsmax(key), "K%dK", i);
|
||||||
|
new val;
|
||||||
|
if (!TrieGetCell(t, key, val))
|
||||||
|
{
|
||||||
|
server_print("TrieGetCell(%d, '%s', %d) failed", t, key, val);
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (val != i)
|
||||||
|
{
|
||||||
|
server_print("val mismatch, expected: %d got: %d", i, val);
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (ok)
|
||||||
|
pass("Cell tests");
|
||||||
|
|
||||||
|
else
|
||||||
|
fail("Cell tests");
|
||||||
|
|
||||||
|
TrieClear(t);
|
||||||
|
TrieDestroy(t);
|
||||||
|
|
||||||
|
t = TrieCreate();
|
||||||
|
|
||||||
|
if (t == oldhandle)
|
||||||
|
pass("Recycle handles");
|
||||||
|
|
||||||
|
else
|
||||||
|
fail("Recycle handles");
|
||||||
|
|
||||||
|
ok = true;
|
||||||
|
for (new i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
static val[32];
|
||||||
|
formatex(key, charsmax(key), "K%dK", i);
|
||||||
|
formatex(val, charsmax(val), "V%dV", i);
|
||||||
|
TrieSetString(t, key, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (new i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
formatex(key, charsmax(key), "K%dK", i);
|
||||||
|
static val[32];
|
||||||
|
static exp[32];
|
||||||
|
formatex(exp, charsmax(exp), "V%dV", i);
|
||||||
|
if (!TrieGetString(t, key, val, charsmax(val)))
|
||||||
|
{
|
||||||
|
server_print("TrieGetString(%d, '%s', %s) failed", t, key, val);
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (!equal(val, exp))
|
||||||
|
{
|
||||||
|
server_print("val mismatch, key: '%s' expected: '%s' got: '%s'", key, exp, val);
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (ok)
|
||||||
|
pass("String tests");
|
||||||
|
|
||||||
|
else
|
||||||
|
fail("String tests");
|
||||||
|
|
||||||
|
TrieDestroy(t);
|
||||||
|
|
||||||
|
check_frees();
|
||||||
|
|
||||||
|
t = TrieCreate();
|
||||||
|
ok = true;
|
||||||
|
for (new i = 0; i < 1000; i++)
|
||||||
|
{
|
||||||
|
formatex(key, charsmax(key), "!%d!", i);
|
||||||
|
TrieSetString(t, key, key);
|
||||||
|
}
|
||||||
|
for (new i = 0; i < 1000; i++)
|
||||||
|
{
|
||||||
|
formatex(key, charsmax(key), "!%d!", i);
|
||||||
|
|
||||||
|
if (!TrieKeyExists(t, key))
|
||||||
|
{
|
||||||
|
ok = false;
|
||||||
|
server_print("Key '%s' does not exist", key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!TrieDeleteKey(t, key))
|
||||||
|
{
|
||||||
|
server_print("Key '%s' could not be deleted", key);
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ok)
|
||||||
|
pass("Exists/Delete");
|
||||||
|
|
||||||
|
else
|
||||||
|
fail("Exists/Delete");
|
||||||
|
|
||||||
|
check_frees();
|
||||||
|
TrieClear(t);
|
||||||
|
TrieDestroy(t);
|
||||||
|
check_frees();
|
||||||
|
done();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user