// The C Plus Plus headers.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <stdarg.h>
// The other further headers.
#include "Header.h"
#include "amxxmodule.h"
#include "sqlite3.h"
// The definitions.
#define MAXIMUM_CHARACTERS_FOR_STRING 4096U
#define MAXIMUM_CHARACTERS_FOR_COLUMN 128U
#define MAXIMUM_ROWS_TO_SELECT 2048U
#define MAXIMUM_COLUMNS_TO_HAVE 64U
// The Database_Row class. Each row will contain 64 columns as long as 128 maximum characters.
class Database_Row
{
public:
char Column[MAXIMUM_COLUMNS_TO_HAVE][MAXIMUM_CHARACTERS_FOR_COLUMN];
};
// The data used into the extension.
Database_Row g_Row[MAXIMUM_ROWS_TO_SELECT];
sqlite3 * g_Handle = NULL;
char g_String[MAXIMUM_CHARACTERS_FOR_STRING];
int g_Rows = 0U;
int g_Iterator = 0U;
int g_Length = 0U;
// The SQLite handlers.
int SQLite_SelectQueryHandler(void *, int Count, char ** Data, char **)
{
if (g_Rows < MAXIMUM_ROWS_TO_SELECT)
{
for (g_Iterator = 0; g_Iterator < Count && g_Iterator < MAXIMUM_COLUMNS_TO_HAVE; g_Iterator++)
{
_snprintf(g_Row[g_Rows].Column[g_Iterator], MAXIMUM_CHARACTERS_FOR_COLUMN, "%s", \
Data[g_Iterator] ? Data[g_Iterator] : "NULL");
}
}
// Let this one to increment everytime. It will be usefull for getting the rows count from any table.
g_Rows++;
return 0U;
}
int SQLite_UpdateQueryHandler(void *, int, char **, char **)
{
// Do nothing.
return 0U;
}
// The AMX Mod X functions.
static cell AMX_NATIVE_CALL Query(AMX * Handle, cell * Parameters)
{
g_Rows = 0U;
sqlite3_exec(g_Handle, MF_GetAmxString(Handle, Parameters[1U], 0U, 0U), Parameters[2U] ? \
SQLite_SelectQueryHandler : SQLite_UpdateQueryHandler, NULL, NULL);
return g_Rows;
}
static cell AMX_NATIVE_CALL Get(AMX * Handle, cell * Parameters)
{
// If the coder will fail, this won't log any error. Will just set the buffer as "NULL" and will return zero.
if (Parameters[1U] >= 0U && Parameters[1U] < MAXIMUM_ROWS_TO_SELECT && Parameters[2U] >= 0U && \
Parameters[2U] < MAXIMUM_COLUMNS_TO_HAVE)
{
MF_SetAmxString(Handle, Parameters[3U], g_Row[Parameters[1U]].Column[Parameters[2U]], Parameters[4U]);
return (cell)atoi(g_Row[Parameters[1U]].Column[Parameters[2U]]);
}
MF_SetAmxString(Handle, Parameters[3U], "NULL", Parameters[4U]);
return 0U;
}
static cell AMX_NATIVE_CALL Safe(AMX * Handle, cell * Parameters)
{
// Run into an error whether coder wants to replace a bad character with another bad character.
if (Parameters[2] == '\'' || Parameters[2] == '"' || Parameters[2] == '\\' || Parameters[2] == '`')
{
MF_LogError(Handle, AMX_ERR_NATIVE, \
"Unable to replace a bad character with another bad character. Bad characters are \\, ', \" and `.");
return 0U;
}
g_Length = _snprintf(g_String, MAXIMUM_CHARACTERS_FOR_STRING, "%s", MF_GetAmxString(Handle, Parameters[1U], 0U, 0U));
// Check for each character.
for (g_Iterator = 0; g_Iterator < g_Length; g_Iterator++)
{
if (g_String[g_Iterator] == '\'' || g_String[g_Iterator] == '"' || g_String[g_Iterator] == '\\' \
|| g_String[g_Iterator] == '`')
{
// Replace bad character with the given one.
g_String[g_Iterator] = Parameters[2U];
}
}
MF_SetAmxString(Handle, Parameters[1U], g_String, g_Length);
return 1U;
}
// Functions bundle.
const AMX_NATIVE_INFO g_Functions[] =
{
{ "Database_Query", Query },
{ "Database_Get", Get },
{ "Database_Safe", Safe },
{ NULL, NULL }
};
// AMX Mod X forwards.
void OnAmxxAttach(void)
{
MF_AddNatives(g_Functions);
sqlite3_open("Database.SQ3", &g_Handle);
}
void OnAmxxDetach(void)
{
sqlite3_close(g_Handle);
}
Comments