mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-25 06:15:37 +03:00
initial import of sqlitex
This commit is contained in:
parent
3cde89bc74
commit
aa1308e32e
451
dlls/sqlite/basic_sql.cpp
Normal file
451
dlls/sqlite/basic_sql.cpp
Normal file
@ -0,0 +1,451 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "sh_list.h"
|
||||||
|
#include "sqlite_header.h"
|
||||||
|
#include "sqlheaders.h"
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
using namespace SourceHook;
|
||||||
|
|
||||||
|
SqliteDriver g_Sqlite;
|
||||||
|
|
||||||
|
void FreeConnection(void *p, unsigned int num)
|
||||||
|
{
|
||||||
|
SQL_Connection *cn = (SQL_Connection *)p;
|
||||||
|
|
||||||
|
free(cn->host);
|
||||||
|
free(cn->user);
|
||||||
|
free(cn->pass);
|
||||||
|
free(cn->db);
|
||||||
|
|
||||||
|
delete cn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeQuery(void *p, unsigned int num)
|
||||||
|
{
|
||||||
|
AmxQueryInfo *qry = (AmxQueryInfo *)p;
|
||||||
|
|
||||||
|
qry->pQuery->FreeHandle();
|
||||||
|
delete qry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeDatabase(void *p, unsigned int num)
|
||||||
|
{
|
||||||
|
IDatabase *db = (IDatabase *)p;
|
||||||
|
|
||||||
|
db->FreeHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_MakeDbTuple(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
SQL_Connection *sql = new SQL_Connection;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
char *host = strdup(MF_GetAmxString(amx, params[1], 0, &len));
|
||||||
|
|
||||||
|
char *p = strchr(host, ':');
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
sql->port = atoi(p+1);
|
||||||
|
*p = '\0';
|
||||||
|
} else {
|
||||||
|
sql->port = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sql->host = host;
|
||||||
|
sql->user = strdup(MF_GetAmxString(amx, params[2], 0, &len));
|
||||||
|
sql->pass = strdup(MF_GetAmxString(amx, params[3], 0, &len));
|
||||||
|
sql->db = strdup(MF_GetAmxString(amx, params[4], 0, &len));
|
||||||
|
|
||||||
|
unsigned int num = MakeHandle(sql, Handle_Connection, FreeConnection);
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_FreeHandle(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
if (!FreeHandle(params[1]))
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_Connect(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
SQL_Connection *sql = (SQL_Connection *)GetHandle(params[1], Handle_Connection);
|
||||||
|
if (!sql)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabaseInfo nfo;
|
||||||
|
nfo.database = sql->db;
|
||||||
|
nfo.user = "";
|
||||||
|
nfo.pass = "";
|
||||||
|
nfo.port = 0;
|
||||||
|
nfo.host = "";
|
||||||
|
|
||||||
|
char buffer[512];
|
||||||
|
int errcode;
|
||||||
|
|
||||||
|
IDatabase *pDb = g_Sqlite.Connect(&nfo, &errcode, buffer, sizeof(buffer)-1);
|
||||||
|
|
||||||
|
if (!pDb)
|
||||||
|
{
|
||||||
|
cell *c_err = MF_GetAmxAddr(amx, params[2]);
|
||||||
|
|
||||||
|
*c_err = errcode;
|
||||||
|
MF_SetAmxString(amx, params[3], buffer, params[4]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MakeHandle(pDb, Handle_Database, FreeDatabase);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_PrepareQuery(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
IDatabase *pDb = (IDatabase *)GetHandle(params[1], Handle_Database);
|
||||||
|
if (!pDb)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len;
|
||||||
|
char *fmt = MF_FormatAmxString(amx, params, 2, &len);
|
||||||
|
|
||||||
|
IQuery *pQuery = pDb->PrepareQuery(fmt);
|
||||||
|
if (!pQuery)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
AmxQueryInfo *qinfo = new AmxQueryInfo;
|
||||||
|
qinfo->pQuery = pQuery;
|
||||||
|
|
||||||
|
memset(&qinfo->info, 0, sizeof(QueryInfo));
|
||||||
|
|
||||||
|
return MakeHandle(qinfo, Handle_Query, FreeQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_Execute(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
AmxQueryInfo *qInfo = (AmxQueryInfo *)GetHandle(params[1], Handle_Query);
|
||||||
|
if (!qInfo)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qInfo->error[0] = '\0';
|
||||||
|
|
||||||
|
memset(&qInfo->info, 0, sizeof(QueryInfo));
|
||||||
|
|
||||||
|
if (!qInfo->pQuery->Execute(&qInfo->info, qInfo->error, 254))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_QueryError(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
AmxQueryInfo *qInfo = (AmxQueryInfo *)GetHandle(params[1], Handle_Query);
|
||||||
|
if (!qInfo)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MF_SetAmxString(amx, params[2], qInfo->error, params[3]);
|
||||||
|
|
||||||
|
return qInfo->info.errorcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_MoreResults(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
AmxQueryInfo *qInfo = (AmxQueryInfo *)GetHandle(params[1], Handle_Query);
|
||||||
|
if (!qInfo)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!qInfo->info.rs)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (qInfo->info.rs->IsDone() ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_IsNull(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
AmxQueryInfo *qInfo = (AmxQueryInfo *)GetHandle(params[1], Handle_Query);
|
||||||
|
if (!qInfo)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IResultSet *rs = qInfo->info.rs;
|
||||||
|
|
||||||
|
if (!rs || rs->IsDone())
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "No result set in this query!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int col = static_cast<unsigned int>(params[2]);
|
||||||
|
if (col >= rs->FieldCount())
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid column: %d", col);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IResultRow *rr = rs->GetRow();
|
||||||
|
|
||||||
|
return rr->IsNull(col) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_ReadResult(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
AmxQueryInfo *qInfo = (AmxQueryInfo *)GetHandle(params[1], Handle_Query);
|
||||||
|
if (!qInfo)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IResultSet *rs = qInfo->info.rs;
|
||||||
|
|
||||||
|
if (!rs || rs->IsDone())
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "No result set in this query!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IResultRow *row = rs->GetRow();
|
||||||
|
|
||||||
|
unsigned int col = static_cast<unsigned int>(params[2]);
|
||||||
|
if (col >= rs->FieldCount())
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid column: %d", col);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell numparams = params[0] / sizeof(cell);
|
||||||
|
switch (numparams)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
const char *str = row->GetString(col);
|
||||||
|
if (!str)
|
||||||
|
str = "";
|
||||||
|
cell *len = MF_GetAmxAddr(amx, params[4]);
|
||||||
|
MF_SetAmxString(amx, params[3], str, (int)*len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
REAL num = row->GetFloat(col);
|
||||||
|
cell *addr = MF_GetAmxAddr(amx, params[3]);
|
||||||
|
*addr = amx_ftoc(num);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
int num = row->GetInt(col);
|
||||||
|
return num;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Bad number of arguments passed.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_NextRow(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
AmxQueryInfo *qInfo = (AmxQueryInfo *)GetHandle(params[1], Handle_Query);
|
||||||
|
if (!qInfo)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IResultSet *rs = qInfo->info.rs;
|
||||||
|
|
||||||
|
if (!rs || rs->IsDone())
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "No result set in this query!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rs->NextRow();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_AffectedRows(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
AmxQueryInfo *qInfo = (AmxQueryInfo *)GetHandle(params[1], Handle_Query);
|
||||||
|
if (!qInfo)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<cell>(qInfo->info.affected_rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_NumResults(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
AmxQueryInfo *qInfo = (AmxQueryInfo *)GetHandle(params[1], Handle_Query);
|
||||||
|
if (!qInfo)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IResultSet *rs = qInfo->info.rs;
|
||||||
|
|
||||||
|
if (!rs)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rs->RowCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_NumColumns(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
AmxQueryInfo *qInfo = (AmxQueryInfo *)GetHandle(params[1], Handle_Query);
|
||||||
|
if (!qInfo)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IResultSet *rs = qInfo->info.rs;
|
||||||
|
|
||||||
|
if (!rs)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "No result set in this query!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rs->FieldCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_FieldNumToName(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
AmxQueryInfo *qInfo = (AmxQueryInfo *)GetHandle(params[1], Handle_Query);
|
||||||
|
if (!qInfo)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IResultSet *rs = qInfo->info.rs;
|
||||||
|
|
||||||
|
if (!rs)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "No result set in this query!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int col = static_cast<unsigned int>(params[2]);
|
||||||
|
const char *namewa = rs->FieldNumToName(col);
|
||||||
|
|
||||||
|
if (!namewa)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid column: %d", col);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MF_SetAmxString(amx, params[3], namewa, params[4]);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_FieldNameToNum(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
AmxQueryInfo *qInfo = (AmxQueryInfo *)GetHandle(params[1], Handle_Query);
|
||||||
|
if (!qInfo)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IResultSet *rs = qInfo->info.rs;
|
||||||
|
|
||||||
|
if (!rs)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "No result set in this query!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len;
|
||||||
|
char *namewa = MF_GetAmxString(amx, params[2], 0, &len);
|
||||||
|
unsigned int columnId;
|
||||||
|
if (!rs->FieldNameToNum(namewa, &columnId))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return columnId;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_GetAffinity(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
return MF_SetAmxString(amx, params[1], g_Sqlite.NameString(), params[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SQL_SetAffinity(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char *str = MF_GetAmxString(amx, params[1], 0, &len);
|
||||||
|
|
||||||
|
if (stricmp(str, g_Sqlite.NameString()) == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SqlFunctions *pFuncs = (SqlFunctions *)MF_RequestFunction(SQL_DRIVER_FUNC);
|
||||||
|
while (pFuncs)
|
||||||
|
{
|
||||||
|
if (pFuncs->driver->IsCompatDriver(str))
|
||||||
|
{
|
||||||
|
return pFuncs->set_affinity(amx);
|
||||||
|
}
|
||||||
|
pFuncs = pFuncs->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern AMX_NATIVE_INFO g_BaseSqlNatives[] =
|
||||||
|
{
|
||||||
|
{"SQL_MakeDbTuple", SQL_MakeDbTuple},
|
||||||
|
{"SQL_FreeHandle", SQL_FreeHandle},
|
||||||
|
{"SQL_Connect", SQL_Connect},
|
||||||
|
{"SQL_PrepareQuery", SQL_PrepareQuery},
|
||||||
|
{"SQL_Execute", SQL_Execute},
|
||||||
|
{"SQL_QueryError", SQL_QueryError},
|
||||||
|
{"SQL_MoreResults", SQL_MoreResults},
|
||||||
|
{"SQL_IsNull", SQL_IsNull},
|
||||||
|
{"SQL_ReadResult", SQL_ReadResult},
|
||||||
|
{"SQL_NextRow", SQL_NextRow},
|
||||||
|
{"SQL_AffectedRows", SQL_AffectedRows},
|
||||||
|
{"SQL_NumResults", SQL_NumResults},
|
||||||
|
{"SQL_NumColumns", SQL_NumColumns},
|
||||||
|
{"SQL_FieldNumToName", SQL_FieldNumToName},
|
||||||
|
{"SQL_FieldNameToNum", SQL_FieldNameToNum},
|
||||||
|
{"SQL_GetAffinity", SQL_GetAffinity},
|
||||||
|
{"SQL_SetAffinity", SQL_SetAffinity},
|
||||||
|
|
||||||
|
{NULL, NULL},
|
||||||
|
};
|
||||||
|
|
107
dlls/sqlite/handles.cpp
Normal file
107
dlls/sqlite/handles.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include "sh_stack.h"
|
||||||
|
#include "CVector.h"
|
||||||
|
#include "sqlite_header.h"
|
||||||
|
|
||||||
|
struct QHandle
|
||||||
|
{
|
||||||
|
void *_ptr;
|
||||||
|
FREEHANDLE _func;
|
||||||
|
HandleType type;
|
||||||
|
bool isfree;
|
||||||
|
};
|
||||||
|
|
||||||
|
CVector<QHandle *> g_Handles;
|
||||||
|
CStack<unsigned int> g_FreeHandles;
|
||||||
|
|
||||||
|
unsigned int MakeHandle(void *ptr, HandleType type, FREEHANDLE f)
|
||||||
|
{
|
||||||
|
unsigned int num;
|
||||||
|
QHandle *h;
|
||||||
|
|
||||||
|
if (g_FreeHandles.size())
|
||||||
|
{
|
||||||
|
num = g_FreeHandles.front();
|
||||||
|
g_FreeHandles.pop();
|
||||||
|
h = g_Handles[num];
|
||||||
|
} else {
|
||||||
|
h = new QHandle;
|
||||||
|
g_Handles.push_back(h);
|
||||||
|
num = static_cast<unsigned int>(g_Handles.size()) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
h->_ptr = ptr;
|
||||||
|
h->type = type;
|
||||||
|
h->_func = f;
|
||||||
|
h->isfree = false;
|
||||||
|
|
||||||
|
return num + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *GetHandle(unsigned int num, HandleType type)
|
||||||
|
{
|
||||||
|
if (num == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
num--;
|
||||||
|
if (num >= g_Handles.size())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
QHandle *h = g_Handles[num];
|
||||||
|
if (h->isfree || (h->type != type))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return h->_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FreeHandle(unsigned int num)
|
||||||
|
{
|
||||||
|
if (num == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
unsigned int _num = num;
|
||||||
|
|
||||||
|
num--;
|
||||||
|
if (num >= g_Handles.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QHandle *h = g_Handles[num];
|
||||||
|
if (h->isfree)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
h->_func(h->_ptr, _num);
|
||||||
|
h->_ptr = NULL;
|
||||||
|
h->_func = NULL;
|
||||||
|
h->isfree = true;
|
||||||
|
|
||||||
|
g_FreeHandles.push(num);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeAllHandles(HandleType type)
|
||||||
|
{
|
||||||
|
QHandle *q;
|
||||||
|
for (size_t i = 0; i < g_Handles.size(); i++)
|
||||||
|
{
|
||||||
|
q = g_Handles[i];
|
||||||
|
if (q && !q->isfree && q->type == type)
|
||||||
|
{
|
||||||
|
FreeHandle((unsigned int)i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeHandleTable()
|
||||||
|
{
|
||||||
|
QHandle *q;
|
||||||
|
for (size_t i = 0; i < g_Handles.size(); i++)
|
||||||
|
{
|
||||||
|
q = g_Handles[i];
|
||||||
|
if (q && !q->isfree)
|
||||||
|
FreeHandle((unsigned int)i);
|
||||||
|
}
|
||||||
|
g_Handles.clear();
|
||||||
|
while (!g_FreeHandles.empty())
|
||||||
|
g_FreeHandles.pop();
|
||||||
|
}
|
47
dlls/sqlite/module.cpp
Normal file
47
dlls/sqlite/module.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include "amxxmodule.h"
|
||||||
|
#include "sqlite_header.h"
|
||||||
|
#include "sqlheaders.h"
|
||||||
|
|
||||||
|
static g_ident = 0;
|
||||||
|
|
||||||
|
SqlFunctions g_SqliteFuncs =
|
||||||
|
{
|
||||||
|
&g_Sqlite,
|
||||||
|
SetMysqlAffinity,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
int SetMysqlAffinity(AMX *amx)
|
||||||
|
{
|
||||||
|
MF_AmxReRegister(amx, g_BaseSqlNatives, -1);
|
||||||
|
MF_AmxReRegister(amx, g_ThreadSqlNatives, -1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnAmxxAttach()
|
||||||
|
{
|
||||||
|
MF_AddNatives(g_BaseSqlNatives);
|
||||||
|
MF_AddNatives(g_ThreadSqlNatives);
|
||||||
|
g_SqliteFuncs.prev = (SqlFunctions *)MF_RegisterFunctionEx(&g_SqliteFuncs, SQL_DRIVER_FUNC);
|
||||||
|
|
||||||
|
MF_AddLibraries("dbi", LibType_Class, &g_ident);
|
||||||
|
|
||||||
|
//override any mysqlx old compat stuff
|
||||||
|
MF_AddNatives(g_OldCompatNatives);
|
||||||
|
MF_OverrideNatives(g_OldCompatNatives);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnAmxxDetach()
|
||||||
|
{
|
||||||
|
ShutdownThreading();
|
||||||
|
MF_RemoveLibraries(&g_ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnPluginsUnloaded()
|
||||||
|
{
|
||||||
|
FreeAllHandles(Handle_OldResult);
|
||||||
|
FreeAllHandles(Handle_OldDb);
|
||||||
|
FreeAllHandles(Handle_Connection);
|
||||||
|
}
|
||||||
|
|
426
dlls/sqlite/oldcompat_sql.cpp
Normal file
426
dlls/sqlite/oldcompat_sql.cpp
Normal file
@ -0,0 +1,426 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "sh_list.h"
|
||||||
|
#include "sqlite_header.h"
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
struct olddb_s
|
||||||
|
{
|
||||||
|
IDatabase *pDatabase;
|
||||||
|
char error[255];
|
||||||
|
int errcode;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct oldresult_s
|
||||||
|
{
|
||||||
|
IQuery *pQuery;
|
||||||
|
QueryInfo info;
|
||||||
|
bool firstCall;
|
||||||
|
};
|
||||||
|
|
||||||
|
void FreeOldDb(void *ptr, unsigned int hndl)
|
||||||
|
{
|
||||||
|
olddb_s *old = (olddb_s *)ptr;
|
||||||
|
|
||||||
|
if (old->pDatabase)
|
||||||
|
{
|
||||||
|
old->pDatabase->FreeHandle();
|
||||||
|
old->pDatabase = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete old;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeOldResult(void *ptr, unsigned int hndl)
|
||||||
|
{
|
||||||
|
oldresult_s *oldres = (oldresult_s *)ptr;
|
||||||
|
|
||||||
|
if (oldres->pQuery)
|
||||||
|
{
|
||||||
|
oldres->pQuery->FreeHandle();
|
||||||
|
oldres->pQuery = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete oldres;
|
||||||
|
}
|
||||||
|
|
||||||
|
//native Sql:dbi_connect(_host[], _user[], _pass[], _dbname[], _error[]="", _maxlength=0);
|
||||||
|
static cell AMX_NATIVE_CALL dbi_connect(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
DatabaseInfo info;
|
||||||
|
char *name = MF_GetAmxString(amx, params[4], 3, &len);
|
||||||
|
|
||||||
|
info.host = "";
|
||||||
|
info.user = "";
|
||||||
|
info.pass = "";
|
||||||
|
info.database = name;
|
||||||
|
|
||||||
|
int err;
|
||||||
|
char error[512];
|
||||||
|
IDatabase *pDatabase = g_Sqlite.Connect(&info, &err, error, sizeof(error)-1);
|
||||||
|
if (!pDatabase)
|
||||||
|
{
|
||||||
|
MF_SetAmxString(amx, params[5], error, params[6]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
olddb_s *old = new olddb_s;
|
||||||
|
int hndl;
|
||||||
|
|
||||||
|
old->pDatabase = pDatabase;
|
||||||
|
hndl = MakeHandle(old, Handle_OldDb, FreeOldDb);
|
||||||
|
|
||||||
|
return hndl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//native Result:dbi_query(Sql:_sql, _query[], {Float,_}:...);
|
||||||
|
static cell AMX_NATIVE_CALL dbi_query(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
olddb_s *old = (olddb_s *)GetHandle(params[1], Handle_OldDb);
|
||||||
|
if (!old)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid DBI handle %d", params[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len;
|
||||||
|
char *queryString = MF_FormatAmxString(amx, params, 2, &len);
|
||||||
|
|
||||||
|
IQuery *pQuery = old->pDatabase->PrepareQuery(queryString);
|
||||||
|
QueryInfo info;
|
||||||
|
|
||||||
|
old->error[0] = '\0';
|
||||||
|
old->errcode = 0;
|
||||||
|
|
||||||
|
if (!pQuery->Execute(&info, old->error, 254))
|
||||||
|
{
|
||||||
|
old->errcode = info.errorcode;
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
if (info.rs && info.rs->RowCount())
|
||||||
|
{
|
||||||
|
oldresult_s *oldrs = new oldresult_s;
|
||||||
|
int hndl;
|
||||||
|
|
||||||
|
oldrs->info = info;
|
||||||
|
oldrs->pQuery = pQuery;
|
||||||
|
hndl = MakeHandle(oldrs, Handle_OldResult, FreeOldResult);
|
||||||
|
return hndl;
|
||||||
|
} else {
|
||||||
|
pQuery->FreeHandle();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** never reach here */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//native Result:dbi_query2(Sql:_sql, &rows, _query[], {Float,_}:...);
|
||||||
|
static cell AMX_NATIVE_CALL dbi_query2(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
olddb_s *old = (olddb_s *)GetHandle(params[1], Handle_OldDb);
|
||||||
|
if (!old)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid DBI handle %d", params[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len;
|
||||||
|
char *queryString = MF_FormatAmxString(amx, params, 3, &len);
|
||||||
|
|
||||||
|
IQuery *pQuery = old->pDatabase->PrepareQuery(queryString);
|
||||||
|
QueryInfo info;
|
||||||
|
|
||||||
|
old->error[0] = '\0';
|
||||||
|
old->errcode = 0;
|
||||||
|
|
||||||
|
if (!pQuery->Execute(&info, old->error, 254))
|
||||||
|
{
|
||||||
|
old->errcode = info.errorcode;
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
cell *addr = MF_GetAmxAddr(amx, params[2]);
|
||||||
|
*addr = static_cast<cell>(info.affected_rows);
|
||||||
|
if (info.rs && info.rs->RowCount())
|
||||||
|
{
|
||||||
|
oldresult_s *oldrs = new oldresult_s;
|
||||||
|
int hndl;
|
||||||
|
|
||||||
|
oldrs->info = info;
|
||||||
|
oldrs->pQuery = pQuery;
|
||||||
|
oldrs->firstCall = true;
|
||||||
|
hndl = MakeHandle(oldrs, Handle_OldResult, FreeOldResult);
|
||||||
|
return hndl;
|
||||||
|
} else {
|
||||||
|
pQuery->FreeHandle();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** never reach here */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//native dbi_nextrow(Result:_result);
|
||||||
|
static cell AMX_NATIVE_CALL dbi_nextrow(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
oldresult_s *oldrs = (oldresult_s *)GetHandle(params[1], Handle_OldResult);
|
||||||
|
if (!oldrs)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid DBI result handle %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldrs->firstCall)
|
||||||
|
{
|
||||||
|
oldrs->firstCall = false;
|
||||||
|
return (oldrs->info.rs->IsDone() ? 0 : 1);
|
||||||
|
} else {
|
||||||
|
oldrs->info.rs->NextRow();
|
||||||
|
return (oldrs->info.rs->IsDone() ? 0 : 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//native dbi_field(Result:_result, _fieldnum, {Float,_}:... );
|
||||||
|
static cell AMX_NATIVE_CALL dbi_field(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
oldresult_s *oldrs = (oldresult_s *)GetHandle(params[1], Handle_OldResult);
|
||||||
|
if (!oldrs)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid DBI result handle %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IResultSet *rs = oldrs->info.rs;
|
||||||
|
IResultRow *rr = rs->GetRow();
|
||||||
|
unsigned int num = (unsigned int)params[2] - 1;
|
||||||
|
if (num >= rs->FieldCount())
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid column %d", params[2]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell stype = params[0] / sizeof(cell);
|
||||||
|
const char *data = rr->GetString(num);
|
||||||
|
if (!data)
|
||||||
|
data = "";
|
||||||
|
|
||||||
|
switch (stype)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
return atoi(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
cell *destaddr = MF_GetAmxAddr(amx, params[3]);
|
||||||
|
REAL fdata = atof(data);
|
||||||
|
*destaddr = amx_ftoc(fdata);
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
return MF_SetAmxString(amx, params[3], data, params[4]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** never reach here */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//native dbi_result(Result:_result, _field[], {Float,_}:... );
|
||||||
|
static cell AMX_NATIVE_CALL dbi_result(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
oldresult_s *oldrs = (oldresult_s *)GetHandle(params[1], Handle_OldResult);
|
||||||
|
if (!oldrs)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid DBI result handle %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IResultSet *rs = oldrs->info.rs;
|
||||||
|
IResultRow *rr = rs->GetRow();
|
||||||
|
unsigned int num;
|
||||||
|
bool found = false;
|
||||||
|
unsigned int fields = rs->FieldCount();
|
||||||
|
int len;
|
||||||
|
char *field = MF_GetAmxString(amx, params[2], 0, &len);
|
||||||
|
for (unsigned int i=0; i<fields; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(field, rs->FieldNumToName(i)) == 0)
|
||||||
|
{
|
||||||
|
num = i;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Unknown column \"%s\"", field);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell stype = params[0] / sizeof(cell);
|
||||||
|
const char *data = rr->GetString(num);
|
||||||
|
if (!data)
|
||||||
|
data = "";
|
||||||
|
|
||||||
|
switch (stype)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
return atoi(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
cell *destaddr = MF_GetAmxAddr(amx, params[3]);
|
||||||
|
REAL fdata = atof(data);
|
||||||
|
*destaddr = amx_ftoc(fdata);
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
return MF_SetAmxString(amx, params[3], data, params[4]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** never reach here */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//native dbi_num_rows(Result:_result);
|
||||||
|
static cell AMX_NATIVE_CALL dbi_num_rows(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
oldresult_s *oldrs = (oldresult_s *)GetHandle(params[1], Handle_OldResult);
|
||||||
|
if (!oldrs)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid DBI result handle %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return oldrs->info.rs->RowCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
//native dbi_free_result(&Result:result);
|
||||||
|
static cell AMX_NATIVE_CALL dbi_free_result(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
cell *_r = MF_GetAmxAddr(amx, params[1]);
|
||||||
|
cell num = *_r;
|
||||||
|
|
||||||
|
if (!num)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
oldresult_s *oldrs = (oldresult_s *)GetHandle(num, Handle_OldResult);
|
||||||
|
if (!oldrs)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid DBI result handle %d", num);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeHandle(num);
|
||||||
|
|
||||||
|
*_r = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//native dbi_close(&Sql:_sql);
|
||||||
|
static cell AMX_NATIVE_CALL dbi_close(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
cell *_r = MF_GetAmxAddr(amx, params[1]);
|
||||||
|
cell num = *_r;
|
||||||
|
olddb_s *old = (olddb_s *)GetHandle(num, Handle_OldDb);
|
||||||
|
if (!old)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid DBI handle %d", num);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeHandle(num);
|
||||||
|
|
||||||
|
*_r = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//native dbi_error(Sql:_sql, _error[], _len);
|
||||||
|
static cell AMX_NATIVE_CALL dbi_error(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
olddb_s *old = (olddb_s *)GetHandle(params[1], Handle_OldDb);
|
||||||
|
if (!old)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid DBI handle %d", params[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MF_SetAmxString(amx, params[2], old->error, params[3]);
|
||||||
|
return old->errcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
//native dbi_type(_type[], _len);
|
||||||
|
static cell AMX_NATIVE_CALL dbi_type(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
return MF_SetAmxString(amx, params[1], "mysql", params[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//native dbi_num_fields(Result:result);
|
||||||
|
static cell AMX_NATIVE_CALL dbi_num_fields(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
oldresult_s *oldrs = (oldresult_s *)GetHandle(params[1], Handle_OldResult);
|
||||||
|
if (!oldrs)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid DBI result handle %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return oldrs->info.rs->FieldCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
//native dbi_field_name(Result:result, field, name[], maxLength);
|
||||||
|
static cell AMX_NATIVE_CALL dbi_field_name(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
oldresult_s *oldrs = (oldresult_s *)GetHandle(params[1], Handle_OldResult);
|
||||||
|
if (!oldrs)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid DBI result handle %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *name = oldrs->info.rs->FieldNumToName(static_cast<unsigned int>(params[2]-1));
|
||||||
|
if (!name)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
MF_SetAmxString(amx, params[3], name, params[4]);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AMX_NATIVE_INFO g_OldCompatNatives[] =
|
||||||
|
{
|
||||||
|
{ "dbi_connect", dbi_connect },
|
||||||
|
{ "dbi_query", dbi_query },
|
||||||
|
{ "dbi_query2", dbi_query2 },
|
||||||
|
{ "dbi_field", dbi_field },
|
||||||
|
{ "dbi_nextrow", dbi_nextrow },
|
||||||
|
{ "dbi_close", dbi_close },
|
||||||
|
{ "dbi_error", dbi_error },
|
||||||
|
{ "dbi_type", dbi_type },
|
||||||
|
{ "dbi_free_result", dbi_free_result },
|
||||||
|
{ "dbi_num_rows", dbi_num_rows },
|
||||||
|
{ "dbi_result", dbi_result },
|
||||||
|
{ "dbi_num_fields", dbi_num_fields },
|
||||||
|
{ "dbi_field_name", dbi_field_name },
|
||||||
|
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
@ -70,32 +70,58 @@ template <class T> class CVector
|
|||||||
// change size
|
// change size
|
||||||
if (size == m_Size)
|
if (size == m_Size)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (!size)
|
||||||
|
{
|
||||||
|
if (m_Data)
|
||||||
|
{
|
||||||
|
delete [] m_Data;
|
||||||
|
m_Data = NULL;
|
||||||
|
m_Size = 0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
T *newData = new T[size];
|
T *newData = new T[size];
|
||||||
if (!newData)
|
if (!newData)
|
||||||
return false;
|
return false;
|
||||||
if (m_Data)
|
if (m_Data)
|
||||||
{
|
{
|
||||||
size_t end = (m_Size < size) ? (m_Size) : size;
|
size_t end = (m_CurrentUsedSize < size) ? (m_CurrentUsedSize) : size;
|
||||||
for (size_t i=0; i<end; i++)
|
for (size_t i=0; i<end; i++)
|
||||||
newData[i] = m_Data[i];
|
newData[i] = m_Data[i];
|
||||||
delete [] m_Data;
|
delete [] m_Data;
|
||||||
}
|
}
|
||||||
if (m_Size < size)
|
|
||||||
m_CurrentSize = size;
|
|
||||||
m_Data = newData;
|
m_Data = newData;
|
||||||
m_Size = size;
|
m_Size = size;
|
||||||
|
if (m_CurrentUsedSize > m_Size)
|
||||||
|
m_CurrentUsedSize = m_Size;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeMemIfPossible()
|
void FreeMemIfPossible()
|
||||||
{
|
{
|
||||||
|
if (!m_Data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_CurrentUsedSize)
|
||||||
|
{
|
||||||
|
ChangeSize(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t newSize = m_Size;
|
||||||
|
while (m_CurrentUsedSize <= newSize / 2)
|
||||||
|
newSize /= 2;
|
||||||
|
|
||||||
|
if (newSize != m_Size)
|
||||||
|
ChangeSize(newSize);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
T *m_Data;
|
T *m_Data;
|
||||||
size_t m_Size;
|
size_t m_Size;
|
||||||
size_t m_CurrentUsedSize;
|
size_t m_CurrentUsedSize;
|
||||||
size_t m_CurrentSize;
|
|
||||||
public:
|
public:
|
||||||
class iterator
|
class iterator
|
||||||
{
|
{
|
||||||
@ -189,7 +215,7 @@ public:
|
|||||||
|
|
||||||
iterator & operator-=(size_t offset)
|
iterator & operator-=(size_t offset)
|
||||||
{
|
{
|
||||||
m_Ptr += offset;
|
m_Ptr -= offset;
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +229,7 @@ public:
|
|||||||
iterator operator-(size_t offset) const
|
iterator operator-(size_t offset) const
|
||||||
{
|
{
|
||||||
iterator tmp(*this);
|
iterator tmp(*this);
|
||||||
tmp.m_Ptr += offset;
|
tmp.m_Ptr -= offset;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,12 +303,12 @@ public:
|
|||||||
return m_Size;
|
return m_Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator begin()
|
iterator begin() const
|
||||||
{
|
{
|
||||||
return iterator(m_Data);
|
return iterator(m_Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator end()
|
iterator end() const
|
||||||
{
|
{
|
||||||
return iterator(m_Data + m_CurrentUsedSize);
|
return iterator(m_Data + m_CurrentUsedSize);
|
||||||
}
|
}
|
||||||
@ -296,7 +322,9 @@ public:
|
|||||||
|
|
||||||
bool reserve(size_t newSize)
|
bool reserve(size_t newSize)
|
||||||
{
|
{
|
||||||
|
if (newSize > m_Size)
|
||||||
return ChangeSize(newSize);
|
return ChangeSize(newSize);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool push_back(const T & elem)
|
bool push_back(const T & elem)
|
||||||
@ -317,14 +345,15 @@ public:
|
|||||||
--m_CurrentUsedSize;
|
--m_CurrentUsedSize;
|
||||||
if (m_CurrentUsedSize < 0)
|
if (m_CurrentUsedSize < 0)
|
||||||
m_CurrentUsedSize = 0;
|
m_CurrentUsedSize = 0;
|
||||||
// :TODO: free memory sometimes
|
|
||||||
|
FreeMemIfPossible();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool resize(size_t newSize)
|
bool resize(size_t newSize)
|
||||||
{
|
{
|
||||||
if (!ChangeSize(newSize))
|
if (!ChangeSize(newSize))
|
||||||
return false;
|
return false;
|
||||||
FreeMemIfPossible();
|
m_CurrentUsedSize = newSize;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,15 +426,13 @@ public:
|
|||||||
return m_Data[m_CurrentUsedSize - 1];
|
return m_Data[m_CurrentUsedSize - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool insert(iterator where, const T & value)
|
iterator insert(iterator where, const T & value)
|
||||||
{
|
{
|
||||||
// we have to insert before
|
|
||||||
// if it is begin, don't decrement
|
|
||||||
if (where != m_Data)
|
|
||||||
--where;
|
|
||||||
// validate iter
|
// validate iter
|
||||||
if (where < m_Data || where >= (m_Data + m_CurrentUsedSize))
|
if (where < m_Data || where > (m_Data + m_CurrentUsedSize))
|
||||||
return false;
|
return iterator(0);
|
||||||
|
|
||||||
|
size_t ofs = where - begin();
|
||||||
|
|
||||||
++m_CurrentUsedSize;
|
++m_CurrentUsedSize;
|
||||||
if (!GrowIfNeeded())
|
if (!GrowIfNeeded())
|
||||||
@ -414,34 +441,50 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memmove(where.base() + 1, where.base(), m_CurrentUsedSize - (where - m_Data));
|
where = begin() + ofs;
|
||||||
memcpy(where.base(), &value, sizeof(T));
|
|
||||||
return true;
|
// Move subsequent entries
|
||||||
|
for (T *ptr = m_Data + m_CurrentUsedSize - 2; ptr >= where.base(); --ptr)
|
||||||
|
*(ptr + 1) = *ptr;
|
||||||
|
|
||||||
|
*where.base() = value;
|
||||||
|
|
||||||
|
return where;
|
||||||
}
|
}
|
||||||
|
|
||||||
void erase(iterator where)
|
iterator erase(iterator where)
|
||||||
{
|
{
|
||||||
// validate iter
|
// validate iter
|
||||||
if (where < m_Data || where >= (m_Data + m_CurrentUsedSize))
|
if (where < m_Data || where >= (m_Data + m_CurrentUsedSize))
|
||||||
return false;
|
return iterator(0);
|
||||||
|
|
||||||
|
size_t ofs = where - begin();
|
||||||
|
|
||||||
if (m_CurrentUsedSize > 1)
|
if (m_CurrentUsedSize > 1)
|
||||||
{
|
{
|
||||||
// move
|
// move
|
||||||
memmove(where.base(), where.base() + 1, m_CurrentUsedSize - 1);
|
T *theend = m_Data + m_CurrentUsedSize;
|
||||||
|
for (T *ptr = where.base() + 1; ptr < theend; ++ptr)
|
||||||
|
*(ptr - 1) = *ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
--m_CurrentUsedSize;
|
--m_CurrentUsedSize;
|
||||||
// :TODO: free memory sometimes
|
|
||||||
|
FreeMemIfPossible();
|
||||||
|
|
||||||
|
return begin() + ofs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
m_Size = 0;
|
m_Size = 0;
|
||||||
m_CurrentUsedSize = 0;
|
m_CurrentUsedSize = 0;
|
||||||
|
if (m_Data)
|
||||||
|
{
|
||||||
delete [] m_Data;
|
delete [] m_Data;
|
||||||
m_Data = NULL;
|
m_Data = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __CVECTOR_H__
|
#endif // __CVECTOR_H__
|
3125
dlls/sqlite/sdk/amxxmodule.cpp
Executable file
3125
dlls/sqlite/sdk/amxxmodule.cpp
Executable file
File diff suppressed because it is too large
Load Diff
2454
dlls/sqlite/sdk/amxxmodule.h
Executable file
2454
dlls/sqlite/sdk/amxxmodule.h
Executable file
File diff suppressed because it is too large
Load Diff
491
dlls/sqlite/sdk/moduleconfig.h
Executable file
491
dlls/sqlite/sdk/moduleconfig.h
Executable file
@ -0,0 +1,491 @@
|
|||||||
|
// Configuration
|
||||||
|
|
||||||
|
#ifndef __MODULECONFIG_H__
|
||||||
|
#define __MODULECONFIG_H__
|
||||||
|
|
||||||
|
// Module info
|
||||||
|
#define MODULE_NAME "SQLiteX"
|
||||||
|
#define MODULE_VERSION "1.75"
|
||||||
|
#define MODULE_AUTHOR "AMX Mod X Dev Team"
|
||||||
|
#define MODULE_URL "http://www.amxmodx.org/"
|
||||||
|
#define MODULE_LOGTAG "SQLITEX"
|
||||||
|
#define MODULE_LIBRARY "sqlitex"
|
||||||
|
#define MODULE_LIBCLASS "sqlx"
|
||||||
|
// If you want the module not to be reloaded on mapchange, remove / comment out the next line
|
||||||
|
#define MODULE_RELOAD_ON_MAPCHANGE
|
||||||
|
|
||||||
|
#ifdef __DATE__
|
||||||
|
#define MODULE_DATE __DATE__
|
||||||
|
#else // __DATE__
|
||||||
|
#define MODULE_DATE "Unknown"
|
||||||
|
#endif // __DATE__
|
||||||
|
|
||||||
|
// metamod plugin?
|
||||||
|
#define USE_METAMOD
|
||||||
|
|
||||||
|
// use memory manager/tester?
|
||||||
|
// note that if you use this, you cannot construct/allocate
|
||||||
|
// anything before the module attached (OnAmxxAttach).
|
||||||
|
// be careful of default constructors using new/malloc!
|
||||||
|
// #define MEMORY_TEST
|
||||||
|
|
||||||
|
// Unless you use STL or exceptions, keep this commented.
|
||||||
|
// It allows you to compile without libstdc++.so as a dependency
|
||||||
|
// #define NO_ALLOC_OVERRIDES
|
||||||
|
|
||||||
|
// Uncomment this if you are using MSVC8 or greater and want to fix some of the compatibility issues yourself
|
||||||
|
// #define NO_MSVC8_AUTO_COMPAT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMXX Init functions
|
||||||
|
* Also consider using FN_META_*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** AMXX query */
|
||||||
|
//#define FN_AMXX_QUERY OnAmxxQuery
|
||||||
|
|
||||||
|
/** AMXX attach
|
||||||
|
* Do native functions init here (MF_AddNatives)
|
||||||
|
*/
|
||||||
|
#define FN_AMXX_ATTACH OnAmxxAttach
|
||||||
|
|
||||||
|
/** AMXX Detach (unload) */
|
||||||
|
#define FN_AMXX_DETACH OnAmxxDetach
|
||||||
|
|
||||||
|
/** All plugins loaded
|
||||||
|
* Do forward functions init here (MF_RegisterForward)
|
||||||
|
*/
|
||||||
|
#define FN_AMXX_PLUGINSLOADED OnPluginsLoaded
|
||||||
|
|
||||||
|
/** All plugins are about to be unloaded */
|
||||||
|
#define FN_AMXX_PLUGINSUNLOADING OnPluginsUnloading
|
||||||
|
|
||||||
|
/** All plugins are now unloaded */
|
||||||
|
#define FN_AMXX_PLUGINSUNLOADED OnPluginsUnloaded
|
||||||
|
|
||||||
|
/**** METAMOD ****/
|
||||||
|
// If your module doesn't use metamod, you may close the file now :)
|
||||||
|
#ifdef USE_METAMOD
|
||||||
|
// ----
|
||||||
|
// Hook Functions
|
||||||
|
// Uncomment these to be called
|
||||||
|
// You can also change the function name
|
||||||
|
|
||||||
|
// - Metamod init functions
|
||||||
|
// Also consider using FN_AMXX_*
|
||||||
|
// Meta query
|
||||||
|
//#define FN_META_QUERY OnMetaQuery
|
||||||
|
// Meta attach
|
||||||
|
//#define FN_META_ATTACH OnMetaAttach
|
||||||
|
// Meta detach
|
||||||
|
//#define FN_META_DETACH OnMetaDetach
|
||||||
|
|
||||||
|
// (wd) are Will Day's notes
|
||||||
|
// - GetEntityAPI2 functions
|
||||||
|
// #define FN_GameDLLInit GameDLLInit /* pfnGameInit() */
|
||||||
|
// #define FN_DispatchSpawn DispatchSpawn /* pfnSpawn() */
|
||||||
|
// #define FN_DispatchThink DispatchThink /* pfnThink() */
|
||||||
|
// #define FN_DispatchUse DispatchUse /* pfnUse() */
|
||||||
|
// #define FN_DispatchTouch DispatchTouch /* pfnTouch() */
|
||||||
|
// #define FN_DispatchBlocked DispatchBlocked /* pfnBlocked() */
|
||||||
|
// #define FN_DispatchKeyValue DispatchKeyValue /* pfnKeyValue() */
|
||||||
|
// #define FN_DispatchSave DispatchSave /* pfnSave() */
|
||||||
|
// #define FN_DispatchRestore DispatchRestore /* pfnRestore() */
|
||||||
|
// #define FN_DispatchObjectCollsionBox DispatchObjectCollsionBox /* pfnSetAbsBox() */
|
||||||
|
// #define FN_SaveWriteFields SaveWriteFields /* pfnSaveWriteFields() */
|
||||||
|
// #define FN_SaveReadFields SaveReadFields /* pfnSaveReadFields() */
|
||||||
|
// #define FN_SaveGlobalState SaveGlobalState /* pfnSaveGlobalState() */
|
||||||
|
// #define FN_RestoreGlobalState RestoreGlobalState /* pfnRestoreGlobalState() */
|
||||||
|
// #define FN_ResetGlobalState ResetGlobalState /* pfnResetGlobalState() */
|
||||||
|
// #define FN_ClientConnect ClientConnect /* pfnClientConnect() (wd) Client has connected */
|
||||||
|
// #define FN_ClientDisconnect ClientDisconnect /* pfnClientDisconnect() (wd) Player has left the game */
|
||||||
|
// #define FN_ClientKill ClientKill /* pfnClientKill() (wd) Player has typed "kill" */
|
||||||
|
// #define FN_ClientPutInServer ClientPutInServer /* pfnClientPutInServer() (wd) Client is entering the game */
|
||||||
|
// #define FN_ClientCommand ClientCommand /* pfnClientCommand() (wd) Player has sent a command (typed or from a bind) */
|
||||||
|
// #define FN_ClientUserInfoChanged ClientUserInfoChanged /* pfnClientUserInfoChanged() (wd) Client has updated their setinfo structure */
|
||||||
|
// #define FN_ServerActivate ServerActivate /* pfnServerActivate() (wd) Server is starting a new map */
|
||||||
|
// #define FN_ServerDeactivate ServerDeactivate /* pfnServerDeactivate() (wd) Server is leaving the map (shutdown or changelevel); SDK2 */
|
||||||
|
// #define FN_PlayerPreThink PlayerPreThink /* pfnPlayerPreThink() */
|
||||||
|
// #define FN_PlayerPostThink PlayerPostThink /* pfnPlayerPostThink() */
|
||||||
|
// #define FN_StartFrame StartFrame /* pfnStartFrame() */
|
||||||
|
// #define FN_ParmsNewLevel ParmsNewLevel /* pfnParmsNewLevel() */
|
||||||
|
// #define FN_ParmsChangeLevel ParmsChangeLevel /* pfnParmsChangeLevel() */
|
||||||
|
// #define FN_GetGameDescription GetGameDescription /* pfnGetGameDescription() Returns string describing current .dll. E.g. "TeamFotrress 2" "Half-Life" */
|
||||||
|
// #define FN_PlayerCustomization PlayerCustomization /* pfnPlayerCustomization() Notifies .dll of new customization for player. */
|
||||||
|
// #define FN_SpectatorConnect SpectatorConnect /* pfnSpectatorConnect() Called when spectator joins server */
|
||||||
|
// #define FN_SpectatorDisconnect SpectatorDisconnect /* pfnSpectatorDisconnect() Called when spectator leaves the server */
|
||||||
|
// #define FN_SpectatorThink SpectatorThink /* pfnSpectatorThink() Called when spectator sends a command packet (usercmd_t) */
|
||||||
|
// #define FN_Sys_Error Sys_Error /* pfnSys_Error() Notify game .dll that engine is going to shut down. Allows mod authors to set a breakpoint. SDK2 */
|
||||||
|
// #define FN_PM_Move PM_Move /* pfnPM_Move() (wd) SDK2 */
|
||||||
|
// #define FN_PM_Init PM_Init /* pfnPM_Init() Server version of player movement initialization; (wd) SDK2 */
|
||||||
|
// #define FN_PM_FindTextureType PM_FindTextureType /* pfnPM_FindTextureType() (wd) SDK2 */
|
||||||
|
// #define FN_SetupVisibility SetupVisibility /* pfnSetupVisibility() Set up PVS and PAS for networking for this client; (wd) SDK2 */
|
||||||
|
// #define FN_UpdateClientData UpdateClientData /* pfnUpdateClientData() Set up data sent only to specific client; (wd) SDK2 */
|
||||||
|
// #define FN_AddToFullPack AddToFullPack /* pfnAddToFullPack() (wd) SDK2 */
|
||||||
|
// #define FN_CreateBaseline CreateBaseline /* pfnCreateBaseline() Tweak entity baseline for network encoding allows setup of player baselines too.; (wd) SDK2 */
|
||||||
|
// #define FN_RegisterEncoders RegisterEncoders /* pfnRegisterEncoders() Callbacks for network encoding; (wd) SDK2 */
|
||||||
|
// #define FN_GetWeaponData GetWeaponData /* pfnGetWeaponData() (wd) SDK2 */
|
||||||
|
// #define FN_CmdStart CmdStart /* pfnCmdStart() (wd) SDK2 */
|
||||||
|
// #define FN_CmdEnd CmdEnd /* pfnCmdEnd() (wd) SDK2 */
|
||||||
|
// #define FN_ConnectionlessPacket ConnectionlessPacket /* pfnConnectionlessPacket() (wd) SDK2 */
|
||||||
|
// #define FN_GetHullBounds GetHullBounds /* pfnGetHullBounds() (wd) SDK2 */
|
||||||
|
// #define FN_CreateInstancedBaselines CreateInstancedBaselines /* pfnCreateInstancedBaselines() (wd) SDK2 */
|
||||||
|
// #define FN_InconsistentFile InconsistentFile /* pfnInconsistentFile() (wd) SDK2 */
|
||||||
|
// #define FN_AllowLagCompensation AllowLagCompensation /* pfnAllowLagCompensation() (wd) SDK2 */
|
||||||
|
|
||||||
|
// - GetEntityAPI2_Post functions
|
||||||
|
// #define FN_GameDLLInit_Post GameDLLInit_Post
|
||||||
|
// #define FN_DispatchSpawn_Post DispatchSpawn_Post
|
||||||
|
// #define FN_DispatchThink_Post DispatchThink_Post
|
||||||
|
// #define FN_DispatchUse_Post DispatchUse_Post
|
||||||
|
// #define FN_DispatchTouch_Post DispatchTouch_Post
|
||||||
|
// #define FN_DispatchBlocked_Post DispatchBlocked_Post
|
||||||
|
// #define FN_DispatchKeyValue_Post DispatchKeyValue_Post
|
||||||
|
// #define FN_DispatchSave_Post DispatchSave_Post
|
||||||
|
// #define FN_DispatchRestore_Post DispatchRestore_Post
|
||||||
|
// #define FN_DispatchObjectCollsionBox_Post DispatchObjectCollsionBox_Post
|
||||||
|
// #define FN_SaveWriteFields_Post SaveWriteFields_Post
|
||||||
|
// #define FN_SaveReadFields_Post SaveReadFields_Post
|
||||||
|
// #define FN_SaveGlobalState_Post SaveGlobalState_Post
|
||||||
|
// #define FN_RestoreGlobalState_Post RestoreGlobalState_Post
|
||||||
|
// #define FN_ResetGlobalState_Post ResetGlobalState_Post
|
||||||
|
// #define FN_ClientConnect_Post ClientConnect_Post
|
||||||
|
// #define FN_ClientDisconnect_Post ClientDisconnect_Post
|
||||||
|
// #define FN_ClientKill_Post ClientKill_Post
|
||||||
|
// #define FN_ClientPutInServer_Post ClientPutInServer_Post
|
||||||
|
// #define FN_ClientCommand_Post ClientCommand_Post
|
||||||
|
// #define FN_ClientUserInfoChanged_Post ClientUserInfoChanged_Post
|
||||||
|
// #define FN_ServerActivate_Post ServerActivate_Post
|
||||||
|
// #define FN_ServerDeactivate_Post ServerDeactivate_Post
|
||||||
|
// #define FN_PlayerPreThink_Post PlayerPreThink_Post
|
||||||
|
// #define FN_PlayerPostThink_Post PlayerPostThink_Post
|
||||||
|
// #define FN_StartFrame_Post StartFrame_Post
|
||||||
|
// #define FN_ParmsNewLevel_Post ParmsNewLevel_Post
|
||||||
|
// #define FN_ParmsChangeLevel_Post ParmsChangeLevel_Post
|
||||||
|
// #define FN_GetGameDescription_Post GetGameDescription_Post
|
||||||
|
// #define FN_PlayerCustomization_Post PlayerCustomization_Post
|
||||||
|
// #define FN_SpectatorConnect_Post SpectatorConnect_Post
|
||||||
|
// #define FN_SpectatorDisconnect_Post SpectatorDisconnect_Post
|
||||||
|
// #define FN_SpectatorThink_Post SpectatorThink_Post
|
||||||
|
// #define FN_Sys_Error_Post Sys_Error_Post
|
||||||
|
// #define FN_PM_Move_Post PM_Move_Post
|
||||||
|
// #define FN_PM_Init_Post PM_Init_Post
|
||||||
|
// #define FN_PM_FindTextureType_Post PM_FindTextureType_Post
|
||||||
|
// #define FN_SetupVisibility_Post SetupVisibility_Post
|
||||||
|
// #define FN_UpdateClientData_Post UpdateClientData_Post
|
||||||
|
// #define FN_AddToFullPack_Post AddToFullPack_Post
|
||||||
|
// #define FN_CreateBaseline_Post CreateBaseline_Post
|
||||||
|
// #define FN_RegisterEncoders_Post RegisterEncoders_Post
|
||||||
|
// #define FN_GetWeaponData_Post GetWeaponData_Post
|
||||||
|
// #define FN_CmdStart_Post CmdStart_Post
|
||||||
|
// #define FN_CmdEnd_Post CmdEnd_Post
|
||||||
|
// #define FN_ConnectionlessPacket_Post ConnectionlessPacket_Post
|
||||||
|
// #define FN_GetHullBounds_Post GetHullBounds_Post
|
||||||
|
// #define FN_CreateInstancedBaselines_Post CreateInstancedBaselines_Post
|
||||||
|
// #define FN_InconsistentFile_Post InconsistentFile_Post
|
||||||
|
// #define FN_AllowLagCompensation_Post AllowLagCompensation_Post
|
||||||
|
|
||||||
|
// - GetEngineAPI functions
|
||||||
|
// #define FN_PrecacheModel PrecacheModel
|
||||||
|
// #define FN_PrecacheSound PrecacheSound
|
||||||
|
// #define FN_SetModel SetModel
|
||||||
|
// #define FN_ModelIndex ModelIndex
|
||||||
|
// #define FN_ModelFrames ModelFrames
|
||||||
|
// #define FN_SetSize SetSize
|
||||||
|
// #define FN_ChangeLevel ChangeLevel
|
||||||
|
// #define FN_GetSpawnParms GetSpawnParms
|
||||||
|
// #define FN_SaveSpawnParms SaveSpawnParms
|
||||||
|
// #define FN_VecToYaw VecToYaw
|
||||||
|
// #define FN_VecToAngles VecToAngles
|
||||||
|
// #define FN_MoveToOrigin MoveToOrigin
|
||||||
|
// #define FN_ChangeYaw ChangeYaw
|
||||||
|
// #define FN_ChangePitch ChangePitch
|
||||||
|
// #define FN_FindEntityByString FindEntityByString
|
||||||
|
// #define FN_GetEntityIllum GetEntityIllum
|
||||||
|
// #define FN_FindEntityInSphere FindEntityInSphere
|
||||||
|
// #define FN_FindClientInPVS FindClientInPVS
|
||||||
|
// #define FN_EntitiesInPVS EntitiesInPVS
|
||||||
|
// #define FN_MakeVectors MakeVectors
|
||||||
|
// #define FN_AngleVectors AngleVectors
|
||||||
|
// #define FN_CreateEntity CreateEntity
|
||||||
|
// #define FN_RemoveEntity RemoveEntity
|
||||||
|
// #define FN_CreateNamedEntity CreateNamedEntity
|
||||||
|
// #define FN_MakeStatic MakeStatic
|
||||||
|
// #define FN_EntIsOnFloor EntIsOnFloor
|
||||||
|
// #define FN_DropToFloor DropToFloor
|
||||||
|
// #define FN_WalkMove WalkMove
|
||||||
|
// #define FN_SetOrigin SetOrigin
|
||||||
|
// #define FN_EmitSound EmitSound
|
||||||
|
// #define FN_EmitAmbientSound EmitAmbientSound
|
||||||
|
// #define FN_TraceLine TraceLine
|
||||||
|
// #define FN_TraceToss TraceToss
|
||||||
|
// #define FN_TraceMonsterHull TraceMonsterHull
|
||||||
|
// #define FN_TraceHull TraceHull
|
||||||
|
// #define FN_TraceModel TraceModel
|
||||||
|
// #define FN_TraceTexture TraceTexture
|
||||||
|
// #define FN_TraceSphere TraceSphere
|
||||||
|
// #define FN_GetAimVector GetAimVector
|
||||||
|
// #define FN_ServerCommand ServerCommand
|
||||||
|
// #define FN_ServerExecute ServerExecute
|
||||||
|
// #define FN_engClientCommand engClientCommand
|
||||||
|
// #define FN_ParticleEffect ParticleEffect
|
||||||
|
// #define FN_LightStyle LightStyle
|
||||||
|
// #define FN_DecalIndex DecalIndex
|
||||||
|
// #define FN_PointContents PointContents
|
||||||
|
// #define FN_MessageBegin MessageBegin
|
||||||
|
// #define FN_MessageEnd MessageEnd
|
||||||
|
// #define FN_WriteByte WriteByte
|
||||||
|
// #define FN_WriteChar WriteChar
|
||||||
|
// #define FN_WriteShort WriteShort
|
||||||
|
// #define FN_WriteLong WriteLong
|
||||||
|
// #define FN_WriteAngle WriteAngle
|
||||||
|
// #define FN_WriteCoord WriteCoord
|
||||||
|
// #define FN_WriteString WriteString
|
||||||
|
// #define FN_WriteEntity WriteEntity
|
||||||
|
// #define FN_CVarRegister CVarRegister
|
||||||
|
// #define FN_CVarGetFloat CVarGetFloat
|
||||||
|
// #define FN_CVarGetString CVarGetString
|
||||||
|
// #define FN_CVarSetFloat CVarSetFloat
|
||||||
|
// #define FN_CVarSetString CVarSetString
|
||||||
|
// #define FN_AlertMessage AlertMessage
|
||||||
|
// #define FN_EngineFprintf EngineFprintf
|
||||||
|
// #define FN_PvAllocEntPrivateData PvAllocEntPrivateData
|
||||||
|
// #define FN_PvEntPrivateData PvEntPrivateData
|
||||||
|
// #define FN_FreeEntPrivateData FreeEntPrivateData
|
||||||
|
// #define FN_SzFromIndex SzFromIndex
|
||||||
|
// #define FN_AllocString AllocString
|
||||||
|
// #define FN_GetVarsOfEnt GetVarsOfEnt
|
||||||
|
// #define FN_PEntityOfEntOffset PEntityOfEntOffset
|
||||||
|
// #define FN_EntOffsetOfPEntity EntOffsetOfPEntity
|
||||||
|
// #define FN_IndexOfEdict IndexOfEdict
|
||||||
|
// #define FN_PEntityOfEntIndex PEntityOfEntIndex
|
||||||
|
// #define FN_FindEntityByVars FindEntityByVars
|
||||||
|
// #define FN_GetModelPtr GetModelPtr
|
||||||
|
// #define FN_RegUserMsg RegUserMsg
|
||||||
|
// #define FN_AnimationAutomove AnimationAutomove
|
||||||
|
// #define FN_GetBonePosition GetBonePosition
|
||||||
|
// #define FN_FunctionFromName FunctionFromName
|
||||||
|
// #define FN_NameForFunction NameForFunction
|
||||||
|
// #define FN_ClientPrintf ClientPrintf
|
||||||
|
// #define FN_ServerPrint ServerPrint
|
||||||
|
// #define FN_Cmd_Args Cmd_Args
|
||||||
|
// #define FN_Cmd_Argv Cmd_Argv
|
||||||
|
// #define FN_Cmd_Argc Cmd_Argc
|
||||||
|
// #define FN_GetAttachment GetAttachment
|
||||||
|
// #define FN_CRC32_Init CRC32_Init
|
||||||
|
// #define FN_CRC32_ProcessBuffer CRC32_ProcessBuffer
|
||||||
|
// #define FN_CRC32_ProcessByte CRC32_ProcessByte
|
||||||
|
// #define FN_CRC32_Final CRC32_Final
|
||||||
|
// #define FN_RandomLong RandomLong
|
||||||
|
// #define FN_RandomFloat RandomFloat
|
||||||
|
// #define FN_SetView SetView
|
||||||
|
// #define FN_Time Time
|
||||||
|
// #define FN_CrosshairAngle CrosshairAngle
|
||||||
|
// #define FN_LoadFileForMe LoadFileForMe
|
||||||
|
// #define FN_FreeFile FreeFile
|
||||||
|
// #define FN_EndSection EndSection
|
||||||
|
// #define FN_CompareFileTime CompareFileTime
|
||||||
|
// #define FN_GetGameDir GetGameDir
|
||||||
|
// #define FN_Cvar_RegisterVariable Cvar_RegisterVariable
|
||||||
|
// #define FN_FadeClientVolume FadeClientVolume
|
||||||
|
// #define FN_SetClientMaxspeed SetClientMaxspeed
|
||||||
|
// #define FN_CreateFakeClient CreateFakeClient
|
||||||
|
// #define FN_RunPlayerMove RunPlayerMove
|
||||||
|
// #define FN_NumberOfEntities NumberOfEntities
|
||||||
|
// #define FN_GetInfoKeyBuffer GetInfoKeyBuffer
|
||||||
|
// #define FN_InfoKeyValue InfoKeyValue
|
||||||
|
// #define FN_SetKeyValue SetKeyValue
|
||||||
|
// #define FN_SetClientKeyValue SetClientKeyValue
|
||||||
|
// #define FN_IsMapValid IsMapValid
|
||||||
|
// #define FN_StaticDecal StaticDecal
|
||||||
|
// #define FN_PrecacheGeneric PrecacheGeneric
|
||||||
|
// #define FN_GetPlayerUserId GetPlayerUserId
|
||||||
|
// #define FN_BuildSoundMsg BuildSoundMsg
|
||||||
|
// #define FN_IsDedicatedServer IsDedicatedServer
|
||||||
|
// #define FN_CVarGetPointer CVarGetPointer
|
||||||
|
// #define FN_GetPlayerWONId GetPlayerWONId
|
||||||
|
// #define FN_Info_RemoveKey Info_RemoveKey
|
||||||
|
// #define FN_GetPhysicsKeyValue GetPhysicsKeyValue
|
||||||
|
// #define FN_SetPhysicsKeyValue SetPhysicsKeyValue
|
||||||
|
// #define FN_GetPhysicsInfoString GetPhysicsInfoString
|
||||||
|
// #define FN_PrecacheEvent PrecacheEvent
|
||||||
|
// #define FN_PlaybackEvent PlaybackEvent
|
||||||
|
// #define FN_SetFatPVS SetFatPVS
|
||||||
|
// #define FN_SetFatPAS SetFatPAS
|
||||||
|
// #define FN_CheckVisibility CheckVisibility
|
||||||
|
// #define FN_DeltaSetField DeltaSetField
|
||||||
|
// #define FN_DeltaUnsetField DeltaUnsetField
|
||||||
|
// #define FN_DeltaAddEncoder DeltaAddEncoder
|
||||||
|
// #define FN_GetCurrentPlayer GetCurrentPlayer
|
||||||
|
// #define FN_CanSkipPlayer CanSkipPlayer
|
||||||
|
// #define FN_DeltaFindField DeltaFindField
|
||||||
|
// #define FN_DeltaSetFieldByIndex DeltaSetFieldByIndex
|
||||||
|
// #define FN_DeltaUnsetFieldByIndex DeltaUnsetFieldByIndex
|
||||||
|
// #define FN_SetGroupMask SetGroupMask
|
||||||
|
// #define FN_engCreateInstancedBaseline engCreateInstancedBaseline
|
||||||
|
// #define FN_Cvar_DirectSet Cvar_DirectSet
|
||||||
|
// #define FN_ForceUnmodified ForceUnmodified
|
||||||
|
// #define FN_GetPlayerStats GetPlayerStats
|
||||||
|
// #define FN_AddServerCommand AddServerCommand
|
||||||
|
// #define FN_Voice_GetClientListening Voice_GetClientListening
|
||||||
|
// #define FN_Voice_SetClientListening Voice_SetClientListening
|
||||||
|
// #define FN_GetPlayerAuthId GetPlayerAuthId
|
||||||
|
|
||||||
|
// - GetEngineAPI_Post functions
|
||||||
|
// #define FN_PrecacheModel_Post PrecacheModel_Post
|
||||||
|
// #define FN_PrecacheSound_Post PrecacheSound_Post
|
||||||
|
// #define FN_SetModel_Post SetModel_Post
|
||||||
|
// #define FN_ModelIndex_Post ModelIndex_Post
|
||||||
|
// #define FN_ModelFrames_Post ModelFrames_Post
|
||||||
|
// #define FN_SetSize_Post SetSize_Post
|
||||||
|
// #define FN_ChangeLevel_Post ChangeLevel_Post
|
||||||
|
// #define FN_GetSpawnParms_Post GetSpawnParms_Post
|
||||||
|
// #define FN_SaveSpawnParms_Post SaveSpawnParms_Post
|
||||||
|
// #define FN_VecToYaw_Post VecToYaw_Post
|
||||||
|
// #define FN_VecToAngles_Post VecToAngles_Post
|
||||||
|
// #define FN_MoveToOrigin_Post MoveToOrigin_Post
|
||||||
|
// #define FN_ChangeYaw_Post ChangeYaw_Post
|
||||||
|
// #define FN_ChangePitch_Post ChangePitch_Post
|
||||||
|
// #define FN_FindEntityByString_Post FindEntityByString_Post
|
||||||
|
// #define FN_GetEntityIllum_Post GetEntityIllum_Post
|
||||||
|
// #define FN_FindEntityInSphere_Post FindEntityInSphere_Post
|
||||||
|
// #define FN_FindClientInPVS_Post FindClientInPVS_Post
|
||||||
|
// #define FN_EntitiesInPVS_Post EntitiesInPVS_Post
|
||||||
|
// #define FN_MakeVectors_Post MakeVectors_Post
|
||||||
|
// #define FN_AngleVectors_Post AngleVectors_Post
|
||||||
|
// #define FN_CreateEntity_Post CreateEntity_Post
|
||||||
|
// #define FN_RemoveEntity_Post RemoveEntity_Post
|
||||||
|
// #define FN_CreateNamedEntity_Post CreateNamedEntity_Post
|
||||||
|
// #define FN_MakeStatic_Post MakeStatic_Post
|
||||||
|
// #define FN_EntIsOnFloor_Post EntIsOnFloor_Post
|
||||||
|
// #define FN_DropToFloor_Post DropToFloor_Post
|
||||||
|
// #define FN_WalkMove_Post WalkMove_Post
|
||||||
|
// #define FN_SetOrigin_Post SetOrigin_Post
|
||||||
|
// #define FN_EmitSound_Post EmitSound_Post
|
||||||
|
// #define FN_EmitAmbientSound_Post EmitAmbientSound_Post
|
||||||
|
// #define FN_TraceLine_Post TraceLine_Post
|
||||||
|
// #define FN_TraceToss_Post TraceToss_Post
|
||||||
|
// #define FN_TraceMonsterHull_Post TraceMonsterHull_Post
|
||||||
|
// #define FN_TraceHull_Post TraceHull_Post
|
||||||
|
// #define FN_TraceModel_Post TraceModel_Post
|
||||||
|
// #define FN_TraceTexture_Post TraceTexture_Post
|
||||||
|
// #define FN_TraceSphere_Post TraceSphere_Post
|
||||||
|
// #define FN_GetAimVector_Post GetAimVector_Post
|
||||||
|
// #define FN_ServerCommand_Post ServerCommand_Post
|
||||||
|
// #define FN_ServerExecute_Post ServerExecute_Post
|
||||||
|
// #define FN_engClientCommand_Post engClientCommand_Post
|
||||||
|
// #define FN_ParticleEffect_Post ParticleEffect_Post
|
||||||
|
// #define FN_LightStyle_Post LightStyle_Post
|
||||||
|
// #define FN_DecalIndex_Post DecalIndex_Post
|
||||||
|
// #define FN_PointContents_Post PointContents_Post
|
||||||
|
// #define FN_MessageBegin_Post MessageBegin_Post
|
||||||
|
// #define FN_MessageEnd_Post MessageEnd_Post
|
||||||
|
// #define FN_WriteByte_Post WriteByte_Post
|
||||||
|
// #define FN_WriteChar_Post WriteChar_Post
|
||||||
|
// #define FN_WriteShort_Post WriteShort_Post
|
||||||
|
// #define FN_WriteLong_Post WriteLong_Post
|
||||||
|
// #define FN_WriteAngle_Post WriteAngle_Post
|
||||||
|
// #define FN_WriteCoord_Post WriteCoord_Post
|
||||||
|
// #define FN_WriteString_Post WriteString_Post
|
||||||
|
// #define FN_WriteEntity_Post WriteEntity_Post
|
||||||
|
// #define FN_CVarRegister_Post CVarRegister_Post
|
||||||
|
// #define FN_CVarGetFloat_Post CVarGetFloat_Post
|
||||||
|
// #define FN_CVarGetString_Post CVarGetString_Post
|
||||||
|
// #define FN_CVarSetFloat_Post CVarSetFloat_Post
|
||||||
|
// #define FN_CVarSetString_Post CVarSetString_Post
|
||||||
|
// #define FN_AlertMessage_Post AlertMessage_Post
|
||||||
|
// #define FN_EngineFprintf_Post EngineFprintf_Post
|
||||||
|
// #define FN_PvAllocEntPrivateData_Post PvAllocEntPrivateData_Post
|
||||||
|
// #define FN_PvEntPrivateData_Post PvEntPrivateData_Post
|
||||||
|
// #define FN_FreeEntPrivateData_Post FreeEntPrivateData_Post
|
||||||
|
// #define FN_SzFromIndex_Post SzFromIndex_Post
|
||||||
|
// #define FN_AllocString_Post AllocString_Post
|
||||||
|
// #define FN_GetVarsOfEnt_Post GetVarsOfEnt_Post
|
||||||
|
// #define FN_PEntityOfEntOffset_Post PEntityOfEntOffset_Post
|
||||||
|
// #define FN_EntOffsetOfPEntity_Post EntOffsetOfPEntity_Post
|
||||||
|
// #define FN_IndexOfEdict_Post IndexOfEdict_Post
|
||||||
|
// #define FN_PEntityOfEntIndex_Post PEntityOfEntIndex_Post
|
||||||
|
// #define FN_FindEntityByVars_Post FindEntityByVars_Post
|
||||||
|
// #define FN_GetModelPtr_Post GetModelPtr_Post
|
||||||
|
// #define FN_RegUserMsg_Post RegUserMsg_Post
|
||||||
|
// #define FN_AnimationAutomove_Post AnimationAutomove_Post
|
||||||
|
// #define FN_GetBonePosition_Post GetBonePosition_Post
|
||||||
|
// #define FN_FunctionFromName_Post FunctionFromName_Post
|
||||||
|
// #define FN_NameForFunction_Post NameForFunction_Post
|
||||||
|
// #define FN_ClientPrintf_Post ClientPrintf_Post
|
||||||
|
// #define FN_ServerPrint_Post ServerPrint_Post
|
||||||
|
// #define FN_Cmd_Args_Post Cmd_Args_Post
|
||||||
|
// #define FN_Cmd_Argv_Post Cmd_Argv_Post
|
||||||
|
// #define FN_Cmd_Argc_Post Cmd_Argc_Post
|
||||||
|
// #define FN_GetAttachment_Post GetAttachment_Post
|
||||||
|
// #define FN_CRC32_Init_Post CRC32_Init_Post
|
||||||
|
// #define FN_CRC32_ProcessBuffer_Post CRC32_ProcessBuffer_Post
|
||||||
|
// #define FN_CRC32_ProcessByte_Post CRC32_ProcessByte_Post
|
||||||
|
// #define FN_CRC32_Final_Post CRC32_Final_Post
|
||||||
|
// #define FN_RandomLong_Post RandomLong_Post
|
||||||
|
// #define FN_RandomFloat_Post RandomFloat_Post
|
||||||
|
// #define FN_SetView_Post SetView_Post
|
||||||
|
// #define FN_Time_Post Time_Post
|
||||||
|
// #define FN_CrosshairAngle_Post CrosshairAngle_Post
|
||||||
|
// #define FN_LoadFileForMe_Post LoadFileForMe_Post
|
||||||
|
// #define FN_FreeFile_Post FreeFile_Post
|
||||||
|
// #define FN_EndSection_Post EndSection_Post
|
||||||
|
// #define FN_CompareFileTime_Post CompareFileTime_Post
|
||||||
|
// #define FN_GetGameDir_Post GetGameDir_Post
|
||||||
|
// #define FN_Cvar_RegisterVariable_Post Cvar_RegisterVariable_Post
|
||||||
|
// #define FN_FadeClientVolume_Post FadeClientVolume_Post
|
||||||
|
// #define FN_SetClientMaxspeed_Post SetClientMaxspeed_Post
|
||||||
|
// #define FN_CreateFakeClient_Post CreateFakeClient_Post
|
||||||
|
// #define FN_RunPlayerMove_Post RunPlayerMove_Post
|
||||||
|
// #define FN_NumberOfEntities_Post NumberOfEntities_Post
|
||||||
|
// #define FN_GetInfoKeyBuffer_Post GetInfoKeyBuffer_Post
|
||||||
|
// #define FN_InfoKeyValue_Post InfoKeyValue_Post
|
||||||
|
// #define FN_SetKeyValue_Post SetKeyValue_Post
|
||||||
|
// #define FN_SetClientKeyValue_Post SetClientKeyValue_Post
|
||||||
|
// #define FN_IsMapValid_Post IsMapValid_Post
|
||||||
|
// #define FN_StaticDecal_Post StaticDecal_Post
|
||||||
|
// #define FN_PrecacheGeneric_Post PrecacheGeneric_Post
|
||||||
|
// #define FN_GetPlayerUserId_Post GetPlayerUserId_Post
|
||||||
|
// #define FN_BuildSoundMsg_Post BuildSoundMsg_Post
|
||||||
|
// #define FN_IsDedicatedServer_Post IsDedicatedServer_Post
|
||||||
|
// #define FN_CVarGetPointer_Post CVarGetPointer_Post
|
||||||
|
// #define FN_GetPlayerWONId_Post GetPlayerWONId_Post
|
||||||
|
// #define FN_Info_RemoveKey_Post Info_RemoveKey_Post
|
||||||
|
// #define FN_GetPhysicsKeyValue_Post GetPhysicsKeyValue_Post
|
||||||
|
// #define FN_SetPhysicsKeyValue_Post SetPhysicsKeyValue_Post
|
||||||
|
// #define FN_GetPhysicsInfoString_Post GetPhysicsInfoString_Post
|
||||||
|
// #define FN_PrecacheEvent_Post PrecacheEvent_Post
|
||||||
|
// #define FN_PlaybackEvent_Post PlaybackEvent_Post
|
||||||
|
// #define FN_SetFatPVS_Post SetFatPVS_Post
|
||||||
|
// #define FN_SetFatPAS_Post SetFatPAS_Post
|
||||||
|
// #define FN_CheckVisibility_Post CheckVisibility_Post
|
||||||
|
// #define FN_DeltaSetField_Post DeltaSetField_Post
|
||||||
|
// #define FN_DeltaUnsetField_Post DeltaUnsetField_Post
|
||||||
|
// #define FN_DeltaAddEncoder_Post DeltaAddEncoder_Post
|
||||||
|
// #define FN_GetCurrentPlayer_Post GetCurrentPlayer_Post
|
||||||
|
// #define FN_CanSkipPlayer_Post CanSkipPlayer_Post
|
||||||
|
// #define FN_DeltaFindField_Post DeltaFindField_Post
|
||||||
|
// #define FN_DeltaSetFieldByIndex_Post DeltaSetFieldByIndex_Post
|
||||||
|
// #define FN_DeltaUnsetFieldByIndex_Post DeltaUnsetFieldByIndex_Post
|
||||||
|
// #define FN_SetGroupMask_Post SetGroupMask_Post
|
||||||
|
// #define FN_engCreateInstancedBaseline_Post engCreateInstancedBaseline_Post
|
||||||
|
// #define FN_Cvar_DirectSet_Post Cvar_DirectSet_Post
|
||||||
|
// #define FN_ForceUnmodified_Post ForceUnmodified_Post
|
||||||
|
// #define FN_GetPlayerStats_Post GetPlayerStats_Post
|
||||||
|
// #define FN_AddServerCommand_Post AddServerCommand_Post
|
||||||
|
// #define FN_Voice_GetClientListening_Post Voice_GetClientListening_Post
|
||||||
|
// #define FN_Voice_SetClientListening_Post Voice_SetClientListening_Post
|
||||||
|
// #define FN_GetPlayerAuthId_Post GetPlayerAuthId_Post
|
||||||
|
|
||||||
|
// #define FN_OnFreeEntPrivateData OnFreeEntPrivateData
|
||||||
|
// #define FN_GameShutdown GameShutdown
|
||||||
|
// #define FN_ShouldCollide ShouldCollide
|
||||||
|
|
||||||
|
// #define FN_OnFreeEntPrivateData_Post OnFreeEntPrivateData_Post
|
||||||
|
// #define FN_GameShutdown_Post GameShutdown_Post
|
||||||
|
// #define FN_ShouldCollide_Post ShouldCollide_Post
|
||||||
|
|
||||||
|
|
||||||
|
#endif // USE_METAMOD
|
||||||
|
|
||||||
|
#endif // __MODULECONFIG_H__
|
297
dlls/sqlite/sdk/sh_list.h
Normal file
297
dlls/sqlite/sdk/sh_list.h
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
/* ======== SourceMM ========
|
||||||
|
* Copyright (C) 2004-2005 Metamod:Source Development Team
|
||||||
|
* No warranties of any kind
|
||||||
|
*
|
||||||
|
* License: zlib/libpng
|
||||||
|
*
|
||||||
|
* Author(s): David "BAILOPAN" Anderson
|
||||||
|
* ============================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_SMM_LIST_H
|
||||||
|
#define _INCLUDE_SMM_LIST_H
|
||||||
|
|
||||||
|
// MSVC8 fix for offsetof macro redefition warnings
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#if _MSC_VER >= 1400
|
||||||
|
#undef offsetof
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
namespace SourceHook
|
||||||
|
{
|
||||||
|
//This class is from CSDM for AMX Mod X
|
||||||
|
/*
|
||||||
|
A circular, doubly-linked list with one sentinel node
|
||||||
|
|
||||||
|
Empty:
|
||||||
|
m_Head = sentinel
|
||||||
|
m_Head->next = m_Head;
|
||||||
|
m_Head->prev = m_Head;
|
||||||
|
One element:
|
||||||
|
m_Head = sentinel
|
||||||
|
m_Head->next = node1
|
||||||
|
m_Head->prev = node1
|
||||||
|
node1->next = m_Head
|
||||||
|
node1->prev = m_Head
|
||||||
|
Two elements:
|
||||||
|
m_Head = sentinel
|
||||||
|
m_Head->next = node1
|
||||||
|
m_Head->prev = node2
|
||||||
|
node1->next = node2
|
||||||
|
node1->prev = m_Head
|
||||||
|
node2->next = m_Head
|
||||||
|
node2->prev = node1
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
class List
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class iterator;
|
||||||
|
friend class iterator;
|
||||||
|
class ListNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ListNode(const T & o) : obj(o) { };
|
||||||
|
ListNode() { };
|
||||||
|
T obj;
|
||||||
|
ListNode *next;
|
||||||
|
ListNode *prev;
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
// Initializes the sentinel node.
|
||||||
|
// BAIL used malloc instead of new in order to bypass the need for a constructor.
|
||||||
|
ListNode *_Initialize()
|
||||||
|
{
|
||||||
|
ListNode *n = (ListNode *)malloc(sizeof(ListNode));
|
||||||
|
n->next = n;
|
||||||
|
n->prev = n;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
List() : m_Head(_Initialize()), m_Size(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
List(const List &src) : m_Head(_Initialize()), m_Size(0)
|
||||||
|
{
|
||||||
|
iterator iter;
|
||||||
|
for (iter=src.begin(); iter!=src.end(); iter++)
|
||||||
|
push_back( (*iter) );
|
||||||
|
}
|
||||||
|
~List()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
// Don't forget to free the sentinel
|
||||||
|
if (m_Head)
|
||||||
|
{
|
||||||
|
free(m_Head);
|
||||||
|
m_Head = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void push_back(const T &obj)
|
||||||
|
{
|
||||||
|
ListNode *node = new ListNode(obj);
|
||||||
|
|
||||||
|
node->prev = m_Head->prev;
|
||||||
|
node->next = m_Head;
|
||||||
|
m_Head->prev->next = node;
|
||||||
|
m_Head->prev = node;
|
||||||
|
|
||||||
|
m_Size++;
|
||||||
|
}
|
||||||
|
size_t size()
|
||||||
|
{
|
||||||
|
return m_Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
ListNode *node = m_Head->next;
|
||||||
|
ListNode *temp;
|
||||||
|
m_Head->next = m_Head;
|
||||||
|
m_Head->prev = m_Head;
|
||||||
|
|
||||||
|
// Iterate through the nodes until we find g_Head (the sentinel) again
|
||||||
|
while (node != m_Head)
|
||||||
|
{
|
||||||
|
temp = node->next;
|
||||||
|
delete node;
|
||||||
|
node = temp;
|
||||||
|
}
|
||||||
|
m_Size = 0;
|
||||||
|
}
|
||||||
|
bool empty()
|
||||||
|
{
|
||||||
|
return (m_Size == 0);
|
||||||
|
}
|
||||||
|
T & back()
|
||||||
|
{
|
||||||
|
return m_Head->prev->obj;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
ListNode *m_Head;
|
||||||
|
size_t m_Size;
|
||||||
|
public:
|
||||||
|
class iterator
|
||||||
|
{
|
||||||
|
friend class List;
|
||||||
|
public:
|
||||||
|
iterator()
|
||||||
|
{
|
||||||
|
m_This = NULL;
|
||||||
|
}
|
||||||
|
iterator(const List &src)
|
||||||
|
{
|
||||||
|
m_This = src.m_Head;
|
||||||
|
}
|
||||||
|
iterator(ListNode *n) : m_This(n)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
iterator(const iterator &where)
|
||||||
|
{
|
||||||
|
m_This = where.m_This;
|
||||||
|
}
|
||||||
|
//pre decrement
|
||||||
|
iterator & operator--()
|
||||||
|
{
|
||||||
|
if (m_This)
|
||||||
|
m_This = m_This->prev;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
//post decrement
|
||||||
|
iterator operator--(int)
|
||||||
|
{
|
||||||
|
iterator old(*this);
|
||||||
|
if (m_This)
|
||||||
|
m_This = m_This->prev;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
//pre increment
|
||||||
|
iterator & operator++()
|
||||||
|
{
|
||||||
|
if (m_This)
|
||||||
|
m_This = m_This->next;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
//post increment
|
||||||
|
iterator operator++(int)
|
||||||
|
{
|
||||||
|
iterator old(*this);
|
||||||
|
if (m_This)
|
||||||
|
m_This = m_This->next;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T & operator * () const
|
||||||
|
{
|
||||||
|
return m_This->obj;
|
||||||
|
}
|
||||||
|
T & operator * ()
|
||||||
|
{
|
||||||
|
return m_This->obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
T * operator -> ()
|
||||||
|
{
|
||||||
|
return &(m_This->obj);
|
||||||
|
}
|
||||||
|
const T * operator -> () const
|
||||||
|
{
|
||||||
|
return &(m_This->obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator != (const iterator &where) const
|
||||||
|
{
|
||||||
|
return (m_This != where.m_This);
|
||||||
|
}
|
||||||
|
bool operator ==(const iterator &where) const
|
||||||
|
{
|
||||||
|
return (m_This == where.m_This);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
ListNode *m_This;
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
iterator begin() const
|
||||||
|
{
|
||||||
|
return iterator(m_Head->next);
|
||||||
|
}
|
||||||
|
iterator end() const
|
||||||
|
{
|
||||||
|
return iterator(m_Head);
|
||||||
|
}
|
||||||
|
iterator erase(iterator &where)
|
||||||
|
{
|
||||||
|
ListNode *pNode = where.m_This;
|
||||||
|
iterator iter(where);
|
||||||
|
iter++;
|
||||||
|
|
||||||
|
|
||||||
|
// Works for all cases: empty list, erasing first element, erasing tail, erasing in the middle...
|
||||||
|
pNode->prev->next = pNode->next;
|
||||||
|
pNode->next->prev = pNode->prev;
|
||||||
|
|
||||||
|
delete pNode;
|
||||||
|
m_Size--;
|
||||||
|
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator insert(iterator where, const T &obj)
|
||||||
|
{
|
||||||
|
// Insert obj right before where
|
||||||
|
|
||||||
|
ListNode *node = new ListNode(obj);
|
||||||
|
ListNode *pWhereNode = where.m_This;
|
||||||
|
|
||||||
|
pWhereNode->prev->next = node;
|
||||||
|
node->prev = pWhereNode->prev;
|
||||||
|
pWhereNode->prev = node;
|
||||||
|
node->next = pWhereNode;
|
||||||
|
|
||||||
|
m_Size++;
|
||||||
|
|
||||||
|
return iterator(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void remove(const T & obj)
|
||||||
|
{
|
||||||
|
iterator b;
|
||||||
|
for (b=begin(); b!=end(); b++)
|
||||||
|
{
|
||||||
|
if ( (*b) == obj )
|
||||||
|
{
|
||||||
|
erase( b );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename U>
|
||||||
|
iterator find(const U & equ)
|
||||||
|
{
|
||||||
|
iterator iter;
|
||||||
|
for (iter=begin(); iter!=end(); iter++)
|
||||||
|
{
|
||||||
|
if ( (*iter) == equ )
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
return end();
|
||||||
|
}
|
||||||
|
List & operator =(const List &src)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
iterator iter;
|
||||||
|
for (iter=src.begin(); iter!=src.end(); iter++)
|
||||||
|
push_back( (*iter) );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; //NAMESPACE
|
||||||
|
|
||||||
|
#endif //_INCLUDE_CSDM_LIST_H
|
219
dlls/sqlite/sdk/sh_stack.h
Executable file
219
dlls/sqlite/sdk/sh_stack.h
Executable file
@ -0,0 +1,219 @@
|
|||||||
|
/* ======== SourceMM ========
|
||||||
|
* Copyright (C) 2004-2005 Metamod:Source Development Team
|
||||||
|
* No warranties of any kind
|
||||||
|
*
|
||||||
|
* License: zlib/libpng
|
||||||
|
*
|
||||||
|
* Author(s): Pavol "PM OnoTo" Marko
|
||||||
|
* ============================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SH_STACK_H__
|
||||||
|
#define __SH_STACK_H__
|
||||||
|
|
||||||
|
#define SH_STACK_DEFAULT_SIZE 4
|
||||||
|
|
||||||
|
//namespace SourceHook
|
||||||
|
//{/
|
||||||
|
// Vector
|
||||||
|
template <class T> class CStack
|
||||||
|
{
|
||||||
|
T *m_Elements;
|
||||||
|
size_t m_AllocatedSize;
|
||||||
|
size_t m_UsedSize;
|
||||||
|
public:
|
||||||
|
friend class iterator;
|
||||||
|
class iterator
|
||||||
|
{
|
||||||
|
CStack<T> *m_pParent;
|
||||||
|
size_t m_Index;
|
||||||
|
public:
|
||||||
|
iterator(CStack<T> *pParent, size_t id) : m_pParent(pParent), m_Index(id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator(CStack<T> *pParent) : m_pParent(pParent), m_Index(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator() : m_pParent(NULL), m_Index(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
T &operator *()
|
||||||
|
{
|
||||||
|
return m_pParent->m_Elements[m_Index];
|
||||||
|
}
|
||||||
|
const T &operator *() const
|
||||||
|
{
|
||||||
|
return m_pParent->m_Elements[m_Index];
|
||||||
|
}
|
||||||
|
|
||||||
|
T * operator->()
|
||||||
|
{
|
||||||
|
return m_pParent->m_Elements + m_Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T * operator->() const
|
||||||
|
{
|
||||||
|
return m_pParent->m_Elements + m_Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator & operator++() // preincrement
|
||||||
|
{
|
||||||
|
++m_Index;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator operator++(int) // postincrement
|
||||||
|
{
|
||||||
|
iterator tmp = *this;
|
||||||
|
++m_Index;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator & operator--() // predecrement
|
||||||
|
{
|
||||||
|
--m_Index;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator operator--(int) // postdecrememnt
|
||||||
|
{
|
||||||
|
iterator tmp = *this;
|
||||||
|
--m_Index;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const iterator & right) const
|
||||||
|
{
|
||||||
|
return (m_pParent == right.m_pParent && m_Index == right.m_Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const iterator & right) const
|
||||||
|
{
|
||||||
|
return !(*this == right);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
CStack() : m_Elements(new T[SH_STACK_DEFAULT_SIZE]),
|
||||||
|
m_AllocatedSize(SH_STACK_DEFAULT_SIZE),
|
||||||
|
m_UsedSize(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
CStack(size_t size) : m_Elements(new T[size]),
|
||||||
|
m_AllocatedSize(size),
|
||||||
|
m_UsedSize(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CStack(const CStack &other) : m_Elements(NULL),
|
||||||
|
m_AllocatedSize(0),
|
||||||
|
m_UsedSize(0)
|
||||||
|
{
|
||||||
|
reserve(other.m_AllocatedSize);
|
||||||
|
m_UsedSize = other.m_UsedSize;
|
||||||
|
for (size_t i = 0; i < m_UsedSize; ++i)
|
||||||
|
m_Elements[i] = other.m_Elements[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
~CStack()
|
||||||
|
{
|
||||||
|
if (m_Elements)
|
||||||
|
delete [] m_Elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator=(const CStack &other)
|
||||||
|
{
|
||||||
|
if (m_AllocatedSize < other.m_AllocatedSize)
|
||||||
|
{
|
||||||
|
if (m_Elements)
|
||||||
|
delete [] m_Elements;
|
||||||
|
m_Elements = new T[other.m_AllocatedSize];
|
||||||
|
m_AllocatedSize = other.m_AllocatedSize;
|
||||||
|
}
|
||||||
|
m_UsedSize = other.m_UsedSize;
|
||||||
|
for (size_t i = 0; i < m_UsedSize; ++i)
|
||||||
|
m_Elements[i] = other.m_Elements[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool push(const T &val)
|
||||||
|
{
|
||||||
|
if (m_UsedSize + 1 == m_AllocatedSize)
|
||||||
|
{
|
||||||
|
// zOHNOES! REALLOCATE!
|
||||||
|
m_AllocatedSize *= 2;
|
||||||
|
T *newElements = new T[m_AllocatedSize];
|
||||||
|
if (!newElements)
|
||||||
|
{
|
||||||
|
m_AllocatedSize /= 2;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (m_Elements)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_UsedSize; ++i)
|
||||||
|
newElements[i] = m_Elements[i];
|
||||||
|
delete [] m_Elements;
|
||||||
|
}
|
||||||
|
m_Elements = newElements;
|
||||||
|
}
|
||||||
|
m_Elements[m_UsedSize++] = val;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void pop()
|
||||||
|
{
|
||||||
|
--m_UsedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
T &front()
|
||||||
|
{
|
||||||
|
return m_Elements[m_UsedSize - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T &front() const
|
||||||
|
{
|
||||||
|
return m_Elements[m_UsedSize - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator begin()
|
||||||
|
{
|
||||||
|
return iterator(this, 0);
|
||||||
|
}
|
||||||
|
iterator end()
|
||||||
|
{
|
||||||
|
return iterator(this, m_UsedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size()
|
||||||
|
{
|
||||||
|
return m_UsedSize;
|
||||||
|
}
|
||||||
|
size_t capacity()
|
||||||
|
{
|
||||||
|
return m_AllocatedSize;
|
||||||
|
}
|
||||||
|
bool empty()
|
||||||
|
{
|
||||||
|
return m_UsedSize == 0 ? true : false;
|
||||||
|
}
|
||||||
|
bool reserve(size_t size)
|
||||||
|
{
|
||||||
|
if (size > m_AllocatedSize)
|
||||||
|
{
|
||||||
|
T *newElements = new T[size];
|
||||||
|
if (!newElements)
|
||||||
|
return false;
|
||||||
|
if (m_Elements)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_UsedSize; ++i)
|
||||||
|
newElements[i] = m_Elements[i];
|
||||||
|
delete [] m_Elements;
|
||||||
|
}
|
||||||
|
m_Elements = newElements;
|
||||||
|
m_AllocatedSize = size;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//}; //namespace SourceHook
|
||||||
|
|
||||||
|
#endif
|
@ -1,41 +1,26 @@
|
|||||||
/* AMX Mod X
|
/* ======== SourceMM ========
|
||||||
|
* Copyright (C) 2004-2005 Metamod:Source Development Team
|
||||||
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* by the AMX Mod X Development Team
|
* License: zlib/libpng
|
||||||
* originally developed by OLO
|
|
||||||
*
|
*
|
||||||
*
|
* Author(s): David "BAILOPAN" Anderson
|
||||||
* This program 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 2 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, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* AMX Mod X
|
||||||
|
*
|
||||||
|
* by the AMX Mod X Development Team
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef _INCLUDE_CSTRING_H
|
#ifndef _INCLUDE_CSTRING_H
|
||||||
#define _INCLUDE_CSTRING_H
|
#define _INCLUDE_CSTRING_H
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
//by David "BAILOPAN" Anderson
|
namespace SourceHook
|
||||||
|
{
|
||||||
class String
|
class String
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -59,13 +44,6 @@ public:
|
|||||||
assign(src);
|
assign(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * _fread(FILE *fp)
|
|
||||||
{
|
|
||||||
Grow(512, false);
|
|
||||||
char *ret = fgets(v, 511, fp);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
String(const String &src)
|
String(const String &src)
|
||||||
{
|
{
|
||||||
v = NULL;
|
v = NULL;
|
||||||
@ -107,10 +85,8 @@ public:
|
|||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
} else {
|
} else {
|
||||||
size_t len = strlen(d);
|
Grow(strlen(d) + 1, false);
|
||||||
Grow(len + 1, false);
|
strcpy(v, d);
|
||||||
memcpy(v, d, len);
|
|
||||||
v[len] = '\0';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +96,7 @@ public:
|
|||||||
v[0] = '\0';
|
v[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
int compare (const char *d) const
|
int compare (const char *d)
|
||||||
{
|
{
|
||||||
if (!v)
|
if (!v)
|
||||||
return strcmp("", d);
|
return strcmp("", d);
|
||||||
@ -386,4 +362,6 @@ public:
|
|||||||
static const int npos = -1;
|
static const int npos = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}; //NAMESPACE
|
||||||
|
|
||||||
#endif //_INCLUDE_CSTRING_H
|
#endif //_INCLUDE_CSTRING_H
|
17
dlls/sqlite/sqlheaders.h
Normal file
17
dlls/sqlite/sqlheaders.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef _INCLUDE_SQLHEADERS_H
|
||||||
|
#define _INCLUDE_SQLHEADERS_H
|
||||||
|
|
||||||
|
#include "ISQLDriver.h"
|
||||||
|
|
||||||
|
#define SQL_DRIVER_FUNC "GetSqlFuncs"
|
||||||
|
|
||||||
|
typedef int (*SQLAFFINITY)(AMX *amx);
|
||||||
|
|
||||||
|
struct SqlFunctions
|
||||||
|
{
|
||||||
|
SourceMod::ISQLDriver *driver;
|
||||||
|
SQLAFFINITY set_affinity;
|
||||||
|
SqlFunctions *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SQLHEADERS_H
|
@ -1,458 +0,0 @@
|
|||||||
/* AMX Mod X
|
|
||||||
* MySQL Module
|
|
||||||
*
|
|
||||||
* by the AMX Mod X Development Team
|
|
||||||
*
|
|
||||||
* This file is part of AMX Mod X.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program 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 2 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, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include "sqlite_amx.h"
|
|
||||||
|
|
||||||
unsigned int lastDb;
|
|
||||||
|
|
||||||
CVector<SQLResult*> Results;
|
|
||||||
CVector<SQL*> DBList;
|
|
||||||
|
|
||||||
// ///////////////////////////////
|
|
||||||
// Sqlite natives for AMX scripting
|
|
||||||
// ///////////////////////////////
|
|
||||||
|
|
||||||
// Sql:dbi_connect(host[],user[],pass[],dbname[],error[],maxlength) :
|
|
||||||
// - open connection
|
|
||||||
// not used: host, user, pass
|
|
||||||
static cell AMX_NATIVE_CALL sql_connect(AMX *amx, cell *params) // 6 param
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
int id = -1;
|
|
||||||
//char *host = MF_GetAmxString(amx,params[1], 0, &i);
|
|
||||||
//char *user = MF_GetAmxString(amx,params[2], 1, &i);
|
|
||||||
//char *pass = MF_GetAmxString(amx,params[3], 2, &i);
|
|
||||||
char *dbname = MF_GetAmxString(amx,params[4], 3, &i);
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
if (!strlen(dbname)) {
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Received invalid parameter.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SQL *c=NULL;
|
|
||||||
|
|
||||||
for (i=0; (unsigned int)i<DBList.size(); i++) {
|
|
||||||
if (DBList[i]->isFree) {
|
|
||||||
id = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id>=0) {
|
|
||||||
c = DBList[id];
|
|
||||||
} else {
|
|
||||||
c = new SQL;
|
|
||||||
DBList.push_back(c);
|
|
||||||
id = (unsigned int)(DBList.size() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char pathbuffer[1024];
|
|
||||||
MF_BuildPathnameR(pathbuffer, 1023, "%s", dbname);
|
|
||||||
#if defined _DEBUG
|
|
||||||
MF_PrintSrvConsole("Sqlite connect uses path: \"%s\"\n", pathbuffer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!c->Connect(pathbuffer))
|
|
||||||
{
|
|
||||||
if (c->ErrorStr.size() < 1)
|
|
||||||
{
|
|
||||||
c->Error();
|
|
||||||
}
|
|
||||||
MF_SetAmxString(amx, params[5], c->ErrorStr.c_str(), params[6]);
|
|
||||||
return CONNECT_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
MF_SetAmxString(amx,params[5],"",params[6]);
|
|
||||||
|
|
||||||
lastDb = id;
|
|
||||||
|
|
||||||
return id+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// dbi_error(Sql:sql,dest[],maxlength)
|
|
||||||
// - store maxlength characters from mysql error in current row to dest
|
|
||||||
static cell AMX_NATIVE_CALL sql_error(AMX *amx, cell *params) // 3 params
|
|
||||||
{
|
|
||||||
unsigned int id = params[1]-1;
|
|
||||||
if (id >= DBList.size() || DBList[id]->isFree)
|
|
||||||
id = lastDb;
|
|
||||||
|
|
||||||
SQL *sql = DBList[id];
|
|
||||||
|
|
||||||
if (sql->ErrorStr.size() > 1)
|
|
||||||
{
|
|
||||||
MF_SetAmxString(amx, params[2], sql->ErrorStr.c_str(), params[3]);
|
|
||||||
sql->ErrorStr.assign("");
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
sql->Error();
|
|
||||||
if (sql->ErrorStr.size() > 1)
|
|
||||||
{
|
|
||||||
MF_SetAmxString(amx, params[2], sql->ErrorStr.c_str(), params[3]);
|
|
||||||
sql->ErrorStr.assign("");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MF_SetAmxString(amx, params[2], "", params[3]);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Result:dbi_query(Sql:sql,query[]) - returns 0 on success, <0 on failure, >0 on result set
|
|
||||||
static cell AMX_NATIVE_CALL sql_query(AMX *amx, cell *params) // 2 params
|
|
||||||
{
|
|
||||||
unsigned int id = params[1] - 1;
|
|
||||||
|
|
||||||
if (id >= DBList.size() || DBList[id]->isFree) {
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid database handle %d", id);
|
|
||||||
return QUERY_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastDb = id;
|
|
||||||
|
|
||||||
int len = 0;
|
|
||||||
const char *query = MF_FormatAmxString(amx, params, 2, &len);
|
|
||||||
|
|
||||||
SQL *sql = DBList[id];
|
|
||||||
|
|
||||||
return sql->Query(query); //Return the result set handle, if any
|
|
||||||
}
|
|
||||||
|
|
||||||
// dbi_nextrow(Sql:sql) :
|
|
||||||
// - read next row
|
|
||||||
// - return :
|
|
||||||
// . number of line
|
|
||||||
// . 0 at end
|
|
||||||
static cell AMX_NATIVE_CALL sql_nextrow(AMX *amx, cell *params) // 1 param
|
|
||||||
{
|
|
||||||
unsigned int id = params[1]-1;
|
|
||||||
|
|
||||||
if (id == -1)
|
|
||||||
{
|
|
||||||
//the user should have checked, but we'll return 0 anyway
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id >= Results.size() || Results[id]->isFree)
|
|
||||||
{
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid result handle %d", id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SQLResult *Result = Results[id];
|
|
||||||
|
|
||||||
return Result->Nextrow();
|
|
||||||
}
|
|
||||||
|
|
||||||
// dbi_close(Sql:sql) :
|
|
||||||
// - free result
|
|
||||||
// - close connection
|
|
||||||
static cell AMX_NATIVE_CALL sql_close(AMX *amx, cell *params) // 1 param
|
|
||||||
{
|
|
||||||
cell *addr = MF_GetAmxAddr(amx, params[1]);
|
|
||||||
unsigned int id = (*addr) - 1;
|
|
||||||
if (id >= DBList.size() || DBList[id]->isFree) {
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid database handle %d", id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastDb = id;
|
|
||||||
|
|
||||||
SQL *sql = DBList[id];
|
|
||||||
|
|
||||||
sql->Disconnect();
|
|
||||||
|
|
||||||
*addr = 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Returns a field from a query result handle.
|
|
||||||
// 2 param - returns integer
|
|
||||||
// 3 param - stores float in cell byref
|
|
||||||
// 4 param - stores string
|
|
||||||
static cell AMX_NATIVE_CALL sql_getfield(AMX *amx, cell *params) // 2-4 params
|
|
||||||
{
|
|
||||||
unsigned int id = params[1]-1;
|
|
||||||
|
|
||||||
if (id >= Results.size() || Results[id]->isFree)
|
|
||||||
{
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid result handle %d.", id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SQLResult *Result = Results[id];
|
|
||||||
if (Result->m_rowCount == 0)
|
|
||||||
{
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Record set is empty.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int numParams = (*params)/sizeof(cell);
|
|
||||||
cell *fAddr = NULL;
|
|
||||||
const char *field = Result->GetField(params[2]-1);
|
|
||||||
if (field == NULL)
|
|
||||||
{
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Field error.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (numParams)
|
|
||||||
{
|
|
||||||
case 2:
|
|
||||||
return atoi(field);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
fAddr = MF_GetAmxAddr(amx, params[3]);
|
|
||||||
*fAddr = amx_ftoc((REAL)atof(field));
|
|
||||||
return 1;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
return MF_SetAmxString(amx, params[3], field?field:"", *(MF_GetAmxAddr(amx, params[4])));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Returns a field from a query result handle.
|
|
||||||
// 2 param - returns integer
|
|
||||||
// 3 param - stores float in cell byref
|
|
||||||
// 4 param - stores string
|
|
||||||
static cell AMX_NATIVE_CALL sql_getresult(AMX *amx, cell *params) // 4 params
|
|
||||||
{
|
|
||||||
unsigned int id = params[1]-1;
|
|
||||||
|
|
||||||
if (id >= Results.size())
|
|
||||||
{
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid result handle %d", id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SQLResult *Result = Results[id];
|
|
||||||
int numParams = (*params)/sizeof(cell);
|
|
||||||
cell *fAddr = NULL;
|
|
||||||
int len = 0;
|
|
||||||
const char *column = MF_GetAmxString(amx, params[2], 0, &len);
|
|
||||||
const char *field = Result->GetField(column);
|
|
||||||
if (field == NULL)
|
|
||||||
{
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Unknown error");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (numParams)
|
|
||||||
{
|
|
||||||
case 2:
|
|
||||||
return atoi(field);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
fAddr = MF_GetAmxAddr(amx, params[3]);
|
|
||||||
*fAddr = amx_ftoc((REAL)atof(field));
|
|
||||||
return 1;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
len = *(MF_GetAmxAddr(amx, params[4]));
|
|
||||||
return MF_SetAmxString(amx, params[3], field?field:"", params[4]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL sql_free_result(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
cell *addr = (MF_GetAmxAddr(amx, params[1]));
|
|
||||||
unsigned int id = (*addr) - 1;
|
|
||||||
|
|
||||||
if (id == -1)
|
|
||||||
{
|
|
||||||
//the user should have checked, but we'll return 0 anyway
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id >= Results.size())
|
|
||||||
{
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid result handle %d", id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SQLResult *Result = Results[id];
|
|
||||||
|
|
||||||
*addr = 0;
|
|
||||||
|
|
||||||
if (Result->isFree) {
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Tried to free result %d, but the result was already free!", id + 1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result->FreeResult();
|
|
||||||
|
|
||||||
#if defined _DEBUG
|
|
||||||
if (id + 1 == SQLResult::latestStoredResultId)
|
|
||||||
MF_PrintSrvConsole("***FREED: %d\n", id + 1);
|
|
||||||
else
|
|
||||||
MF_PrintSrvConsole("***FREED: %d WARNING LAST STORED: %d!\n", id + 1, SQLResult::latestStoredResultId);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL sql_num_rows(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
unsigned int id = params[1]-1;
|
|
||||||
|
|
||||||
if (id == -1)
|
|
||||||
{
|
|
||||||
//the user should have checked, but we'll return 0 anyway
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id >= Results.size() || Results[id]->isFree)
|
|
||||||
{
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid result handle %d", id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SQLResult *Result = Results[id];
|
|
||||||
|
|
||||||
return (cell)Result->NumRows();
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL sql_type(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
return MF_SetAmxString(amx, params[1], "sqlite", params[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL sql_num_fields(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
unsigned int id = params[1]-1;
|
|
||||||
|
|
||||||
if (id == -1)
|
|
||||||
{
|
|
||||||
//the user should have checked, but we'll return 0 anyway
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id >= Results.size() || Results[id]->isFree)
|
|
||||||
{
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid result handle %d", id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SQLResult *Result = Results[id];
|
|
||||||
|
|
||||||
return Result->m_columnCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL sql_field_name(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
unsigned int id = params[1]-1;
|
|
||||||
|
|
||||||
if (id == -1)
|
|
||||||
{
|
|
||||||
//the user should have checked, but we'll return 0 anyway
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id >= Results.size() || Results[id]->isFree)
|
|
||||||
{
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid result handle %d", id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SQLResult *Result = Results[id];
|
|
||||||
|
|
||||||
int field = params[2];
|
|
||||||
|
|
||||||
if (field < 1 || field > (int)Result->m_columnCount)
|
|
||||||
{
|
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid field number %d", field);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MF_SetAmxString(amx, params[3], Result->m_fieldNames[field-1].c_str(), params[4]);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
AMX_NATIVE_INFO mysql_Natives[] = {
|
|
||||||
{ "dbi_connect", sql_connect },
|
|
||||||
{ "dbi_query", sql_query },
|
|
||||||
{ "dbi_field", sql_getfield },
|
|
||||||
{ "dbi_nextrow", sql_nextrow },
|
|
||||||
{ "dbi_close", sql_close },
|
|
||||||
{ "dbi_error", sql_error },
|
|
||||||
{ "dbi_type", sql_type },
|
|
||||||
{ "dbi_free_result", sql_free_result },
|
|
||||||
{ "dbi_num_rows", sql_num_rows },
|
|
||||||
{ "dbi_result", sql_getresult },
|
|
||||||
{ "dbi_num_fields", sql_num_fields },
|
|
||||||
{ "dbi_field_name", sql_field_name },
|
|
||||||
{ NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
void OnAmxxAttach()
|
|
||||||
{
|
|
||||||
SQLResult *Dump = new SQLResult;
|
|
||||||
Dump->isFree = false;
|
|
||||||
Results.push_back(Dump);
|
|
||||||
MF_OverrideNatives(mysql_Natives);
|
|
||||||
MF_AddNatives(mysql_Natives);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnAmxxDetach()
|
|
||||||
{
|
|
||||||
unsigned int i = 0;
|
|
||||||
for (i=0; i<Results.size(); i++)
|
|
||||||
{
|
|
||||||
if (!Results[i]->isFree)
|
|
||||||
Results[i]->FreeResult();
|
|
||||||
delete Results[i];
|
|
||||||
}
|
|
||||||
for (i=0; i<DBList.size(); i++)
|
|
||||||
{
|
|
||||||
DBList[i]->Disconnect();
|
|
||||||
delete DBList[i];
|
|
||||||
}
|
|
||||||
Results.clear();
|
|
||||||
DBList.clear();
|
|
||||||
|
|
||||||
//RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
|
@ -1,270 +0,0 @@
|
|||||||
#include "sqlite_amx.h"
|
|
||||||
|
|
||||||
SQL::SQL()
|
|
||||||
{
|
|
||||||
isFree = true;
|
|
||||||
sqlite = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SQL::~SQL()
|
|
||||||
{
|
|
||||||
if (!isFree)
|
|
||||||
Disconnect();
|
|
||||||
}
|
|
||||||
int SQL::Error()
|
|
||||||
{
|
|
||||||
if (sqlite == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ErrorCode = sqlite3_errcode(sqlite);
|
|
||||||
ErrorStr.assign(sqlite3_errmsg(sqlite));
|
|
||||||
|
|
||||||
return ErrorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SQL::Connect(const char *base)
|
|
||||||
{
|
|
||||||
Database.assign(base);
|
|
||||||
|
|
||||||
isFree = false;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
this->ErrorCode = sqlite3_open(Database.c_str(), &sqlite);
|
|
||||||
if (ErrorCode != SQLITE_OK) {
|
|
||||||
err = Error();
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
MF_Log("DB Connection failed(%d): %s", err, sqlite3_errmsg(sqlite));
|
|
||||||
sqlite3_close(sqlite);
|
|
||||||
isFree = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isFree = false;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQL::Disconnect()
|
|
||||||
{
|
|
||||||
Database.clear();
|
|
||||||
|
|
||||||
if (sqlite != NULL)
|
|
||||||
sqlite3_close(sqlite);
|
|
||||||
|
|
||||||
sqlite = NULL;
|
|
||||||
|
|
||||||
isFree = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SQL::Query(const char *query)
|
|
||||||
{
|
|
||||||
if (sqlite == NULL || isFree)
|
|
||||||
{
|
|
||||||
ErrorCode = -1;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int i = 0;
|
|
||||||
int id = -1;
|
|
||||||
for (i=0; i < Results.size(); i++)
|
|
||||||
{
|
|
||||||
if (Results[i]->isFree) {
|
|
||||||
id = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id < 0) {
|
|
||||||
|
|
||||||
SQLResult *p = new SQLResult;
|
|
||||||
|
|
||||||
int ret = p->Query(this, query);
|
|
||||||
|
|
||||||
if (ret != 0)
|
|
||||||
{
|
|
||||||
delete p;
|
|
||||||
|
|
||||||
if (ret == -1)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
Results.push_back(p);
|
|
||||||
#if defined _DEBUG
|
|
||||||
MF_PrintSrvConsole("***STORE: %d (push_back)\n", Results.size());
|
|
||||||
SQLResult::latestStoredResultId = Results.size();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return Results.size();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SQLResult *r = Results[id];
|
|
||||||
int ret = Results[id]->Query(this, query);
|
|
||||||
if (ret != 0)
|
|
||||||
{
|
|
||||||
if (ret == -1)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
#if defined _DEBUG
|
|
||||||
MF_PrintSrvConsole("***STORE: %d\n", id + 1);
|
|
||||||
SQLResult::latestStoredResultId = id + 1;
|
|
||||||
#endif
|
|
||||||
return (id + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SQLResult::SQLResult()
|
|
||||||
{
|
|
||||||
isFree = true;
|
|
||||||
m_fieldNames = 0;
|
|
||||||
m_hasData = false;
|
|
||||||
m_currentRow = -1;
|
|
||||||
m_data = NULL;
|
|
||||||
m_errorMsg = NULL;
|
|
||||||
m_rowCount = 0;
|
|
||||||
m_columnCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SQLResult::~SQLResult()
|
|
||||||
{
|
|
||||||
if (!isFree)
|
|
||||||
FreeResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
int SQLResult::Query(SQL *cn, const char *query)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
int sqlite3_get_table(
|
|
||||||
sqlite3*, // An open database
|
|
||||||
const char *sql, // SQL to be executed
|
|
||||||
char ***resultp, // Result written to a char *[] that this points to
|
|
||||||
int *nrow, // Number of result rows written here
|
|
||||||
int *ncolumn, // Number of result columns written here
|
|
||||||
char **errmsg // Error msg written here
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
int rowCount, columnCount;
|
|
||||||
int result = sqlite3_get_table(cn->sqlite, query, &m_data, &rowCount, &columnCount, &m_errorMsg);
|
|
||||||
m_rowCount = rowCount;
|
|
||||||
m_columnCount = columnCount;
|
|
||||||
if (result != SQLITE_OK)
|
|
||||||
{
|
|
||||||
MF_Log("Query error: %s", m_errorMsg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!m_rowCount)
|
|
||||||
return -1;
|
|
||||||
m_hasData = true;
|
|
||||||
this->m_fieldNames = new String[m_columnCount];
|
|
||||||
for (unsigned int i = 0; i < m_columnCount; i++)
|
|
||||||
m_fieldNames[i].assign(m_data[i]);
|
|
||||||
|
|
||||||
#if defined _DEBUG
|
|
||||||
MF_PrintSrvConsole("SQLite: Select query returned %d rows in %d columns.\n", m_rowCount, m_columnCount);
|
|
||||||
for (unsigned int i = 0; i < m_columnCount; i++) {
|
|
||||||
MF_PrintSrvConsole("%15s", m_fieldNames[i].c_str());
|
|
||||||
}
|
|
||||||
MF_PrintSrvConsole("\n");
|
|
||||||
for (unsigned int i = 0; i < m_rowCount; i++) {
|
|
||||||
for (unsigned int j = 0; j < m_columnCount; j++) {
|
|
||||||
MF_PrintSrvConsole("%15s", m_data[(1 + i) * m_columnCount + j]);
|
|
||||||
}
|
|
||||||
MF_PrintSrvConsole("\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
isFree = false;
|
|
||||||
return 0; // Return 0 here? and 1 on error... 0's get stored and 1's get deleted
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SQLResult::Nextrow()
|
|
||||||
{
|
|
||||||
if (isFree)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (++m_currentRow >= (int)this->m_rowCount) {
|
|
||||||
//m_currentRow = -1; <-- this is probably bad and inconsistent...
|
|
||||||
//FreeResult(); <-- this is probably bad and inconsistent... freeing should be the responsibility of the scripter
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLResult::FreeResult()
|
|
||||||
{
|
|
||||||
if (isFree)
|
|
||||||
return;
|
|
||||||
/*
|
|
||||||
#if defined _DEBUG
|
|
||||||
MF_PrintSrvConsole("FREEING a result!\n");
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
isFree = true;
|
|
||||||
|
|
||||||
if (m_hasData) {
|
|
||||||
sqlite3_free_table(m_data);
|
|
||||||
|
|
||||||
delete [] this->m_fieldNames;
|
|
||||||
|
|
||||||
m_hasData = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_currentRow = -1;
|
|
||||||
m_columnCount = 0;
|
|
||||||
m_rowCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *SQLResult::GetField(unsigned int field)
|
|
||||||
{
|
|
||||||
if (isFree || field >= m_columnCount || m_currentRow < 0 || m_currentRow >= (int)m_rowCount)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *data = m_data[(m_currentRow + 1) * m_columnCount + field];
|
|
||||||
|
|
||||||
return (data ? data : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *SQLResult::GetField(const char *field)
|
|
||||||
{
|
|
||||||
unsigned int i = 0;
|
|
||||||
int id = -1;
|
|
||||||
if (field == NULL)
|
|
||||||
return NULL;
|
|
||||||
for (i=0; i < m_columnCount; i++)
|
|
||||||
{
|
|
||||||
if (strcmp(m_fieldNames[i].c_str(), field) == 0)
|
|
||||||
{
|
|
||||||
id = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id<0 || id>=(int)m_columnCount)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetField(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int SQLResult::NumRows()
|
|
||||||
{
|
|
||||||
if (isFree)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return m_rowCount;
|
|
||||||
}
|
|
||||||
#if defined _DEBUG
|
|
||||||
unsigned int SQLResult::latestStoredResultId = 0;
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#ifndef __linux__
|
|
||||||
#define WINDOWS_LEAN_AND_MEAN
|
|
||||||
#include <winsock.h>
|
|
||||||
#endif
|
|
||||||
#include "amxxmodule.h"
|
|
||||||
#include "CVector.h"
|
|
||||||
#include "CString.h"
|
|
||||||
#include "sqlite3.h"
|
|
||||||
|
|
||||||
#define MEM_ALLOC_FAILED -20
|
|
||||||
#define CONNECT_FAILED -10
|
|
||||||
#define QUERY_FAILED -5
|
|
||||||
|
|
||||||
class SQL
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SQL();
|
|
||||||
~SQL();
|
|
||||||
int Connect(/*const char *host, const char *user, const char *pass,*/ const char *base);
|
|
||||||
int Query(const char *query);
|
|
||||||
void Disconnect();
|
|
||||||
int Error();
|
|
||||||
|
|
||||||
sqlite3 *sqlite;
|
|
||||||
|
|
||||||
String ErrorStr;
|
|
||||||
int ErrorCode;
|
|
||||||
|
|
||||||
String Database;
|
|
||||||
|
|
||||||
bool isFree;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SQLResult
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SQLResult();
|
|
||||||
~SQLResult();
|
|
||||||
int Query(SQL *cn, const char *query);
|
|
||||||
bool Nextrow();
|
|
||||||
void FreeResult();
|
|
||||||
const char *GetField(unsigned int field);
|
|
||||||
const char *GetField(const char *field);
|
|
||||||
unsigned int NumRows();
|
|
||||||
|
|
||||||
String *m_fieldNames;
|
|
||||||
bool isFree;
|
|
||||||
int m_currentRow;
|
|
||||||
bool m_hasData;
|
|
||||||
|
|
||||||
char **m_data;
|
|
||||||
char *m_errorMsg;
|
|
||||||
unsigned int m_rowCount, m_columnCount;
|
|
||||||
#if defined _DEBUG
|
|
||||||
static unsigned int latestStoredResultId;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
char *amx_string(AMX *amx, cell ¶m, int &len);
|
|
||||||
|
|
||||||
extern CVector<SQLResult*> Results;
|
|
||||||
extern CVector<SQL*> DBList;
|
|
||||||
|
|
54
dlls/sqlite/sqlite_header.h
Normal file
54
dlls/sqlite/sqlite_header.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#ifndef _INCLUDE_AMXMODX_MYSQL2_HEADER_H
|
||||||
|
#define _INCLUDE_AMXMODX_MYSQL2_HEADER_H
|
||||||
|
|
||||||
|
#include "SqliteDriver.h"
|
||||||
|
#include "amxxmodule.h"
|
||||||
|
#include "ThreadSupport.h"
|
||||||
|
#include "ThreadWorker.h"
|
||||||
|
|
||||||
|
#define SQLITE_THREADED
|
||||||
|
|
||||||
|
struct AmxQueryInfo
|
||||||
|
{
|
||||||
|
IQuery *pQuery;
|
||||||
|
QueryInfo info;
|
||||||
|
char error[255];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum HandleType
|
||||||
|
{
|
||||||
|
Handle_Invalid = -1,
|
||||||
|
Handle_Connection = 0,
|
||||||
|
Handle_Database,
|
||||||
|
Handle_Query,
|
||||||
|
Handle_OldDb,
|
||||||
|
Handle_OldResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SQL_Connection
|
||||||
|
{
|
||||||
|
char *host;
|
||||||
|
char *user;
|
||||||
|
char *pass;
|
||||||
|
char *db;
|
||||||
|
int port;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*FREEHANDLE)(void *, unsigned int);
|
||||||
|
|
||||||
|
unsigned int MakeHandle(void *ptr, HandleType type, FREEHANDLE f);
|
||||||
|
void *GetHandle(unsigned int num, HandleType type);
|
||||||
|
bool FreeHandle(unsigned int num);
|
||||||
|
void FreeAllHandles(HandleType type);
|
||||||
|
void FreeHandleTable();
|
||||||
|
void ShutdownThreading();
|
||||||
|
int SetMysqlAffinity(AMX *amx);
|
||||||
|
|
||||||
|
extern AMX_NATIVE_INFO g_BaseSqlNatives[];
|
||||||
|
extern AMX_NATIVE_INFO g_ThreadSqlNatives[];
|
||||||
|
extern AMX_NATIVE_INFO g_OldCompatNatives[];
|
||||||
|
extern MainThreader g_Threader;
|
||||||
|
extern ThreadWorker *g_pWorker;
|
||||||
|
extern SourceMod::SqliteDriver g_Sqlite;
|
||||||
|
|
||||||
|
#endif //_INCLUDE_AMXMODX_MYSQL2_HEADER_H
|
136
dlls/sqlite/sqlitepp/ISQLDriver.h
Normal file
136
dlls/sqlite/sqlitepp/ISQLDriver.h
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#ifndef _INCLUDE_SOURCEMOD_DATABASE2_H
|
||||||
|
#define _INCLUDE_SOURCEMOD_DATABASE2_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
namespace SourceMod
|
||||||
|
{
|
||||||
|
class IResultRow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* This will return NULL if the entry is NULL.
|
||||||
|
* Remember that in SQL, a field can have NULL
|
||||||
|
* entries, which are not the same as 0 or "".
|
||||||
|
*/
|
||||||
|
virtual const char *GetString(unsigned int columnId) =0;
|
||||||
|
virtual double GetDouble(unsigned int columnId) =0;
|
||||||
|
virtual float GetFloat(unsigned int columnId) =0;
|
||||||
|
virtual int GetInt(unsigned int columnId) =0;
|
||||||
|
virtual bool IsNull(unsigned int columnId) =0;
|
||||||
|
/**
|
||||||
|
* NULL can be returned. The length will be zero if so.
|
||||||
|
*/
|
||||||
|
virtual const char *GetRaw(unsigned int columnId, size_t *length) =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IResultSet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//free the handle if necessary (see IQuery).
|
||||||
|
virtual void FreeHandle() =0;
|
||||||
|
public: //Basic stuff
|
||||||
|
virtual unsigned int RowCount() =0;
|
||||||
|
virtual unsigned int FieldCount() =0;
|
||||||
|
virtual const char *FieldNumToName(unsigned int num) =0;
|
||||||
|
virtual bool FieldNameToNum(const char *name, unsigned int *columnId) =0;
|
||||||
|
public: //iteration
|
||||||
|
/**
|
||||||
|
* Returns true if there are no more handles left.
|
||||||
|
*/
|
||||||
|
virtual bool IsDone() =0;
|
||||||
|
/**
|
||||||
|
* Returns the current row. If "IsDone()" is false
|
||||||
|
* this is guaranteed to return non-NULL.
|
||||||
|
* Handles to IResultRow are guaranteed to not leak
|
||||||
|
* (you don't need to free them), however,
|
||||||
|
* they should be considered volatile - don't cache
|
||||||
|
* them.
|
||||||
|
*/
|
||||||
|
virtual IResultRow *GetRow() =0;
|
||||||
|
/**
|
||||||
|
* Advances to the next row. Note that you need to
|
||||||
|
* call IsDone() after each call to NextRow().
|
||||||
|
*/
|
||||||
|
virtual void NextRow() =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueryInfo
|
||||||
|
{
|
||||||
|
IResultSet *rs;
|
||||||
|
unsigned long long affected_rows;
|
||||||
|
int errorcode;
|
||||||
|
bool success;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IQuery
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//you must free the handle when done
|
||||||
|
virtual void FreeHandle() =0;
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Executes the query. Specify optional error string buffer.
|
||||||
|
* If "info" is NULL, no results will be stored.
|
||||||
|
* Returns false on failure.
|
||||||
|
* Calling Execute() multiple times will cause each result handle
|
||||||
|
* to be freed in succession. That means that you do not need to
|
||||||
|
* explicitly free IResultSets when using Execute(), but their
|
||||||
|
* handles are deep-invalidated on succesive calls, and
|
||||||
|
* thus Execute() is also not thread safe.
|
||||||
|
*/
|
||||||
|
virtual bool Execute(QueryInfo *info, char *error, size_t maxlength) =0;
|
||||||
|
/**
|
||||||
|
* Same as above, except result handles are not freed for you.
|
||||||
|
*/
|
||||||
|
virtual bool ExecuteR(QueryInfo *info, char *error, size_t maxlength) =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ISQLDriver;
|
||||||
|
|
||||||
|
class IDatabase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Closes the database and frees the handle.
|
||||||
|
*/
|
||||||
|
virtual void FreeHandle() =0;
|
||||||
|
/**
|
||||||
|
* Returns the parent driver.
|
||||||
|
*/
|
||||||
|
virtual ISQLDriver *Driver() =0;
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Query preparation.
|
||||||
|
*/
|
||||||
|
virtual IQuery *PrepareQueryFmt(const char *fmt, ...) =0;
|
||||||
|
virtual IQuery *PrepareQueryFmt(const char *fmt, va_list ap) =0;
|
||||||
|
virtual IQuery *PrepareQuery(const char *query) =0;
|
||||||
|
/**
|
||||||
|
* Quotes a string properly.
|
||||||
|
* Returns 0 on success. On failure, returns
|
||||||
|
* the size of the buffer needed, or a negative number
|
||||||
|
* on internal failure.
|
||||||
|
*/
|
||||||
|
virtual int QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newsize) =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DatabaseInfo
|
||||||
|
{
|
||||||
|
const char *host;
|
||||||
|
const char *database;
|
||||||
|
const char *user;
|
||||||
|
const char *pass;
|
||||||
|
unsigned int port;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ISQLDriver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual IDatabase *Connect(DatabaseInfo *info, int *errcode, char *error, size_t maxlength) =0;
|
||||||
|
virtual const char *NameString() =0;
|
||||||
|
virtual bool IsCompatDriver(const char *namestring) =0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_DATABASE2_H
|
80
dlls/sqlite/sqlitepp/SqliteDatabase.cpp
Normal file
80
dlls/sqlite/sqlitepp/SqliteDatabase.cpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "SqliteDriver.h"
|
||||||
|
#include "SqliteDatabase.h"
|
||||||
|
#include "SqliteQuery.h"
|
||||||
|
|
||||||
|
#if defined WIN32 && !defined vsnprintf
|
||||||
|
#define vsnprintf _vsnprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
SqliteDatabase::SqliteDatabase(sqlite3 *sql, SqliteDriver *drvr) :
|
||||||
|
m_pSql(sql), m_pParent(drvr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SqliteDatabase::~SqliteDatabase()
|
||||||
|
{
|
||||||
|
Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SqliteDatabase::Disconnect()
|
||||||
|
{
|
||||||
|
if (m_pSql)
|
||||||
|
{
|
||||||
|
sqlite3_close(m_pSql);
|
||||||
|
m_pSql = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SqliteDatabase::FreeHandle()
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ISQLDriver *SqliteDatabase::Driver()
|
||||||
|
{
|
||||||
|
return static_cast<ISQLDriver *>(m_pParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
IQuery *SqliteDatabase::PrepareQuery(const char *query)
|
||||||
|
{
|
||||||
|
SqliteQuery *pQuery = new SqliteQuery(this, query);
|
||||||
|
return static_cast<IQuery *>(pQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
IQuery *SqliteDatabase::PrepareQueryFmt(const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
char buffer[4096];
|
||||||
|
|
||||||
|
vsnprintf(buffer, sizeof(buffer)-1, fmt, ap);
|
||||||
|
|
||||||
|
return PrepareQuery(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
IQuery *SqliteDatabase::PrepareQueryFmt(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
IQuery *qry;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
qry = PrepareQueryFmt(fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return qry;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SqliteDatabase::QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newsize)
|
||||||
|
{
|
||||||
|
unsigned long size = static_cast<unsigned long>(strlen(str));
|
||||||
|
unsigned long needed = size*2 + 1;
|
||||||
|
|
||||||
|
if (size < needed)
|
||||||
|
return (int)needed;
|
||||||
|
|
||||||
|
sqlite3_snprintf(static_cast<int>(maxlen), buffer, "%q", str);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
34
dlls/sqlite/sqlitepp/SqliteDatabase.h
Normal file
34
dlls/sqlite/sqlitepp/SqliteDatabase.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef _INCLUDE_SOURCEMOD_SQLITE_DATABASE_H
|
||||||
|
#define _INCLUDE_SOURCEMOD_SQLITE_DATABASE_H
|
||||||
|
|
||||||
|
#include "SqliteHeaders.h"
|
||||||
|
#include "SqliteDriver.h"
|
||||||
|
|
||||||
|
namespace SourceMod
|
||||||
|
{
|
||||||
|
class SqliteDriver;
|
||||||
|
|
||||||
|
class SqliteDatabase : public IDatabase
|
||||||
|
{
|
||||||
|
friend class SqliteQuery;
|
||||||
|
public:
|
||||||
|
SqliteDatabase(sqlite3 *sql, SqliteDriver *drvr);
|
||||||
|
~SqliteDatabase();
|
||||||
|
public:
|
||||||
|
void FreeHandle();
|
||||||
|
ISQLDriver *Driver();
|
||||||
|
public:
|
||||||
|
IQuery *PrepareQueryFmt(const char *fmt, ...);
|
||||||
|
IQuery *PrepareQueryFmt(const char *fmt, va_list ap);
|
||||||
|
IQuery *PrepareQuery(const char *query);
|
||||||
|
int QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newsize);
|
||||||
|
private:
|
||||||
|
void Disconnect();
|
||||||
|
private:
|
||||||
|
sqlite3 *m_pSql;
|
||||||
|
SqliteDriver *m_pParent;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_SQLITE_DATABASE_H
|
||||||
|
|
44
dlls/sqlite/sqlitepp/SqliteDriver.cpp
Normal file
44
dlls/sqlite/sqlitepp/SqliteDriver.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "SqliteHeaders.h"
|
||||||
|
#include "SqliteDriver.h"
|
||||||
|
#include "SqliteDatabase.h"
|
||||||
|
|
||||||
|
#if defined WIN32
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#define strncasecmp strnicmp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
bool SqliteDriver::IsCompatDriver(const char *namestr)
|
||||||
|
{
|
||||||
|
return (strncasecmp(namestr, "sqlite", 5) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SqliteDriver::NameString()
|
||||||
|
{
|
||||||
|
return "sqlite";
|
||||||
|
}
|
||||||
|
|
||||||
|
IDatabase *SqliteDriver::Connect(DatabaseInfo *info, int *errcode, char *error, size_t maxlength)
|
||||||
|
{
|
||||||
|
sqlite3 *pSql;
|
||||||
|
int err = sqlite3_open(info->database, &pSql);
|
||||||
|
if (err != SQLITE_OK)
|
||||||
|
{
|
||||||
|
if (errcode)
|
||||||
|
{
|
||||||
|
*errcode = sqlite3_errcode(pSql);
|
||||||
|
}
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
snprintf(error, maxlength, "%s", sqlite3_errmsg(pSql));
|
||||||
|
}
|
||||||
|
sqlite3_close(pSql);
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
SqliteDatabase *pDb = new SqliteDatabase(pSql, this);
|
||||||
|
return static_cast<IDatabase *>(pDb);
|
||||||
|
}
|
||||||
|
}
|
17
dlls/sqlite/sqlitepp/SqliteDriver.h
Normal file
17
dlls/sqlite/sqlitepp/SqliteDriver.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef _INCLUDE_SOURCEMOD_SQLITE_DRIVER_H
|
||||||
|
#define _INCLUDE_SOURCEMOD_SQLITE_DRIVER_H
|
||||||
|
|
||||||
|
#include "SqliteHeaders.h"
|
||||||
|
|
||||||
|
namespace SourceMod
|
||||||
|
{
|
||||||
|
class SqliteDriver : public ISQLDriver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IDatabase *Connect(DatabaseInfo *info, int *errcode, char *error, size_t maxlength);
|
||||||
|
const char *NameString();
|
||||||
|
bool IsCompatDriver(const char *namestr);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_SQLITE_DRIVER_H
|
17
dlls/sqlite/sqlitepp/SqliteHeaders.h
Normal file
17
dlls/sqlite/sqlitepp/SqliteHeaders.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef _INCLUDE_SOURCEMOD_SQLITE_HEADERS_H
|
||||||
|
#define _INCLUDE_SOURCEMOD_SQLITE_HEADERS_H
|
||||||
|
|
||||||
|
#if _MSC_VER >= 1400
|
||||||
|
/* disable deprecation warnings */
|
||||||
|
#if !defined _CRT_SECURE_NO_DEPRECATE
|
||||||
|
#define _CRT_SECURE_NO_DEPRECATE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma warning (disable:4996)
|
||||||
|
#endif //_MSC_VER >= 1400
|
||||||
|
|
||||||
|
#include <ISQLDriver.h>
|
||||||
|
|
||||||
|
#include "sqlite3.h"
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_SQLITE_HEADERS_H
|
93
dlls/sqlite/sqlitepp/SqliteQuery.cpp
Normal file
93
dlls/sqlite/sqlitepp/SqliteQuery.cpp
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "SqliteQuery.h"
|
||||||
|
#include "SqliteDatabase.h"
|
||||||
|
#include "SqliteResultSet.h"
|
||||||
|
|
||||||
|
#if defined WIN32
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
SqliteQuery::SqliteQuery(SqliteDatabase *db, const char *query) :
|
||||||
|
m_pDatabase(db), m_LastRes(NULL)
|
||||||
|
{
|
||||||
|
m_QueryString = new char[strlen(query)+1];
|
||||||
|
strcpy(m_QueryString, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
SqliteQuery::~SqliteQuery()
|
||||||
|
{
|
||||||
|
if (m_LastRes)
|
||||||
|
{
|
||||||
|
m_LastRes->FreeHandle();
|
||||||
|
m_LastRes = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] m_QueryString;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SqliteQuery::FreeHandle()
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqliteQuery::Execute(QueryInfo *info, char *error, size_t maxlength)
|
||||||
|
{
|
||||||
|
bool res = ExecuteR(info, error, maxlength);
|
||||||
|
|
||||||
|
if (m_LastRes)
|
||||||
|
{
|
||||||
|
m_LastRes->FreeHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_LastRes = (SqliteResultSet *)info->rs;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqliteQuery::ExecuteR(QueryInfo *info, char *error, size_t maxlength)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
char *errmsg;
|
||||||
|
char **results;
|
||||||
|
int rows, cols;
|
||||||
|
|
||||||
|
err = sqlite3_get_table(m_pDatabase->m_pSql, m_QueryString, &results, &rows, &cols, &errmsg);
|
||||||
|
|
||||||
|
if (err != SQLITE_OK)
|
||||||
|
{
|
||||||
|
if (error && maxlength && errmsg)
|
||||||
|
{
|
||||||
|
snprintf(error, maxlength, "%s", errmsg);
|
||||||
|
}
|
||||||
|
info->affected_rows = 0;
|
||||||
|
info->errorcode = err;
|
||||||
|
info->rs = NULL;
|
||||||
|
info->success = false;
|
||||||
|
} else {
|
||||||
|
info->affected_rows = sqlite3_changes(m_pDatabase->m_pSql);
|
||||||
|
info->errorcode = 0;
|
||||||
|
info->success = true;
|
||||||
|
if (cols)
|
||||||
|
{
|
||||||
|
SqliteResults data;
|
||||||
|
data.cols = cols;
|
||||||
|
data.rows = rows;
|
||||||
|
data.results = results;
|
||||||
|
|
||||||
|
SqliteResultSet *pRes = new SqliteResultSet(data);
|
||||||
|
m_LastRes = pRes;
|
||||||
|
info->rs = static_cast<IResultSet *>(pRes);
|
||||||
|
} else {
|
||||||
|
info->rs = NULL;
|
||||||
|
if (results)
|
||||||
|
{
|
||||||
|
sqlite3_free_table(results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return info->success;
|
||||||
|
}
|
34
dlls/sqlite/sqlitepp/SqliteQuery.h
Normal file
34
dlls/sqlite/sqlitepp/SqliteQuery.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef _INCLUDE_SOURCEMOD_SQLITE_QUERY_H
|
||||||
|
#define _INCLUDE_SOURCEMOD_SQLITE_QUERY_H
|
||||||
|
|
||||||
|
#include "SqliteHeaders.h"
|
||||||
|
|
||||||
|
namespace SourceMod
|
||||||
|
{
|
||||||
|
class SqliteDatabase;;
|
||||||
|
class SqliteResultSet;
|
||||||
|
|
||||||
|
class SqliteQuery : public IQuery
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct SqliteResults
|
||||||
|
{
|
||||||
|
char **results;
|
||||||
|
int rows;
|
||||||
|
int cols;
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
SqliteQuery(SqliteDatabase *db, const char *query);
|
||||||
|
~SqliteQuery();
|
||||||
|
public:
|
||||||
|
void FreeHandle();
|
||||||
|
bool Execute(QueryInfo *info, char *error, size_t maxlength);
|
||||||
|
bool ExecuteR(QueryInfo *info, char *error, size_t maxlength);
|
||||||
|
private:
|
||||||
|
SqliteDatabase *m_pDatabase;
|
||||||
|
SqliteResultSet *m_LastRes;
|
||||||
|
char *m_QueryString;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_SQLITE_QUERY_H
|
160
dlls/sqlite/sqlitepp/SqliteResultSet.cpp
Normal file
160
dlls/sqlite/sqlitepp/SqliteResultSet.cpp
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "SqliteResultSet.h"
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
SqliteResultSet::SqliteResultSet(SqliteQuery::SqliteResults &res)
|
||||||
|
{
|
||||||
|
m_pResults = res.results;
|
||||||
|
m_Columns = res.cols;
|
||||||
|
m_Rows = res.rows;
|
||||||
|
|
||||||
|
m_CurRow = 1;
|
||||||
|
m_CurIndex = (m_CurRow * m_Columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
SqliteResultSet::~SqliteResultSet()
|
||||||
|
{
|
||||||
|
if (m_pResults)
|
||||||
|
{
|
||||||
|
sqlite3_free_table(m_pResults);
|
||||||
|
m_pResults = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SqliteResultSet::GetStringSafe(unsigned int columnId)
|
||||||
|
{
|
||||||
|
if (columnId > m_Columns)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *data = m_pResults[m_CurIndex + columnId];
|
||||||
|
|
||||||
|
return data ? data : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SqliteResultSet::GetString(unsigned int columnId)
|
||||||
|
{
|
||||||
|
if (columnId > m_Columns)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_pResults[m_CurIndex + columnId];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqliteResultSet::IsNull(unsigned int columnId)
|
||||||
|
{
|
||||||
|
return (GetString(columnId) == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
double SqliteResultSet::GetDouble(unsigned int columnId)
|
||||||
|
{
|
||||||
|
return atof(GetStringSafe(columnId));
|
||||||
|
}
|
||||||
|
|
||||||
|
float SqliteResultSet::GetFloat(unsigned int columnId)
|
||||||
|
{
|
||||||
|
return (float)atof(GetStringSafe(columnId));
|
||||||
|
}
|
||||||
|
|
||||||
|
int SqliteResultSet::GetInt(unsigned int columnId)
|
||||||
|
{
|
||||||
|
return atoi(GetStringSafe(columnId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* :TODO: - convert this whole beast to sqlite3_prepare/step
|
||||||
|
* that way we get finer control and actual raw/null data.
|
||||||
|
*/
|
||||||
|
const char *SqliteResultSet::GetRaw(unsigned int columnId, size_t *length)
|
||||||
|
{
|
||||||
|
if (columnId >= m_Columns)
|
||||||
|
{
|
||||||
|
if (length)
|
||||||
|
{
|
||||||
|
*length = 0;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *str = GetString(columnId);
|
||||||
|
if (!str)
|
||||||
|
{
|
||||||
|
if (length)
|
||||||
|
{
|
||||||
|
*length = 0;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
if (length)
|
||||||
|
{
|
||||||
|
*length = strlen(str);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SqliteResultSet::FreeHandle()
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
IResultRow *SqliteResultSet::GetRow()
|
||||||
|
{
|
||||||
|
return static_cast<IResultRow *>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int SqliteResultSet::RowCount()
|
||||||
|
{
|
||||||
|
return m_Rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SqliteResultSet::FieldNumToName(unsigned int num)
|
||||||
|
{
|
||||||
|
if (num >= m_Columns)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_pResults[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqliteResultSet::FieldNameToNum(const char *name, unsigned int *columnId)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i<m_Columns; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(m_pResults[i], name) == 0)
|
||||||
|
{
|
||||||
|
if (columnId)
|
||||||
|
{
|
||||||
|
*columnId = i;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (columnId)
|
||||||
|
{
|
||||||
|
*columnId = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int SqliteResultSet::FieldCount()
|
||||||
|
{
|
||||||
|
return m_Columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqliteResultSet::IsDone()
|
||||||
|
{
|
||||||
|
return (m_CurRow > m_Rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SqliteResultSet::NextRow()
|
||||||
|
{
|
||||||
|
m_CurIndex = (++m_CurRow * m_Columns);
|
||||||
|
}
|
53
dlls/sqlite/sqlitepp/SqliteResultSet.h
Normal file
53
dlls/sqlite/sqlitepp/SqliteResultSet.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#ifndef _INCLUDE_SOURCEMOD_SQLITE_RESULTSET_H
|
||||||
|
#define _INCLUDE_SOURCEMOD_SQLITE_RESULTSET_H
|
||||||
|
|
||||||
|
#include "SqliteHeaders.h"
|
||||||
|
#include "SqliteDriver.h"
|
||||||
|
#include "SqliteDatabase.h"
|
||||||
|
#include "SqliteQuery.h"
|
||||||
|
|
||||||
|
namespace SourceMod
|
||||||
|
{
|
||||||
|
class SqliteResultSet : public IResultSet, public IResultRow
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* IResultSet
|
||||||
|
*/
|
||||||
|
public:
|
||||||
|
SqliteResultSet(SqliteQuery::SqliteResults &res);
|
||||||
|
~SqliteResultSet();
|
||||||
|
public:
|
||||||
|
void FreeHandle();
|
||||||
|
public:
|
||||||
|
unsigned int RowCount();
|
||||||
|
unsigned int FieldCount();
|
||||||
|
const char *FieldNumToName(unsigned int num);
|
||||||
|
bool FieldNameToNum(const char *name, unsigned int *columnId);
|
||||||
|
public:
|
||||||
|
bool IsDone();
|
||||||
|
IResultRow *GetRow();
|
||||||
|
void NextRow();
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* IResultRow
|
||||||
|
*/
|
||||||
|
public:
|
||||||
|
const char *GetString(unsigned int columnId);
|
||||||
|
double GetDouble(unsigned int columnId);
|
||||||
|
float GetFloat(unsigned int columnId);
|
||||||
|
int GetInt(unsigned int columnId);
|
||||||
|
bool IsNull(unsigned int columnId);
|
||||||
|
const char *GetRaw(unsigned int columnId, size_t *length);
|
||||||
|
private:
|
||||||
|
const char *GetStringSafe(unsigned int columnId);
|
||||||
|
private:
|
||||||
|
char **m_pResults;
|
||||||
|
unsigned int m_Columns;
|
||||||
|
unsigned int m_Rows;
|
||||||
|
unsigned int m_CurRow;
|
||||||
|
unsigned int m_CurIndex;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_SQLITE_RESULTSET_H
|
249
dlls/sqlite/thread/BaseWorker.cpp
Normal file
249
dlls/sqlite/thread/BaseWorker.cpp
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
#include "BaseWorker.h"
|
||||||
|
|
||||||
|
BaseWorker::BaseWorker() :
|
||||||
|
m_perFrame(SM_DEFAULT_THREADS_PER_FRAME),
|
||||||
|
m_state(Worker_Stopped)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseWorker::~BaseWorker()
|
||||||
|
{
|
||||||
|
if (m_state != Worker_Stopped || m_state != Worker_Invalid)
|
||||||
|
Stop(true);
|
||||||
|
|
||||||
|
if (m_ThreadQueue.size())
|
||||||
|
Flush(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseWorker::MakeThread(IThread *pThread)
|
||||||
|
{
|
||||||
|
ThreadParams pt;
|
||||||
|
|
||||||
|
pt.flags = Thread_AutoRelease;
|
||||||
|
pt.prio = ThreadPrio_Normal;
|
||||||
|
|
||||||
|
MakeThread(pThread, &pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
IThreadHandle *BaseWorker::MakeThread(IThread *pThread, ThreadFlags flags)
|
||||||
|
{
|
||||||
|
ThreadParams pt;
|
||||||
|
|
||||||
|
pt.flags = flags;
|
||||||
|
pt.prio = ThreadPrio_Normal;
|
||||||
|
|
||||||
|
return MakeThread(pThread, &pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
IThreadHandle *BaseWorker::MakeThread(IThread *pThread, const ThreadParams *params)
|
||||||
|
{
|
||||||
|
if (m_state != Worker_Running)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
SWThreadHandle *swt = new SWThreadHandle(this, params, pThread);
|
||||||
|
|
||||||
|
AddThreadToQueue(swt);
|
||||||
|
|
||||||
|
return swt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseWorker::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min)
|
||||||
|
{
|
||||||
|
max = ThreadPrio_Normal;
|
||||||
|
min = ThreadPrio_Normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int BaseWorker::Flush(bool flush_cancel)
|
||||||
|
{
|
||||||
|
SWThreadHandle *swt;
|
||||||
|
unsigned int num = 0;
|
||||||
|
|
||||||
|
while ((swt=PopThreadFromQueue()) != NULL)
|
||||||
|
{
|
||||||
|
swt->m_state = Thread_Done;
|
||||||
|
if (!flush_cancel)
|
||||||
|
swt->pThread->RunThread(swt);
|
||||||
|
swt->pThread->OnTerminate(swt, flush_cancel);
|
||||||
|
if (swt->m_params.flags & Thread_AutoRelease)
|
||||||
|
delete swt;
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWThreadHandle *BaseWorker::PopThreadFromQueue()
|
||||||
|
{
|
||||||
|
if (!m_ThreadQueue.size())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
SourceHook::List<SWThreadHandle *>::iterator begin;
|
||||||
|
SWThreadHandle *swt;
|
||||||
|
|
||||||
|
begin = m_ThreadQueue.begin();
|
||||||
|
swt = (*begin);
|
||||||
|
m_ThreadQueue.erase(begin);
|
||||||
|
|
||||||
|
return swt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseWorker::AddThreadToQueue(SWThreadHandle *pHandle)
|
||||||
|
{
|
||||||
|
m_ThreadQueue.push_back(pHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int BaseWorker::GetMaxThreadsPerFrame()
|
||||||
|
{
|
||||||
|
return m_perFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkerState BaseWorker::GetStatus(unsigned int *threads)
|
||||||
|
{
|
||||||
|
if (threads)
|
||||||
|
*threads = m_perFrame;
|
||||||
|
|
||||||
|
return m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int BaseWorker::RunFrame()
|
||||||
|
{
|
||||||
|
unsigned int done = 0;
|
||||||
|
unsigned int max = GetMaxThreadsPerFrame();
|
||||||
|
SWThreadHandle *swt = NULL;
|
||||||
|
IThread *pThread = NULL;
|
||||||
|
|
||||||
|
while (done < max)
|
||||||
|
{
|
||||||
|
if ((swt=PopThreadFromQueue()) == NULL)
|
||||||
|
break;
|
||||||
|
pThread = swt->pThread;
|
||||||
|
swt->m_state = Thread_Running;
|
||||||
|
pThread->RunThread(swt);
|
||||||
|
swt->m_state = Thread_Done;
|
||||||
|
pThread->OnTerminate(swt, false);
|
||||||
|
if (swt->m_params.flags & Thread_AutoRelease)
|
||||||
|
delete swt;
|
||||||
|
done++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseWorker::SetMaxThreadsPerFrame(unsigned int threads)
|
||||||
|
{
|
||||||
|
m_perFrame = threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseWorker::Start()
|
||||||
|
{
|
||||||
|
if (m_state != Worker_Invalid && m_state != Worker_Stopped)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_state = Worker_Running;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseWorker::Stop(bool flush_cancel)
|
||||||
|
{
|
||||||
|
if (m_state == Worker_Invalid || m_state == Worker_Stopped)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (m_state == Worker_Paused)
|
||||||
|
{
|
||||||
|
if (!Unpause())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_state = Worker_Stopped;
|
||||||
|
Flush(flush_cancel);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseWorker::Pause()
|
||||||
|
{
|
||||||
|
if (m_state != Worker_Running)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_state = Worker_Paused;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool BaseWorker::Unpause()
|
||||||
|
{
|
||||||
|
if (m_state != Worker_Paused)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_state = Worker_Running;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
* THREAD HANDLE STUFF *
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
void SWThreadHandle::DestroyThis()
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SWThreadHandle::GetParams(ThreadParams *p)
|
||||||
|
{
|
||||||
|
*p = m_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadPriority SWThreadHandle::GetPriority()
|
||||||
|
{
|
||||||
|
return m_params.prio;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadState SWThreadHandle::GetState()
|
||||||
|
{
|
||||||
|
return m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
IThreadCreator *SWThreadHandle::Parent()
|
||||||
|
{
|
||||||
|
return m_parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SWThreadHandle::SetPriority(ThreadPriority prio)
|
||||||
|
{
|
||||||
|
if (m_params.prio != ThreadPrio_Normal)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_params.prio = prio;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SWThreadHandle::Unpause()
|
||||||
|
{
|
||||||
|
if (m_state != Thread_Paused)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_state = Thread_Running;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SWThreadHandle::WaitForThread()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWThreadHandle::SWThreadHandle(IThreadCreator *parent, const ThreadParams *p, IThread *thread) :
|
||||||
|
m_parent(parent), m_params(*p), pThread(thread), m_state(Thread_Paused)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IThread *SWThreadHandle::GetThread()
|
||||||
|
{
|
||||||
|
return pThread;
|
||||||
|
}
|
72
dlls/sqlite/thread/BaseWorker.h
Normal file
72
dlls/sqlite/thread/BaseWorker.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#ifndef _INCLUDE_SOURCEMOD_BASEWORKER_H
|
||||||
|
#define _INCLUDE_SOURCEMOD_BASEWORKER_H
|
||||||
|
|
||||||
|
#include "sh_list.h"
|
||||||
|
#include "ThreadSupport.h"
|
||||||
|
|
||||||
|
#define SM_DEFAULT_THREADS_PER_FRAME 1
|
||||||
|
|
||||||
|
class BaseWorker;
|
||||||
|
|
||||||
|
//SW = Simple Wrapper
|
||||||
|
class SWThreadHandle : public IThreadHandle
|
||||||
|
{
|
||||||
|
friend class BaseWorker;
|
||||||
|
public:
|
||||||
|
SWThreadHandle(IThreadCreator *parent, const ThreadParams *p, IThread *thread);
|
||||||
|
IThread *GetThread();
|
||||||
|
public:
|
||||||
|
//NOTE: We don't support this by default.
|
||||||
|
//It's specific usage that'd require many mutexes
|
||||||
|
virtual bool WaitForThread();
|
||||||
|
public:
|
||||||
|
virtual void DestroyThis();
|
||||||
|
virtual IThreadCreator *Parent();
|
||||||
|
virtual void GetParams(ThreadParams *ptparams);
|
||||||
|
public:
|
||||||
|
//Priorities not supported by default.
|
||||||
|
virtual ThreadPriority GetPriority();
|
||||||
|
virtual bool SetPriority(ThreadPriority prio);
|
||||||
|
public:
|
||||||
|
virtual ThreadState GetState();
|
||||||
|
virtual bool Unpause();
|
||||||
|
private:
|
||||||
|
ThreadState m_state;
|
||||||
|
ThreadParams m_params;
|
||||||
|
IThreadCreator *m_parent;
|
||||||
|
IThread *pThread;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BaseWorker : public IWorker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BaseWorker();
|
||||||
|
virtual ~BaseWorker();
|
||||||
|
public: //IWorker
|
||||||
|
virtual unsigned int RunFrame();
|
||||||
|
//Controls the worker
|
||||||
|
virtual bool Pause();
|
||||||
|
virtual bool Unpause();
|
||||||
|
virtual bool Start();
|
||||||
|
virtual bool Stop(bool flush_cancel);
|
||||||
|
//Flushes out any remaining threads
|
||||||
|
virtual unsigned int Flush(bool flush_cancel);
|
||||||
|
//returns status and number of threads in queue
|
||||||
|
virtual WorkerState GetStatus(unsigned int *numThreads);
|
||||||
|
public: //IThreadCreator
|
||||||
|
virtual void MakeThread(IThread *pThread);
|
||||||
|
virtual IThreadHandle *MakeThread(IThread *pThread, ThreadFlags flags);
|
||||||
|
virtual IThreadHandle *MakeThread(IThread *pThread, const ThreadParams *params);
|
||||||
|
virtual void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min);
|
||||||
|
public: //BaseWorker
|
||||||
|
virtual void AddThreadToQueue(SWThreadHandle *pHandle);
|
||||||
|
virtual SWThreadHandle *PopThreadFromQueue();
|
||||||
|
virtual void SetMaxThreadsPerFrame(unsigned int threads);
|
||||||
|
virtual unsigned int GetMaxThreadsPerFrame();
|
||||||
|
protected:
|
||||||
|
SourceHook::List<SWThreadHandle *> m_ThreadQueue;
|
||||||
|
unsigned int m_perFrame;
|
||||||
|
volatile WorkerState m_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_BASEWORKER_H
|
222
dlls/sqlite/thread/IThreader.h
Normal file
222
dlls/sqlite/thread/IThreader.h
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
#ifndef _INCLUDE_SOURCEMOD_THREADER_H
|
||||||
|
#define _INCLUDE_SOURCEMOD_THREADER_H
|
||||||
|
|
||||||
|
namespace SourceMod
|
||||||
|
{
|
||||||
|
enum ThreadFlags
|
||||||
|
{
|
||||||
|
Thread_Default = 0,
|
||||||
|
//auto release handle on finish
|
||||||
|
//you are not guaranteed the handle for this is valid after
|
||||||
|
// calling MakeThread(), so never use it until OnTerminate is called.
|
||||||
|
Thread_AutoRelease = 1,
|
||||||
|
//Thread is created "suspended", meaning
|
||||||
|
// it is inactive until unpaused.
|
||||||
|
Thread_CreateSuspended = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ThreadPriority
|
||||||
|
{
|
||||||
|
ThreadPrio_Minimum = -8,
|
||||||
|
ThreadPrio_Low = -3,
|
||||||
|
ThreadPrio_Normal = 0,
|
||||||
|
ThreadPrio_High = 3,
|
||||||
|
ThreadPrio_Maximum = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ThreadState
|
||||||
|
{
|
||||||
|
Thread_Running = 0,
|
||||||
|
Thread_Paused = 1,
|
||||||
|
Thread_Done = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ThreadParams
|
||||||
|
{
|
||||||
|
ThreadParams() :
|
||||||
|
flags(Thread_Default),
|
||||||
|
prio(ThreadPrio_Normal)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
ThreadFlags flags;
|
||||||
|
ThreadPriority prio;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IThreadCreator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes a handle to a thread
|
||||||
|
*/
|
||||||
|
class IThreadHandle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IThreadHandle() { };
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Pauses parent thread until this thread completes.
|
||||||
|
*/
|
||||||
|
virtual bool WaitForThread() =0;
|
||||||
|
/**
|
||||||
|
* Destroys the thread handle.
|
||||||
|
* This will not necessarily cancel the thread.
|
||||||
|
*/
|
||||||
|
virtual void DestroyThis() =0;
|
||||||
|
/**
|
||||||
|
* Returns the parent threader.
|
||||||
|
*/
|
||||||
|
virtual IThreadCreator *Parent() =0;
|
||||||
|
/**
|
||||||
|
* Returns the thread states.
|
||||||
|
*/
|
||||||
|
virtual void GetParams(ThreadParams *ptparams) =0;
|
||||||
|
/**
|
||||||
|
* Returns priority
|
||||||
|
*/
|
||||||
|
virtual ThreadPriority GetPriority() =0;
|
||||||
|
/**
|
||||||
|
* Sets thread priority
|
||||||
|
*/
|
||||||
|
virtual bool SetPriority(ThreadPriority prio) =0;
|
||||||
|
/**
|
||||||
|
* Gets thread state
|
||||||
|
*/
|
||||||
|
virtual ThreadState GetState() =0;
|
||||||
|
/**
|
||||||
|
* Attempts to unpause a paused thread.
|
||||||
|
*/
|
||||||
|
virtual bool Unpause() =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes a single unit of execution/context flow
|
||||||
|
*/
|
||||||
|
class IThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//Called when the thread runs
|
||||||
|
virtual void RunThread(IThreadHandle *pHandle) =0;
|
||||||
|
//Called when the thread terminates.
|
||||||
|
//"Cancel" is true if the thread did not finish
|
||||||
|
//(this could mean suspended or terminated abruptly)
|
||||||
|
virtual void OnTerminate(IThreadHandle *pHandle, bool cancel) =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes a thread creator
|
||||||
|
*/
|
||||||
|
class IThreadCreator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//Makes a thread and cleans up the handle for you
|
||||||
|
virtual void MakeThread(IThread *pThread) =0;
|
||||||
|
//Makes a thread with flag specified
|
||||||
|
virtual IThreadHandle *MakeThread(IThread *pThread, ThreadFlags flags) =0;
|
||||||
|
//Makes a thread, full options can be specified
|
||||||
|
virtual IThreadHandle *MakeThread(IThread *pThread, const ThreadParams *params) =0;
|
||||||
|
//Return priority bounds
|
||||||
|
virtual void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min) =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic Mutex
|
||||||
|
*/
|
||||||
|
class IMutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IMutex() { };
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Attempts to lock, but returns instantly.
|
||||||
|
*/
|
||||||
|
virtual bool TryLock() =0;
|
||||||
|
/**
|
||||||
|
* Attempts to lock by waiting for release.
|
||||||
|
*/
|
||||||
|
virtual void Lock() =0;
|
||||||
|
/**
|
||||||
|
* Unlocks mutex.
|
||||||
|
*/
|
||||||
|
virtual void Unlock() =0;
|
||||||
|
/**
|
||||||
|
* Frees the mutex handle.
|
||||||
|
*/
|
||||||
|
virtual void DestroyThis() =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class IEventSignal
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Waits for the signal.
|
||||||
|
*/
|
||||||
|
virtual void Wait() =0;
|
||||||
|
/**
|
||||||
|
* Triggers the signal.
|
||||||
|
* Resets the signals after triggering.
|
||||||
|
*/
|
||||||
|
virtual void Signal() =0;
|
||||||
|
/**
|
||||||
|
* Frees the signal handle.
|
||||||
|
*/
|
||||||
|
virtual void DestroyThis() =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes a threading system
|
||||||
|
*/
|
||||||
|
class IThreader : public IThreadCreator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual IMutex *MakeMutex() =0;
|
||||||
|
virtual void MakeThread(IThread *pThread) =0;
|
||||||
|
virtual IThreadHandle *MakeThread(IThread *pThread, ThreadFlags flags) =0;
|
||||||
|
virtual IThreadHandle *MakeThread(IThread *pThread, const ThreadParams *params) =0;
|
||||||
|
virtual void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min) =0;
|
||||||
|
virtual void ThreadSleep(unsigned int ms) =0;
|
||||||
|
/**
|
||||||
|
* Creates a non-signalled event.
|
||||||
|
*/
|
||||||
|
virtual IEventSignal *MakeEventSignal() =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum WorkerState
|
||||||
|
{
|
||||||
|
Worker_Invalid = -3,
|
||||||
|
Worker_Stopped = -2,
|
||||||
|
Worker_Paused = -1,
|
||||||
|
Worker_Running,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is an extension of the threader that is implemented.
|
||||||
|
* It "simulates" threading in a queue, and processes the queue whenever
|
||||||
|
* RunFrame is called (leaving it up to the implementation).
|
||||||
|
* Worker may or may not be started upon instantiation.
|
||||||
|
*/
|
||||||
|
class IWorker : public IThreadCreator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual unsigned int RunFrame() =0;
|
||||||
|
virtual void MakeThread(IThread *pThread) =0;
|
||||||
|
virtual IThreadHandle *MakeThread(IThread *pThread, ThreadFlags flags) =0;
|
||||||
|
virtual IThreadHandle *MakeThread(IThread *pThread, const ThreadParams *params) =0;
|
||||||
|
virtual void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min) =0;
|
||||||
|
public:
|
||||||
|
//Controls the worker
|
||||||
|
virtual bool Pause() =0;
|
||||||
|
virtual bool Unpause() =0;
|
||||||
|
virtual bool Start() =0;
|
||||||
|
//If flush is true, all remaining tasks will be cancelled.
|
||||||
|
//Otherwise, it will wait until the tasks have been depleted, then
|
||||||
|
// end.
|
||||||
|
virtual bool Stop(bool flush_cancel) =0;
|
||||||
|
//Flushes out any remaining threads
|
||||||
|
virtual unsigned int Flush(bool flush_cancel) =0;
|
||||||
|
//returns status and number of threads in queue
|
||||||
|
virtual WorkerState GetStatus(unsigned int *numThreads) =0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_THREADER_H
|
263
dlls/sqlite/thread/PosixThreads.cpp
Normal file
263
dlls/sqlite/thread/PosixThreads.cpp
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
#include "PosixThreads.h"
|
||||||
|
|
||||||
|
void PosixThreader::ThreadSleep(unsigned int ms)
|
||||||
|
{
|
||||||
|
usleep( ms * 1000 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void PosixThreader::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min)
|
||||||
|
{
|
||||||
|
max = ThreadPrio_Normal;
|
||||||
|
min = ThreadPrio_Normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMutex *PosixThreader::MakeMutex()
|
||||||
|
{
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
|
if (pthread_mutex_init(&mutex, NULL) != 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
PosixMutex *pMutex = new PosixMutex(mutex);
|
||||||
|
|
||||||
|
return pMutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PosixThreader::MakeThread(IThread *pThread)
|
||||||
|
{
|
||||||
|
ThreadParams defparams;
|
||||||
|
|
||||||
|
defparams.flags = Thread_AutoRelease;
|
||||||
|
defparams.prio = ThreadPrio_Normal;
|
||||||
|
|
||||||
|
MakeThread(pThread, &defparams);
|
||||||
|
}
|
||||||
|
|
||||||
|
IThreadHandle *PosixThreader::MakeThread(IThread *pThread, ThreadFlags flags)
|
||||||
|
{
|
||||||
|
ThreadParams defparams;
|
||||||
|
|
||||||
|
defparams.flags = flags;
|
||||||
|
defparams.prio = ThreadPrio_Normal;
|
||||||
|
|
||||||
|
return MakeThread(pThread, &defparams);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *Posix_ThreadGate(void *param)
|
||||||
|
{
|
||||||
|
PosixThreader::ThreadHandle *pHandle =
|
||||||
|
reinterpret_cast<PosixThreader::ThreadHandle *>(param);
|
||||||
|
|
||||||
|
//Block this thread from being started initially.
|
||||||
|
pthread_mutex_lock(&pHandle->m_runlock);
|
||||||
|
//if we get here, we've obtained the lock and are allowed to run.
|
||||||
|
//unlock and continue.
|
||||||
|
pthread_mutex_unlock(&pHandle->m_runlock);
|
||||||
|
|
||||||
|
pHandle->m_run->RunThread(pHandle);
|
||||||
|
|
||||||
|
ThreadParams params;
|
||||||
|
pthread_mutex_lock(&pHandle->m_statelock);
|
||||||
|
pHandle->m_state = Thread_Done;
|
||||||
|
pHandle->GetParams(¶ms);
|
||||||
|
pthread_mutex_unlock(&pHandle->m_statelock);
|
||||||
|
|
||||||
|
pHandle->m_run->OnTerminate(pHandle, false);
|
||||||
|
if (params.flags & Thread_AutoRelease)
|
||||||
|
delete pHandle;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadParams g_defparams;
|
||||||
|
IThreadHandle *PosixThreader::MakeThread(IThread *pThread, const ThreadParams *params)
|
||||||
|
{
|
||||||
|
if (params == NULL)
|
||||||
|
params = &g_defparams;
|
||||||
|
|
||||||
|
PosixThreader::ThreadHandle *pHandle =
|
||||||
|
new PosixThreader::ThreadHandle(this, pThread, params);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&pHandle->m_runlock);
|
||||||
|
|
||||||
|
int err;
|
||||||
|
err = pthread_create(&pHandle->m_thread, NULL, Posix_ThreadGate, (void *)pHandle);
|
||||||
|
|
||||||
|
if (err != 0)
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&pHandle->m_runlock);
|
||||||
|
delete pHandle;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Don't bother setting priority...
|
||||||
|
|
||||||
|
if (!(pHandle->m_params.flags & Thread_CreateSuspended))
|
||||||
|
{
|
||||||
|
pHandle->m_state = Thread_Running;
|
||||||
|
err = pthread_mutex_unlock(&pHandle->m_runlock);
|
||||||
|
if (err != 0)
|
||||||
|
pHandle->m_state = Thread_Paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEventSignal *PosixThreader::MakeEventSignal()
|
||||||
|
{
|
||||||
|
return new PosixEventSignal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************
|
||||||
|
**** Mutexes ****
|
||||||
|
*****************/
|
||||||
|
|
||||||
|
PosixThreader::PosixMutex::~PosixMutex()
|
||||||
|
{
|
||||||
|
pthread_mutex_destroy(&m_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PosixThreader::PosixMutex::TryLock()
|
||||||
|
{
|
||||||
|
int err = pthread_mutex_trylock(&m_mutex);
|
||||||
|
|
||||||
|
return (err == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PosixThreader::PosixMutex::Lock()
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&m_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PosixThreader::PosixMutex::Unlock()
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&m_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PosixThreader::PosixMutex::DestroyThis()
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************
|
||||||
|
* Thread Handles *
|
||||||
|
******************/
|
||||||
|
|
||||||
|
PosixThreader::ThreadHandle::ThreadHandle(IThreader *parent, IThread *run, const ThreadParams *params) :
|
||||||
|
m_parent(parent), m_run(run), m_params(*params), m_state(Thread_Paused)
|
||||||
|
{
|
||||||
|
pthread_mutex_init(&m_runlock, NULL);
|
||||||
|
pthread_mutex_init(&m_statelock, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
PosixThreader::ThreadHandle::~ThreadHandle()
|
||||||
|
{
|
||||||
|
pthread_mutex_destroy(&m_runlock);
|
||||||
|
pthread_mutex_destroy(&m_statelock);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PosixThreader::ThreadHandle::WaitForThread()
|
||||||
|
{
|
||||||
|
void *arg;
|
||||||
|
|
||||||
|
if (pthread_join(m_thread, &arg) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadState PosixThreader::ThreadHandle::GetState()
|
||||||
|
{
|
||||||
|
ThreadState state;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&m_statelock);
|
||||||
|
state = m_state;
|
||||||
|
pthread_mutex_unlock(&m_statelock);
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
IThreadCreator *PosixThreader::ThreadHandle::Parent()
|
||||||
|
{
|
||||||
|
return m_parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PosixThreader::ThreadHandle::DestroyThis()
|
||||||
|
{
|
||||||
|
if (m_params.flags & Thread_AutoRelease)
|
||||||
|
return;
|
||||||
|
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PosixThreader::ThreadHandle::GetParams(ThreadParams *ptparams)
|
||||||
|
{
|
||||||
|
if (!ptparams)
|
||||||
|
return;
|
||||||
|
|
||||||
|
*ptparams = m_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadPriority PosixThreader::ThreadHandle::GetPriority()
|
||||||
|
{
|
||||||
|
return ThreadPrio_Normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PosixThreader::ThreadHandle::SetPriority(ThreadPriority prio)
|
||||||
|
{
|
||||||
|
return (prio == ThreadPrio_Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PosixThreader::ThreadHandle::Unpause()
|
||||||
|
{
|
||||||
|
if (m_state != Thread_Paused)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_state = Thread_Running;
|
||||||
|
|
||||||
|
if (pthread_mutex_unlock(&m_runlock) != 0)
|
||||||
|
{
|
||||||
|
m_state = Thread_Paused;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************
|
||||||
|
* EVENT SIGNALS *
|
||||||
|
*****************/
|
||||||
|
|
||||||
|
PosixThreader::PosixEventSignal::PosixEventSignal()
|
||||||
|
{
|
||||||
|
pthread_cond_init(&m_cond, NULL);
|
||||||
|
pthread_mutex_init(&m_mutex, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
PosixThreader::PosixEventSignal::~PosixEventSignal()
|
||||||
|
{
|
||||||
|
pthread_cond_destroy(&m_cond);
|
||||||
|
pthread_mutex_destroy(&m_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PosixThreader::PosixEventSignal::Wait()
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&m_mutex);
|
||||||
|
pthread_cond_wait(&m_cond, &m_mutex);
|
||||||
|
pthread_mutex_unlock(&m_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PosixThreader::PosixEventSignal::Signal()
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&m_mutex);
|
||||||
|
pthread_cond_broadcast(&m_cond);
|
||||||
|
pthread_mutex_unlock(&m_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PosixThreader::PosixEventSignal::DestroyThis()
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
82
dlls/sqlite/thread/PosixThreads.h
Normal file
82
dlls/sqlite/thread/PosixThreads.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#ifndef _INCLUDE_POSIXTHREADS_H_
|
||||||
|
#define _INCLUDE_POSIXTHREADS_H_
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include "IThreader.h"
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
void *Posix_ThreadGate(void *param);
|
||||||
|
|
||||||
|
class PosixThreader : public IThreader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class ThreadHandle : public IThreadHandle
|
||||||
|
{
|
||||||
|
friend class PosixThreader;
|
||||||
|
friend void *Posix_ThreadGate(void *param);
|
||||||
|
public:
|
||||||
|
ThreadHandle(IThreader *parent, IThread *run, const ThreadParams *params);
|
||||||
|
virtual ~ThreadHandle();
|
||||||
|
public:
|
||||||
|
virtual bool WaitForThread();
|
||||||
|
virtual void DestroyThis();
|
||||||
|
virtual IThreadCreator *Parent();
|
||||||
|
virtual void GetParams(ThreadParams *ptparams);
|
||||||
|
virtual ThreadPriority GetPriority();
|
||||||
|
virtual bool SetPriority(ThreadPriority prio);
|
||||||
|
virtual ThreadState GetState();
|
||||||
|
virtual bool Unpause();
|
||||||
|
protected:
|
||||||
|
IThreader *m_parent; //Parent handle
|
||||||
|
pthread_t m_thread; //Windows HANDLE
|
||||||
|
ThreadParams m_params; //Current Parameters
|
||||||
|
IThread *m_run; //Runnable context
|
||||||
|
pthread_mutex_t m_statelock;
|
||||||
|
pthread_mutex_t m_runlock;
|
||||||
|
ThreadState m_state; //internal state
|
||||||
|
};
|
||||||
|
class PosixMutex : public IMutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PosixMutex(pthread_mutex_t m) : m_mutex(m)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
virtual ~PosixMutex();
|
||||||
|
public:
|
||||||
|
virtual bool TryLock();
|
||||||
|
virtual void Lock();
|
||||||
|
virtual void Unlock();
|
||||||
|
virtual void DestroyThis();
|
||||||
|
protected:
|
||||||
|
pthread_mutex_t m_mutex;
|
||||||
|
};
|
||||||
|
class PosixEventSignal : public IEventSignal
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PosixEventSignal();
|
||||||
|
virtual ~PosixEventSignal();
|
||||||
|
public:
|
||||||
|
virtual void Wait();
|
||||||
|
virtual void Signal();
|
||||||
|
virtual void DestroyThis();
|
||||||
|
protected:
|
||||||
|
pthread_cond_t m_cond;
|
||||||
|
pthread_mutex_t m_mutex;
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
virtual IMutex *MakeMutex();
|
||||||
|
virtual void MakeThread(IThread *pThread);
|
||||||
|
virtual IThreadHandle *MakeThread(IThread *pThread, ThreadFlags flags);
|
||||||
|
virtual IThreadHandle *MakeThread(IThread *pThread, const ThreadParams *params);
|
||||||
|
virtual void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min);
|
||||||
|
virtual void ThreadSleep(unsigned int ms);
|
||||||
|
virtual IEventSignal *MakeEventSignal();
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined SM_DEFAULT_THREADER && !defined SM_MAIN_THREADER
|
||||||
|
#define SM_MAIN_THREADER PosixThreader;
|
||||||
|
typedef class PosixThreader MainThreader;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //_INCLUDE_POSIXTHREADS_H_
|
10
dlls/sqlite/thread/ThreadSupport.h
Normal file
10
dlls/sqlite/thread/ThreadSupport.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
|
||||||
|
#define _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
|
||||||
|
|
||||||
|
#if defined __linux__
|
||||||
|
#include "PosixThreads.h"
|
||||||
|
#elif defined WIN32
|
||||||
|
#include "WinThreads.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
|
245
dlls/sqlite/thread/ThreadWorker.cpp
Normal file
245
dlls/sqlite/thread/ThreadWorker.cpp
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
#include "ThreadWorker.h"
|
||||||
|
|
||||||
|
ThreadWorker::ThreadWorker() :
|
||||||
|
m_Threader(NULL),
|
||||||
|
m_QueueLock(NULL),
|
||||||
|
m_StateLock(NULL),
|
||||||
|
m_PauseSignal(NULL),
|
||||||
|
m_AddSignal(NULL),
|
||||||
|
me(NULL),
|
||||||
|
m_think_time(DEFAULT_THINK_TIME_MS)
|
||||||
|
{
|
||||||
|
m_state = Worker_Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadWorker::ThreadWorker(IThreader *pThreader, unsigned int thinktime) :
|
||||||
|
m_Threader(pThreader),
|
||||||
|
m_QueueLock(NULL),
|
||||||
|
m_StateLock(NULL),
|
||||||
|
m_PauseSignal(NULL),
|
||||||
|
m_AddSignal(NULL),
|
||||||
|
me(NULL),
|
||||||
|
m_think_time(thinktime)
|
||||||
|
{
|
||||||
|
if (m_Threader)
|
||||||
|
{
|
||||||
|
m_state = Worker_Stopped;
|
||||||
|
} else {
|
||||||
|
m_state = Worker_Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadWorker::~ThreadWorker()
|
||||||
|
{
|
||||||
|
if (m_state != Worker_Stopped || m_state != Worker_Invalid)
|
||||||
|
Stop(true);
|
||||||
|
|
||||||
|
if (m_ThreadQueue.size())
|
||||||
|
Flush(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThreadWorker::OnTerminate(IThreadHandle *pHandle, bool cancel)
|
||||||
|
{
|
||||||
|
//we don't particularly care
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThreadWorker::RunThread(IThreadHandle *pHandle)
|
||||||
|
{
|
||||||
|
WorkerState this_state = Worker_Running;
|
||||||
|
size_t num;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Check number of items in the queue
|
||||||
|
*/
|
||||||
|
if (this_state != Worker_Stopped)
|
||||||
|
{
|
||||||
|
m_QueueLock->Lock();
|
||||||
|
num = m_ThreadQueue.size();
|
||||||
|
if (!num)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* if none, wait for an item
|
||||||
|
*/
|
||||||
|
m_Waiting = true;
|
||||||
|
m_QueueLock->Unlock();
|
||||||
|
m_AddSignal->Wait();
|
||||||
|
m_Waiting = false;
|
||||||
|
} else {
|
||||||
|
m_QueueLock->Unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_StateLock->Lock();
|
||||||
|
this_state = m_state;
|
||||||
|
m_StateLock->Unlock();
|
||||||
|
if (this_state != Worker_Running)
|
||||||
|
{
|
||||||
|
if (this_state == Worker_Paused || this_state == Worker_Stopped)
|
||||||
|
{
|
||||||
|
//wait until the lock is cleared.
|
||||||
|
if (this_state == Worker_Paused)
|
||||||
|
m_PauseSignal->Wait();
|
||||||
|
if (this_state == Worker_Stopped)
|
||||||
|
{
|
||||||
|
//if we're supposed to flush cleanrly,
|
||||||
|
// run all of the remaining frames first.
|
||||||
|
if (!m_FlushType)
|
||||||
|
{
|
||||||
|
while (m_ThreadQueue.size())
|
||||||
|
RunFrame();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Run the frame.
|
||||||
|
*/
|
||||||
|
RunFrame();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wait in between threads if specified
|
||||||
|
*/
|
||||||
|
if (m_think_time)
|
||||||
|
m_Threader->ThreadSleep(m_think_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SWThreadHandle *ThreadWorker::PopThreadFromQueue()
|
||||||
|
{
|
||||||
|
if (m_state <= Worker_Stopped && !m_QueueLock)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
SWThreadHandle *swt;
|
||||||
|
m_QueueLock->Lock();
|
||||||
|
swt = BaseWorker::PopThreadFromQueue();
|
||||||
|
m_QueueLock->Unlock();
|
||||||
|
|
||||||
|
return swt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThreadWorker::AddThreadToQueue(SWThreadHandle *pHandle)
|
||||||
|
{
|
||||||
|
if (m_state <= Worker_Stopped)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_QueueLock->Lock();
|
||||||
|
BaseWorker::AddThreadToQueue(pHandle);
|
||||||
|
if (m_Waiting)
|
||||||
|
{
|
||||||
|
m_AddSignal->Signal();
|
||||||
|
}
|
||||||
|
m_QueueLock->Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkerState ThreadWorker::GetStatus(unsigned int *threads)
|
||||||
|
{
|
||||||
|
WorkerState state;
|
||||||
|
|
||||||
|
m_StateLock->Lock();
|
||||||
|
state = BaseWorker::GetStatus(threads);
|
||||||
|
m_StateLock->Unlock();
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ThreadWorker::Start()
|
||||||
|
{
|
||||||
|
if (m_state == Worker_Invalid)
|
||||||
|
{
|
||||||
|
if (m_Threader == NULL)
|
||||||
|
return false;
|
||||||
|
} else if (m_state != Worker_Stopped) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Waiting = false;
|
||||||
|
m_QueueLock = m_Threader->MakeMutex();
|
||||||
|
m_StateLock = m_Threader->MakeMutex();
|
||||||
|
m_PauseSignal = m_Threader->MakeEventSignal();
|
||||||
|
m_AddSignal = m_Threader->MakeEventSignal();
|
||||||
|
m_state = Worker_Running;
|
||||||
|
ThreadParams pt;
|
||||||
|
pt.flags = Thread_Default;
|
||||||
|
pt.prio = ThreadPrio_Normal;
|
||||||
|
me = m_Threader->MakeThread(this, &pt);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ThreadWorker::Stop(bool flush_cancel)
|
||||||
|
{
|
||||||
|
if (m_state == Worker_Invalid || m_state == Worker_Stopped)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
WorkerState oldstate;
|
||||||
|
|
||||||
|
//set new state
|
||||||
|
m_StateLock->Lock();
|
||||||
|
oldstate = m_state;
|
||||||
|
m_state = Worker_Stopped;
|
||||||
|
m_FlushType = flush_cancel;
|
||||||
|
m_StateLock->Unlock();
|
||||||
|
|
||||||
|
if (oldstate == Worker_Paused)
|
||||||
|
{
|
||||||
|
Unpause();
|
||||||
|
} else {
|
||||||
|
m_AddSignal->Signal();
|
||||||
|
Pause();
|
||||||
|
Unpause();
|
||||||
|
}
|
||||||
|
|
||||||
|
me->WaitForThread();
|
||||||
|
//destroy it
|
||||||
|
me->DestroyThis();
|
||||||
|
//flush all remaining events
|
||||||
|
Flush(true);
|
||||||
|
|
||||||
|
//free mutex locks
|
||||||
|
m_QueueLock->DestroyThis();
|
||||||
|
m_StateLock->DestroyThis();
|
||||||
|
m_PauseSignal->DestroyThis();
|
||||||
|
m_AddSignal->DestroyThis();
|
||||||
|
|
||||||
|
//invalidizzle
|
||||||
|
m_QueueLock = NULL;
|
||||||
|
m_StateLock = NULL;
|
||||||
|
m_PauseSignal = NULL;
|
||||||
|
m_AddSignal = NULL;
|
||||||
|
me = NULL;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ThreadWorker::Pause()
|
||||||
|
{
|
||||||
|
if (m_state != Worker_Running)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_StateLock->Lock();
|
||||||
|
m_state = Worker_Paused;
|
||||||
|
m_StateLock->Unlock();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ThreadWorker::Unpause()
|
||||||
|
{
|
||||||
|
if (m_state != Worker_Paused)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_StateLock->Lock();
|
||||||
|
m_state = Worker_Running;
|
||||||
|
m_StateLock->Unlock();
|
||||||
|
m_PauseSignal->Signal();
|
||||||
|
if (m_Waiting)
|
||||||
|
{
|
||||||
|
m_AddSignal->Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
40
dlls/sqlite/thread/ThreadWorker.h
Normal file
40
dlls/sqlite/thread/ThreadWorker.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef _INCLUDE_SOURCEMOD_THREADWORKER_H
|
||||||
|
#define _INCLUDE_SOURCEMOD_THREADWORKER_H
|
||||||
|
|
||||||
|
#include "BaseWorker.h"
|
||||||
|
|
||||||
|
#define DEFAULT_THINK_TIME_MS 500
|
||||||
|
|
||||||
|
class ThreadWorker : public BaseWorker, public IThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ThreadWorker();
|
||||||
|
ThreadWorker(IThreader *pThreader, unsigned int thinktime=DEFAULT_THINK_TIME_MS);
|
||||||
|
virtual ~ThreadWorker();
|
||||||
|
public: //IThread
|
||||||
|
virtual void OnTerminate(IThreadHandle *pHandle, bool cancel);
|
||||||
|
virtual void RunThread(IThreadHandle *pHandle);
|
||||||
|
public: //IWorker
|
||||||
|
//Controls the worker
|
||||||
|
virtual bool Pause();
|
||||||
|
virtual bool Unpause();
|
||||||
|
virtual bool Start();
|
||||||
|
virtual bool Stop(bool flush_cancel);
|
||||||
|
//returns status and number of threads in queue
|
||||||
|
virtual WorkerState GetStatus(unsigned int *numThreads);
|
||||||
|
public: //BaseWorker
|
||||||
|
virtual void AddThreadToQueue(SWThreadHandle *pHandle);
|
||||||
|
virtual SWThreadHandle *PopThreadFromQueue();
|
||||||
|
protected:
|
||||||
|
IThreader *m_Threader;
|
||||||
|
IMutex *m_QueueLock;
|
||||||
|
IMutex *m_StateLock;
|
||||||
|
IEventSignal *m_PauseSignal;
|
||||||
|
IEventSignal *m_AddSignal;
|
||||||
|
IThreadHandle *me;
|
||||||
|
unsigned int m_think_time;
|
||||||
|
volatile bool m_Waiting;
|
||||||
|
volatile bool m_FlushType;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_THREADWORKER_H
|
289
dlls/sqlite/thread/WinThreads.cpp
Normal file
289
dlls/sqlite/thread/WinThreads.cpp
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
#include "WinThreads.h"
|
||||||
|
|
||||||
|
void WinThreader::ThreadSleep(unsigned int ms)
|
||||||
|
{
|
||||||
|
Sleep((DWORD)ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
IMutex *WinThreader::MakeMutex()
|
||||||
|
{
|
||||||
|
HANDLE mutex = CreateMutexA(NULL, FALSE, NULL);
|
||||||
|
|
||||||
|
if (mutex == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
WinMutex *pMutex = new WinMutex(mutex);
|
||||||
|
|
||||||
|
return pMutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
IThreadHandle *WinThreader::MakeThread(IThread *pThread, ThreadFlags flags)
|
||||||
|
{
|
||||||
|
ThreadParams defparams;
|
||||||
|
|
||||||
|
defparams.flags = flags;
|
||||||
|
defparams.prio = ThreadPrio_Normal;
|
||||||
|
|
||||||
|
return MakeThread(pThread, &defparams);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinThreader::MakeThread(IThread *pThread)
|
||||||
|
{
|
||||||
|
ThreadParams defparams;
|
||||||
|
|
||||||
|
defparams.flags = Thread_AutoRelease;
|
||||||
|
defparams.prio = ThreadPrio_Normal;
|
||||||
|
|
||||||
|
MakeThread(pThread, &defparams);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WINAPI Win32_ThreadGate(LPVOID param)
|
||||||
|
{
|
||||||
|
WinThreader::ThreadHandle *pHandle =
|
||||||
|
reinterpret_cast<WinThreader::ThreadHandle *>(param);
|
||||||
|
|
||||||
|
pHandle->m_run->RunThread(pHandle);
|
||||||
|
|
||||||
|
ThreadParams params;
|
||||||
|
EnterCriticalSection(&pHandle->m_crit);
|
||||||
|
pHandle->m_state = Thread_Done;
|
||||||
|
pHandle->GetParams(¶ms);
|
||||||
|
LeaveCriticalSection(&pHandle->m_crit);
|
||||||
|
|
||||||
|
pHandle->m_run->OnTerminate(pHandle, false);
|
||||||
|
if (params.flags & Thread_AutoRelease)
|
||||||
|
delete pHandle;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinThreader::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min)
|
||||||
|
{
|
||||||
|
max = ThreadPrio_Maximum;
|
||||||
|
min = ThreadPrio_Minimum;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadParams g_defparams;
|
||||||
|
IThreadHandle *WinThreader::MakeThread(IThread *pThread, const ThreadParams *params)
|
||||||
|
{
|
||||||
|
if (params == NULL)
|
||||||
|
params = &g_defparams;
|
||||||
|
|
||||||
|
WinThreader::ThreadHandle *pHandle =
|
||||||
|
new WinThreader::ThreadHandle(this, NULL, pThread, params);
|
||||||
|
|
||||||
|
DWORD tid;
|
||||||
|
pHandle->m_thread =
|
||||||
|
CreateThread(NULL, 0, &Win32_ThreadGate, (LPVOID)pHandle, CREATE_SUSPENDED, &tid);
|
||||||
|
|
||||||
|
if (!pHandle->m_thread)
|
||||||
|
{
|
||||||
|
delete pHandle;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pHandle->m_params.prio != ThreadPrio_Normal)
|
||||||
|
{
|
||||||
|
pHandle->SetPriority(pHandle->m_params.prio);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(pHandle->m_params.flags & Thread_CreateSuspended))
|
||||||
|
{
|
||||||
|
pHandle->Unpause();
|
||||||
|
}
|
||||||
|
|
||||||
|
return pHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEventSignal *WinThreader::MakeEventSignal()
|
||||||
|
{
|
||||||
|
HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||||
|
|
||||||
|
if (!event)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
WinEvent *pEvent = new WinEvent(event);
|
||||||
|
|
||||||
|
return pEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************
|
||||||
|
**** Mutexes ****
|
||||||
|
*****************/
|
||||||
|
|
||||||
|
WinThreader::WinMutex::~WinMutex()
|
||||||
|
{
|
||||||
|
if (m_mutex)
|
||||||
|
{
|
||||||
|
CloseHandle(m_mutex);
|
||||||
|
m_mutex = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinThreader::WinMutex::TryLock()
|
||||||
|
{
|
||||||
|
if (!m_mutex)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (WaitForSingleObject(m_mutex, 0) != WAIT_FAILED)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinThreader::WinMutex::Lock()
|
||||||
|
{
|
||||||
|
if (!m_mutex)
|
||||||
|
return;
|
||||||
|
|
||||||
|
WaitForSingleObject(m_mutex, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinThreader::WinMutex::Unlock()
|
||||||
|
{
|
||||||
|
if (!m_mutex)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ReleaseMutex(m_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinThreader::WinMutex::DestroyThis()
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************
|
||||||
|
* Thread Handles *
|
||||||
|
******************/
|
||||||
|
|
||||||
|
WinThreader::ThreadHandle::ThreadHandle(IThreader *parent, HANDLE hthread, IThread *run, const ThreadParams *params) :
|
||||||
|
m_parent(parent), m_thread(hthread), m_run(run), m_params(*params),
|
||||||
|
m_state(Thread_Paused)
|
||||||
|
{
|
||||||
|
InitializeCriticalSection(&m_crit);
|
||||||
|
}
|
||||||
|
|
||||||
|
WinThreader::ThreadHandle::~ThreadHandle()
|
||||||
|
{
|
||||||
|
if (m_thread)
|
||||||
|
{
|
||||||
|
CloseHandle(m_thread);
|
||||||
|
m_thread = NULL;
|
||||||
|
}
|
||||||
|
DeleteCriticalSection(&m_crit);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinThreader::ThreadHandle::WaitForThread()
|
||||||
|
{
|
||||||
|
if (m_thread == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (WaitForSingleObject(m_thread, INFINITE) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadState WinThreader::ThreadHandle::GetState()
|
||||||
|
{
|
||||||
|
ThreadState state;
|
||||||
|
|
||||||
|
EnterCriticalSection(&m_crit);
|
||||||
|
state = m_state;
|
||||||
|
LeaveCriticalSection(&m_crit);
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
IThreadCreator *WinThreader::ThreadHandle::Parent()
|
||||||
|
{
|
||||||
|
return m_parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinThreader::ThreadHandle::DestroyThis()
|
||||||
|
{
|
||||||
|
if (m_params.flags & Thread_AutoRelease)
|
||||||
|
return;
|
||||||
|
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinThreader::ThreadHandle::GetParams(ThreadParams *ptparams)
|
||||||
|
{
|
||||||
|
if (!ptparams)
|
||||||
|
return;
|
||||||
|
|
||||||
|
*ptparams = m_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadPriority WinThreader::ThreadHandle::GetPriority()
|
||||||
|
{
|
||||||
|
return m_params.prio;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinThreader::ThreadHandle::SetPriority(ThreadPriority prio)
|
||||||
|
{
|
||||||
|
if (!m_thread)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
BOOL res = FALSE;
|
||||||
|
|
||||||
|
if (prio >= ThreadPrio_Maximum)
|
||||||
|
res = SetThreadPriority(m_thread, THREAD_PRIORITY_HIGHEST);
|
||||||
|
else if (prio <= ThreadPrio_Minimum)
|
||||||
|
res = SetThreadPriority(m_thread, THREAD_PRIORITY_LOWEST);
|
||||||
|
else if (prio == ThreadPrio_Normal)
|
||||||
|
res = SetThreadPriority(m_thread, THREAD_PRIORITY_NORMAL);
|
||||||
|
else if (prio == ThreadPrio_High)
|
||||||
|
res = SetThreadPriority(m_thread, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||||
|
else if (prio == ThreadPrio_Low)
|
||||||
|
res = SetThreadPriority(m_thread, THREAD_PRIORITY_BELOW_NORMAL);
|
||||||
|
|
||||||
|
m_params.prio = prio;
|
||||||
|
|
||||||
|
return (res != FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinThreader::ThreadHandle::Unpause()
|
||||||
|
{
|
||||||
|
if (!m_thread)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (m_state != Thread_Paused)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_state = Thread_Running;
|
||||||
|
|
||||||
|
if (ResumeThread(m_thread) == -1)
|
||||||
|
{
|
||||||
|
m_state = Thread_Paused;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************
|
||||||
|
* EVENT SIGNALS *
|
||||||
|
*****************/
|
||||||
|
|
||||||
|
WinThreader::WinEvent::~WinEvent()
|
||||||
|
{
|
||||||
|
CloseHandle(m_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinThreader::WinEvent::Wait()
|
||||||
|
{
|
||||||
|
WaitForSingleObject(m_event, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinThreader::WinEvent::Signal()
|
||||||
|
{
|
||||||
|
SetEvent(m_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinThreader::WinEvent::DestroyThis()
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
82
dlls/sqlite/thread/WinThreads.h
Normal file
82
dlls/sqlite/thread/WinThreads.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#ifndef _INCLUDE_WINTHREADS_H_
|
||||||
|
#define _INCLUDE_WINTHREADS_H_
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include "IThreader.h"
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
DWORD WINAPI Win32_ThreadGate(LPVOID param);
|
||||||
|
|
||||||
|
class WinThreader : public IThreader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class ThreadHandle : public IThreadHandle
|
||||||
|
{
|
||||||
|
friend class WinThreader;
|
||||||
|
friend DWORD WINAPI Win32_ThreadGate(LPVOID param);
|
||||||
|
public:
|
||||||
|
ThreadHandle(IThreader *parent, HANDLE hthread, IThread *run, const ThreadParams *params);
|
||||||
|
virtual ~ThreadHandle();
|
||||||
|
public:
|
||||||
|
virtual bool WaitForThread();
|
||||||
|
virtual void DestroyThis();
|
||||||
|
virtual IThreadCreator *Parent();
|
||||||
|
virtual void GetParams(ThreadParams *ptparams);
|
||||||
|
virtual ThreadPriority GetPriority();
|
||||||
|
virtual bool SetPriority(ThreadPriority prio);
|
||||||
|
virtual ThreadState GetState();
|
||||||
|
virtual bool Unpause();
|
||||||
|
protected:
|
||||||
|
IThreader *m_parent; //Parent handle
|
||||||
|
HANDLE m_thread; //Windows HANDLE
|
||||||
|
ThreadParams m_params; //Current Parameters
|
||||||
|
IThread *m_run; //Runnable context
|
||||||
|
ThreadState m_state; //internal state
|
||||||
|
CRITICAL_SECTION m_crit;
|
||||||
|
};
|
||||||
|
class WinMutex : public IMutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WinMutex(HANDLE mutex) : m_mutex(mutex)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
virtual ~WinMutex();
|
||||||
|
public:
|
||||||
|
virtual bool TryLock();
|
||||||
|
virtual void Lock();
|
||||||
|
virtual void Unlock();
|
||||||
|
virtual void DestroyThis();
|
||||||
|
protected:
|
||||||
|
HANDLE m_mutex;
|
||||||
|
};
|
||||||
|
class WinEvent : public IEventSignal
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WinEvent(HANDLE event) : m_event(event)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
virtual ~WinEvent();
|
||||||
|
public:
|
||||||
|
virtual void Wait();
|
||||||
|
virtual void Signal();
|
||||||
|
virtual void DestroyThis();
|
||||||
|
public:
|
||||||
|
HANDLE m_event;
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
virtual IMutex *MakeMutex();
|
||||||
|
virtual void MakeThread(IThread *pThread);
|
||||||
|
virtual IThreadHandle *MakeThread(IThread *pThread, ThreadFlags flags);
|
||||||
|
virtual IThreadHandle *MakeThread(IThread *pThread, const ThreadParams *params);
|
||||||
|
virtual void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min);
|
||||||
|
virtual void ThreadSleep(unsigned int ms);
|
||||||
|
virtual IEventSignal *MakeEventSignal();
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined SM_DEFAULT_THREADER && !defined SM_MAIN_THREADER
|
||||||
|
#define SM_MAIN_THREADER WinThreader;
|
||||||
|
typedef class WinThreader MainThreader;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //_INCLUDE_WINTHREADS_H_
|
661
dlls/sqlite/threading.cpp
Normal file
661
dlls/sqlite/threading.cpp
Normal file
@ -0,0 +1,661 @@
|
|||||||
|
#include "amxxmodule.h"
|
||||||
|
#include "sqlite_header.h"
|
||||||
|
#include "threading.h"
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
using namespace SourceHook;
|
||||||
|
|
||||||
|
MainThreader g_Threader;
|
||||||
|
ThreadWorker *g_pWorker = NULL;
|
||||||
|
extern DLL_FUNCTIONS *g_pFunctionTable;
|
||||||
|
StringPool g_StringPool;
|
||||||
|
IMutex *g_QueueLock = NULL;
|
||||||
|
CStack<MysqlThread *> g_ThreadQueue;
|
||||||
|
CStack<MysqlThread *> g_FreeThreads;
|
||||||
|
float g_lasttime = 0.0f;
|
||||||
|
|
||||||
|
void ShutdownThreading()
|
||||||
|
{
|
||||||
|
if (g_pWorker)
|
||||||
|
{
|
||||||
|
g_pWorker->Stop(true);
|
||||||
|
delete g_pWorker;
|
||||||
|
g_pWorker = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_QueueLock->Lock();
|
||||||
|
while (!g_ThreadQueue.empty())
|
||||||
|
{
|
||||||
|
delete g_ThreadQueue.front();
|
||||||
|
g_ThreadQueue.pop();
|
||||||
|
}
|
||||||
|
while (!g_FreeThreads.empty())
|
||||||
|
{
|
||||||
|
delete g_FreeThreads.front();
|
||||||
|
g_FreeThreads.pop();
|
||||||
|
}
|
||||||
|
g_QueueLock->Unlock();
|
||||||
|
g_QueueLock->DestroyThis();
|
||||||
|
|
||||||
|
FreeHandleTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
//public QueryHandler(state, Handle:query, error[], errnum, data[], size)
|
||||||
|
//native SQL_ThreadQuery(Handle:cn_tuple, const handler[], const query[], const data[]="", dataSize=0);
|
||||||
|
static cell AMX_NATIVE_CALL SQL_ThreadQuery(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
if (!g_pWorker)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Thread worker was unable to start.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SQL_Connection *cn = (SQL_Connection *)GetHandle(params[1], Handle_Connection);
|
||||||
|
if (!cn)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len;
|
||||||
|
const char *handler = MF_GetAmxString(amx, params[2], 0, &len);
|
||||||
|
int fwd = MF_RegisterSPForwardByName(amx, handler, FP_CELL, FP_CELL, FP_STRING, FP_CELL, FP_ARRAY, FP_CELL, FP_DONE);
|
||||||
|
if (fwd < 1)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Function not found: %s", handler);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MysqlThread *kmThread;
|
||||||
|
g_QueueLock->Lock();
|
||||||
|
if (g_FreeThreads.empty())
|
||||||
|
{
|
||||||
|
kmThread = new MysqlThread();
|
||||||
|
} else {
|
||||||
|
kmThread = g_FreeThreads.front();
|
||||||
|
g_FreeThreads.pop();
|
||||||
|
}
|
||||||
|
g_QueueLock->Unlock();
|
||||||
|
|
||||||
|
kmThread->SetInfo(cn->db);
|
||||||
|
kmThread->SetForward(fwd);
|
||||||
|
kmThread->SetQuery(MF_GetAmxString(amx, params[3], 1, &len));
|
||||||
|
kmThread->SetCellData(MF_GetAmxAddr(amx, params[4]), (ucell)params[5]);
|
||||||
|
|
||||||
|
g_pWorker->MakeThread(kmThread);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MysqlThread::MysqlThread()
|
||||||
|
{
|
||||||
|
m_fwd = 0;
|
||||||
|
m_data = NULL;
|
||||||
|
m_datalen = 0;
|
||||||
|
m_maxdatalen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MysqlThread::~MysqlThread()
|
||||||
|
{
|
||||||
|
if (m_fwd)
|
||||||
|
{
|
||||||
|
MF_UnregisterSPForward(m_fwd);
|
||||||
|
m_fwd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] m_data;
|
||||||
|
m_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MysqlThread::SetCellData(cell data[], ucell len)
|
||||||
|
{
|
||||||
|
if (len > m_maxdatalen)
|
||||||
|
{
|
||||||
|
delete [] m_data;
|
||||||
|
m_data = new cell[len];
|
||||||
|
m_maxdatalen = len;
|
||||||
|
}
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
m_datalen = len;
|
||||||
|
memcpy(m_data, data, len*sizeof(cell));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MysqlThread::SetForward(int forward)
|
||||||
|
{
|
||||||
|
m_fwd = forward;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MysqlThread::SetInfo(const char *db)
|
||||||
|
{
|
||||||
|
m_db.assign(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MysqlThread::SetQuery(const char *query)
|
||||||
|
{
|
||||||
|
m_query.assign(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MysqlThread::RunThread(IThreadHandle *pHandle)
|
||||||
|
{
|
||||||
|
DatabaseInfo info;
|
||||||
|
|
||||||
|
info.database = m_db.c_str();
|
||||||
|
info.pass = "";
|
||||||
|
info.user = "";
|
||||||
|
info.host = "";
|
||||||
|
info.port = 0;
|
||||||
|
|
||||||
|
memset(&m_qrInfo, 0, sizeof(m_qrInfo));
|
||||||
|
|
||||||
|
IDatabase *pDatabase = g_Sqlite.Connect(&info, &m_qrInfo.amxinfo.info.errorcode, m_qrInfo.amxinfo.error, 254);
|
||||||
|
IQuery *pQuery = NULL;
|
||||||
|
if (!pDatabase)
|
||||||
|
{
|
||||||
|
m_qrInfo.connect_success = false;
|
||||||
|
m_qrInfo.query_success = false;
|
||||||
|
} else {
|
||||||
|
m_qrInfo.connect_success = true;
|
||||||
|
pQuery = pDatabase->PrepareQuery(m_query.c_str());
|
||||||
|
if (!pQuery->Execute(&m_qrInfo.amxinfo.info, m_qrInfo.amxinfo.error, 254))
|
||||||
|
{
|
||||||
|
m_qrInfo.query_success = false;
|
||||||
|
} else {
|
||||||
|
m_qrInfo.query_success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_qrInfo.query_success && m_qrInfo.amxinfo.info.rs)
|
||||||
|
{
|
||||||
|
m_atomicResult.CopyFrom(m_qrInfo.amxinfo.info.rs);
|
||||||
|
m_qrInfo.amxinfo.pQuery = NULL;
|
||||||
|
m_qrInfo.amxinfo.info.rs = &m_atomicResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pQuery)
|
||||||
|
{
|
||||||
|
pQuery->FreeHandle();
|
||||||
|
pQuery = NULL;
|
||||||
|
}
|
||||||
|
if (pDatabase)
|
||||||
|
{
|
||||||
|
pDatabase->FreeHandle();
|
||||||
|
pDatabase = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MysqlThread::Invalidate()
|
||||||
|
{
|
||||||
|
m_atomicResult.FreeHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MysqlThread::OnTerminate(IThreadHandle *pHandle, bool cancel)
|
||||||
|
{
|
||||||
|
if (cancel)
|
||||||
|
{
|
||||||
|
Invalidate();
|
||||||
|
g_QueueLock->Lock();
|
||||||
|
g_FreeThreads.push(this);
|
||||||
|
g_QueueLock->Unlock();
|
||||||
|
} else {
|
||||||
|
g_QueueLock->Lock();
|
||||||
|
g_ThreadQueue.push(this);
|
||||||
|
g_QueueLock->Unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NullFunc(void *ptr, unsigned int num)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//public QueryHandler(state, Handle:query, error[], errnum, data[], size)
|
||||||
|
void MysqlThread::Execute()
|
||||||
|
{
|
||||||
|
cell data_addr;
|
||||||
|
if (m_datalen)
|
||||||
|
{
|
||||||
|
data_addr = MF_PrepareCellArray(m_data, m_datalen);
|
||||||
|
} else {
|
||||||
|
static cell tmpdata[1] = {0};
|
||||||
|
data_addr = MF_PrepareCellArray(tmpdata, 1);
|
||||||
|
}
|
||||||
|
int state = 0;
|
||||||
|
if (!m_qrInfo.connect_success)
|
||||||
|
{
|
||||||
|
state = -2;
|
||||||
|
} else if (!m_qrInfo.query_success) {
|
||||||
|
state = -1;
|
||||||
|
}
|
||||||
|
if (state != 0)
|
||||||
|
{
|
||||||
|
MF_ExecuteForward(m_fwd,
|
||||||
|
(cell)state,
|
||||||
|
(cell)0,
|
||||||
|
m_qrInfo.amxinfo.error,
|
||||||
|
m_qrInfo.amxinfo.info.errorcode,
|
||||||
|
data_addr,
|
||||||
|
m_datalen);
|
||||||
|
} else {
|
||||||
|
unsigned int hndl = MakeHandle(&m_qrInfo.amxinfo, Handle_Query, NullFunc);
|
||||||
|
MF_ExecuteForward(m_fwd,
|
||||||
|
(cell)0,
|
||||||
|
(cell)hndl,
|
||||||
|
"",
|
||||||
|
(cell)0,
|
||||||
|
data_addr,
|
||||||
|
m_datalen);
|
||||||
|
FreeHandle(hndl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************
|
||||||
|
* METAMOD STUFF *
|
||||||
|
*****************/
|
||||||
|
|
||||||
|
void OnPluginsLoaded()
|
||||||
|
{
|
||||||
|
if (g_pWorker)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_StringPool.IsThreadable())
|
||||||
|
{
|
||||||
|
g_StringPool.SetMutex(g_Threader.MakeMutex());
|
||||||
|
g_QueueLock = g_Threader.MakeMutex();
|
||||||
|
}
|
||||||
|
g_pWorker = new ThreadWorker(&g_Threader, 250);
|
||||||
|
if (!g_pWorker->Start())
|
||||||
|
{
|
||||||
|
delete g_pWorker;
|
||||||
|
g_pWorker = NULL;
|
||||||
|
}
|
||||||
|
g_pFunctionTable->pfnSpawn = NULL;
|
||||||
|
|
||||||
|
g_lasttime = 0.0f;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartFrame()
|
||||||
|
{
|
||||||
|
if (g_pWorker && (g_lasttime < gpGlobals->time))
|
||||||
|
{
|
||||||
|
g_lasttime = gpGlobals->time + 0.3f;
|
||||||
|
g_QueueLock->Lock();
|
||||||
|
size_t remaining = g_ThreadQueue.size();
|
||||||
|
if (remaining)
|
||||||
|
{
|
||||||
|
MysqlThread *kmThread;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
kmThread = g_ThreadQueue.front();
|
||||||
|
g_ThreadQueue.pop();
|
||||||
|
g_QueueLock->Unlock();
|
||||||
|
kmThread->Execute();
|
||||||
|
kmThread->Invalidate();
|
||||||
|
g_FreeThreads.push(kmThread);
|
||||||
|
g_QueueLock->Lock();
|
||||||
|
} while (!g_ThreadQueue.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
g_QueueLock->Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_META(MRES_IGNORED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnPluginsUnloading()
|
||||||
|
{
|
||||||
|
if (!g_pWorker)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_pWorker->Stop(false);
|
||||||
|
delete g_pWorker;
|
||||||
|
g_pWorker = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
* ATOMIC RESULT STUFF *
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
AtomicResult::AtomicResult()
|
||||||
|
{
|
||||||
|
m_IsFree = true;
|
||||||
|
m_CurRow = 0;
|
||||||
|
m_AllocFields = 0;
|
||||||
|
m_AllocRows = 0;
|
||||||
|
m_Rows = NULL;
|
||||||
|
m_Fields = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
AtomicResult::~AtomicResult()
|
||||||
|
{
|
||||||
|
if (!m_IsFree)
|
||||||
|
{
|
||||||
|
FreeHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_AllocFields)
|
||||||
|
{
|
||||||
|
delete [] m_Fields;
|
||||||
|
m_AllocFields = 0;
|
||||||
|
m_Fields = NULL;
|
||||||
|
}
|
||||||
|
if (m_AllocRows)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i<m_AllocRows; i++)
|
||||||
|
delete [] m_Rows[i];
|
||||||
|
delete [] m_Rows;
|
||||||
|
m_AllocRows = 0;
|
||||||
|
m_Rows = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int AtomicResult::RowCount()
|
||||||
|
{
|
||||||
|
return m_RowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AtomicResult::IsNull(unsigned int columnId)
|
||||||
|
{
|
||||||
|
return (GetString(columnId) == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int AtomicResult::FieldCount()
|
||||||
|
{
|
||||||
|
return m_FieldCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AtomicResult::FieldNameToNum(const char *name, unsigned int *columnId)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i<m_FieldCount; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(g_StringPool.GetString(m_Fields[i]), name) == 0)
|
||||||
|
{
|
||||||
|
if (*columnId)
|
||||||
|
*columnId = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *AtomicResult::FieldNumToName(unsigned int num)
|
||||||
|
{
|
||||||
|
if (num >= m_FieldCount)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return g_StringPool.GetString(m_Fields[num]);
|
||||||
|
}
|
||||||
|
|
||||||
|
double AtomicResult::GetDouble(unsigned int columnId)
|
||||||
|
{
|
||||||
|
return atof(GetStringSafe(columnId));
|
||||||
|
}
|
||||||
|
|
||||||
|
float AtomicResult::GetFloat(unsigned int columnId)
|
||||||
|
{
|
||||||
|
return atof(GetStringSafe(columnId));
|
||||||
|
}
|
||||||
|
|
||||||
|
int AtomicResult::GetInt(unsigned int columnId)
|
||||||
|
{
|
||||||
|
return atoi(GetStringSafe(columnId));
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *AtomicResult::GetRaw(unsigned int columnId, size_t *length)
|
||||||
|
{
|
||||||
|
//we don't support this yet...
|
||||||
|
*length = 0;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *AtomicResult::GetStringSafe(unsigned int columnId)
|
||||||
|
{
|
||||||
|
const char *str = GetString(columnId);
|
||||||
|
|
||||||
|
return str ? str : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *AtomicResult::GetString(unsigned int columnId)
|
||||||
|
{
|
||||||
|
if (columnId >= m_FieldCount)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return g_StringPool.GetString(m_Rows[m_CurRow][columnId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
IResultRow *AtomicResult::GetRow()
|
||||||
|
{
|
||||||
|
return static_cast<IResultRow *>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AtomicResult::IsDone()
|
||||||
|
{
|
||||||
|
if (m_CurRow >= m_RowCount)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomicResult::NextRow()
|
||||||
|
{
|
||||||
|
m_CurRow++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomicResult::_InternalClear()
|
||||||
|
{
|
||||||
|
if (m_IsFree)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_IsFree = true;
|
||||||
|
|
||||||
|
g_StringPool.StartHardLock();
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<m_FieldCount; i++)
|
||||||
|
g_StringPool.FreeString(m_Fields[i]);
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<m_RowCount; i++)
|
||||||
|
{
|
||||||
|
for (unsigned int j=0; j<m_FieldCount; j++)
|
||||||
|
g_StringPool.FreeString(m_Rows[i][j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_StringPool.StopHardLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomicResult::FreeHandle()
|
||||||
|
{
|
||||||
|
_InternalClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomicResult::CopyFrom(IResultSet *rs)
|
||||||
|
{
|
||||||
|
if (!m_IsFree)
|
||||||
|
{
|
||||||
|
_InternalClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_IsFree = false;
|
||||||
|
|
||||||
|
m_FieldCount = rs->FieldCount();
|
||||||
|
m_RowCount = rs->RowCount();
|
||||||
|
if (m_RowCount > m_AllocRows)
|
||||||
|
{
|
||||||
|
/** allocate new array, zero it */
|
||||||
|
stridx_t **newRows = new stridx_t *[m_RowCount];
|
||||||
|
memset(newRows, 0, m_RowCount * sizeof(stridx_t *));
|
||||||
|
/** if we have a new field count, just delete all the old stuff. */
|
||||||
|
if (m_FieldCount > m_AllocFields)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i<m_AllocRows; i++)
|
||||||
|
{
|
||||||
|
delete [] m_Rows[i];
|
||||||
|
newRows[i] = new stridx_t[m_FieldCount];
|
||||||
|
}
|
||||||
|
for (unsigned int i=m_AllocRows; i<m_RowCount; i++)
|
||||||
|
newRows[i] = new stridx_t[m_FieldCount];
|
||||||
|
} else {
|
||||||
|
/** copy the old pointers */
|
||||||
|
memcpy(newRows, m_Rows, m_AllocRows * sizeof(stridx_t *));
|
||||||
|
for (unsigned int i=m_AllocRows; i<m_RowCount; i++)
|
||||||
|
newRows[i] = new stridx_t[m_AllocFields];
|
||||||
|
}
|
||||||
|
delete [] m_Rows;
|
||||||
|
m_Rows = newRows;
|
||||||
|
m_AllocRows = m_RowCount;
|
||||||
|
}
|
||||||
|
if (m_FieldCount > m_AllocFields)
|
||||||
|
{
|
||||||
|
delete [] m_Fields;
|
||||||
|
m_Fields = new stridx_t[m_FieldCount];
|
||||||
|
m_AllocFields = m_FieldCount;
|
||||||
|
}
|
||||||
|
m_CurRow = 0;
|
||||||
|
|
||||||
|
g_StringPool.StartHardLock();
|
||||||
|
|
||||||
|
IResultRow *row;
|
||||||
|
unsigned int idx = 0;
|
||||||
|
while (!rs->IsDone())
|
||||||
|
{
|
||||||
|
row = rs->GetRow();
|
||||||
|
for (size_t i=0; i<m_FieldCount; i++)
|
||||||
|
m_Rows[idx][i] = g_StringPool.MakeString(row->GetString(i));
|
||||||
|
rs->NextRow();
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<m_FieldCount; i++)
|
||||||
|
m_Fields[i] = g_StringPool.MakeString(rs->FieldNumToName(i));
|
||||||
|
|
||||||
|
g_StringPool.StopHardLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* STRING POOL STUFF *
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
StringPool::StringPool()
|
||||||
|
{
|
||||||
|
m_mutex = NULL;
|
||||||
|
m_stoplock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringPool::~StringPool()
|
||||||
|
{
|
||||||
|
if (m_stoplock)
|
||||||
|
StopHardLock();
|
||||||
|
|
||||||
|
if (m_mutex)
|
||||||
|
UnsetMutex();
|
||||||
|
|
||||||
|
for (size_t i=0; i<m_Strings.size(); i++)
|
||||||
|
delete m_Strings[i];
|
||||||
|
|
||||||
|
m_Strings.clear();
|
||||||
|
m_UseTable.clear();
|
||||||
|
while (!m_FreeStrings.empty())
|
||||||
|
m_FreeStrings.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringPool::IsThreadable()
|
||||||
|
{
|
||||||
|
return (m_mutex != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *StringPool::GetString(stridx_t idx)
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= (int)m_Strings.size() || !m_UseTable[idx])
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return m_Strings[idx]->c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringPool::FreeString(stridx_t idx)
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= (int)m_Strings.size())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_stoplock && m_mutex)
|
||||||
|
m_mutex->Lock();
|
||||||
|
|
||||||
|
if (m_UseTable[idx])
|
||||||
|
{
|
||||||
|
m_FreeStrings.push(idx);
|
||||||
|
m_UseTable[idx] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_stoplock && m_mutex)
|
||||||
|
m_mutex->Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
stridx_t StringPool::MakeString(const char *str)
|
||||||
|
{
|
||||||
|
if (!str)
|
||||||
|
return StringPool::NullString;
|
||||||
|
|
||||||
|
if (!m_stoplock && m_mutex)
|
||||||
|
m_mutex->Lock();
|
||||||
|
|
||||||
|
stridx_t idx;
|
||||||
|
|
||||||
|
if (m_FreeStrings.empty())
|
||||||
|
{
|
||||||
|
idx = static_cast<stridx_t>(m_Strings.size());
|
||||||
|
SourceHook::String *shString = new SourceHook::String(str);
|
||||||
|
m_Strings.push_back(shString);
|
||||||
|
m_UseTable.push_back(1);
|
||||||
|
} else {
|
||||||
|
idx = m_FreeStrings.front();
|
||||||
|
m_FreeStrings.pop();
|
||||||
|
m_UseTable[idx] = 1;
|
||||||
|
m_Strings[idx]->assign(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_stoplock && m_mutex)
|
||||||
|
m_mutex->Unlock();
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringPool::SetMutex(IMutex *m)
|
||||||
|
{
|
||||||
|
m_mutex = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringPool::UnsetMutex()
|
||||||
|
{
|
||||||
|
if (m_mutex)
|
||||||
|
{
|
||||||
|
m_mutex->DestroyThis();
|
||||||
|
m_mutex = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringPool::StartHardLock()
|
||||||
|
{
|
||||||
|
if (m_stoplock)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_mutex->Lock();
|
||||||
|
m_stoplock = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringPool::StopHardLock()
|
||||||
|
{
|
||||||
|
if (!m_stoplock)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_mutex->Unlock();
|
||||||
|
m_stoplock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AMX_NATIVE_INFO g_ThreadSqlNatives[] =
|
||||||
|
{
|
||||||
|
{"SQL_ThreadQuery", SQL_ThreadQuery},
|
||||||
|
{NULL, NULL},
|
||||||
|
};
|
110
dlls/sqlite/threading.h
Normal file
110
dlls/sqlite/threading.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#ifndef _INCLUDE_MYSQL_THREADING_H
|
||||||
|
#define _INCLUDE_MYSQL_THREADING_H
|
||||||
|
|
||||||
|
#include "IThreader.h"
|
||||||
|
#include "ISQLDriver.h"
|
||||||
|
#include "sh_string.h"
|
||||||
|
#include "CVector.h"
|
||||||
|
#include "sh_stack.h"
|
||||||
|
|
||||||
|
struct QueuedResultInfo
|
||||||
|
{
|
||||||
|
AmxQueryInfo amxinfo;
|
||||||
|
bool connect_success;
|
||||||
|
bool query_success;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int stridx_t;
|
||||||
|
|
||||||
|
class StringPool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StringPool();
|
||||||
|
~StringPool();
|
||||||
|
void SetMutex(IMutex *m);
|
||||||
|
void UnsetMutex();
|
||||||
|
bool IsThreadable();
|
||||||
|
public:
|
||||||
|
stridx_t MakeString(const char *str);
|
||||||
|
void FreeString(stridx_t idx);
|
||||||
|
const char *GetString(stridx_t idx);
|
||||||
|
void StartHardLock();
|
||||||
|
void StopHardLock();
|
||||||
|
public:
|
||||||
|
static const int NullString = -1;
|
||||||
|
private:
|
||||||
|
CStack<stridx_t> m_FreeStrings;
|
||||||
|
CVector<stridx_t> m_UseTable;
|
||||||
|
CVector<SourceHook::String *> m_Strings;
|
||||||
|
IMutex *m_mutex;
|
||||||
|
bool m_stoplock;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AtomicResult :
|
||||||
|
public IResultSet,
|
||||||
|
public IResultRow
|
||||||
|
{
|
||||||
|
friend class MysqlThread;
|
||||||
|
public:
|
||||||
|
AtomicResult();
|
||||||
|
~AtomicResult();
|
||||||
|
public:
|
||||||
|
//free the handle if necessary (see IQuery).
|
||||||
|
virtual void FreeHandle();
|
||||||
|
virtual unsigned int RowCount();
|
||||||
|
virtual unsigned int FieldCount();
|
||||||
|
virtual const char *FieldNumToName(unsigned int num);
|
||||||
|
virtual bool FieldNameToNum(const char *name, unsigned int *columnId);
|
||||||
|
virtual bool IsDone();
|
||||||
|
virtual IResultRow *GetRow();
|
||||||
|
virtual void NextRow();
|
||||||
|
public:
|
||||||
|
virtual const char *GetString(unsigned int columnId);
|
||||||
|
virtual const char *GetStringSafe(unsigned int columnId);
|
||||||
|
virtual double GetDouble(unsigned int columnId);
|
||||||
|
virtual float GetFloat(unsigned int columnId);
|
||||||
|
virtual int GetInt(unsigned int columnId);
|
||||||
|
virtual bool IsNull(unsigned int columnId);
|
||||||
|
virtual const char *GetRaw(unsigned int columnId, size_t *length);
|
||||||
|
public:
|
||||||
|
void CopyFrom(IResultSet *rs);
|
||||||
|
private:
|
||||||
|
void _InternalClear();
|
||||||
|
private:
|
||||||
|
unsigned int m_RowCount;
|
||||||
|
unsigned int m_FieldCount;
|
||||||
|
unsigned int m_AllocFields;
|
||||||
|
unsigned int m_AllocRows;
|
||||||
|
stridx_t *m_Fields;
|
||||||
|
stridx_t **m_Rows;
|
||||||
|
unsigned int m_CurRow;
|
||||||
|
bool m_IsFree;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MysqlThread : public IThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MysqlThread();
|
||||||
|
~MysqlThread();
|
||||||
|
public:
|
||||||
|
void SetInfo(const char *db);
|
||||||
|
void SetQuery(const char *query);
|
||||||
|
void SetCellData(cell data[], ucell len);
|
||||||
|
void SetForward(int forward);
|
||||||
|
void Invalidate();
|
||||||
|
void Execute();
|
||||||
|
public:
|
||||||
|
void RunThread(IThreadHandle *pHandle);
|
||||||
|
void OnTerminate(IThreadHandle *pHandle, bool cancel);
|
||||||
|
private:
|
||||||
|
SourceHook::String m_query;
|
||||||
|
SourceHook::String m_db;
|
||||||
|
cell *m_data;
|
||||||
|
ucell m_datalen;
|
||||||
|
size_t m_maxdatalen;
|
||||||
|
int m_fwd;
|
||||||
|
QueuedResultInfo m_qrInfo;
|
||||||
|
AtomicResult m_atomicResult;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_MYSQL_THREADING_H
|
Loading…
Reference in New Issue
Block a user