mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-06-16 07:07:13 +02:00
Migrated the host module to C++ exceptions as well.
Also enabled the latest C++ revision in the project. Replaced the Random library with the one provided by C++11. Implemented a simple AES256 encryption class. Various other fixes and improvements.
This commit is contained in:
@ -33,7 +33,7 @@ Int32 Document::Cmp(const Document & o) const
|
||||
{
|
||||
if (m_Doc == o.m_Doc)
|
||||
return 0;
|
||||
else if (this > &o)
|
||||
else if (m_Doc.m_Ptr > o.m_Doc.m_Ptr)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
|
@ -109,14 +109,6 @@ public:
|
||||
return m_Doc;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether any data has been loaded into this document.
|
||||
*/
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return m_Doc->IsEmpty();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the number of active references to this document instance.
|
||||
*/
|
||||
@ -125,6 +117,14 @@ public:
|
||||
return m_Doc.Count();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether any data has been loaded into this document.
|
||||
*/
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return m_Doc->IsEmpty();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Deallocate all memory stored by this document.
|
||||
*/
|
||||
|
@ -18,7 +18,7 @@ Int32 Entries::Cmp(const Entries & o) const
|
||||
{
|
||||
if (m_Elem == o.m_Elem)
|
||||
return 0;
|
||||
else if (this > &o)
|
||||
else if (m_List.size() > o.m_List.size())
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
|
120
modules/mmdb/Common.cpp
Normal file
120
modules/mmdb/Common.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Common.hpp"
|
||||
#include "Module.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <cfloat>
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqrat.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQChar g_Buffer[4096]; // Common buffer to reduce memory allocations.
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SStr GetTempBuff()
|
||||
{
|
||||
return g_Buffer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Uint32 GetTempBuffSize()
|
||||
{
|
||||
return sizeof(g_Buffer);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SqThrowF(CSStr str, ...)
|
||||
{
|
||||
// Initialize the argument list
|
||||
va_list args;
|
||||
va_start (args, str);
|
||||
// Write the requested contents
|
||||
if (snprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
|
||||
strcpy(g_Buffer, "Unknown error has occurred");
|
||||
// Release the argument list
|
||||
va_end(args);
|
||||
// Throw the exception with the resulted message
|
||||
throw Sqrat::Exception(g_Buffer);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CSStr FmtStr(CSStr str, ...)
|
||||
{
|
||||
// Initialize the argument list
|
||||
va_list args;
|
||||
va_start (args, str);
|
||||
// Write the requested contents
|
||||
if (snprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
|
||||
g_Buffer[0] = 0; /* make sure the string is terminated */
|
||||
// Release the argument list
|
||||
va_end(args);
|
||||
// Return the data from the buffer
|
||||
return g_Buffer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
StackGuard::StackGuard(HSQUIRRELVM vm)
|
||||
: m_Top(sq_gettop(vm)), m_VM(vm)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
StackGuard::~StackGuard()
|
||||
{
|
||||
sq_pop(m_VM, sq_gettop(m_VM) - m_Top);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
DbRef::Pointer DbRef::Create()
|
||||
{
|
||||
return reinterpret_cast< Pointer >(malloc(sizeof(Type)));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DbRef::Destroy(Pointer db)
|
||||
{
|
||||
if (db)
|
||||
free(db);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const char NumLimit< char >::Min = CHAR_MIN;
|
||||
const signed char NumLimit< signed char >::Min = SCHAR_MIN;
|
||||
const unsigned char NumLimit< unsigned char >::Min = 0;
|
||||
const signed short NumLimit< signed short >::Min = SHRT_MIN;
|
||||
const unsigned short NumLimit< unsigned short >::Min = 0;
|
||||
const signed int NumLimit< signed int >::Min = INT_MIN;
|
||||
const unsigned int NumLimit< unsigned int >::Min = 0;
|
||||
const signed long NumLimit< signed long >::Min = LONG_MIN;
|
||||
const unsigned long NumLimit< unsigned long >::Min = 0;
|
||||
const signed long long NumLimit< signed long long >::Min = LLONG_MIN;
|
||||
const unsigned long long NumLimit< unsigned long long >::Min = 0;
|
||||
const float NumLimit< float >::Min = FLT_MIN;
|
||||
const double NumLimit< double >::Min = DBL_MIN;
|
||||
const long double NumLimit< long double >::Min = LDBL_MIN;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const char NumLimit< char >::Max = CHAR_MAX;
|
||||
const signed char NumLimit< signed char >::Max = SCHAR_MAX;
|
||||
const unsigned char NumLimit< unsigned char >::Max = UCHAR_MAX;
|
||||
const signed short NumLimit< signed short >::Max = SHRT_MAX;
|
||||
const unsigned short NumLimit< unsigned short >::Max = USHRT_MAX;
|
||||
const signed int NumLimit< signed int >::Max = INT_MAX;
|
||||
const unsigned int NumLimit< unsigned int >::Max = UINT_MAX;
|
||||
const signed long NumLimit< signed long >::Max = LONG_MAX;
|
||||
const unsigned long NumLimit< unsigned long >::Max = ULONG_MAX;
|
||||
const signed long long NumLimit< signed long long >::Max = LLONG_MAX;
|
||||
const unsigned long long NumLimit< unsigned long long >::Max = ULLONG_MAX;
|
||||
const float NumLimit< float >::Max = FLT_MAX;
|
||||
const double NumLimit< double >::Max = DBL_MAX;
|
||||
const long double NumLimit< long double >::Max = LDBL_MAX;
|
||||
|
||||
} // Namespace:: SqMod
|
453
modules/mmdb/Common.hpp
Normal file
453
modules/mmdb/Common.hpp
Normal file
@ -0,0 +1,453 @@
|
||||
#ifndef _SQMMDB_COMMON_HPP_
|
||||
#define _SQMMDB_COMMON_HPP_
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "ModBase.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <maxminddb.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* SOFTWARE INFORMATION
|
||||
*/
|
||||
#define SQMMDB_NAME "Squirrel MaxmindDB Module"
|
||||
#define SQMMDB_AUTHOR "Sandu Liviu Catalin (S.L.C)"
|
||||
#define SQMMDB_COPYRIGHT "Copyright (C) 2016 Sandu Liviu Catalin"
|
||||
#define SQMMDB_HOST_NAME "SqModMMDBHost"
|
||||
#define SQMMDB_VERSION 001
|
||||
#define SQMMDB_VERSION_STR "0.0.1"
|
||||
#define SQMMDB_VERSION_MAJOR 0
|
||||
#define SQMMDB_VERSION_MINOR 0
|
||||
#define SQMMDB_VERSION_PATCH 1
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Forward declarations.
|
||||
*/
|
||||
class Database;
|
||||
class SockAddr;
|
||||
class EntryDataList;
|
||||
class LookupResult;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the temporary buffer.
|
||||
*/
|
||||
SStr GetTempBuff();
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the size of the temporary buffer.
|
||||
*/
|
||||
Uint32 GetTempBuffSize();
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Throw a formatted exception.
|
||||
*/
|
||||
void SqThrowF(CSStr str, ...);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Generate a formatted string.
|
||||
*/
|
||||
CSStr FmtStr(CSStr str, ...);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Implements RAII to restore the VM stack to it's initial size on function exit.
|
||||
*/
|
||||
struct StackGuard
|
||||
{
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
StackGuard(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~StackGuard();
|
||||
|
||||
private:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
StackGuard(const StackGuard &);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
StackGuard(StackGuard &&);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
StackGuard & operator = (const StackGuard &);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move assignment operator.
|
||||
*/
|
||||
StackGuard & operator = (StackGuard &&);
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Int32 m_Top; /* The top of the stack when this instance was created. */
|
||||
HSQUIRRELVM m_VM; /* The VM where the stack should be restored. */
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Manages a reference counted INI document instance.
|
||||
*/
|
||||
class DbRef
|
||||
{
|
||||
// --------------------------------------------------------------------------------------------
|
||||
friend class Database;
|
||||
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef MMDB_s Type; // The managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type* Pointer; // Pointer to the managed type.
|
||||
typedef const Type* ConstPtr; // Constant pointer to the managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type& Reference; // Reference to the managed type.
|
||||
typedef const Type& ConstRef; // Constant reference to the managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef unsigned int Counter; // Reference counter type.
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Pointer m_Ptr; // The document reader, writer and manager instance.
|
||||
Counter* m_Ref; // Reference count to the managed instance.
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Creates a database structure.
|
||||
*/
|
||||
static Pointer Create();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destroyes the specified database structure.
|
||||
*/
|
||||
static void Destroy(Pointer db);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Grab a strong reference to a document instance.
|
||||
*/
|
||||
void Grab()
|
||||
{
|
||||
if (m_Ptr)
|
||||
++(*m_Ref);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Drop a strong reference to a document instance.
|
||||
*/
|
||||
void Drop()
|
||||
{
|
||||
if (m_Ptr && --(*m_Ref) == 0)
|
||||
{
|
||||
MMDB_close(m_Ptr);
|
||||
Destroy(m_Ptr);
|
||||
delete m_Ref;
|
||||
m_Ptr = NULL;
|
||||
m_Ref = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
DbRef(bool make)
|
||||
: m_Ptr(make ? Create() : NULL), m_Ref(m_Ptr ? new Counter(1) : NULL)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor (null).
|
||||
*/
|
||||
DbRef()
|
||||
: m_Ptr(NULL), m_Ref(NULL)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
DbRef(const DbRef & o)
|
||||
: m_Ptr(o.m_Ptr), m_Ref(o.m_Ref)
|
||||
|
||||
{
|
||||
Grab();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
DbRef(DbRef && o)
|
||||
: m_Ptr(o.m_Ptr), m_Ref(o.m_Ref)
|
||||
|
||||
{
|
||||
o.m_Ptr = NULL;
|
||||
o.m_Ref = NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~DbRef()
|
||||
{
|
||||
Drop();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
DbRef & operator = (const DbRef & o)
|
||||
{
|
||||
if (m_Ptr != o.m_Ptr)
|
||||
{
|
||||
Drop();
|
||||
m_Ptr = o.m_Ptr;
|
||||
m_Ref = o.m_Ref;
|
||||
Grab();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move assignment operator.
|
||||
*/
|
||||
DbRef & operator = (DbRef && o)
|
||||
{
|
||||
if (m_Ptr != o.m_Ptr)
|
||||
{
|
||||
m_Ptr = o.m_Ptr;
|
||||
m_Ref = o.m_Ref;
|
||||
o.m_Ptr = NULL;
|
||||
o.m_Ref = NULL;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an equality comparison between two document instances.
|
||||
*/
|
||||
bool operator == (const DbRef & o) const
|
||||
{
|
||||
return (m_Ptr == o.m_Ptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an inequality comparison between two document instances.
|
||||
*/
|
||||
bool operator != (const DbRef & o) const
|
||||
{
|
||||
return (m_Ptr != o.m_Ptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to boolean for use in boolean operations.
|
||||
*/
|
||||
operator bool () const
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed instance pointer.
|
||||
*/
|
||||
operator Pointer ()
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed instance pointer.
|
||||
*/
|
||||
operator ConstPtr () const
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed instance reference.
|
||||
*/
|
||||
operator Reference ()
|
||||
{
|
||||
assert(m_Ptr);
|
||||
return *m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed instance reference.
|
||||
*/
|
||||
operator ConstRef () const
|
||||
{
|
||||
assert(m_Ptr);
|
||||
return *m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Member operator for dereferencing the managed pointer.
|
||||
*/
|
||||
Pointer operator -> () const
|
||||
{
|
||||
assert(m_Ptr);
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Indirection operator for obtaining a reference of the managed pointer.
|
||||
*/
|
||||
Reference operator * () const
|
||||
{
|
||||
assert(m_Ptr);
|
||||
return *m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the raw handle structure pointer.
|
||||
*/
|
||||
Pointer DbPtr()
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the raw handle structure pointer.
|
||||
*/
|
||||
Pointer DbPtr() const
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the number of active references to the managed instance.
|
||||
*/
|
||||
Counter Count() const
|
||||
{
|
||||
return (m_Ptr && m_Ref) ? (*m_Ref) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template < typename T > struct NumLimit;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <> struct NumLimit< char > { static const char Min, Max; };
|
||||
template <> struct NumLimit< signed char > { static const signed char Min, Max; };
|
||||
template <> struct NumLimit< unsigned char > { static const unsigned char Min, Max; };
|
||||
template <> struct NumLimit< signed short > { static const signed short Min, Max; };
|
||||
template <> struct NumLimit< unsigned short > { static const unsigned short Min, Max; };
|
||||
template <> struct NumLimit< signed int > { static const signed int Min, Max; };
|
||||
template <> struct NumLimit< unsigned int > { static const unsigned int Min, Max; };
|
||||
template <> struct NumLimit< signed long > { static const signed long Min, Max; };
|
||||
template <> struct NumLimit< unsigned long > { static const unsigned long Min, Max; };
|
||||
template <> struct NumLimit< signed long long > { static const signed long long Min, Max; };
|
||||
template <> struct NumLimit< unsigned long long > { static const unsigned long long Min, Max; };
|
||||
template <> struct NumLimit< float > { static const float Min, Max; };
|
||||
template <> struct NumLimit< double > { static const double Min, Max; };
|
||||
template <> struct NumLimit< long double > { static const long double Min, Max; };
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template< typename T > inline bool EpsEq(const T a, const T b)
|
||||
{
|
||||
return abs(a - b) <= 0;
|
||||
}
|
||||
|
||||
template <> inline bool EpsEq(const Float32 a, const Float32 b)
|
||||
{
|
||||
return fabs(a - b) <= 0.000001f;
|
||||
}
|
||||
|
||||
template <> inline bool EpsEq(const Float64 a, const Float64 b)
|
||||
{
|
||||
return fabs(a - b) <= 0.000000001d;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template< typename T > inline bool EpsLt(const T a, const T b)
|
||||
{
|
||||
return !EpsEq(a, b) && (a < b);
|
||||
}
|
||||
|
||||
template <> inline bool EpsLt(const Float32 a, const Float32 b)
|
||||
{
|
||||
return !EpsEq(a, b) && (a - b) < 0.000001f;
|
||||
}
|
||||
|
||||
template <> inline bool EpsLt(const Float64 a, const Float64 b)
|
||||
{
|
||||
return !EpsEq(a, b) && (a - b) < 0.000000001d;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template< typename T > inline bool EpsGt(const T a, const T b)
|
||||
{
|
||||
return !EpsEq(a, b) && (a > b);
|
||||
}
|
||||
|
||||
template <> inline bool EpsGt(const Float32 a, const Float32 b)
|
||||
{
|
||||
return !EpsEq(a, b) && (a - b) > 0.000001f;
|
||||
}
|
||||
|
||||
template <> inline bool EpsGt(const Float64 a, const Float64 b)
|
||||
{
|
||||
return !EpsEq(a, b) && (a - b) > 0.000000001d;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template< typename T > inline bool EpsLtEq(const T a, const T b)
|
||||
{
|
||||
return !EpsEq(a, b) || (a < b);
|
||||
}
|
||||
|
||||
template <> inline bool EpsLtEq(const Float32 a, const Float32 b)
|
||||
{
|
||||
return !EpsEq(a, b) || (a - b) < 0.000001f;
|
||||
}
|
||||
|
||||
template <> inline bool EpsLtEq(const Float64 a, const Float64 b)
|
||||
{
|
||||
return !EpsEq(a, b) || (a - b) < 0.000000001d;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template< typename T > inline bool EpsGtEq(const T a, const T b)
|
||||
{
|
||||
return !EpsEq(a, b) || (a > b);
|
||||
}
|
||||
|
||||
template <> inline bool EpsGtEq(const Float32 a, const Float32 b)
|
||||
{
|
||||
return !EpsEq(a, b) || (a - b) > 0.000001f;
|
||||
}
|
||||
|
||||
template <> inline bool EpsGtEq(const Float64 a, const Float64 b)
|
||||
{
|
||||
return !EpsEq(a, b) || (a - b) > 0.000000001d;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template< typename T > inline T Clamp(T val, T min, T max)
|
||||
{
|
||||
return val < min ? min : (val > max ? max : val);
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQMMDB_COMMON_HPP_
|
116
modules/mmdb/Database.cpp
Normal file
116
modules/mmdb/Database.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Database.hpp"
|
||||
#include "SockAddr.hpp"
|
||||
#include "LookupResult.hpp"
|
||||
#include "Module.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqrat.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger Database::Typename(HSQUIRRELVM vm)
|
||||
{
|
||||
static const SQChar name[] = _SC("SqMMDBDatabase");
|
||||
sq_pushstring(vm, name, sizeof(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Database::Validate() const
|
||||
{
|
||||
// Is the document handle valid?
|
||||
if (!m_Db)
|
||||
SqThrowF("Invalid Maxmind database reference");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 Database::Cmp(const Database & o) const
|
||||
{
|
||||
if (m_Db == o.m_Db)
|
||||
return 0;
|
||||
else if (m_Db.m_Ptr > o.m_Db.m_Ptr)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Database::Open(CSStr filepath)
|
||||
{
|
||||
Open(filepath, 0);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Database::Open(CSStr filepath, Uint32 flags)
|
||||
{
|
||||
// Is there a database handle available?
|
||||
if (!m_Db)
|
||||
m_Db = DbRef(true); // Create a database handle
|
||||
// Check if the database handle could be allocated one more time
|
||||
if (!m_Db)
|
||||
SqThrowF("Unable to create a Maxmind database reference");
|
||||
// Are there any other references?
|
||||
else if (m_Db.Count() > 1)
|
||||
// To load new values now, would mean to cause undefined behavior in existing references
|
||||
SqThrowF("Loading is disabled while database is referenced");
|
||||
// Validate the specified file path
|
||||
else if (!filepath || strlen(filepath) <= 0)
|
||||
SqThrowF("Invalid database file path");
|
||||
// Let's attempt to open the specified database
|
||||
const Int32 status = MMDB_open(filepath, flags, m_Db.m_Ptr);
|
||||
// Validate the result of the operation
|
||||
if (status != MMDB_SUCCESS)
|
||||
{
|
||||
// Release the database reference
|
||||
m_Db.Drop();
|
||||
// Now it's safe to throw the error
|
||||
SqThrowF("Unable to open the specified database [%s]", MMDB_strerror(status));
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LookupResult Database::LookupString(CSStr addr)
|
||||
{
|
||||
// Validate the database handle
|
||||
Validate();
|
||||
// Validate the specified string
|
||||
if (!addr || strlen(addr) <= 0)
|
||||
SqThrowF("Invalid address string");
|
||||
// Dummy variables to obtain the status codes
|
||||
int gai_error, mmdb_error;
|
||||
// Attempt to perform the actual lookup
|
||||
MMDB_lookup_result_s result = MMDB_lookup_string(m_Db, addr, &gai_error, &mmdb_error);
|
||||
// Validate the result of the getaddrinfo() function call
|
||||
if (gai_error != 0)
|
||||
SqThrowF("Unable to resolve address (%s) because [%s]", addr, gai_strerror(gai_error));
|
||||
// Validate the lookup status code
|
||||
else if (mmdb_error != MMDB_SUCCESS)
|
||||
SqThrowF("Unable to lookup address (%s) because [%s]", addr, MMDB_strerror(mmdb_error));
|
||||
// Now it's safe to return the lookup result
|
||||
return LookupResult(m_Db, result);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LookupResult Database::LookupSockAddr(SockAddr & addr)
|
||||
{
|
||||
// Validate the database handle
|
||||
Validate();
|
||||
// Validate the specified socket address
|
||||
if (!addr.IsValid())
|
||||
SqThrowF("Invalid address instance");
|
||||
// Dummy variable to obtain the status codes
|
||||
int mmdb_error;
|
||||
// Attempt to perform the actual lookup
|
||||
MMDB_lookup_result_s result = MMDB_lookup_sockaddr(m_Db, addr.GetHandle()->ai_addr, &mmdb_error);
|
||||
// Validate the lookup status code
|
||||
if (mmdb_error != MMDB_SUCCESS)
|
||||
SqThrowF("Unable to lookup address (%s) because [%s]",
|
||||
addr.GetAddress(), MMDB_strerror(mmdb_error));
|
||||
// Now it's safe to return the lookup result
|
||||
return LookupResult(m_Db, result);
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
132
modules/mmdb/Database.hpp
Normal file
132
modules/mmdb/Database.hpp
Normal file
@ -0,0 +1,132 @@
|
||||
#ifndef _SQMMDB_DATABASE_HPP_
|
||||
#define _SQMMDB_DATABASE_HPP_
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Common.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Class that can read/write and alter the contents of INI files.
|
||||
*/
|
||||
class Database
|
||||
{
|
||||
protected:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor. (disabled)
|
||||
*/
|
||||
Database(const Database &);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator. (disabled)
|
||||
*/
|
||||
Database & operator = (const Database &);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the document reference and throw an error if invalid.
|
||||
*/
|
||||
void Validate() const;
|
||||
|
||||
private:
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
DbRef m_Db; /* The main INI document instance. */
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
Database()
|
||||
: m_Db()
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
Database(CSStr filepath)
|
||||
: m_Db()
|
||||
{
|
||||
Open(filepath, 0);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
Database(CSStr filepath, Uint32 flags)
|
||||
: m_Db()
|
||||
{
|
||||
Open(filepath, flags);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~Database()
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to compare two instances of this type.
|
||||
*/
|
||||
Int32 Cmp(const Database & o) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a string.
|
||||
*/
|
||||
CSStr ToString() const
|
||||
{
|
||||
return _SC("");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to retrieve the name from instances of this type.
|
||||
*/
|
||||
static SQInteger Typename(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether this instance references a valid INI document.
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return m_Db;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the number of active references to this document instance.
|
||||
*/
|
||||
Uint32 GetRefCount() const
|
||||
{
|
||||
return m_Db.Count();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to open the specified database.
|
||||
*/
|
||||
void Open(CSStr filepath);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to open the specified database.
|
||||
*/
|
||||
void Open(CSStr filepath, Uint32 addr);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Look up an IP address that is passed in as a null-terminated string.
|
||||
*/
|
||||
LookupResult LookupString(CSStr addr);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Looks up an IP address that has already been resolved by getaddrinfo().
|
||||
*/
|
||||
LookupResult LookupSockAddr(SockAddr & sockaddr);
|
||||
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQMMDB_DATABASE_HPP_
|
382
modules/mmdb/EntryDataList.cpp
Normal file
382
modules/mmdb/EntryDataList.cpp
Normal file
@ -0,0 +1,382 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "EntryDataList.hpp"
|
||||
#include "Module.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqrat.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger EntryDataList::Typename(HSQUIRRELVM vm)
|
||||
{
|
||||
static const SQChar name[] = _SC("SqMMDBEntryDataList");
|
||||
sq_pushstring(vm, name, sizeof(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void EntryDataList::Validate() const
|
||||
{
|
||||
// Is the document handle valid?
|
||||
if (!m_Db)
|
||||
SqThrowF("Invalid Maxmind database reference");
|
||||
// Do we have a valid list?
|
||||
else if (!m_List)
|
||||
SqThrowF("Invalid entry data list");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void EntryDataList::ValidateElem() const
|
||||
{
|
||||
// Is the document handle valid?
|
||||
if (!m_Db)
|
||||
SqThrowF("Invalid Maxmind database reference");
|
||||
// Do we have a valid list?
|
||||
else if (!m_List)
|
||||
SqThrowF("Invalid entry data list");
|
||||
// Do we have a valid element?
|
||||
else if (!m_Elem)
|
||||
SqThrowF("Invalid entry data element");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void EntryDataList::ValidateData() const
|
||||
{
|
||||
// Is the document handle valid?
|
||||
if (!m_Db)
|
||||
SqThrowF("Invalid Maxmind database reference");
|
||||
// Do we have a valid list?
|
||||
else if (!m_List)
|
||||
SqThrowF("Invalid entry data list");
|
||||
// Do we have a valid element?
|
||||
else if (!m_Elem)
|
||||
SqThrowF("Invalid entry data element");
|
||||
// Do we have some valid data?
|
||||
else if (!m_Elem->entry_data.has_data)
|
||||
SqThrowF("Entry data element has no data");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CSStr EntryDataList::AsTypeStr(Uint32 id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case MMDB_DATA_TYPE_EXTENDED: return _SC("extended");
|
||||
case MMDB_DATA_TYPE_POINTER: return _SC("pointer");
|
||||
case MMDB_DATA_TYPE_UTF8_STRING: return _SC("string");
|
||||
case MMDB_DATA_TYPE_DOUBLE: return _SC("double");
|
||||
case MMDB_DATA_TYPE_BYTES: return _SC("bytes");
|
||||
case MMDB_DATA_TYPE_UINT16: return _SC("uint16");
|
||||
case MMDB_DATA_TYPE_UINT32: return _SC("uint32");
|
||||
case MMDB_DATA_TYPE_MAP: return _SC("map");
|
||||
case MMDB_DATA_TYPE_INT32: return _SC("int32");
|
||||
case MMDB_DATA_TYPE_UINT64: return _SC("uint64");
|
||||
case MMDB_DATA_TYPE_UINT128: return _SC("uint128");
|
||||
case MMDB_DATA_TYPE_ARRAY: return _SC("array");
|
||||
case MMDB_DATA_TYPE_CONTAINER: return _SC("container");
|
||||
case MMDB_DATA_TYPE_END_MARKER: return _SC("endmarker");
|
||||
case MMDB_DATA_TYPE_BOOLEAN: return _SC("boolean");
|
||||
case MMDB_DATA_TYPE_FLOAT: return _SC("float");
|
||||
default: return _SC("unknonw");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
EntryDataList::~EntryDataList()
|
||||
{
|
||||
// Do we have to free any list?
|
||||
if (m_List)
|
||||
MMDB_free_entry_data_list(m_List);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 EntryDataList::Cmp(const EntryDataList & o) const
|
||||
{
|
||||
if (m_List == o.m_List)
|
||||
return 0;
|
||||
else if (m_List > o.m_List)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Uint32 EntryDataList::GetCount() const
|
||||
{
|
||||
// Do we even have a list?
|
||||
if (!m_List)
|
||||
return 0;
|
||||
// Get the start of the list
|
||||
Pointer elem = m_List;
|
||||
// Prepare a counter
|
||||
Uint32 count = 1;
|
||||
// Loop through list elements
|
||||
while ((elem = elem->next)) ++count;
|
||||
// Return the counter
|
||||
return count;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool EntryDataList::Next()
|
||||
{
|
||||
// Validate the database and list handle
|
||||
Validate();
|
||||
// Do we have a valid element currently?
|
||||
if (m_Elem)
|
||||
return (m_Elem = m_Elem->next);
|
||||
// Nothing to advance
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool EntryDataList::Advance(Int32 n)
|
||||
{
|
||||
// Validate the database and list handle
|
||||
Validate();
|
||||
// Do we have a valid element currently?
|
||||
if (m_Elem)
|
||||
// Attempt to skip as many elements as possible
|
||||
while ((n > 0) && (m_Elem = m_Elem->next)) --n;
|
||||
// Return whether we have a valid element
|
||||
return m_Elem;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void EntryDataList::Reset()
|
||||
{
|
||||
// Validate the database and list handle
|
||||
Validate();
|
||||
// Go back to the first element
|
||||
m_Elem = m_List;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CSStr EntryDataList::GetString() const
|
||||
{
|
||||
// Validate the database, list and element handle
|
||||
ValidateData();
|
||||
// Attempt to perform the requested conversion
|
||||
switch (m_Elem->entry_data.type)
|
||||
{
|
||||
case MMDB_DATA_TYPE_UTF8_STRING:
|
||||
return m_Elem->entry_data.utf8_string;
|
||||
case MMDB_DATA_TYPE_DOUBLE:
|
||||
return FmtStr("%f", m_Elem->entry_data.double_value);
|
||||
case MMDB_DATA_TYPE_UINT16:
|
||||
return FmtStr("%u", m_Elem->entry_data.uint16);
|
||||
case MMDB_DATA_TYPE_UINT32:
|
||||
return FmtStr("%u", m_Elem->entry_data.uint32);
|
||||
case MMDB_DATA_TYPE_INT32:
|
||||
return FmtStr("%d", m_Elem->entry_data.int32);
|
||||
case MMDB_DATA_TYPE_UINT64:
|
||||
return FmtStr("%llu", m_Elem->entry_data.uint64);
|
||||
case MMDB_DATA_TYPE_BOOLEAN:
|
||||
return m_Elem->entry_data.boolean ? _SC("true") : _SC("false");
|
||||
case MMDB_DATA_TYPE_FLOAT:
|
||||
return FmtStr("%f", m_Elem->entry_data.float_value);
|
||||
default:
|
||||
SqThrowF("Unsupported conversion from (%s) to (string)", AsTypeStr(m_Elem->entry_data.type));
|
||||
}
|
||||
// Shouldn't really reach this point
|
||||
return _SC("");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger EntryDataList::GetInteger() const
|
||||
{
|
||||
// Validate the database, list and element handle
|
||||
ValidateData();
|
||||
// Attempt to perform the requested conversion
|
||||
switch (m_Elem->entry_data.type)
|
||||
{
|
||||
#ifdef _SQ64
|
||||
case MMDB_DATA_TYPE_UTF8_STRING:
|
||||
return strtoll(m_Elem->entry_data.utf8_string, NULL, 10);
|
||||
case MMDB_DATA_TYPE_DOUBLE:
|
||||
return llround(m_Elem->entry_data.double_value);
|
||||
case MMDB_DATA_TYPE_UINT16:
|
||||
return m_Elem->entry_data.uint16;
|
||||
case MMDB_DATA_TYPE_UINT32:
|
||||
return m_Elem->entry_data.uint32;
|
||||
case MMDB_DATA_TYPE_INT32:
|
||||
return m_Elem->entry_data.int32;
|
||||
case MMDB_DATA_TYPE_UINT64:
|
||||
return Clamp(m_Elem->entry_data.uint64, 0, Uint64(NumLimit< SQInteger >::Max));
|
||||
case MMDB_DATA_TYPE_BOOLEAN:
|
||||
return m_Elem->entry_data.boolean ? 1 : 0;
|
||||
case MMDB_DATA_TYPE_FLOAT:
|
||||
return llround(m_Elem->entry_data.float_value);
|
||||
default:
|
||||
SqThrowF("Unsupported conversion from (%s) to (int32)", AsTypeStr(m_Elem->entry_data.type));
|
||||
#else
|
||||
case MMDB_DATA_TYPE_UTF8_STRING:
|
||||
return strtol(m_Elem->entry_data.utf8_string, NULL, 10);
|
||||
case MMDB_DATA_TYPE_DOUBLE:
|
||||
return lround(m_Elem->entry_data.double_value);
|
||||
case MMDB_DATA_TYPE_UINT16:
|
||||
return m_Elem->entry_data.uint16;
|
||||
case MMDB_DATA_TYPE_UINT32:
|
||||
return Clamp(m_Elem->entry_data.uint32, 0U, Uint32(NumLimit< SQInteger >::Max));
|
||||
case MMDB_DATA_TYPE_INT32:
|
||||
return m_Elem->entry_data.int32;
|
||||
case MMDB_DATA_TYPE_UINT64:
|
||||
return Clamp(m_Elem->entry_data.uint64, 0ULL, Uint64(NumLimit< SQInteger >::Max));
|
||||
case MMDB_DATA_TYPE_BOOLEAN:
|
||||
return m_Elem->entry_data.boolean ? 1 : 0;
|
||||
case MMDB_DATA_TYPE_FLOAT:
|
||||
return lround(m_Elem->entry_data.float_value);
|
||||
default:
|
||||
SqThrowF("Unsupported conversion from (%s) to (int64)", AsTypeStr(m_Elem->entry_data.type));
|
||||
#endif // _SQ64
|
||||
}
|
||||
// Shouldn't really reach this point
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQFloat EntryDataList::GetFloat() const
|
||||
{
|
||||
// Validate the database, list and element handle
|
||||
ValidateData();
|
||||
// Attempt to perform the requested conversion
|
||||
switch (m_Elem->entry_data.type)
|
||||
{
|
||||
#ifdef SQUSEDOUBLE
|
||||
case MMDB_DATA_TYPE_UTF8_STRING:
|
||||
return static_cast< SQFloat >(strtod(m_Elem->entry_data.utf8_string, NULL));
|
||||
#else
|
||||
return static_cast< SQFloat >(strtof(m_Elem->entry_data.utf8_string, NULL));
|
||||
#endif // SQUSEDOUBLE
|
||||
case MMDB_DATA_TYPE_DOUBLE:
|
||||
return static_cast< SQFloat >(m_Elem->entry_data.double_value);
|
||||
case MMDB_DATA_TYPE_UINT16:
|
||||
return static_cast< SQFloat >(m_Elem->entry_data.uint16);
|
||||
case MMDB_DATA_TYPE_UINT32:
|
||||
return static_cast< SQFloat >(round(m_Elem->entry_data.uint32));
|
||||
case MMDB_DATA_TYPE_INT32:
|
||||
return static_cast< SQFloat >(round(m_Elem->entry_data.int32));
|
||||
case MMDB_DATA_TYPE_UINT64:
|
||||
return static_cast< SQFloat >(round(m_Elem->entry_data.uint64));
|
||||
case MMDB_DATA_TYPE_BOOLEAN:
|
||||
return m_Elem->entry_data.boolean ? 1.0 : 0.0;
|
||||
case MMDB_DATA_TYPE_FLOAT:
|
||||
return static_cast< SQFloat >(m_Elem->entry_data.float_value);
|
||||
default:
|
||||
SqThrowF("Unsupported conversion from (%s) to (float)", AsTypeStr(m_Elem->entry_data.type));
|
||||
}
|
||||
// Shouldn't really reach this point
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object EntryDataList::GetLong() const
|
||||
{
|
||||
// Validate the database, list and element handle
|
||||
ValidateData();
|
||||
// Where the long number is retrieved
|
||||
Uint64 longint = 0;
|
||||
Int64 slong = 0;
|
||||
// Attempt to perform the requested conversion
|
||||
switch (m_Elem->entry_data.type)
|
||||
{
|
||||
case MMDB_DATA_TYPE_UTF8_STRING:
|
||||
longint = strtoull(m_Elem->entry_data.utf8_string, NULL, 10);
|
||||
break;
|
||||
case MMDB_DATA_TYPE_DOUBLE:
|
||||
{
|
||||
slong = llround(m_Elem->entry_data.double_value);
|
||||
longint = slong >= 0 ? slong : 0;
|
||||
} break;
|
||||
case MMDB_DATA_TYPE_UINT16:
|
||||
longint = m_Elem->entry_data.uint16;
|
||||
break;
|
||||
case MMDB_DATA_TYPE_UINT32:
|
||||
longint = m_Elem->entry_data.uint32;
|
||||
break;
|
||||
case MMDB_DATA_TYPE_INT32:
|
||||
longint = m_Elem->entry_data.int32 >= 0 ? m_Elem->entry_data.int32 : 0;
|
||||
break;
|
||||
case MMDB_DATA_TYPE_UINT64:
|
||||
longint = m_Elem->entry_data.uint64;
|
||||
break;
|
||||
case MMDB_DATA_TYPE_BOOLEAN:
|
||||
longint = m_Elem->entry_data.boolean ? 1 : 0;
|
||||
break;
|
||||
case MMDB_DATA_TYPE_FLOAT:
|
||||
{
|
||||
slong = llround(m_Elem->entry_data.float_value);
|
||||
longint = slong >= 0 ? slong : 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SqThrowF("Unsupported conversion from (%s) to (uint64)", AsTypeStr(m_Elem->entry_data.type));
|
||||
}
|
||||
// Obtain the initial stack size
|
||||
const StackGuard sg(_SqVM);
|
||||
// Push a long integer instance with the requested value on the stack
|
||||
_SqMod->PushULongObject(_SqVM, longint);
|
||||
// Get the object from the stack and return it
|
||||
return Var< Object >(_SqVM, -1).value;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool EntryDataList::GetBool() const
|
||||
{
|
||||
// Validate the database, list and element handle
|
||||
ValidateData();
|
||||
// Attempt to perform the requested conversion
|
||||
switch (m_Elem->entry_data.type)
|
||||
{
|
||||
case MMDB_DATA_TYPE_UTF8_STRING:
|
||||
return !!(m_Elem->entry_data.utf8_string);
|
||||
case MMDB_DATA_TYPE_DOUBLE:
|
||||
return EpsGt(m_Elem->entry_data.double_value, 0.0d);
|
||||
case MMDB_DATA_TYPE_UINT16:
|
||||
return (m_Elem->entry_data.uint16 > 0);
|
||||
case MMDB_DATA_TYPE_UINT32:
|
||||
return (m_Elem->entry_data.uint32 > 0);
|
||||
case MMDB_DATA_TYPE_INT32:
|
||||
return (m_Elem->entry_data.int32 > 0);
|
||||
case MMDB_DATA_TYPE_UINT64:
|
||||
return (m_Elem->entry_data.uint64 > 0);
|
||||
case MMDB_DATA_TYPE_BOOLEAN:
|
||||
return m_Elem->entry_data.boolean;
|
||||
case MMDB_DATA_TYPE_FLOAT:
|
||||
return EpsGt(m_Elem->entry_data.float_value, 0.0f);
|
||||
default:
|
||||
SqThrowF("Unsupported conversion from (%s) to (boolean)", AsTypeStr(m_Elem->entry_data.type));
|
||||
}
|
||||
// Shouldn't really reach this point
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void EntryDataList::DumpTo(CSStr filepath, Int32 indent) const
|
||||
{
|
||||
// Validate the database and list handle
|
||||
Validate();
|
||||
// Validate the specified file path
|
||||
if (!filepath || strlen(filepath) <= 0)
|
||||
SqThrowF("Invalid file path");
|
||||
// Attempt to open the specified file
|
||||
FILE * fp = fopen(filepath, "w");
|
||||
// Validate the file handle
|
||||
if (!fp)
|
||||
SqThrowF("Unable to open file %s", filepath);
|
||||
// Attempt to dump the entry data list
|
||||
Int32 status = MMDB_dump_entry_data_list(fp, m_List, indent);
|
||||
// Close the file handle
|
||||
fclose(fp);
|
||||
// Validate the result of the operation
|
||||
if (status != MMDB_SUCCESS)
|
||||
// Now it's safe to throw the error
|
||||
SqThrowF("Unable to dump the list [%s]", MMDB_strerror(status));
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
291
modules/mmdb/EntryDataList.hpp
Normal file
291
modules/mmdb/EntryDataList.hpp
Normal file
@ -0,0 +1,291 @@
|
||||
#ifndef _SQMMDB_LOOKUPRESULT_HPP_
|
||||
#define _SQMMDB_LOOKUPRESULT_HPP_
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Common.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Class that can be used to traverse a list of results.
|
||||
*/
|
||||
class EntryDataList
|
||||
{
|
||||
protected:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef MMDB_entry_data_list_s Type; // The managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type* Pointer; // Pointer to the managed type.
|
||||
typedef const Type* ConstPtr; // Constant pointer to the managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type& Reference; // Reference to the managed type.
|
||||
typedef const Type& ConstRef; // Constant reference to the managed type.
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the database pointer and list handle and throw an error if invalid.
|
||||
*/
|
||||
void Validate() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Do a regular validation and also validate the currently processed element.
|
||||
*/
|
||||
void ValidateElem() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Do a regular validation and also validate the currently processed element data.
|
||||
*/
|
||||
void ValidateData() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used to retrieve the string representation of the specified type identifier.
|
||||
*/
|
||||
static CSStr AsTypeStr(Uint32 id);
|
||||
|
||||
private:
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
DbRef m_Db; /* The database from which this list comes from. */
|
||||
Pointer m_List; /* The managed entry data list. */
|
||||
Pointer m_Elem; /* The currently processed element from the list. */
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
EntryDataList(const DbRef & db, Pointer list)
|
||||
: m_Db(db), m_List(list), m_Elem(list)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
EntryDataList();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor. (disabled)
|
||||
*/
|
||||
EntryDataList(const EntryDataList &) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
EntryDataList(EntryDataList && o)
|
||||
: m_Db(o.m_Db)
|
||||
, m_List(o.m_List)
|
||||
, m_Elem(o.m_Elem)
|
||||
{
|
||||
o.m_List = nullptr;
|
||||
o.m_Elem = nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~EntryDataList();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator. (disabled)
|
||||
*/
|
||||
EntryDataList & operator = (const EntryDataList &) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move assignment operator.
|
||||
*/
|
||||
EntryDataList & operator = (EntryDataList && o)
|
||||
{
|
||||
if (m_List != o.m_List)
|
||||
{
|
||||
m_Db = o.m_Db;
|
||||
m_List = o.m_List;
|
||||
m_Elem = o.m_Elem;
|
||||
o.m_List = nullptr;
|
||||
o.m_Elem = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal entry data list structure pointer.
|
||||
*/
|
||||
Pointer GetHandle()
|
||||
{
|
||||
return m_List;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal entry data list structure pointer.
|
||||
*/
|
||||
Pointer GetHandle() const
|
||||
{
|
||||
return m_List;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to compare two instances of this type.
|
||||
*/
|
||||
Int32 Cmp(const EntryDataList & o) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a string.
|
||||
*/
|
||||
CSStr ToString() const
|
||||
{
|
||||
return m_Elem ? AsTypeStr(m_Elem->entry_data.type) : _SC("invalid");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to retrieve the name from instances of this type.
|
||||
*/
|
||||
static SQInteger Typename(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether this instance references a valid database and entry data list structure.
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return m_Db && m_List;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether a valid element is currently processed.
|
||||
*/
|
||||
bool HaveElement() const
|
||||
{
|
||||
return m_Elem;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used to retrieve the type of the current element as a string.
|
||||
*/
|
||||
CSStr TypeStr() const
|
||||
{
|
||||
// Validate the database and list handle
|
||||
Validate();
|
||||
// return the requested information
|
||||
return m_Elem ? AsTypeStr(m_Elem->entry_data.type) : _SC("invalid");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the total entries in the list.
|
||||
*/
|
||||
Uint32 GetCount() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Go to the next element.
|
||||
*/
|
||||
bool Next();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Advance a certain number of elements.
|
||||
*/
|
||||
bool Advance(Int32 n);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Go back to the first element in the list.
|
||||
*/
|
||||
void Reset();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether a valid element is currently processed.
|
||||
*/
|
||||
bool HasData() const
|
||||
{
|
||||
// Validate the database, list and element handle
|
||||
ValidateElem();
|
||||
// Return the requested information
|
||||
return m_Elem->entry_data.has_data;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the type identifier of the current element.
|
||||
*/
|
||||
SQInteger GetType() const
|
||||
{
|
||||
// Validate the database, list and element handle
|
||||
ValidateElem();
|
||||
// Return the requested information
|
||||
return static_cast< SQInteger >(m_Elem->entry_data.type);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the offset of the current element.
|
||||
*/
|
||||
SQInteger GetOffset() const
|
||||
{
|
||||
// Validate the database, list and element handle
|
||||
ValidateElem();
|
||||
// Return the requested information
|
||||
return static_cast< SQInteger >(m_Elem->entry_data.offset);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the offset of the next element.
|
||||
*/
|
||||
SQInteger GetOffsetToNext() const
|
||||
{
|
||||
// Validate the database, list and element handle
|
||||
ValidateElem();
|
||||
// Return the requested information
|
||||
return static_cast< SQInteger >(m_Elem->entry_data.offset_to_next);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the offset of the next element.
|
||||
*/
|
||||
SQInteger DataSize() const
|
||||
{
|
||||
// Validate the database, list and element handle
|
||||
ValidateElem();
|
||||
// Return the requested information
|
||||
return static_cast< SQInteger >(m_Elem->entry_data.data_size);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value from the current element as a string.
|
||||
*/
|
||||
CSStr GetString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value from the current element as a native integer.
|
||||
*/
|
||||
SQInteger GetInteger() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value from the current element as a floating point.
|
||||
*/
|
||||
SQFloat GetFloat() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value from the current element as a long integer.
|
||||
*/
|
||||
Object GetLong() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value from the current element as a boolean.
|
||||
*/
|
||||
bool GetBool() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Dumpt the contents of the list to the specified list.
|
||||
*/
|
||||
void DumpTo(CSStr filepath)
|
||||
{
|
||||
DumpTo(filepath, 0);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Dumpt the contents of the list to the specified list.
|
||||
*/
|
||||
void DumpTo(CSStr filepath, Int32 indent) const;
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQMMDB_LOOKUPRESULT_HPP_
|
54
modules/mmdb/LookupResult.cpp
Normal file
54
modules/mmdb/LookupResult.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "LookupResult.hpp"
|
||||
#include "Module.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger LookupResult::Typename(HSQUIRRELVM vm)
|
||||
{
|
||||
static const SQChar name[] = _SC("SqMMDBLookupResult");
|
||||
sq_pushstring(vm, name, sizeof(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LookupResult::Validate() const
|
||||
{
|
||||
// Is the document handle valid?
|
||||
if (!m_Db)
|
||||
SqThrowF("Invalid Maxmind database reference");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LookupResult::LookupResult()
|
||||
: m_Db(), m_Result()
|
||||
{
|
||||
memset(&m_Result, 0, sizeof(Type));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 LookupResult::Cmp(const LookupResult & o) const
|
||||
{
|
||||
if (m_Db == o.m_Db)
|
||||
return 0;
|
||||
else if (m_Db.DbPtr() > o.m_Db.DbPtr())
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
EntryDataList LookupResult::GetValueA(CSStr path, Array & arr) const
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
EntryDataList LookupResult::GetValueT(CSStr path, Table & tbl) const
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
164
modules/mmdb/LookupResult.hpp
Normal file
164
modules/mmdb/LookupResult.hpp
Normal file
@ -0,0 +1,164 @@
|
||||
#ifndef _SQMMDB_LOOKUPRESULT_HPP_
|
||||
#define _SQMMDB_LOOKUPRESULT_HPP_
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Common.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Class that can hold and be used to work with lookup results.
|
||||
*/
|
||||
class LookupResult
|
||||
{
|
||||
// --------------------------------------------------------------------------------------------
|
||||
friend class Database; // Only a valid database instance can construct this type.
|
||||
|
||||
protected:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef MMDB_lookup_result_s Type; // The managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type* Pointer; // Pointer to the managed type.
|
||||
typedef const Type* ConstPtr; // Constant pointer to the managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type& Reference; // Reference to the managed type.
|
||||
typedef const Type& ConstRef; // Constant reference to the managed type.
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the database pointer and throw an error if invalid.
|
||||
*/
|
||||
void Validate() const;
|
||||
|
||||
private:
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
DbRef m_Db; /* The database from which this result comes from. */
|
||||
Type m_Result; /* The managed result structure. */
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Construct and take ownership of a certain result.
|
||||
*/
|
||||
LookupResult(const DbRef & db, Reference result)
|
||||
: m_Db(db), m_Result(result)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor. (null)
|
||||
*/
|
||||
LookupResult();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
LookupResult(const LookupResult &) = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
LookupResult(LookupResult &&) = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~LookupResult()
|
||||
{
|
||||
/* We let the smart reference deal with deallocations if necessary. */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
LookupResult & operator = (const LookupResult &) = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move assignment operator.
|
||||
*/
|
||||
LookupResult & operator = (LookupResult &&) = default;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal result structure reference.
|
||||
*/
|
||||
Reference GetHandle()
|
||||
{
|
||||
return m_Result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal result structure reference.
|
||||
*/
|
||||
ConstRef GetHandle() const
|
||||
{
|
||||
return m_Result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to compare two instances of this type.
|
||||
*/
|
||||
Int32 Cmp(const LookupResult & o) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a string.
|
||||
*/
|
||||
CSStr ToString() const
|
||||
{
|
||||
return FmtStr("%u", m_Result.entry.offset);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to retrieve the name from instances of this type.
|
||||
*/
|
||||
static SQInteger Typename(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether this instance references a valid database and result structure.
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return m_Db && m_Result.found_entry;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether the result contains a valid entry in the associated database.
|
||||
*/
|
||||
bool FoundEntry() const
|
||||
{
|
||||
// Validate the database handle
|
||||
Validate();
|
||||
// Return the requested information
|
||||
return m_Result.found_entry;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the net-mask from the result structure.
|
||||
*/
|
||||
SQInteger GetNetMask() const
|
||||
{
|
||||
// Validate the database handle
|
||||
Validate();
|
||||
// Return the requested information
|
||||
return static_cast< SQInteger >(m_Result.netmask);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Lookup data in the associated result using an array as the path.
|
||||
*/
|
||||
EntryDataList GetValueA(CSStr path, Array & arr) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Lookup data in the associated result using a table as the path.
|
||||
*/
|
||||
EntryDataList GetValueT(CSStr path, Table & tbl) const;
|
||||
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQMMDB_LOOKUPRESULT_HPP_
|
302
modules/mmdb/Module.cpp
Normal file
302
modules/mmdb/Module.cpp
Normal file
@ -0,0 +1,302 @@
|
||||
// --------------------------------------------------------------------------------------------
|
||||
#include "Module.hpp"
|
||||
#include "Common.hpp"
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
#include <sqrat.h>
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
namespace SqMod {
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
PluginFuncs* _Func = NULL;
|
||||
PluginCallbacks* _Clbk = NULL;
|
||||
PluginInfo* _Info = NULL;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
HSQAPI _SqAPI = NULL;
|
||||
HSQEXPORTS _SqMod = NULL;
|
||||
HSQUIRRELVM _SqVM = NULL;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Bind speciffic functions to certain server events.
|
||||
*/
|
||||
void BindCallbacks();
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Undo changes made with BindCallbacks().
|
||||
*/
|
||||
void UnbindCallbacks();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Register the module API under the specified virtual machine.
|
||||
*/
|
||||
void RegisterAPI(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Initialize the plugin by obtaining the API provided by the host plugin.
|
||||
*/
|
||||
void OnSquirrelInitialize()
|
||||
{
|
||||
// Attempt to import the plugin API exported by the host plugin
|
||||
_SqMod = sq_api_import(_Func);
|
||||
// Did we failed to obtain the plugin exports?
|
||||
if(!_SqMod)
|
||||
OutputError("Failed to attach [%s] on host plugin.", SQMMDB_NAME);
|
||||
else
|
||||
{
|
||||
// Obtain the Squirrel API
|
||||
_SqAPI = _SqMod->GetSquirrelAPI();
|
||||
// Expand the Squirrel API into global functions
|
||||
sq_api_expand(_SqAPI);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Load the module on the virtual machine provided by the host module.
|
||||
*/
|
||||
void OnSquirrelLoad()
|
||||
{
|
||||
// Make sure that we have a valid plugin API
|
||||
if (!_SqMod)
|
||||
return; /* Unable to proceed. */
|
||||
// Obtain the Squirrel API and VM
|
||||
_SqVM = _SqMod->GetSquirrelVM();
|
||||
// Make sure that a valid virtual machine exists
|
||||
if (!_SqVM)
|
||||
return; /* Unable to proceed. */
|
||||
// Set this as the default database
|
||||
DefaultVM::Set(_SqVM);
|
||||
// Register the module API
|
||||
RegisterAPI(_SqVM);
|
||||
// Notify about the current status
|
||||
OutputMessage("Registered: %s", SQMMDB_NAME);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* The virtual machine is about to be terminated and script resources should be released.
|
||||
*/
|
||||
void OnSquirrelTerminate()
|
||||
{
|
||||
OutputMessage("Terminating: %s", SQMMDB_NAME);
|
||||
// Release the current database (if any)
|
||||
DefaultVM::Set(NULL);
|
||||
// Release script resources...
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the module API to make sure we don't run into issues.
|
||||
*/
|
||||
bool CheckAPIVer(CCStr ver)
|
||||
{
|
||||
// Obtain the numeric representation of the API version
|
||||
long vernum = strtol(ver, NULL, 10);
|
||||
// Check against version mismatch
|
||||
if (vernum == SQMOD_API_VER)
|
||||
return true;
|
||||
// Log the incident
|
||||
OutputError("API version mismatch on %s", SQMMDB_NAME);
|
||||
OutputMessage("=> Requested: %ld Have: %ld", vernum, SQMOD_API_VER);
|
||||
// Invoker should not attempt to communicate through the module API
|
||||
return false;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* React to command sent by other plugins.
|
||||
*/
|
||||
static int OnInternalCommand(unsigned int type, const char * text)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case SQMOD_INITIALIZE_CMD:
|
||||
if (CheckAPIVer(text))
|
||||
OnSquirrelInitialize();
|
||||
break;
|
||||
case SQMOD_LOAD_CMD:
|
||||
OnSquirrelLoad();
|
||||
break;
|
||||
case SQMOD_TERMINATE_CMD:
|
||||
OnSquirrelTerminate();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* The server was initialized and this plugin was loaded successfully.
|
||||
*/
|
||||
static int OnInitServer()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void OnShutdownServer(void)
|
||||
{
|
||||
// The server may still send callbacks
|
||||
UnbindCallbacks();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BindCallbacks()
|
||||
{
|
||||
_Clbk->OnInitServer = OnInitServer;
|
||||
_Clbk->OnInternalCommand = OnInternalCommand;
|
||||
_Clbk->OnShutdownServer = OnShutdownServer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void UnbindCallbacks()
|
||||
{
|
||||
_Clbk->OnInitServer = NULL;
|
||||
_Clbk->OnInternalCommand = NULL;
|
||||
_Clbk->OnShutdownServer = NULL;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
void RegisterAPI(HSQUIRRELVM vm)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
void OutputMessageImpl(const char * msg, va_list args)
|
||||
{
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO csb_before;
|
||||
GetConsoleScreenBufferInfo( hstdout, &csb_before);
|
||||
SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN);
|
||||
printf("[SQMOD] ");
|
||||
|
||||
SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
|
||||
vprintf(msg, args);
|
||||
puts("");
|
||||
|
||||
SetConsoleTextAttribute(hstdout, csb_before.wAttributes);
|
||||
#else
|
||||
printf("%c[0;32m[SQMOD]%c[0;37m", 27, 27, msg);
|
||||
vprintf(msg, args);
|
||||
puts("");
|
||||
#endif
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
void OutputErrorImpl(const char * msg, va_list args)
|
||||
{
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO csb_before;
|
||||
GetConsoleScreenBufferInfo( hstdout, &csb_before);
|
||||
SetConsoleTextAttribute(hstdout, FOREGROUND_RED | FOREGROUND_INTENSITY);
|
||||
printf("[SQMOD] ");
|
||||
|
||||
SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
|
||||
vprintf(msg, args);
|
||||
puts("");
|
||||
|
||||
SetConsoleTextAttribute(hstdout, csb_before.wAttributes);
|
||||
#else
|
||||
printf("%c[0;32m[SQMOD]%c[0;37m", 27, 27, msg);
|
||||
vprintf(msg, args);
|
||||
puts("");
|
||||
#endif
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
void OutputDebug(const char * msg, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
// Initialize the arguments list
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
// Call the output function
|
||||
OutputMessageImpl(msg, args);
|
||||
// Finalize the arguments list
|
||||
va_end(args);
|
||||
#else
|
||||
SQMOD_UNUSED_VAR(msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
void OutputMessage(const char * msg, ...)
|
||||
{
|
||||
// Initialize the arguments list
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
// Call the output function
|
||||
OutputMessageImpl(msg, args);
|
||||
// Finalize the arguments list
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
void OutputError(const char * msg, ...)
|
||||
{
|
||||
// Initialize the arguments list
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
// Call the output function
|
||||
OutputErrorImpl(msg, args);
|
||||
// Finalize the arguments list
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
SQMOD_API_EXPORT unsigned int VcmpPluginInit(PluginFuncs* functions, PluginCallbacks* callbacks, PluginInfo* info)
|
||||
{
|
||||
using namespace SqMod;
|
||||
// Output plugin header
|
||||
puts("");
|
||||
OutputMessage("--------------------------------------------------------------------");
|
||||
OutputMessage("Plugin: %s", SQMMDB_NAME);
|
||||
OutputMessage("Author: %s", SQMMDB_AUTHOR);
|
||||
OutputMessage("Legal: %s", SQMMDB_COPYRIGHT);
|
||||
OutputMessage("--------------------------------------------------------------------");
|
||||
puts("");
|
||||
// Attempt to find the host plugin ID
|
||||
int host_plugin_id = functions->FindPlugin((char *)(SQMOD_HOST_NAME));
|
||||
// See if our plugin was loaded after the host plugin
|
||||
if (host_plugin_id < 0)
|
||||
{
|
||||
OutputError("%s could find the host plugin", SQMMDB_NAME);
|
||||
// Don't load!
|
||||
return SQMOD_FAILURE;
|
||||
}
|
||||
// Should never reach this point but just in case
|
||||
else if (host_plugin_id > (info->nPluginId))
|
||||
{
|
||||
OutputError("%s loaded after the host plugin", SQMMDB_NAME);
|
||||
// Don't load!
|
||||
return SQMOD_FAILURE;
|
||||
}
|
||||
// Store server proxies
|
||||
_Func = functions;
|
||||
_Clbk = callbacks;
|
||||
_Info = info;
|
||||
// Assign plugin information
|
||||
_Info->uPluginVer = SQMMDB_VERSION;
|
||||
strcpy(_Info->szName, SQMMDB_HOST_NAME);
|
||||
// Bind callbacks
|
||||
BindCallbacks();
|
||||
// Notify that the plugin was successfully loaded
|
||||
OutputMessage("Successfully loaded %s", SQMMDB_NAME);
|
||||
// Dummy spacing
|
||||
puts("");
|
||||
// Done!
|
||||
return SQMOD_SUCCESS;
|
||||
}
|
41
modules/mmdb/Module.hpp
Normal file
41
modules/mmdb/Module.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef _SQMMDB_MODULE_HPP_
|
||||
#define _SQMMDB_MODULE_HPP_
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "SqMod.h"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Proxies to comunicate with the server.
|
||||
*/
|
||||
extern PluginFuncs* _Func;
|
||||
extern PluginCallbacks* _Clbk;
|
||||
extern PluginInfo* _Info;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Proxies to comunicate with the Squirrel plugin.
|
||||
*/
|
||||
extern HSQAPI _SqAPI;
|
||||
extern HSQEXPORTS _SqMod;
|
||||
extern HSQUIRRELVM _SqVM;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Output a message only if the _DEBUG was defined.
|
||||
*/
|
||||
void OutputDebug(const char * msg, ...);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Output a formatted user message to the console.
|
||||
*/
|
||||
void OutputMessage(const char * msg, ...);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Output a formatted error message to the console.
|
||||
*/
|
||||
void OutputError(const char * msg, ...);
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQMMDB_MODULE_HPP_
|
68
modules/mmdb/SockAddr.cpp
Normal file
68
modules/mmdb/SockAddr.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Sockaddr.hpp"
|
||||
#include "Module.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger SockAddr::Typename(HSQUIRRELVM vm)
|
||||
{
|
||||
static const SQChar name[] = _SC("SqMMDBSockAddr");
|
||||
sq_pushstring(vm, name, sizeof(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SockAddr::Validate() const
|
||||
{
|
||||
// Is the document handle valid?
|
||||
if (!m_Handle)
|
||||
SqThrowF("Invalid sockaddr structure handle");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SockAddr::SockAddr(CSStr addr)
|
||||
: m_Handle(NULL), m_Addres(_SC(""))
|
||||
{
|
||||
struct addrinfo hints;
|
||||
// Configure the hints structure
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
// We set ai_socktype so that we only get one result back
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
// Attempt to obtain information about the specified address
|
||||
Int32 status = getaddrinfo(addr, NULL, &hints, &m_Handle);
|
||||
// Validate the success of the operation
|
||||
if (!status)
|
||||
{
|
||||
// See if we must free any handles (just in case)
|
||||
if (m_Handle)
|
||||
freeaddrinfo(m_Handle);
|
||||
// Now it's safe to throw the error
|
||||
SqThrowF("Unable to query the specified address for information [%s]", gai_strerror(status));
|
||||
}
|
||||
// Save the specified string address
|
||||
m_Addres.assign(addr ? addr : _SC(""));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SockAddr::~SockAddr()
|
||||
{
|
||||
if (m_Handle)
|
||||
freeaddrinfo(m_Handle);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 SockAddr::Cmp(const SockAddr & o) const
|
||||
{
|
||||
if (m_Handle == o.m_Handle)
|
||||
return 0;
|
||||
else if (m_Handle > o.m_Handle)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
} // Namespace:: SqMod
|
147
modules/mmdb/Sockaddr.hpp
Normal file
147
modules/mmdb/Sockaddr.hpp
Normal file
@ -0,0 +1,147 @@
|
||||
#ifndef _SQMMDB_SOCKADDR_HPP_
|
||||
#define _SQMMDB_SOCKADDR_HPP_
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Common.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Class that can obtain information from string addresses and be used repeatedly thereafter.
|
||||
*/
|
||||
class SockAddr
|
||||
{
|
||||
protected:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef struct addrinfo Type; // The managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type* Pointer; // Pointer to the managed type.
|
||||
typedef const Type* ConstPtr; // Constant pointer to the managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type& Reference; // Reference to the managed type.
|
||||
typedef const Type& ConstRef; // Constant reference to the managed type.
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the sockaddr pointer and throw an error if invalid.
|
||||
*/
|
||||
void Validate() const;
|
||||
|
||||
private:
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
Pointer m_Handle; /* The managed sockaddr structure. */
|
||||
String m_Addres; /* The address that was queried for information. */
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
SockAddr()
|
||||
: m_Handle(NULL), m_Addres(_SC(""))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
SockAddr(CSStr addr);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor. (disabled)
|
||||
*/
|
||||
SockAddr(const SockAddr &) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
SockAddr(SockAddr && o)
|
||||
: m_Handle(o.m_Handle)
|
||||
, m_Addres(o.m_Addres)
|
||||
{
|
||||
o.m_Handle = nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~SockAddr();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator. (disabled)
|
||||
*/
|
||||
SockAddr & operator = (const SockAddr &) = delete;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move assignment operator.
|
||||
*/
|
||||
SockAddr & operator = (SockAddr && o)
|
||||
{
|
||||
if (m_Handle != o.m_Handle)
|
||||
{
|
||||
m_Handle = o.m_Handle;
|
||||
m_Addres = o.m_Addres;
|
||||
o.m_Handle = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal addrinfo structure pointer.
|
||||
*/
|
||||
Pointer GetHandle()
|
||||
{
|
||||
return m_Handle;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal addrinfo structure pointer.
|
||||
*/
|
||||
Pointer GetHandle() const
|
||||
{
|
||||
return m_Handle;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to compare two instances of this type.
|
||||
*/
|
||||
Int32 Cmp(const SockAddr & o) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a string.
|
||||
*/
|
||||
CSStr ToString() const
|
||||
{
|
||||
return m_Addres.c_str();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to retrieve the name from instances of this type.
|
||||
*/
|
||||
static SQInteger Typename(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether this instance references a valid addrinfo structure.
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return m_Handle;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated string address.
|
||||
*/
|
||||
CSStr GetAddress() const
|
||||
{
|
||||
return m_Addres.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQMMDB_SOCKADDR_HPP_
|
@ -389,7 +389,7 @@ SQInteger Connection::ExecF(HSQUIRRELVM vm)
|
||||
SQRESULT ret = sqstd_format(vm, 3, &len, &sql);
|
||||
// Did the format failed?
|
||||
if (SQ_FAILED(ret))
|
||||
return ret;
|
||||
return ret; // Propagate the exception
|
||||
// Attempt to execute the resulted query
|
||||
if ((inst.value->m_Handle = sqlite3_exec(inst.value->m_Handle, sql, NULL, NULL, NULL)) != SQLITE_OK)
|
||||
{
|
||||
@ -399,7 +399,7 @@ SQInteger Connection::ExecF(HSQUIRRELVM vm)
|
||||
// Push the result onto the stack
|
||||
sq_pushinteger(vm, sqlite3_changes(inst.value->m_Handle));
|
||||
}
|
||||
// All methods of retrieving the message value failed
|
||||
// All methods of retrieving the string value failed
|
||||
else
|
||||
return sq_throwerror(vm, "Unable to extract the query string");
|
||||
// At this point we should have a return value on the stack
|
||||
@ -455,14 +455,14 @@ SQInteger Connection::QueueF(HSQUIRRELVM vm)
|
||||
SQRESULT ret = sqstd_format(vm, 3, &len, &sql);
|
||||
// Did the format failed?
|
||||
if (SQ_FAILED(ret))
|
||||
return ret;
|
||||
return ret; // Propagate the exception
|
||||
// Is there even a query to queue?
|
||||
else if (IsQueryEmpty(sql))
|
||||
return sq_throwerror(vm,"No query to queue");
|
||||
// Attempt to queue the specified query
|
||||
inst.value->m_Handle->mQueue.push_back(sql);
|
||||
}
|
||||
// All methods of retrieving the message value failed
|
||||
// All methods of retrieving the string value failed
|
||||
else
|
||||
return sq_throwerror(vm, "Unable to extract the query string");
|
||||
// This function does not return a value
|
||||
@ -519,7 +519,7 @@ SQInteger Connection::QueryF(HSQUIRRELVM vm)
|
||||
SQRESULT ret = sqstd_format(vm, 3, &len, &sql);
|
||||
// Did the format failed?
|
||||
if (SQ_FAILED(ret))
|
||||
return ret;
|
||||
return ret; // Propagate the exception
|
||||
// Attempt to create a statement with the specified query
|
||||
try
|
||||
{
|
||||
@ -530,7 +530,7 @@ SQInteger Connection::QueryF(HSQUIRRELVM vm)
|
||||
return sq_throwerror(vm, e.Message().c_str());
|
||||
}
|
||||
}
|
||||
// All methods of retrieving the message value failed
|
||||
// All methods of retrieving the string value failed
|
||||
else
|
||||
return sq_throwerror(vm, "Unable to extract the query string");
|
||||
// At this point we should have a return value on the stack
|
||||
|
Reference in New Issue
Block a user