mirror of
				https://github.com/VCMP-SqMod/SqMod.git
				synced 2025-11-04 00:07:19 +01:00 
			
		
		
		
	Initial implementation of the MaxmindDB module.
This commit is contained in:
		@@ -106,9 +106,9 @@
 | 
			
		||||
				<Option type="3" />
 | 
			
		||||
				<Option compiler="gcc" />
 | 
			
		||||
				<Compiler>
 | 
			
		||||
					<Add option="-fPIC" />
 | 
			
		||||
					<Add option="-m32" />
 | 
			
		||||
					<Add option="-g" />
 | 
			
		||||
					<Add option="-fPIC" />
 | 
			
		||||
					<Add option="-D_DEBUG" />
 | 
			
		||||
					<Add directory="../config/gcc32" />
 | 
			
		||||
				</Compiler>
 | 
			
		||||
@@ -129,8 +129,8 @@
 | 
			
		||||
				<Option compiler="gcc" />
 | 
			
		||||
				<Compiler>
 | 
			
		||||
					<Add option="-O3" />
 | 
			
		||||
					<Add option="-m32" />
 | 
			
		||||
					<Add option="-fPIC" />
 | 
			
		||||
					<Add option="-m32" />
 | 
			
		||||
					<Add option="-DNDEBUG" />
 | 
			
		||||
					<Add directory="../config/gcc32" />
 | 
			
		||||
				</Compiler>
 | 
			
		||||
@@ -410,6 +410,7 @@
 | 
			
		||||
		<Compiler>
 | 
			
		||||
			<Add option="-Wextra" />
 | 
			
		||||
			<Add option="-Wall" />
 | 
			
		||||
			<Add option="-std=c99" />
 | 
			
		||||
			<Add option="-std=c++14" />
 | 
			
		||||
			<Add option="-DSQMOD_PLUGIN_API" />
 | 
			
		||||
			<Add option="-DSCRAT_USE_EXCEPTIONS" />
 | 
			
		||||
@@ -428,10 +429,18 @@
 | 
			
		||||
		<Unit filename="../modules/mmdb/Common.hpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/Database.cpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/Database.hpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/Description.cpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/Description.hpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/EntryData.cpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/EntryData.hpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/EntryDataList.cpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/EntryDataList.hpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/Handle/Database.cpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/Handle/Database.hpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/LookupResult.cpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/LookupResult.hpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/Metadata.cpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/Metadata.hpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/Module.cpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/SockAddr.cpp" />
 | 
			
		||||
		<Unit filename="../modules/mmdb/Sockaddr.hpp" />
 | 
			
		||||
 
 | 
			
		||||
@@ -7,5 +7,6 @@
 | 
			
		||||
		<Project filename="ModXML.cbp" />
 | 
			
		||||
		<Project filename="ModSQLite.cbp" />
 | 
			
		||||
		<Project filename="ModMySQL.cbp" />
 | 
			
		||||
		<Project filename="ModMMDB.cbp" />
 | 
			
		||||
	</Workspace>
 | 
			
		||||
</CodeBlocks_workspace_file>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,24 +2,451 @@
 | 
			
		||||
#include "Common.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
DbRef::Pointer DbRef::Create()
 | 
			
		||||
// N[0] - contains least significant bits, N[3] - most significant
 | 
			
		||||
static SQChar * Bin128ToDec(const Uint32 N[4])
 | 
			
		||||
{
 | 
			
		||||
    return reinterpret_cast< Pointer >(std::malloc(sizeof(Type)));
 | 
			
		||||
    // log10(x) = log2(x) / log2(10) ~= log2(x) / 3.322
 | 
			
		||||
    static SQChar s[128 / 3 + 1 + 1];
 | 
			
		||||
    Uint32 n[4];
 | 
			
		||||
    SQChar * p = s;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    std::memset(s, '0', sizeof(s) - 1);
 | 
			
		||||
    s[sizeof(s) - 1] = '\0';
 | 
			
		||||
 | 
			
		||||
    std::memcpy(n, N, sizeof(n));
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < 128; i++)
 | 
			
		||||
    {
 | 
			
		||||
        int j, carry;
 | 
			
		||||
 | 
			
		||||
        carry = (n[3] >= 0x80000000);
 | 
			
		||||
        // Shift n[] left, doubling it
 | 
			
		||||
        n[3] = ((n[3] << 1) & 0xFFFFFFFF) + (n[2] >= 0x80000000);
 | 
			
		||||
        n[2] = ((n[2] << 1) & 0xFFFFFFFF) + (n[1] >= 0x80000000);
 | 
			
		||||
        n[1] = ((n[1] << 1) & 0xFFFFFFFF) + (n[0] >= 0x80000000);
 | 
			
		||||
        n[0] = ((n[0] << 1) & 0xFFFFFFFF);
 | 
			
		||||
 | 
			
		||||
        // Add s[] to itself in decimal, doubling it
 | 
			
		||||
        for (j = sizeof(s) - 2; j >= 0; j--)
 | 
			
		||||
        {
 | 
			
		||||
            s[j] += s[j] - '0' + carry;
 | 
			
		||||
 | 
			
		||||
            carry = (s[j] > '9');
 | 
			
		||||
 | 
			
		||||
            if (carry)
 | 
			
		||||
            {
 | 
			
		||||
                s[j] -= 10;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while ((p[0] == '0') && (p < &s[sizeof(s) - 2]))
 | 
			
		||||
    {
 | 
			
		||||
        p++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void DbRef::Destroy(Pointer db)
 | 
			
		||||
CSStr AsTypeStr(Uint32 id)
 | 
			
		||||
{
 | 
			
		||||
    if (db)
 | 
			
		||||
    switch (id)
 | 
			
		||||
    {
 | 
			
		||||
        std::free(db);
 | 
			
		||||
        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");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
bool GetEntryAsBool(const MMDB_entry_data_s & ed)
 | 
			
		||||
{
 | 
			
		||||
    bool value = false;
 | 
			
		||||
    // Identify the type of entry data
 | 
			
		||||
    switch (ed.type)
 | 
			
		||||
    {
 | 
			
		||||
        case MMDB_DATA_TYPE_POINTER: {
 | 
			
		||||
            value = ed.pointer > 0;
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UTF8_STRING: {
 | 
			
		||||
            if (ed.data_size > 0)
 | 
			
		||||
            {
 | 
			
		||||
                value = ConvTo< bool >::From(reinterpret_cast< CSStr >(ed.utf8_string));
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_DOUBLE: {
 | 
			
		||||
            value = ConvTo< bool >::From(ed.double_value);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_BYTES: {
 | 
			
		||||
            for (Uint32 i = 0; i < ed.data_size; ++i)
 | 
			
		||||
            {
 | 
			
		||||
                if (ed.bytes[i] != 0)
 | 
			
		||||
                {
 | 
			
		||||
                    value = true;
 | 
			
		||||
                    // Found somethinf that isn't 0
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT16: {
 | 
			
		||||
            value = ConvTo< bool >::From(ed.uint16);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT32: {
 | 
			
		||||
            value = ConvTo< bool >::From(ed.uint16);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_INT32: {
 | 
			
		||||
            value = ConvTo< bool >::From(ed.uint16);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT64: {
 | 
			
		||||
            value = ConvTo< bool >::From(ed.uint16);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT128: {
 | 
			
		||||
#if defined(MMDB_UINT128_IS_BYTE_ARRAY) && (MMDB_UINT128_IS_BYTE_ARRAY == 1)
 | 
			
		||||
            for (Uint32 i = 0; i < sizeof(ed.uint128); ++i)
 | 
			
		||||
            {
 | 
			
		||||
                if (ed.uint128[i] != 0)
 | 
			
		||||
                {
 | 
			
		||||
                    value = true;
 | 
			
		||||
                    // Found somethinf that isn't 0
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
#else
 | 
			
		||||
            value = ed.uint128 > 0;
 | 
			
		||||
#endif // MMDB_UINT128_IS_BYTE_ARRAY
 | 
			
		||||
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_BOOLEAN: {
 | 
			
		||||
            value = ed.boolean ? true : false;
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_FLOAT: {
 | 
			
		||||
            value = ConvTo< bool >::From(ed.float_value);
 | 
			
		||||
        } break;
 | 
			
		||||
        default:
 | 
			
		||||
            STHROWF("Unsupported conversion from (%s) to (boolean)", AsTypeStr(ed.type));
 | 
			
		||||
    }
 | 
			
		||||
    // Return the extracted value
 | 
			
		||||
    return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQInteger GetEntryAsInteger(const MMDB_entry_data_s & ed)
 | 
			
		||||
{
 | 
			
		||||
    SQInteger value = 0;
 | 
			
		||||
    // Identify the type of entry data
 | 
			
		||||
    switch (ed.type)
 | 
			
		||||
    {
 | 
			
		||||
        case MMDB_DATA_TYPE_POINTER: {
 | 
			
		||||
            value = static_cast< SQInteger >(ed.pointer);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UTF8_STRING: {
 | 
			
		||||
            if (ed.data_size > 0)
 | 
			
		||||
            {
 | 
			
		||||
                value = ConvTo< SQInteger >::From(reinterpret_cast< CSStr >(ed.utf8_string));
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_DOUBLE: {
 | 
			
		||||
            value = ConvTo< SQInteger >::From(ed.double_value);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_BYTES: {
 | 
			
		||||
            std::memcpy(&value, ed.bytes, Clamp(ed.data_size, 0U, sizeof(value)));
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT16: {
 | 
			
		||||
            value = ConvTo< SQInteger >::From(ed.uint16);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT32: {
 | 
			
		||||
            value = ConvTo< SQInteger >::From(ed.uint32);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_INT32: {
 | 
			
		||||
            value = ConvTo< SQInteger >::From(ed.int32);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT64: {
 | 
			
		||||
            value = ConvTo< SQInteger >::From(ed.uint64);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT128: {
 | 
			
		||||
#if defined(MMDB_UINT128_IS_BYTE_ARRAY) && (MMDB_UINT128_IS_BYTE_ARRAY == 1)
 | 
			
		||||
            std::memcpy(&value, ed.uint128, sizeof(value));
 | 
			
		||||
#else
 | 
			
		||||
            std::memcpy(&value, &ed.uint128, sizeof(value));
 | 
			
		||||
#endif // MMDB_UINT128_IS_BYTE_ARRAY
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_BOOLEAN: {
 | 
			
		||||
            value = ed.boolean ? 1 : 0;
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_FLOAT: {
 | 
			
		||||
            value = ConvTo< SQInteger >::From(ed.float_value);
 | 
			
		||||
        } break;
 | 
			
		||||
        default:
 | 
			
		||||
            STHROWF("Unsupported conversion from (%s) to (integer)", AsTypeStr(ed.type));
 | 
			
		||||
    }
 | 
			
		||||
    // Return the extracted value
 | 
			
		||||
    return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQFloat GetEntryAsFloat(const MMDB_entry_data_s & ed)
 | 
			
		||||
{
 | 
			
		||||
    SQFloat value = 0.0;
 | 
			
		||||
    // Identify the type of entry data
 | 
			
		||||
    switch (ed.type)
 | 
			
		||||
    {
 | 
			
		||||
        case MMDB_DATA_TYPE_POINTER: {
 | 
			
		||||
            value = ConvTo< SQFloat >::From(static_cast< SQInteger >(ed.pointer));
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UTF8_STRING: {
 | 
			
		||||
            if (ed.data_size > 0)
 | 
			
		||||
            {
 | 
			
		||||
                value = ConvTo< SQFloat >::From(reinterpret_cast< CSStr >(ed.utf8_string));
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_DOUBLE: {
 | 
			
		||||
            value = ConvTo< SQFloat >::From(ed.double_value);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_BYTES: {
 | 
			
		||||
            // Not our problem if the result will be junk!
 | 
			
		||||
            std::memcpy(&value, ed.bytes, Clamp(ed.data_size, 0U, sizeof(value)));
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT16: {
 | 
			
		||||
            value = ConvTo< SQFloat >::From(ed.uint16);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT32: {
 | 
			
		||||
            value = ConvTo< SQFloat >::From(ed.uint32);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_INT32: {
 | 
			
		||||
            value = ConvTo< SQFloat >::From(ed.int32);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT64: {
 | 
			
		||||
            value = ConvTo< SQFloat >::From(ed.uint64);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT128: {
 | 
			
		||||
            SQInteger num;
 | 
			
		||||
            // Convert to integer first
 | 
			
		||||
#if defined(MMDB_UINT128_IS_BYTE_ARRAY) && (MMDB_UINT128_IS_BYTE_ARRAY == 1)
 | 
			
		||||
            std::memcpy(&num, ed.uint128, sizeof(num));
 | 
			
		||||
#else
 | 
			
		||||
            std::memcpy(&num, &ed.uint128, sizeof(num));
 | 
			
		||||
#endif // MMDB_UINT128_IS_BYTE_ARRAY
 | 
			
		||||
            // Now convert to float
 | 
			
		||||
            value = ConvTo< SQFloat >::From(num);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_BOOLEAN: {
 | 
			
		||||
            value = ed.boolean ? 1.0 : 0.0;
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_FLOAT: {
 | 
			
		||||
            value = ConvTo< SQFloat >::From(ed.float_value);
 | 
			
		||||
        } break;
 | 
			
		||||
        default:
 | 
			
		||||
            STHROWF("Unsupported conversion from (%s) to (float)", AsTypeStr(ed.type));
 | 
			
		||||
    }
 | 
			
		||||
    // Return the extracted value
 | 
			
		||||
    return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object GetEntryAsLong(const MMDB_entry_data_s & ed)
 | 
			
		||||
{
 | 
			
		||||
    Uint64 value = 0;
 | 
			
		||||
    // Identify the type of entry data
 | 
			
		||||
    switch (ed.type)
 | 
			
		||||
    {
 | 
			
		||||
        case MMDB_DATA_TYPE_POINTER: {
 | 
			
		||||
            value = static_cast< Uint64 >(ed.pointer);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UTF8_STRING: {
 | 
			
		||||
            if (ed.data_size > 0)
 | 
			
		||||
            {
 | 
			
		||||
                value = ConvTo< Uint64 >::From(reinterpret_cast< CSStr >(ed.utf8_string));
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_DOUBLE: {
 | 
			
		||||
            value = ConvTo< Uint64 >::From(ed.double_value);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_BYTES: {
 | 
			
		||||
            std::memcpy(&value, ed.bytes, Clamp(ed.data_size, 0U, sizeof(value)));
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT16: {
 | 
			
		||||
            value = ConvTo< Uint64 >::From(ed.uint16);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT32: {
 | 
			
		||||
            value = ConvTo< Uint64 >::From(ed.uint32);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_INT32: {
 | 
			
		||||
            value = ConvTo< Uint64 >::From(ed.int32);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT64: {
 | 
			
		||||
            value = ConvTo< Uint64 >::From(ed.uint64);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT128: {
 | 
			
		||||
#if defined(MMDB_UINT128_IS_BYTE_ARRAY) && (MMDB_UINT128_IS_BYTE_ARRAY == 1)
 | 
			
		||||
            std::memcpy(&value, ed.uint128, sizeof(value));
 | 
			
		||||
#else
 | 
			
		||||
            std::memcpy(&value, &ed.uint128, sizeof(value));
 | 
			
		||||
#endif // MMDB_UINT128_IS_BYTE_ARRAY
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_BOOLEAN: {
 | 
			
		||||
            value = ed.boolean ? 1 : 0;
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_FLOAT: {
 | 
			
		||||
            value = ConvTo< Uint64 >::From(ed.float_value);
 | 
			
		||||
        } break;
 | 
			
		||||
        default:
 | 
			
		||||
            STHROWF("Unsupported conversion from (%s) to (long)", AsTypeStr(ed.type));
 | 
			
		||||
    }
 | 
			
		||||
    // Obtain the initial stack size
 | 
			
		||||
    const StackGuard sg;
 | 
			
		||||
    // Push a long integer instance with the requested value on the stack
 | 
			
		||||
    SqMod_PushULongObject(DefaultVM::Get(), value);
 | 
			
		||||
    // Obtain the object from the stack and return it
 | 
			
		||||
    return Var< Object >(DefaultVM::Get(), -1).value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object GetEntryAsString(const MMDB_entry_data_s & ed)
 | 
			
		||||
{
 | 
			
		||||
    // Obtain the initial stack size
 | 
			
		||||
    const StackGuard sg;
 | 
			
		||||
    // The default vm
 | 
			
		||||
    HSQUIRRELVM vm = DefaultVM::Get();
 | 
			
		||||
    // Identify the type of entry data
 | 
			
		||||
    switch (ed.type)
 | 
			
		||||
    {
 | 
			
		||||
        case MMDB_DATA_TYPE_POINTER: {
 | 
			
		||||
            sq_pushstring(vm, ToStrF("%p", ed.pointer), -1);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UTF8_STRING: {
 | 
			
		||||
            sq_pushstring(vm, ed.utf8_string, ed.data_size);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_DOUBLE: {
 | 
			
		||||
            sq_pushstring(vm, ToStrF("%f", ed.double_value), -1);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_BYTES: {
 | 
			
		||||
            sq_pushstring(vm, reinterpret_cast< CSStr >(ed.bytes), ed.data_size / sizeof(SQChar));
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT16: {
 | 
			
		||||
            sq_pushstring(vm, ToStrF("%u", ed.uint16), -1);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT32: {
 | 
			
		||||
            sq_pushstring(vm, ToStrF("%u", ed.uint32), -1);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_INT32: {
 | 
			
		||||
            sq_pushstring(vm, ToStrF("%d", ed.int32), -1);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT64: {
 | 
			
		||||
            sq_pushstring(vm, ToStrF("%llu", ed.uint64), -1);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT128: {
 | 
			
		||||
#if defined(MMDB_UINT128_IS_BYTE_ARRAY) && (MMDB_UINT128_IS_BYTE_ARRAY == 1)
 | 
			
		||||
            sq_pushstring(vm, Bin128ToDec(reinterpret_cast< const Uint32 * >(ed.uint128)), -1);
 | 
			
		||||
#else
 | 
			
		||||
            sq_pushstring(vm, Bin128ToDec(reinterpret_cast< const Uint32 * >(&ed.uint128)), -1);
 | 
			
		||||
#endif // MMDB_UINT128_IS_BYTE_ARRAY
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_BOOLEAN: {
 | 
			
		||||
            sq_pushstring(vm, ed.boolean ? _SC("true") : _SC("false"), -1);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_FLOAT: {
 | 
			
		||||
            sq_pushstring(vm, ToStrF("%f", ed.float_value), -1);
 | 
			
		||||
        } break;
 | 
			
		||||
        default:
 | 
			
		||||
            STHROWF("Unsupported conversion from (%s) to (string)", AsTypeStr(ed.type));
 | 
			
		||||
    }
 | 
			
		||||
    // Obtain the object from the stack and return it
 | 
			
		||||
    return Var< Object >(vm, -1).value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object GetEntryAsBytes(const MMDB_entry_data_s & ed)
 | 
			
		||||
{
 | 
			
		||||
    // Obtain the initial stack size
 | 
			
		||||
    const StackGuard sg;
 | 
			
		||||
    // The result of operations
 | 
			
		||||
    SQRESULT res = SQ_OK;
 | 
			
		||||
    // The default vm
 | 
			
		||||
    HSQUIRRELVM vm = DefaultVM::Get();
 | 
			
		||||
    // Identify the type of entry data
 | 
			
		||||
    switch (ed.type)
 | 
			
		||||
    {
 | 
			
		||||
        case MMDB_DATA_TYPE_POINTER: {
 | 
			
		||||
            res = SqMod_PushBufferData(vm,
 | 
			
		||||
                    reinterpret_cast< const char * >(&ed.pointer), sizeof(ed.pointer), 0);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UTF8_STRING: {
 | 
			
		||||
            res = SqMod_PushBufferData(vm,
 | 
			
		||||
                    reinterpret_cast< const char * >(ed.utf8_string), ed.data_size, 0);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_DOUBLE: {
 | 
			
		||||
            res = SqMod_PushBufferData(vm,
 | 
			
		||||
                    reinterpret_cast< const char * >(&ed.double_value), sizeof(ed.double_value), 0);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_BYTES: {
 | 
			
		||||
            res = SqMod_PushBufferData(vm,
 | 
			
		||||
                    reinterpret_cast< const char * >(ed.bytes), ed.data_size, 0);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT16: {
 | 
			
		||||
            res = SqMod_PushBufferData(vm,
 | 
			
		||||
                    reinterpret_cast< const char * >(&ed.uint16), sizeof(ed.uint16), 0);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT32: {
 | 
			
		||||
            res = SqMod_PushBufferData(vm,
 | 
			
		||||
                    reinterpret_cast< const char * >(&ed.uint32), sizeof(ed.uint32), 0);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_INT32: {
 | 
			
		||||
            res = SqMod_PushBufferData(vm,
 | 
			
		||||
                    reinterpret_cast< const char * >(&ed.int32), sizeof(ed.int32), 0);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT64: {
 | 
			
		||||
            res = SqMod_PushBufferData(vm,
 | 
			
		||||
                    reinterpret_cast< const char * >(&ed.uint64), sizeof(ed.uint64), 0);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_UINT128: {
 | 
			
		||||
            res = SqMod_PushBufferData(vm,
 | 
			
		||||
                    reinterpret_cast< const char * >(&ed.uint128), sizeof(ed.uint128), 0);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_BOOLEAN: {
 | 
			
		||||
            res = SqMod_PushBufferData(vm,
 | 
			
		||||
                    reinterpret_cast< const char * >(&ed.boolean), sizeof(ed.boolean), 0);
 | 
			
		||||
        } break;
 | 
			
		||||
        case MMDB_DATA_TYPE_FLOAT: {
 | 
			
		||||
            res = SqMod_PushBufferData(vm,
 | 
			
		||||
                                 reinterpret_cast< const char * >(&ed.float_value),
 | 
			
		||||
                                 sizeof(ed.float_value), 0);
 | 
			
		||||
        } break;
 | 
			
		||||
        default:
 | 
			
		||||
            STHROWF("Unsupported conversion from (%s) to (buffer)", AsTypeStr(ed.type));
 | 
			
		||||
    }
 | 
			
		||||
    // Did we fail to push the buffer o the stack?
 | 
			
		||||
    if (SQ_FAILED(res))
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Failed to convert the (%s) value to a buffer.", AsTypeStr(ed.type));
 | 
			
		||||
    }
 | 
			
		||||
    // Obtain the object from the stack and return it
 | 
			
		||||
    return Var< Object >(vm, -1).value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 
 | 
			
		||||
@@ -23,257 +23,74 @@ namespace SqMod {
 | 
			
		||||
#define SQMMDB_VERSION_MINOR 0
 | 
			
		||||
#define SQMMDB_VERSION_PATCH 1
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Handle validation.
 | 
			
		||||
*/
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    #define SQMOD_VALIDATE(x)               (x).Validate(__FILE__, __LINE__)
 | 
			
		||||
    #define SQMOD_GET_VALID(x)              (x).GetValid(__FILE__, __LINE__)
 | 
			
		||||
    #define SQMOD_GET_VALID_ELEM(x)         (x).GetValidElem(__FILE__, __LINE__)
 | 
			
		||||
#else
 | 
			
		||||
    #define SQMOD_VALIDATE(x)               (x).Validate()
 | 
			
		||||
    #define SQMOD_GET_VALID(x)              (x).GetValid()
 | 
			
		||||
    #define SQMOD_GET_VALID_ELEM(x)         (x).GetValidElem()
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Forward declarations.
 | 
			
		||||
*/
 | 
			
		||||
class Database;
 | 
			
		||||
class Metadata;
 | 
			
		||||
class Description;
 | 
			
		||||
class SockAddr;
 | 
			
		||||
class EntryData;
 | 
			
		||||
class EntryDataList;
 | 
			
		||||
class LookupResult;
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Manages a reference counted INI document instance.
 | 
			
		||||
 * Forward declarations.
 | 
			
		||||
*/
 | 
			
		||||
class DbRef
 | 
			
		||||
{
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    friend class Database;
 | 
			
		||||
struct DbHnd;
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Common typedefs.
 | 
			
		||||
*/
 | 
			
		||||
    static Pointer Create();
 | 
			
		||||
typedef SharedPtr< DbHnd > DbRef;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Destroyes the specified database structure.
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Used to retrieve the string representation of the specified type identifier.
 | 
			
		||||
*/
 | 
			
		||||
    static void Destroy(Pointer db);
 | 
			
		||||
CSStr AsTypeStr(Uint32 id);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Grab a strong reference to a document instance.
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Retrieve the value from the specified entry data as a boolean.
 | 
			
		||||
*/
 | 
			
		||||
    void Grab()
 | 
			
		||||
    {
 | 
			
		||||
        if (m_Ptr)
 | 
			
		||||
            ++(*m_Ref);
 | 
			
		||||
    }
 | 
			
		||||
bool GetEntryAsBool(const MMDB_entry_data_s & ed);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Drop a strong reference to a document instance.
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Retrieve the value from the specified entry data as a native integer.
 | 
			
		||||
*/
 | 
			
		||||
    void Drop()
 | 
			
		||||
    {
 | 
			
		||||
        if (m_Ptr && --(*m_Ref) == 0)
 | 
			
		||||
        {
 | 
			
		||||
            MMDB_close(m_Ptr);
 | 
			
		||||
            Destroy(m_Ptr);
 | 
			
		||||
            delete m_Ref;
 | 
			
		||||
            m_Ptr = NULL;
 | 
			
		||||
            m_Ref = NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
SQInteger GetEntryAsInteger(const MMDB_entry_data_s & ed);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Base constructor.
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Retrieve the value from the specified entry data as a floating point.
 | 
			
		||||
*/
 | 
			
		||||
    DbRef(bool make)
 | 
			
		||||
        : m_Ptr(make ? Create() : NULL), m_Ref(m_Ptr ? new Counter(1) : NULL)
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
SQFloat GetEntryAsFloat(const MMDB_entry_data_s & ed);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor (null).
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Retrieve the value from the specified entry data as a long integer.
 | 
			
		||||
*/
 | 
			
		||||
    DbRef()
 | 
			
		||||
        : m_Ptr(NULL), m_Ref(NULL)
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
Object GetEntryAsLong(const MMDB_entry_data_s & ed);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor.
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Retrieve the value from the specified entry data as a string.
 | 
			
		||||
*/
 | 
			
		||||
    DbRef(const DbRef & o)
 | 
			
		||||
        : m_Ptr(o.m_Ptr), m_Ref(o.m_Ref)
 | 
			
		||||
Object GetEntryAsString(const MMDB_entry_data_s & ed);
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        Grab();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor.
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Retrieve the value from the specified entry data as a stream of bytes.
 | 
			
		||||
*/
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
Object GetEntryAsBytes(const MMDB_entry_data_s & ed);
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,9 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Database.hpp"
 | 
			
		||||
#include "SockAddr.hpp"
 | 
			
		||||
#include "Metadata.hpp"
 | 
			
		||||
#include "LookupResult.hpp"
 | 
			
		||||
#include "EntryDataList.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
@@ -9,104 +11,142 @@ namespace SqMod {
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQInteger Database::Typename(HSQUIRRELVM vm)
 | 
			
		||||
{
 | 
			
		||||
    static const SQChar name[] = _SC("SqMMDBDatabase");
 | 
			
		||||
    static const SQChar name[] = _SC("SqMMDatabase");
 | 
			
		||||
    sq_pushstring(vm, name, sizeof(name));
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Database::Validate(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind database reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Database::Validate() const
 | 
			
		||||
{
 | 
			
		||||
    // Is the document handle valid?
 | 
			
		||||
    if (!m_Db)
 | 
			
		||||
        STHROWF("Invalid Maxmind database reference");
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind database reference");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
const DbRef & Database::GetValid(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    Validate(file, line);
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
const DbRef & Database::GetValid() const
 | 
			
		||||
{
 | 
			
		||||
    Validate();
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Metadata Database::GetMetadata() const
 | 
			
		||||
{
 | 
			
		||||
    return Metadata(m_Handle, &(SQMOD_GET_VALID(*this)->mDb).metadata);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 Database::Cmp(const Database & o) const
 | 
			
		||||
Object Database::GetMetadataAsEntryDataList() 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)
 | 
			
		||||
        STHROWF("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
 | 
			
		||||
        STHROWF("Loading is disabled while database is referenced");
 | 
			
		||||
    // Validate the specified file path
 | 
			
		||||
    else if (!filepath || strlen(filepath) <= 0)
 | 
			
		||||
        STHROWF("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
 | 
			
		||||
    MMDB_entry_data_list_s * entry_data_list = nullptr;
 | 
			
		||||
    // Attempt to retrieve the database meta-data as an entry data list
 | 
			
		||||
    const int status = MMDB_get_metadata_as_entry_data_list(&(SQMOD_GET_VALID(*this)->mDb), &entry_data_list);
 | 
			
		||||
    // Validate the status code
 | 
			
		||||
    if (status != MMDB_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
        // Release the database reference
 | 
			
		||||
        m_Db.Drop();
 | 
			
		||||
        // Now it's safe to throw the error
 | 
			
		||||
        STHROWF("Unable to open the specified database [%s]", MMDB_strerror(status));
 | 
			
		||||
        STHROWF("Unable to get entry data list [%s]", MMDB_strerror(status));
 | 
			
		||||
    }
 | 
			
		||||
    // Return the resulted list
 | 
			
		||||
    return Object(new EntryDataList(m_Handle, entry_data_list));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
LookupResult Database::LookupString(CSStr addr)
 | 
			
		||||
{
 | 
			
		||||
    // Validate the database handle
 | 
			
		||||
    Validate();
 | 
			
		||||
    SQMOD_VALIDATE(*this);
 | 
			
		||||
    // Validate the specified string
 | 
			
		||||
    if (!addr || strlen(addr) <= 0)
 | 
			
		||||
    if (!addr || *addr == '\0')
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("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);
 | 
			
		||||
    MMDB_lookup_result_s result = MMDB_lookup_string(&m_Handle->mDb, addr, &gai_error, &mmdb_error);
 | 
			
		||||
    // Validate the result of the getaddrinfo() function call
 | 
			
		||||
    if (gai_error != 0)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to resolve address (%s) because [%s]", addr, gai_strerror(gai_error));
 | 
			
		||||
    }
 | 
			
		||||
    // Validate the lookup status code
 | 
			
		||||
    else if (mmdb_error != MMDB_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("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);
 | 
			
		||||
    return LookupResult(m_Handle, result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
LookupResult Database::LookupSockAddr(SockAddr & addr)
 | 
			
		||||
{
 | 
			
		||||
    // Validate the database handle
 | 
			
		||||
    Validate();
 | 
			
		||||
    SQMOD_VALIDATE(*this);
 | 
			
		||||
    // Validate the specified socket address
 | 
			
		||||
    if (!addr.IsValid())
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("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);
 | 
			
		||||
    MMDB_lookup_result_s result = MMDB_lookup_sockaddr(&m_Handle->mDb, addr.GetHandle()->ai_addr, &mmdb_error);
 | 
			
		||||
    // Validate the lookup status code
 | 
			
		||||
    if (mmdb_error != MMDB_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("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);
 | 
			
		||||
    return LookupResult(m_Handle, result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_Database(Table & mmns)
 | 
			
		||||
{
 | 
			
		||||
    mmns.Bind(_SC("Database"),
 | 
			
		||||
        Class< Database >(mmns.GetVM(), _SC("SqMMDatabase"))
 | 
			
		||||
        // Constructors
 | 
			
		||||
        .Ctor()
 | 
			
		||||
        .Ctor< CSStr >()
 | 
			
		||||
        .Ctor< CSStr, Uint32 >()
 | 
			
		||||
        // Meta-methods
 | 
			
		||||
        .SquirrelFunc(_SC("_typename"), &Database::Typename)
 | 
			
		||||
        .Func(_SC("_tostring"), &Database::ToString)
 | 
			
		||||
        // Properties
 | 
			
		||||
        .Prop(_SC("IsValid"), &Database::IsValid)
 | 
			
		||||
        .Prop(_SC("References"), &Database::GetRefCount)
 | 
			
		||||
        .Prop(_SC("Metadata"), &Database::GetMetadata)
 | 
			
		||||
        .Prop(_SC("MetadataAsEntryDataList"), &Database::GetMetadataAsEntryDataList)
 | 
			
		||||
        // Member Methods
 | 
			
		||||
        .Func(_SC("LookupString"), &Database::LookupString)
 | 
			
		||||
        .Func(_SC("LookupSockAddr"), &Database::LookupSockAddr)
 | 
			
		||||
        // Member Overloads
 | 
			
		||||
        .Overload< void (Database::*)(CSStr) >(_SC("Open"), &Database::Open)
 | 
			
		||||
        .Overload< void (Database::*)(CSStr, Uint32) >(_SC("Open"), &Database::Open)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
#define _SQMMDB_DATABASE_HPP_
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Common.hpp"
 | 
			
		||||
#include "Handle/Database.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
@@ -15,24 +15,29 @@ 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.
 | 
			
		||||
     * Validate the managed database handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void Validate(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void Validate() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed database handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    const DbRef & GetValid(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    const DbRef & GetValid() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // ---------------------------------------------------------------------------------------------
 | 
			
		||||
    DbRef m_Db; /* The main INI document instance. */
 | 
			
		||||
    DbRef m_Handle; /* The main INI document instance. */
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
@@ -40,7 +45,7 @@ public:
 | 
			
		||||
     * Default constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Database()
 | 
			
		||||
        : m_Db()
 | 
			
		||||
        : m_Handle()
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
@@ -49,39 +54,46 @@ public:
 | 
			
		||||
     * Base constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Database(CSStr filepath)
 | 
			
		||||
        : m_Db()
 | 
			
		||||
        : m_Handle(new DbHnd(filepath, 0))
 | 
			
		||||
    {
 | 
			
		||||
        Open(filepath, 0);
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Base constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Database(CSStr filepath, Uint32 flags)
 | 
			
		||||
        : m_Db()
 | 
			
		||||
    {
 | 
			
		||||
        Open(filepath, flags);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Destructor.
 | 
			
		||||
    */
 | 
			
		||||
    ~Database()
 | 
			
		||||
        : m_Handle(new DbHnd(filepath, flags))
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Used by the script engine to compare two instances of this type.
 | 
			
		||||
     * Copy constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 Cmp(const Database & o) const;
 | 
			
		||||
    Database(const Database & o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Database(Database && o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    Database & operator = (const Database & o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    Database & operator = (Database && o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Used by the script engine to convert an instance of this type to a string.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr ToString() const
 | 
			
		||||
    {
 | 
			
		||||
        return _SC("");
 | 
			
		||||
        return m_Handle ? m_Handle->mDb.filename : _SC("");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
@@ -94,7 +106,7 @@ public:
 | 
			
		||||
    */
 | 
			
		||||
    bool IsValid() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Db;
 | 
			
		||||
        return m_Handle;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
@@ -102,18 +114,42 @@ public:
 | 
			
		||||
    */
 | 
			
		||||
    Uint32 GetRefCount() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Db.Count();
 | 
			
		||||
        return m_Handle.Count();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to open the specified database.
 | 
			
		||||
    */
 | 
			
		||||
    void Open(CSStr filepath);
 | 
			
		||||
    void Open(CSStr filepath)
 | 
			
		||||
    {
 | 
			
		||||
        Open(filepath, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to open the specified database.
 | 
			
		||||
    */
 | 
			
		||||
    void Open(CSStr filepath, Uint32 addr);
 | 
			
		||||
    void Open(CSStr filepath, Uint32 flags)
 | 
			
		||||
    {
 | 
			
		||||
        // Make sure there isn't another database handle
 | 
			
		||||
        if (!m_Handle)
 | 
			
		||||
        {
 | 
			
		||||
            m_Handle = DbRef(new DbHnd(filepath, flags));
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            STHROWF("Loading is disabled while database is referenced");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the metadata associated with the managed database handle.
 | 
			
		||||
    */
 | 
			
		||||
    Metadata GetMetadata() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the metadata associated with the managed database handle as an entry data list.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetMetadataAsEntryDataList() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Look up an IP address that is passed in as a null-terminated string.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										87
									
								
								modules/mmdb/Description.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								modules/mmdb/Description.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Description.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQInteger Description::Typename(HSQUIRRELVM vm)
 | 
			
		||||
{
 | 
			
		||||
    static const SQChar name[] = _SC("SqMMDescription");
 | 
			
		||||
    sq_pushstring(vm, name, sizeof(name));
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Description::Validate(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind database reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Description::Validate() const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind database reference");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
Description::Pointer Description::GetValid(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    Validate(file, line);
 | 
			
		||||
    // Validate the referenced description
 | 
			
		||||
    if (!m_Description)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind meta-data description reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
    // Return the description pointer
 | 
			
		||||
    return m_Description;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
Description::Pointer Description::GetValid() const
 | 
			
		||||
{
 | 
			
		||||
    Validate();
 | 
			
		||||
    // Validate the referenced description
 | 
			
		||||
    if (!m_Description)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind meta-data description reference");
 | 
			
		||||
    }
 | 
			
		||||
    // Return the description pointer
 | 
			
		||||
    return m_Description;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_Description(Table & mmns)
 | 
			
		||||
{
 | 
			
		||||
    mmns.Bind(_SC("Description"),
 | 
			
		||||
        Class< Description >(mmns.GetVM(), _SC("SqMMDescription"))
 | 
			
		||||
        // Constructors
 | 
			
		||||
        .Ctor()
 | 
			
		||||
        .Ctor< const Description & >()
 | 
			
		||||
        // Meta-methods
 | 
			
		||||
        .SquirrelFunc(_SC("_typename"), &Description::Typename)
 | 
			
		||||
        .Func(_SC("_tostring"), &Description::ToString)
 | 
			
		||||
        // Properties
 | 
			
		||||
        .Prop(_SC("IsValid"), &Description::IsValid)
 | 
			
		||||
        .Prop(_SC("Value"), &Description::GetDescriptionValue)
 | 
			
		||||
        .Prop(_SC("Language"), &Description::GetDescriptionLanguage)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										154
									
								
								modules/mmdb/Description.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								modules/mmdb/Description.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,154 @@
 | 
			
		||||
#ifndef _SQMMDB_DESCRIPTION_HPP_
 | 
			
		||||
#define _SQMMDB_DESCRIPTION_HPP_
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Handle/Database.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Class that can hold and be used inspect meta-data descriptions.
 | 
			
		||||
*/
 | 
			
		||||
class Description
 | 
			
		||||
{
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    friend class Metadata; // Only a valid meta-data instance can construct this type.
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    typedef MMDB_description_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 managed database handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void Validate(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void Validate() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed database handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    Pointer GetValid(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    Pointer GetValid() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // ---------------------------------------------------------------------------------------------
 | 
			
		||||
    DbRef   m_Handle; // The database associated with this meta-data description.
 | 
			
		||||
    Pointer m_Description; // The inspected meta-data description structure.
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Construct and with a specific meta-data.
 | 
			
		||||
    */
 | 
			
		||||
    Description(const DbRef & db, Pointer metadata)
 | 
			
		||||
        : m_Handle(db), m_Description(metadata)
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor. (null)
 | 
			
		||||
    */
 | 
			
		||||
    Description()
 | 
			
		||||
        : m_Handle(), m_Description(nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Description(const Description &) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Description(Description &&) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    Description & operator = (const Description &) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    Description & operator = (Description &&) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the internal result structure reference.
 | 
			
		||||
    */
 | 
			
		||||
    Pointer GetHandle()
 | 
			
		||||
    {
 | 
			
		||||
        return m_Description;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the internal result structure reference.
 | 
			
		||||
    */
 | 
			
		||||
    ConstPtr GetHandle() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Description;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Used by the script engine to convert an instance of this type to a string.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr ToString() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Description ? m_Description->description : _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 database and result structure.
 | 
			
		||||
    */
 | 
			
		||||
    bool IsValid() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle && m_Description;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value of the managed description handle.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetDescriptionValue() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->description;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the language of the managed description handle.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetDescriptionLanguage() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->language;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 | 
			
		||||
#endif // _SQMMDB_DESCRIPTION_HPP_
 | 
			
		||||
							
								
								
									
										87
									
								
								modules/mmdb/EntryData.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								modules/mmdb/EntryData.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "EntryData.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQInteger EntryData::Typename(HSQUIRRELVM vm)
 | 
			
		||||
{
 | 
			
		||||
    static const SQChar name[] = _SC("SqMMEntryData");
 | 
			
		||||
    sq_pushstring(vm, name, sizeof(name));
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void EntryData::Validate(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind database reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void EntryData::Validate() const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind database reference");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
const DbRef & EntryData::GetValid(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    Validate(file, line);
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
const DbRef & EntryData::GetValid() const
 | 
			
		||||
{
 | 
			
		||||
    Validate();
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
EntryData::EntryData()
 | 
			
		||||
    : m_Handle(), m_Entry()
 | 
			
		||||
{
 | 
			
		||||
    std::memset(&m_Entry, 0, sizeof(Type));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_EntryData(Table & mmns)
 | 
			
		||||
{
 | 
			
		||||
    mmns.Bind(_SC("EntryData"),
 | 
			
		||||
        Class< EntryData >(mmns.GetVM(), _SC("SqMMEntryData"))
 | 
			
		||||
        // Constructors
 | 
			
		||||
        .Ctor()
 | 
			
		||||
        .Ctor< const EntryData & >()
 | 
			
		||||
        // Meta-methods
 | 
			
		||||
        .SquirrelFunc(_SC("_typename"), &EntryData::Typename)
 | 
			
		||||
        .Func(_SC("_tostring"), &EntryData::ToString)
 | 
			
		||||
        // Properties
 | 
			
		||||
        .Prop(_SC("IsValid"), &EntryData::IsValid)
 | 
			
		||||
        .Prop(_SC("TypeName"), &EntryData::TypeName)
 | 
			
		||||
        .Prop(_SC("HasData"), &EntryData::HasData)
 | 
			
		||||
        .Prop(_SC("Type"), &EntryData::GetType)
 | 
			
		||||
        .Prop(_SC("Offset"), &EntryData::GetOffset)
 | 
			
		||||
        .Prop(_SC("DataSize"), &EntryData::DataSize)
 | 
			
		||||
        .Prop(_SC("String"), &EntryData::GetString)
 | 
			
		||||
        .Prop(_SC("Integer"), &EntryData::GetInteger)
 | 
			
		||||
        .Prop(_SC("Float"), &EntryData::GetFloat)
 | 
			
		||||
        .Prop(_SC("Long"), &EntryData::GetLong)
 | 
			
		||||
        .Prop(_SC("Bool"), &EntryData::GetBool)
 | 
			
		||||
        .Prop(_SC("Bytes"), &EntryData::GetBytes)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										255
									
								
								modules/mmdb/EntryData.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								modules/mmdb/EntryData.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,255 @@
 | 
			
		||||
#ifndef _SQMMDB_ENTRYDATA_HPP_
 | 
			
		||||
#define _SQMMDB_ENTRYDATA_HPP_
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Handle/Database.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Class that can hold and be used to inspect entry data values.
 | 
			
		||||
*/
 | 
			
		||||
class EntryData
 | 
			
		||||
{
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    friend class LookupResult; // Only a valid lookup result instance can construct this type.
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    typedef MMDB_entry_data_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 managed database handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void Validate(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void Validate() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed database handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    const DbRef & GetValid(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    const DbRef & GetValid() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // ---------------------------------------------------------------------------------------------
 | 
			
		||||
    DbRef   m_Handle; // The database from which this result comes from.
 | 
			
		||||
    Type    m_Entry; // The managed entry-data structure.
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Construct and take ownership of a certain entry data.
 | 
			
		||||
    */
 | 
			
		||||
    EntryData(const DbRef & db, Reference entry)
 | 
			
		||||
        : m_Handle(db), m_Entry(entry)
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor. (null)
 | 
			
		||||
    */
 | 
			
		||||
    EntryData();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor.
 | 
			
		||||
    */
 | 
			
		||||
    EntryData(const EntryData &) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor.
 | 
			
		||||
    */
 | 
			
		||||
    EntryData(EntryData &&) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    EntryData & operator = (const EntryData &) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    EntryData & operator = (EntryData &&) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the internal result structure reference.
 | 
			
		||||
    */
 | 
			
		||||
    Reference GetHandle()
 | 
			
		||||
    {
 | 
			
		||||
        return m_Entry;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the internal result structure reference.
 | 
			
		||||
    */
 | 
			
		||||
    ConstRef GetHandle() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Entry;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Used by the script engine to convert an instance of this type to a string.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr ToString() const
 | 
			
		||||
    {
 | 
			
		||||
        return AsTypeStr(m_Entry.type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * 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_Handle && m_Entry.has_data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Used to retrieve the type of the current element as a string.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr TypeName() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the handle
 | 
			
		||||
        SQMOD_VALIDATE(*this);
 | 
			
		||||
        // Return the requested information
 | 
			
		||||
        return AsTypeStr(m_Entry.type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See whether a valid element is currently processed.
 | 
			
		||||
    */
 | 
			
		||||
    bool HasData() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the handle
 | 
			
		||||
        SQMOD_VALIDATE(*this);
 | 
			
		||||
        // Return the requested information
 | 
			
		||||
        return ConvTo< bool >::From(m_Entry.has_data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the type identifier of the current element.
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger GetType() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the handle
 | 
			
		||||
        SQMOD_VALIDATE(*this);
 | 
			
		||||
        // Return the requested information
 | 
			
		||||
        return ConvTo< SQInteger >::From(m_Entry.type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the offset of the current element.
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger GetOffset() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the handle
 | 
			
		||||
        SQMOD_VALIDATE(*this);
 | 
			
		||||
        // Return the requested information
 | 
			
		||||
        return ConvTo< SQInteger >::From(m_Entry.offset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the offset of the next element.
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger DataSize() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the handle
 | 
			
		||||
        SQMOD_VALIDATE(*this);
 | 
			
		||||
        // Return the requested information
 | 
			
		||||
        return ConvTo< SQInteger >::From(m_Entry.data_size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value from the current element as a boolean.
 | 
			
		||||
    */
 | 
			
		||||
    bool GetBool() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the handle
 | 
			
		||||
        SQMOD_VALIDATE(*this);
 | 
			
		||||
        // Return the requested information
 | 
			
		||||
        return GetEntryAsBool(m_Entry);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value from the current element as a native integer.
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger GetInteger() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the handle
 | 
			
		||||
        SQMOD_VALIDATE(*this);
 | 
			
		||||
        // Return the requested information
 | 
			
		||||
        return GetEntryAsInteger(m_Entry);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value from the current element as a floating point.
 | 
			
		||||
    */
 | 
			
		||||
    SQFloat GetFloat() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the handle
 | 
			
		||||
        SQMOD_VALIDATE(*this);
 | 
			
		||||
        // Return the requested information
 | 
			
		||||
        return GetEntryAsFloat(m_Entry);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value from the current element as a long integer.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetLong() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the handle
 | 
			
		||||
        SQMOD_VALIDATE(*this);
 | 
			
		||||
        // Return the requested information
 | 
			
		||||
        return GetEntryAsLong(m_Entry);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value from the current element as a string.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetString() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the handle
 | 
			
		||||
        SQMOD_VALIDATE(*this);
 | 
			
		||||
        // Return the requested information
 | 
			
		||||
        return GetEntryAsString(m_Entry);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value from the current element as a stream of bytes.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetBytes() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the handle
 | 
			
		||||
        SQMOD_VALIDATE(*this);
 | 
			
		||||
        // Return the requested information
 | 
			
		||||
        return GetEntryAsBytes(m_Entry);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 | 
			
		||||
#endif // _SQMMDB_ENTRYDATA_HPP_
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
@@ -11,109 +12,97 @@ namespace SqMod {
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQInteger EntryDataList::Typename(HSQUIRRELVM vm)
 | 
			
		||||
{
 | 
			
		||||
    static const SQChar name[] = _SC("SqMMDBEntryDataList");
 | 
			
		||||
    static const SQChar name[] = _SC("SqMMEntryDataList");
 | 
			
		||||
    sq_pushstring(vm, name, sizeof(name));
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void EntryDataList::Validate(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind database reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void EntryDataList::Validate() const
 | 
			
		||||
{
 | 
			
		||||
    // Is the document handle valid?
 | 
			
		||||
    if (!m_Db)
 | 
			
		||||
        STHROWF("Invalid Maxmind database reference");
 | 
			
		||||
    // Do we have a valid list?
 | 
			
		||||
    else if (!m_List)
 | 
			
		||||
        STHROWF("Invalid entry data list");
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind database reference");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void EntryDataList::ValidateElem() const
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
EntryDataList::Pointer EntryDataList::GetValid(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    // Is the document handle valid?
 | 
			
		||||
    if (!m_Db)
 | 
			
		||||
        STHROWF("Invalid Maxmind database reference");
 | 
			
		||||
    // Do we have a valid list?
 | 
			
		||||
    else if (!m_List)
 | 
			
		||||
        STHROWF("Invalid entry data list");
 | 
			
		||||
    // Do we have a valid element?
 | 
			
		||||
    else if (!m_Elem)
 | 
			
		||||
        STHROWF("Invalid entry data element");
 | 
			
		||||
    Validate(file, line);
 | 
			
		||||
    // Validate the managed list
 | 
			
		||||
    if (!m_List)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind entry data list reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
    // return the list
 | 
			
		||||
    return m_List;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
EntryDataList::Pointer EntryDataList::GetValid() const
 | 
			
		||||
{
 | 
			
		||||
    Validate();
 | 
			
		||||
    // Validate the managed list
 | 
			
		||||
    if (!m_List)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind entry data list reference");
 | 
			
		||||
    }
 | 
			
		||||
    // return the list
 | 
			
		||||
    return m_List;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void EntryDataList::ValidateData() const
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
EntryDataList::Pointer EntryDataList::GetValidElem(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    // Is the document handle valid?
 | 
			
		||||
    if (!m_Db)
 | 
			
		||||
        STHROWF("Invalid Maxmind database reference");
 | 
			
		||||
    // Do we have a valid list?
 | 
			
		||||
    else if (!m_List)
 | 
			
		||||
        STHROWF("Invalid entry data list");
 | 
			
		||||
    // Do we have a valid element?
 | 
			
		||||
    else if (!m_Elem)
 | 
			
		||||
        STHROWF("Invalid entry data element");
 | 
			
		||||
    // Do we have some valid data?
 | 
			
		||||
    else if (!m_Elem->entry_data.has_data)
 | 
			
		||||
        STHROWF("Entry data element has no data");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
CSStr EntryDataList::AsTypeStr(Uint32 id)
 | 
			
		||||
    Validate(file, line);
 | 
			
		||||
    // Validate the current element
 | 
			
		||||
    if (!m_List)
 | 
			
		||||
    {
 | 
			
		||||
    switch (id)
 | 
			
		||||
        SqThrowF("Invalid Maxmind entry data element reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
    // return the element
 | 
			
		||||
    return m_Elem;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
EntryDataList::Pointer EntryDataList::GetValidElem() const
 | 
			
		||||
{
 | 
			
		||||
        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()
 | 
			
		||||
    Validate();
 | 
			
		||||
    // Validate the current element
 | 
			
		||||
    if (!m_List)
 | 
			
		||||
    {
 | 
			
		||||
    // Do we have to free any list?
 | 
			
		||||
    if (m_List)
 | 
			
		||||
        MMDB_free_entry_data_list(m_List);
 | 
			
		||||
        SqThrowF("Invalid Maxmind entry data element reference");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
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;
 | 
			
		||||
    // return the element
 | 
			
		||||
    return m_Elem;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
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;
 | 
			
		||||
    Uint32 count = 0;
 | 
			
		||||
    // Do we even have a list?
 | 
			
		||||
    if (m_List)
 | 
			
		||||
    {
 | 
			
		||||
        for (Pointer elem = m_List; elem; elem = elem->next)
 | 
			
		||||
        {
 | 
			
		||||
            ++count;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // Return the counter
 | 
			
		||||
    return count;
 | 
			
		||||
}
 | 
			
		||||
@@ -121,258 +110,92 @@ Uint32 EntryDataList::GetCount() const
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
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;
 | 
			
		||||
    // Validate the database handle
 | 
			
		||||
    SQMOD_VALIDATE(*this);
 | 
			
		||||
    // Attempt to fetch the next element
 | 
			
		||||
    m_Elem = m_Elem ? m_Elem->next : nullptr;
 | 
			
		||||
    // Return whether we have a valid element
 | 
			
		||||
    return !!m_Elem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
bool EntryDataList::Advance(Int32 n)
 | 
			
		||||
bool EntryDataList::Advance(SQInteger n)
 | 
			
		||||
{
 | 
			
		||||
    // Validate the database and list handle
 | 
			
		||||
    Validate();
 | 
			
		||||
    // Do we have a valid element currently?
 | 
			
		||||
    if (m_Elem)
 | 
			
		||||
    // Validate the database handle
 | 
			
		||||
    SQMOD_VALIDATE(*this);
 | 
			
		||||
    // Attempt to skip as many elements as possible
 | 
			
		||||
        while ((n > 0) && (m_Elem = m_Elem->next)) --n;
 | 
			
		||||
    while (n && m_Elem)
 | 
			
		||||
    {
 | 
			
		||||
        // Fetch the next element
 | 
			
		||||
        m_Elem = m_Elem->next;
 | 
			
		||||
        // Decrease the counter
 | 
			
		||||
        --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:
 | 
			
		||||
            STHROWF("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:
 | 
			
		||||
            STHROWF("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:
 | 
			
		||||
            STHROWF("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:
 | 
			
		||||
            STHROWF("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:
 | 
			
		||||
            STHROWF("Unsupported conversion from (%s) to (uint64)", AsTypeStr(m_Elem->entry_data.type));
 | 
			
		||||
    }
 | 
			
		||||
    // Obtain the initial stack size
 | 
			
		||||
    const StackGuard sg;
 | 
			
		||||
    // Push a long integer instance with the requested value on the stack
 | 
			
		||||
    SqMod_PushULongObject(DefaultVM::Get(), longint);
 | 
			
		||||
    // Get the object from the stack and return it
 | 
			
		||||
    return Var< Object >(DefaultVM::Get(), -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:
 | 
			
		||||
            STHROWF("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();
 | 
			
		||||
    SQMOD_VALIDATE(*this);
 | 
			
		||||
    // Validate the specified file path
 | 
			
		||||
    if (!filepath || strlen(filepath) <= 0)
 | 
			
		||||
    if (!filepath || *filepath == '\0')
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Invalid file path");
 | 
			
		||||
    }
 | 
			
		||||
    // Attempt to open the specified file
 | 
			
		||||
    FILE * fp = fopen(filepath, "w");
 | 
			
		||||
    // Validate the file handle
 | 
			
		||||
    if (!fp)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("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
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to dump the list [%s]", MMDB_strerror(status));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_EntryDataList(Table & mmns)
 | 
			
		||||
{
 | 
			
		||||
    mmns.Bind(_SC("EntryDataList"),
 | 
			
		||||
        Class< EntryDataList, NoCopy< EntryDataList > >(mmns.GetVM(), _SC("SqMMEntryDataList"))
 | 
			
		||||
        // Constructors
 | 
			
		||||
        .Ctor()
 | 
			
		||||
        // Meta-methods
 | 
			
		||||
        .SquirrelFunc(_SC("_typename"), &EntryDataList::Typename)
 | 
			
		||||
        .Func(_SC("_tostring"), &EntryDataList::ToString)
 | 
			
		||||
        // Properties
 | 
			
		||||
        .Prop(_SC("IsValid"), &EntryDataList::IsValid)
 | 
			
		||||
        .Prop(_SC("HaveElement"), &EntryDataList::HaveElement)
 | 
			
		||||
        .Prop(_SC("TypeName"), &EntryDataList::TypeName)
 | 
			
		||||
        .Prop(_SC("Count"), &EntryDataList::GetCount)
 | 
			
		||||
        .Prop(_SC("HasData"), &EntryDataList::HasData)
 | 
			
		||||
        .Prop(_SC("Type"), &EntryDataList::GetType)
 | 
			
		||||
        .Prop(_SC("Offset"), &EntryDataList::GetOffset)
 | 
			
		||||
        .Prop(_SC("DataSize"), &EntryDataList::DataSize)
 | 
			
		||||
        .Prop(_SC("String"), &EntryDataList::GetString)
 | 
			
		||||
        .Prop(_SC("Integer"), &EntryDataList::GetInteger)
 | 
			
		||||
        .Prop(_SC("Float"), &EntryDataList::GetFloat)
 | 
			
		||||
        .Prop(_SC("Long"), &EntryDataList::GetLong)
 | 
			
		||||
        .Prop(_SC("Bool"), &EntryDataList::GetBool)
 | 
			
		||||
        .Prop(_SC("Bytes"), &EntryDataList::GetBytes)
 | 
			
		||||
        // Member methods
 | 
			
		||||
        .Func(_SC("Next"), &EntryDataList::Next)
 | 
			
		||||
        .Func(_SC("Advance"), &EntryDataList::Advance)
 | 
			
		||||
        .Func(_SC("Reset"), &EntryDataList::Reset)
 | 
			
		||||
        // Member Overloads
 | 
			
		||||
        .Overload< void (EntryDataList::*)(CSStr) const >(_SC("DumpTo"), &EntryDataList::DumpTo)
 | 
			
		||||
        .Overload< void (EntryDataList::*)(CSStr, Int32) const >(_SC("DumpTo"), &EntryDataList::DumpTo)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,21 @@
 | 
			
		||||
#ifndef _SQMMDB_LOOKUPRESULT_HPP_
 | 
			
		||||
#define _SQMMDB_LOOKUPRESULT_HPP_
 | 
			
		||||
#ifndef _SQMMDB_ENTRYDATALIST_HPP_
 | 
			
		||||
#define _SQMMDB_ENTRYDATALIST_HPP_
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Common.hpp"
 | 
			
		||||
#include "Handle/Database.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Class that can be used to traverse a list of results.
 | 
			
		||||
 * Class that can hold and be used inspect database meta-data.
 | 
			
		||||
*/
 | 
			
		||||
class EntryDataList
 | 
			
		||||
{
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    friend class Database; // Only a valid database instance can construct this type.
 | 
			
		||||
    friend class LookupResult; // Only a valid lookup result instance can construct this type.
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
@@ -26,37 +30,46 @@ protected:
 | 
			
		||||
    typedef const Type&             ConstRef; // Constant reference to the managed type.
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the database pointer and list handle and throw an error if invalid.
 | 
			
		||||
     * Validate the managed database handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void Validate(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void Validate() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Do a regular validation and also validate the currently processed element.
 | 
			
		||||
     * Validate the managed database handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
    void ValidateElem() const;
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    Pointer GetValid(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    Pointer GetValid() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Do a regular validation and also validate the currently processed element data.
 | 
			
		||||
     * Validate the managed database handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
    void ValidateData() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Used to retrieve the string representation of the specified type identifier.
 | 
			
		||||
    */
 | 
			
		||||
    static CSStr AsTypeStr(Uint32 id);
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    Pointer GetValidElem(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    Pointer GetValidElem() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
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. */
 | 
			
		||||
    DbRef   m_Handle; // The database associated with this meta-data.
 | 
			
		||||
    Pointer m_List; // The managed entry data list.
 | 
			
		||||
    Pointer m_Elem; // The currently processed element from the list.
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Base constructor.
 | 
			
		||||
     * Construct and with a specific entry list.
 | 
			
		||||
    */
 | 
			
		||||
    EntryDataList(const DbRef & db, Pointer list)
 | 
			
		||||
        : m_Db(db), m_List(list), m_Elem(list)
 | 
			
		||||
        : m_Handle(db), m_List(list), m_Elem(list)
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
@@ -64,9 +77,13 @@ private:
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor.
 | 
			
		||||
     * Default constructor. (null)
 | 
			
		||||
    */
 | 
			
		||||
    EntryDataList();
 | 
			
		||||
    EntryDataList()
 | 
			
		||||
        : m_Handle(), m_List(nullptr), m_Elem(nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor. (disabled)
 | 
			
		||||
@@ -77,7 +94,7 @@ public:
 | 
			
		||||
     * Move constructor.
 | 
			
		||||
    */
 | 
			
		||||
    EntryDataList(EntryDataList && o)
 | 
			
		||||
        : m_Db(o.m_Db)
 | 
			
		||||
        : m_Handle(o.m_Handle)
 | 
			
		||||
        , m_List(o.m_List)
 | 
			
		||||
        , m_Elem(o.m_Elem)
 | 
			
		||||
    {
 | 
			
		||||
@@ -88,7 +105,14 @@ public:
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Destructor.
 | 
			
		||||
    */
 | 
			
		||||
    ~EntryDataList();
 | 
			
		||||
    ~EntryDataList()
 | 
			
		||||
    {
 | 
			
		||||
        // Do we have to free any list?
 | 
			
		||||
        if (m_List)
 | 
			
		||||
        {
 | 
			
		||||
            MMDB_free_entry_data_list(m_List);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator. (disabled)
 | 
			
		||||
@@ -102,7 +126,7 @@ public:
 | 
			
		||||
    {
 | 
			
		||||
        if (m_List != o.m_List)
 | 
			
		||||
        {
 | 
			
		||||
            m_Db = o.m_Db;
 | 
			
		||||
            m_Handle = o.m_Handle;
 | 
			
		||||
            m_List = o.m_List;
 | 
			
		||||
            m_Elem = o.m_Elem;
 | 
			
		||||
            o.m_List = nullptr;
 | 
			
		||||
@@ -112,7 +136,7 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the internal entry data list structure pointer.
 | 
			
		||||
     * Retrieve the internal result structure reference.
 | 
			
		||||
    */
 | 
			
		||||
    Pointer GetHandle()
 | 
			
		||||
    {
 | 
			
		||||
@@ -120,18 +144,13 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the internal entry data list structure pointer.
 | 
			
		||||
     * Retrieve the internal result structure reference.
 | 
			
		||||
    */
 | 
			
		||||
    Pointer GetHandle() const
 | 
			
		||||
    ConstPtr 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.
 | 
			
		||||
    */
 | 
			
		||||
@@ -146,11 +165,11 @@ public:
 | 
			
		||||
    static SQInteger Typename(HSQUIRRELVM vm);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See whether this instance references a valid database and entry data list structure.
 | 
			
		||||
     * See whether this instance references a valid database and result structure.
 | 
			
		||||
    */
 | 
			
		||||
    bool IsValid() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Db && m_List;
 | 
			
		||||
        return m_Handle && m_List;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
@@ -164,12 +183,9 @@ public:
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Used to retrieve the type of the current element as a string.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr TypeStr() const
 | 
			
		||||
    CSStr TypeName() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the database and list handle
 | 
			
		||||
        Validate();
 | 
			
		||||
        // return the requested information
 | 
			
		||||
        return m_Elem ? AsTypeStr(m_Elem->entry_data.type) : _SC("invalid");
 | 
			
		||||
        return AsTypeStr(SQMOD_GET_VALID_ELEM(*this)->entry_data.type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
@@ -185,22 +201,22 @@ public:
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Advance a certain number of elements.
 | 
			
		||||
    */
 | 
			
		||||
    bool Advance(Int32 n);
 | 
			
		||||
    bool Advance(SQInteger n);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Go back to the first element in the list.
 | 
			
		||||
    */
 | 
			
		||||
    void Reset();
 | 
			
		||||
    void Reset()
 | 
			
		||||
    {
 | 
			
		||||
        m_Elem = SQMOD_GET_VALID_ELEM(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * 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;
 | 
			
		||||
        return ConvTo< bool >::From(SQMOD_GET_VALID_ELEM(*this)->entry_data.has_data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
@@ -208,10 +224,7 @@ public:
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger GetType() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the database, list and element handle
 | 
			
		||||
        ValidateElem();
 | 
			
		||||
        // Return the requested information
 | 
			
		||||
        return static_cast< SQInteger >(m_Elem->entry_data.type);
 | 
			
		||||
        return ConvTo< SQInteger >::From(SQMOD_GET_VALID_ELEM(*this)->entry_data.type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
@@ -219,21 +232,7 @@ public:
 | 
			
		||||
    */
 | 
			
		||||
    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);
 | 
			
		||||
        return ConvTo< SQInteger >::From(SQMOD_GET_VALID_ELEM(*this)->entry_data.offset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
@@ -241,41 +240,61 @@ public:
 | 
			
		||||
    */
 | 
			
		||||
    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);
 | 
			
		||||
        return ConvTo< SQInteger >::From(SQMOD_GET_VALID_ELEM(*this)->entry_data.data_size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value from the current element as a boolean.
 | 
			
		||||
    */
 | 
			
		||||
    bool GetBool() const
 | 
			
		||||
    {
 | 
			
		||||
        return GetEntryAsBool(SQMOD_GET_VALID_ELEM(*this)->entry_data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value from the current element as a native integer.
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger GetInteger() const
 | 
			
		||||
    {
 | 
			
		||||
        return GetEntryAsInteger(SQMOD_GET_VALID_ELEM(*this)->entry_data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value from the current element as a floating point.
 | 
			
		||||
    */
 | 
			
		||||
    SQFloat GetFloat() const
 | 
			
		||||
    {
 | 
			
		||||
        return GetEntryAsFloat(SQMOD_GET_VALID_ELEM(*this)->entry_data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value from the current element as a long integer.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetLong() const
 | 
			
		||||
    {
 | 
			
		||||
        return GetEntryAsLong(SQMOD_GET_VALID_ELEM(*this)->entry_data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value from the current element as a string.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetString() const;
 | 
			
		||||
    Object GetString() const
 | 
			
		||||
    {
 | 
			
		||||
        return GetEntryAsString(SQMOD_GET_VALID_ELEM(*this)->entry_data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value from the current element as a native integer.
 | 
			
		||||
     * Retrieve the value from the current element as a stream of bytes.
 | 
			
		||||
    */
 | 
			
		||||
    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;
 | 
			
		||||
    Object GetBytes() const
 | 
			
		||||
    {
 | 
			
		||||
        return GetEntryAsBytes(SQMOD_GET_VALID_ELEM(*this)->entry_data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Dumpt the contents of the list to the specified list.
 | 
			
		||||
    */
 | 
			
		||||
    void DumpTo(CSStr filepath)
 | 
			
		||||
    void DumpTo(CSStr filepath) const
 | 
			
		||||
    {
 | 
			
		||||
        DumpTo(filepath, 0);
 | 
			
		||||
    }
 | 
			
		||||
@@ -288,4 +307,4 @@ public:
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 | 
			
		||||
#endif // _SQMMDB_LOOKUPRESULT_HPP_
 | 
			
		||||
#endif // _SQMMDB_ENTRYDATALIST_HPP_
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								modules/mmdb/Handle/Database.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								modules/mmdb/Handle/Database.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Handle/Database.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
DbHnd::DbHnd(CSStr filepath, Uint32 flags)
 | 
			
		||||
    : mDb()
 | 
			
		||||
{
 | 
			
		||||
    // Validate the specified file path
 | 
			
		||||
    if (!filepath || *filepath == '\0')
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Invalid database file path");
 | 
			
		||||
    }
 | 
			
		||||
    // Let's attempt to open the specified database
 | 
			
		||||
    const Int32 status = MMDB_open(filepath, flags, &mDb);
 | 
			
		||||
    // Validate the result of the operation
 | 
			
		||||
    if (status != MMDB_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to open the specified database [%s]", MMDB_strerror(status));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
DbHnd::~DbHnd()
 | 
			
		||||
{
 | 
			
		||||
    // We don't need the database handle anymore
 | 
			
		||||
    MMDB_close(&mDb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										69
									
								
								modules/mmdb/Handle/Database.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								modules/mmdb/Handle/Database.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
#ifndef _SQMMDB_HANDLE_DATABASE_HPP_
 | 
			
		||||
#define _SQMMDB_HANDLE_DATABASE_HPP_
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Common.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Manages a reference counted INI document instance.
 | 
			
		||||
*/
 | 
			
		||||
class DbHnd
 | 
			
		||||
{
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    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.
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    MMDB_s     mDb; // The managed database handle.
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor.
 | 
			
		||||
    */
 | 
			
		||||
    DbHnd(CSStr filepath, Uint32 flags);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    DbHnd(const DbHnd & o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    DbHnd(DbHnd && o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Destructor.
 | 
			
		||||
    */
 | 
			
		||||
    ~DbHnd();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    DbHnd & operator = (const DbHnd & o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move assignment operator. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    DbHnd & operator = (DbHnd && o) = delete;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 | 
			
		||||
#endif // _SQMMDB_HANDLE_DATABASE_HPP_
 | 
			
		||||
@@ -1,5 +1,12 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "LookupResult.hpp"
 | 
			
		||||
#include "EntryData.hpp"
 | 
			
		||||
#include "EntryDataList.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
@@ -7,47 +14,164 @@ namespace SqMod {
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQInteger LookupResult::Typename(HSQUIRRELVM vm)
 | 
			
		||||
{
 | 
			
		||||
    static const SQChar name[] = _SC("SqMMDBLookupResult");
 | 
			
		||||
    static const SQChar name[] = _SC("SqMMLookupResult");
 | 
			
		||||
    sq_pushstring(vm, name, sizeof(name));
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void LookupResult::Validate(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind database reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void LookupResult::Validate() const
 | 
			
		||||
{
 | 
			
		||||
    // Is the document handle valid?
 | 
			
		||||
    if (!m_Db)
 | 
			
		||||
        STHROWF("Invalid Maxmind database reference");
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind database reference");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
const DbRef & LookupResult::GetValid(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    Validate(file, line);
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
const DbRef & LookupResult::GetValid() const
 | 
			
		||||
{
 | 
			
		||||
    Validate();
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
LookupResult::LookupResult()
 | 
			
		||||
    : m_Db(), m_Result()
 | 
			
		||||
    : m_Handle(), m_Result()
 | 
			
		||||
{
 | 
			
		||||
    memset(&m_Result, 0, sizeof(Type));
 | 
			
		||||
    std::memset(&m_Result, 0, sizeof(Type));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 LookupResult::Cmp(const LookupResult & o) const
 | 
			
		||||
Object LookupResult::GetEntryDataList()
 | 
			
		||||
{
 | 
			
		||||
    if (m_Db == o.m_Db)
 | 
			
		||||
        return 0;
 | 
			
		||||
    else if (m_Db.DbPtr() > o.m_Db.DbPtr())
 | 
			
		||||
    // See if there's an entry
 | 
			
		||||
    if (!m_Result.found_entry)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Result does not have an entry");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MMDB_entry_data_list_s * entry_data_list = nullptr;
 | 
			
		||||
    // Attempt to retrieve the entire entry data list at once
 | 
			
		||||
    const int status = MMDB_get_entry_data_list(&m_Result.entry, &entry_data_list);
 | 
			
		||||
    // Validate the status code
 | 
			
		||||
    if (status != MMDB_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to get entry data list [%s]", MMDB_strerror(status));
 | 
			
		||||
    }
 | 
			
		||||
    // Return the resulted list
 | 
			
		||||
    return Object(new EntryDataList(m_Handle, entry_data_list));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQInteger LookupResult::GetValue(HSQUIRRELVM vm)
 | 
			
		||||
{
 | 
			
		||||
    const Int32 top = sq_gettop(vm);
 | 
			
		||||
    // The lookup result instance
 | 
			
		||||
    LookupResult * lookup = nullptr;
 | 
			
		||||
    // Attempt to extract the lookup result instance
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        lookup = Var< LookupResult * >(vm, 1).value;
 | 
			
		||||
    }
 | 
			
		||||
    catch (const Sqrat::Exception & e)
 | 
			
		||||
    {
 | 
			
		||||
        return sq_throwerror(vm, e.what());
 | 
			
		||||
    }
 | 
			
		||||
    // Do we have a valid lookup result instance?
 | 
			
		||||
    if (!lookup)
 | 
			
		||||
    {
 | 
			
		||||
        return sq_throwerror(vm, "Invalid lookup result instance");
 | 
			
		||||
    }
 | 
			
		||||
    // See if there's an entry
 | 
			
		||||
    else if (!(lookup->m_Result.found_entry))
 | 
			
		||||
    {
 | 
			
		||||
        return sq_throwerror(vm, "Result does not have an entry");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    typedef std::vector< StackStrF > ArgList;
 | 
			
		||||
    // The list of extracted arguments
 | 
			
		||||
    ArgList arglist;
 | 
			
		||||
    // Extract each argument as a string
 | 
			
		||||
    for (SQInteger i = 2; i <= top; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        arglist.emplace_back(vm, i, false);
 | 
			
		||||
        // Did we fail to extract the argument value?
 | 
			
		||||
        if (SQ_FAILED(arglist.back().mRes))
 | 
			
		||||
        {
 | 
			
		||||
            return arglist.back().mRes; // Propagate the error
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    typedef std::vector< CSStr > PtrList;
 | 
			
		||||
    // The list of pointers to path segments
 | 
			
		||||
    PtrList ptrlist;
 | 
			
		||||
    // Grab the pointers to argument values
 | 
			
		||||
    for (const auto & a : arglist)
 | 
			
		||||
    {
 | 
			
		||||
        ptrlist.push_back(a.mPtr);
 | 
			
		||||
    }
 | 
			
		||||
    // Push null to specify the end of the list
 | 
			
		||||
    ptrlist.push_back(nullptr);
 | 
			
		||||
 | 
			
		||||
    MMDB_entry_data_s entry_data;
 | 
			
		||||
    // Attempt to retrieve the entire entry data list at once
 | 
			
		||||
    const int status = MMDB_aget_value(&(lookup->m_Result.entry), &entry_data, ptrlist.data());
 | 
			
		||||
    // Validate the status code
 | 
			
		||||
    if (status != MMDB_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
        return sq_throwerror(vm, ToStrF("Unable to get entry data [%s]", MMDB_strerror(status)));
 | 
			
		||||
    }
 | 
			
		||||
    // Push the resulted list object onto the stack
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        ClassType< EntryData >::PushInstance(vm, new EntryData(lookup->m_Handle, entry_data));
 | 
			
		||||
    }
 | 
			
		||||
    catch (const Sqrat::Exception & e)
 | 
			
		||||
    {
 | 
			
		||||
        return sq_throwerror(vm, e.what());
 | 
			
		||||
    }
 | 
			
		||||
    // Specify that we returned a value
 | 
			
		||||
    return 1;
 | 
			
		||||
    else
 | 
			
		||||
        return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
EntryDataList LookupResult::GetValueA(CSStr path, Array & arr) const
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_LookupResult(Table & mmns)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
EntryDataList LookupResult::GetValueT(CSStr path, Table & tbl) const
 | 
			
		||||
{
 | 
			
		||||
    
 | 
			
		||||
    mmns.Bind(_SC("LookupResult"),
 | 
			
		||||
        Class< LookupResult >(mmns.GetVM(), _SC("SqMMLookupResult"))
 | 
			
		||||
        // Constructors
 | 
			
		||||
        .Ctor()
 | 
			
		||||
        .Ctor< const LookupResult & >()
 | 
			
		||||
        // Meta-methods
 | 
			
		||||
        .SquirrelFunc(_SC("_typename"), &LookupResult::Typename)
 | 
			
		||||
        .Func(_SC("_tostring"), &LookupResult::ToString)
 | 
			
		||||
        // Properties
 | 
			
		||||
        .Prop(_SC("IsValid"), &LookupResult::IsValid)
 | 
			
		||||
        .Prop(_SC("FoundEntry"), &LookupResult::FoundEntry)
 | 
			
		||||
        .Prop(_SC("NetMask"), &LookupResult::GetNetMask)
 | 
			
		||||
        .Prop(_SC("EntryDataList"), &LookupResult::GetEntryDataList)
 | 
			
		||||
        // Squirrel functions
 | 
			
		||||
        .SquirrelFunc(_SC("GetValue"), &LookupResult::GetValue)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
#define _SQMMDB_LOOKUPRESULT_HPP_
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Common.hpp"
 | 
			
		||||
#include "Handle/Database.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
@@ -29,21 +29,36 @@ protected:
 | 
			
		||||
    typedef const Type&             ConstRef; // Constant reference to the managed type.
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the database pointer and throw an error if invalid.
 | 
			
		||||
     * Validate the managed database handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void Validate(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void Validate() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed database handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    const DbRef & GetValid(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    const DbRef & GetValid() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // ---------------------------------------------------------------------------------------------
 | 
			
		||||
    DbRef   m_Db; /* The database from which this result comes from. */
 | 
			
		||||
    Type    m_Result; /* The managed result structure. */
 | 
			
		||||
    DbRef   m_Handle; // 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)
 | 
			
		||||
        : m_Handle(db), m_Result(result)
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
@@ -99,11 +114,6 @@ public:
 | 
			
		||||
        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.
 | 
			
		||||
    */
 | 
			
		||||
@@ -122,7 +132,7 @@ public:
 | 
			
		||||
    */
 | 
			
		||||
    bool IsValid() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Db && m_Result.found_entry;
 | 
			
		||||
        return m_Handle && m_Result.found_entry;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
@@ -131,7 +141,7 @@ public:
 | 
			
		||||
    bool FoundEntry() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the database handle
 | 
			
		||||
        Validate();
 | 
			
		||||
        SQMOD_VALIDATE(*this);
 | 
			
		||||
        // Return the requested information
 | 
			
		||||
        return m_Result.found_entry;
 | 
			
		||||
    }
 | 
			
		||||
@@ -142,21 +152,20 @@ public:
 | 
			
		||||
    SQInteger GetNetMask() const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the database handle
 | 
			
		||||
        Validate();
 | 
			
		||||
        SQMOD_VALIDATE(*this);
 | 
			
		||||
        // Return the requested information
 | 
			
		||||
        return static_cast< SQInteger >(m_Result.netmask);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Lookup data in the associated result using an array as the path.
 | 
			
		||||
     * Retrieve the entire entry data list.
 | 
			
		||||
    */
 | 
			
		||||
    EntryDataList GetValueA(CSStr path, Array & arr) const;
 | 
			
		||||
    Object GetEntryDataList();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Lookup data in the associated result using a table as the path.
 | 
			
		||||
     * Lookup data in the associated result using the specified path.
 | 
			
		||||
    */
 | 
			
		||||
    EntryDataList GetValueT(CSStr path, Table & tbl) const;
 | 
			
		||||
 | 
			
		||||
    static SQInteger GetValue(HSQUIRRELVM vm);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										108
									
								
								modules/mmdb/Metadata.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								modules/mmdb/Metadata.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,108 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Metadata.hpp"
 | 
			
		||||
#include "Description.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQInteger Metadata::Typename(HSQUIRRELVM vm)
 | 
			
		||||
{
 | 
			
		||||
    static const SQChar name[] = _SC("SqMMMetadata");
 | 
			
		||||
    sq_pushstring(vm, name, sizeof(name));
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Metadata::Validate(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind database reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Metadata::Validate() const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind database reference");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
Metadata::Pointer Metadata::GetValid(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    Validate(file, line);
 | 
			
		||||
    // Validate the referenced meta-data
 | 
			
		||||
    if (!m_Metadata)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind meta-data reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
    // Return the meta-data pointer
 | 
			
		||||
    return m_Metadata;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
Metadata::Pointer Metadata::GetValid() const
 | 
			
		||||
{
 | 
			
		||||
    Validate();
 | 
			
		||||
    // Validate the referenced meta-data
 | 
			
		||||
    if (!m_Metadata)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid Maxmind meta-data reference");
 | 
			
		||||
    }
 | 
			
		||||
    // Return the meta-data pointer
 | 
			
		||||
    return m_Metadata;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Description Metadata::GetDescriptionHandle(Uint32 idx) const
 | 
			
		||||
{
 | 
			
		||||
    // Validate the specified index
 | 
			
		||||
    if (idx > SQMOD_GET_VALID(*this)->description.count)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("The specified description index is out of range: %u > %u", idx, m_Metadata->description.count);
 | 
			
		||||
    }
 | 
			
		||||
    // Return the requested description
 | 
			
		||||
    return Description(m_Handle, m_Metadata->description.descriptions[idx]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_Metadata(Table & mmns)
 | 
			
		||||
{
 | 
			
		||||
    mmns.Bind(_SC("Metadata"),
 | 
			
		||||
        Class< Metadata >(mmns.GetVM(), _SC("SqMMMetadata"))
 | 
			
		||||
        // Constructors
 | 
			
		||||
        .Ctor()
 | 
			
		||||
        .Ctor< const Metadata & >()
 | 
			
		||||
        // Meta-methods
 | 
			
		||||
        .SquirrelFunc(_SC("_typename"), &Metadata::Typename)
 | 
			
		||||
        .Func(_SC("_tostring"), &Metadata::ToString)
 | 
			
		||||
        // Properties
 | 
			
		||||
        .Prop(_SC("IsValid"), &Metadata::IsValid)
 | 
			
		||||
        .Prop(_SC("NodeCount"), &Metadata::GetNodeCount)
 | 
			
		||||
        .Prop(_SC("RecordSize"), &Metadata::GetRecordSize)
 | 
			
		||||
        .Prop(_SC("IpVersion"), &Metadata::GetIpVersion)
 | 
			
		||||
        .Prop(_SC("DatabaseType"), &Metadata::GetDatabaseType)
 | 
			
		||||
        .Prop(_SC("LanguageCount"), &Metadata::GetLanguageCount)
 | 
			
		||||
        .Prop(_SC("BinaryFormatMajorVersion"), &Metadata::GetBinaryFormatMajorVersion)
 | 
			
		||||
        .Prop(_SC("BinaryFormatMinorVersion"), &Metadata::GetBinaryFormatMinorVersion)
 | 
			
		||||
        .Prop(_SC("BuildEpoch"), &Metadata::GetBuildEpoch)
 | 
			
		||||
        .Prop(_SC("DescriptionCount"), &Metadata::GetDescriptionCount)
 | 
			
		||||
        // Member methods
 | 
			
		||||
        .Func(_SC("GetLanguageName"), &Metadata::GetLanguageName)
 | 
			
		||||
        .Func(_SC("GetDescriptionHandle"), &Metadata::GetDescriptionHandle)
 | 
			
		||||
        .Func(_SC("GetDescriptionValue"), &Metadata::GetDescriptionValue)
 | 
			
		||||
        .Func(_SC("GetDescriptionLanguage"), &Metadata::GetDescriptionLanguage)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										262
									
								
								modules/mmdb/Metadata.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										262
									
								
								modules/mmdb/Metadata.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,262 @@
 | 
			
		||||
#ifndef _SQMMDB_METADATA_HPP_
 | 
			
		||||
#define _SQMMDB_METADATA_HPP_
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Handle/Database.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Class that can hold and be used inspect database meta-data.
 | 
			
		||||
*/
 | 
			
		||||
class Metadata
 | 
			
		||||
{
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    friend class Database; // Only a valid database instance can construct this type.
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    typedef MMDB_metadata_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 managed database handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void Validate(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void Validate() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed database handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    Pointer GetValid(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    Pointer GetValid() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // ---------------------------------------------------------------------------------------------
 | 
			
		||||
    DbRef   m_Handle; // The database associated with this meta-data.
 | 
			
		||||
    Pointer m_Metadata; // The inspected meta-data structure.
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Construct and with a specific meta-data.
 | 
			
		||||
    */
 | 
			
		||||
    Metadata(const DbRef & db, Pointer metadata)
 | 
			
		||||
        : m_Handle(db), m_Metadata(metadata)
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor. (null)
 | 
			
		||||
    */
 | 
			
		||||
    Metadata()
 | 
			
		||||
        : m_Handle(), m_Metadata(nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Metadata(const Metadata &) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Metadata(Metadata &&) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    Metadata & operator = (const Metadata &) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    Metadata & operator = (Metadata &&) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the internal result structure reference.
 | 
			
		||||
    */
 | 
			
		||||
    Pointer GetHandle()
 | 
			
		||||
    {
 | 
			
		||||
        return m_Metadata;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the internal result structure reference.
 | 
			
		||||
    */
 | 
			
		||||
    ConstPtr GetHandle() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Metadata;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Used by the script engine to convert an instance of this type to a string.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr ToString() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Metadata ? m_Metadata->database_type : _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 database and result structure.
 | 
			
		||||
    */
 | 
			
		||||
    bool IsValid() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle && m_Metadata;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the node count.
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger GetNodeCount() const
 | 
			
		||||
    {
 | 
			
		||||
        return ConvTo< SQInteger >::From(SQMOD_GET_VALID(*this)->node_count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the record size.
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger GetRecordSize() const
 | 
			
		||||
    {
 | 
			
		||||
        return ConvTo< SQInteger >::From(SQMOD_GET_VALID(*this)->record_size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the IP version.
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger GetIpVersion() const
 | 
			
		||||
    {
 | 
			
		||||
        return ConvTo< SQInteger >::From(SQMOD_GET_VALID(*this)->ip_version);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the database type.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetDatabaseType() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->database_type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the number of language names.
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger GetLanguageCount() const
 | 
			
		||||
    {
 | 
			
		||||
        return ConvTo< SQInteger >::From(SQMOD_GET_VALID(*this)->languages.count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the name of a certain language.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetLanguageName(Uint32 idx) const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the specified index
 | 
			
		||||
        if (idx > SQMOD_GET_VALID(*this)->languages.count)
 | 
			
		||||
        {
 | 
			
		||||
            STHROWF("The specified language index is out of range: %u > %u", idx, m_Metadata->languages.count);
 | 
			
		||||
        }
 | 
			
		||||
        // Return the requested name
 | 
			
		||||
        return m_Metadata->languages.names[idx];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the major version of the binary format.
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger GetBinaryFormatMajorVersion() const
 | 
			
		||||
    {
 | 
			
		||||
        return ConvTo< SQInteger >::From(SQMOD_GET_VALID(*this)->binary_format_major_version);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the minor version of the binary format.
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger GetBinaryFormatMinorVersion() const
 | 
			
		||||
    {
 | 
			
		||||
        return ConvTo< SQInteger >::From(SQMOD_GET_VALID(*this)->binary_format_minor_version);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the build epoch.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetBuildEpoch() const
 | 
			
		||||
    {
 | 
			
		||||
        // Obtain the initial stack size
 | 
			
		||||
        const StackGuard sg;
 | 
			
		||||
        // Push a long integer instance with the requested value on the stack
 | 
			
		||||
        SqMod_PushULongObject(DefaultVM::Get(), ConvTo< Uint64 >::From(SQMOD_GET_VALID(*this)->build_epoch));
 | 
			
		||||
        // Obtain the object from the stack and return it
 | 
			
		||||
        return Var< Object >(DefaultVM::Get(), -1).value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the number of available description handles.
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger GetDescriptionCount() const
 | 
			
		||||
    {
 | 
			
		||||
        return ConvTo< SQInteger >::From(SQMOD_GET_VALID(*this)->description.count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the handle of a certain description.
 | 
			
		||||
    */
 | 
			
		||||
    Description GetDescriptionHandle(Uint32 idx) const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the description of a certain description handle.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetDescriptionValue(Uint32 idx) const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the specified index
 | 
			
		||||
        if (idx > SQMOD_GET_VALID(*this)->description.count)
 | 
			
		||||
        {
 | 
			
		||||
            STHROWF("The specified description index is out of range: %u > %u", idx, m_Metadata->description.count);
 | 
			
		||||
        }
 | 
			
		||||
        // Return the requested description value
 | 
			
		||||
        return m_Metadata->description.descriptions[idx]->description;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the language of a certain description handle.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetDescriptionLanguage(Uint32 idx) const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the specified index
 | 
			
		||||
        if (idx > SQMOD_GET_VALID(*this)->description.count)
 | 
			
		||||
        {
 | 
			
		||||
            STHROWF("The specified description index is out of range: %u > %u", idx, m_Metadata->description.count);
 | 
			
		||||
        }
 | 
			
		||||
        // Return the requested description language
 | 
			
		||||
        return m_Metadata->description.descriptions[idx]->language;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 | 
			
		||||
#endif // _SQMMDB_METADATA_HPP_
 | 
			
		||||
@@ -8,6 +8,15 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
extern void Register_Database(Table & mmns);
 | 
			
		||||
extern void Register_Description(Table & mmns);
 | 
			
		||||
extern void Register_EntryData(Table & mmns);
 | 
			
		||||
extern void Register_EntryDataList(Table & mmns);
 | 
			
		||||
extern void Register_LookupResult(Table & mmns);
 | 
			
		||||
extern void Register_Metadata(Table & mmns);
 | 
			
		||||
extern void Register_SockAddr(Table & mmns);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Register the module API under the obtained virtual machine.
 | 
			
		||||
*/
 | 
			
		||||
@@ -21,6 +30,21 @@ static bool RegisterAPI(HSQUIRRELVM vm)
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Table mmns(vm);
 | 
			
		||||
 | 
			
		||||
    Register_Database(mmns);
 | 
			
		||||
    Register_Description(mmns);
 | 
			
		||||
    Register_EntryData(mmns);
 | 
			
		||||
    Register_EntryDataList(mmns);
 | 
			
		||||
    Register_LookupResult(mmns);
 | 
			
		||||
    Register_Metadata(mmns);
 | 
			
		||||
    Register_SockAddr(mmns);
 | 
			
		||||
 | 
			
		||||
    mmns.Func(_SC("StrError"), MMDB_strerror);
 | 
			
		||||
    mmns.Func(_SC("LibVersion"), MMDB_lib_version);
 | 
			
		||||
 | 
			
		||||
    RootTable(vm).Bind(_SC("SqMMDB"), mmns);
 | 
			
		||||
 | 
			
		||||
    // Registration was successful
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										0
									
								
								modules/mmdb/SearchNode.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								modules/mmdb/SearchNode.cpp
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								modules/mmdb/SearchNode.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								modules/mmdb/SearchNode.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -7,22 +7,48 @@ namespace SqMod {
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQInteger SockAddr::Typename(HSQUIRRELVM vm)
 | 
			
		||||
{
 | 
			
		||||
    static const SQChar name[] = _SC("SqMMDBSockAddr");
 | 
			
		||||
    static const SQChar name[] = _SC("SqMMSockAddr");
 | 
			
		||||
    sq_pushstring(vm, name, sizeof(name));
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void SockAddr::Validate(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid sockaddr structure handle =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void SockAddr::Validate() const
 | 
			
		||||
{
 | 
			
		||||
    // Is the document handle valid?
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
        STHROWF("Invalid sockaddr structure handle");
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid sockaddr structure handle");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
SockAddr::Pointer SockAddr::GetValid(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    Validate(file, line);
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
SockAddr::Pointer SockAddr::GetValid() const
 | 
			
		||||
{
 | 
			
		||||
    Validate();
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SockAddr::SockAddr(CSStr addr)
 | 
			
		||||
    : m_Handle(NULL), m_Addres(_SC(""))
 | 
			
		||||
    : m_Handle(nullptr), m_Addres(_SC(""))
 | 
			
		||||
{
 | 
			
		||||
    struct addrinfo hints;
 | 
			
		||||
    // Configure the hints structure
 | 
			
		||||
@@ -31,13 +57,15 @@ SockAddr::SockAddr(CSStr addr)
 | 
			
		||||
    // 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);
 | 
			
		||||
    Int32 status = getaddrinfo(addr, nullptr, &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
 | 
			
		||||
        STHROWF("Unable to query the specified address for information [%s]", gai_strerror(status));
 | 
			
		||||
    }
 | 
			
		||||
@@ -49,19 +77,26 @@ SockAddr::SockAddr(CSStr addr)
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_SockAddr(Table & mmns)
 | 
			
		||||
{
 | 
			
		||||
    mmns.Bind(_SC("SockAddr"),
 | 
			
		||||
        Class< SockAddr, NoCopy< SockAddr > >(mmns.GetVM(), _SC("SqMMSockAddr"))
 | 
			
		||||
        // Constructors
 | 
			
		||||
        .Ctor()
 | 
			
		||||
        .Ctor< CSStr >()
 | 
			
		||||
        // Meta-methods
 | 
			
		||||
        .SquirrelFunc(_SC("_typename"), &SockAddr::Typename)
 | 
			
		||||
        .Func(_SC("_tostring"), &SockAddr::ToString)
 | 
			
		||||
        // Properties
 | 
			
		||||
        .Prop(_SC("IsValid"), &SockAddr::IsValid)
 | 
			
		||||
        .Prop(_SC("Address"), &SockAddr::GetAddress)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 
 | 
			
		||||
@@ -26,15 +26,29 @@ protected:
 | 
			
		||||
    typedef const Type&     ConstRef; // Constant reference to the managed type.
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the sockaddr pointer and throw an error if invalid.
 | 
			
		||||
     * Validate the managed sockaddr pointer and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void Validate(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void Validate() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed sockaddr pointer and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    Pointer GetValid(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    Pointer GetValid() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // ---------------------------------------------------------------------------------------------
 | 
			
		||||
    Pointer m_Handle; /* The managed sockaddr structure. */
 | 
			
		||||
    String  m_Addres; /* The address that was queried for information. */
 | 
			
		||||
    Pointer m_Handle; // The managed sockaddr structure.
 | 
			
		||||
    String  m_Addres; // The address that was queried for information.
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
@@ -42,7 +56,7 @@ public:
 | 
			
		||||
     * Default constructor.
 | 
			
		||||
    */
 | 
			
		||||
    SockAddr()
 | 
			
		||||
        : m_Handle(NULL), m_Addres(_SC(""))
 | 
			
		||||
        : m_Handle(nullptr), m_Addres(_SC(""))
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
@@ -55,7 +69,7 @@ public:
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    SockAddr(const SockAddr &) = delete;
 | 
			
		||||
    SockAddr(const SockAddr & o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor.
 | 
			
		||||
@@ -75,7 +89,7 @@ public:
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    SockAddr & operator = (const SockAddr &) = delete;
 | 
			
		||||
    SockAddr & operator = (const SockAddr & o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move assignment operator.
 | 
			
		||||
@@ -107,11 +121,6 @@ public:
 | 
			
		||||
        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.
 | 
			
		||||
    */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user