1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 00:37:15 +01:00
SqMod/modules/mmdb/EntryDataList.cpp

383 lines
14 KiB
C++

// ------------------------------------------------------------------------------------------------
#include "EntryDataList.hpp"
#include "Module.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdio>
#include <cstdlib>
// ------------------------------------------------------------------------------------------------
#include <sqrat.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQInteger EntryDataList::Typename(HSQUIRRELVM vm)
{
static const SQChar name[] = _SC("SqMMDBEntryDataList");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
void EntryDataList::Validate() const
{
// Is the document handle valid?
if (!m_Db)
STHROWF("Invalid Maxmind database reference");
// Do we have a valid list?
else if (!m_List)
STHROWF("Invalid entry data list");
}
// ------------------------------------------------------------------------------------------------
void EntryDataList::ValidateElem() 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");
}
// ------------------------------------------------------------------------------------------------
void EntryDataList::ValidateData() 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)
{
switch (id)
{
case MMDB_DATA_TYPE_EXTENDED: return _SC("extended");
case MMDB_DATA_TYPE_POINTER: return _SC("pointer");
case MMDB_DATA_TYPE_UTF8_STRING: return _SC("string");
case MMDB_DATA_TYPE_DOUBLE: return _SC("double");
case MMDB_DATA_TYPE_BYTES: return _SC("bytes");
case MMDB_DATA_TYPE_UINT16: return _SC("uint16");
case MMDB_DATA_TYPE_UINT32: return _SC("uint32");
case MMDB_DATA_TYPE_MAP: return _SC("map");
case MMDB_DATA_TYPE_INT32: return _SC("int32");
case MMDB_DATA_TYPE_UINT64: return _SC("uint64");
case MMDB_DATA_TYPE_UINT128: return _SC("uint128");
case MMDB_DATA_TYPE_ARRAY: return _SC("array");
case MMDB_DATA_TYPE_CONTAINER: return _SC("container");
case MMDB_DATA_TYPE_END_MARKER: return _SC("endmarker");
case MMDB_DATA_TYPE_BOOLEAN: return _SC("boolean");
case MMDB_DATA_TYPE_FLOAT: return _SC("float");
default: return _SC("unknonw");
}
}
// ------------------------------------------------------------------------------------------------
EntryDataList::~EntryDataList()
{
// Do we have to free any list?
if (m_List)
MMDB_free_entry_data_list(m_List);
}
// ------------------------------------------------------------------------------------------------
Int32 EntryDataList::Cmp(const EntryDataList & o) const
{
if (m_List == o.m_List)
return 0;
else if (m_List > o.m_List)
return 1;
else
return -1;
}
// ------------------------------------------------------------------------------------------------
Uint32 EntryDataList::GetCount() const
{
// Do we even have a list?
if (!m_List)
return 0;
// Get the start of the list
Pointer elem = m_List;
// Prepare a counter
Uint32 count = 1;
// Loop through list elements
while ((elem = elem->next)) ++count;
// Return the counter
return count;
}
// ------------------------------------------------------------------------------------------------
bool EntryDataList::Next()
{
// Validate the database and list handle
Validate();
// Do we have a valid element currently?
if (m_Elem)
return (m_Elem = m_Elem->next);
// Nothing to advance
return false;
}
// ------------------------------------------------------------------------------------------------
bool EntryDataList::Advance(Int32 n)
{
// Validate the database and list handle
Validate();
// Do we have a valid element currently?
if (m_Elem)
// Attempt to skip as many elements as possible
while ((n > 0) && (m_Elem = m_Elem->next)) --n;
// Return whether we have a valid element
return m_Elem;
}
// ------------------------------------------------------------------------------------------------
void EntryDataList::Reset()
{
// Validate the database and list handle
Validate();
// Go back to the first element
m_Elem = m_List;
}
// ------------------------------------------------------------------------------------------------
CSStr EntryDataList::GetString() const
{
// Validate the database, list and element handle
ValidateData();
// Attempt to perform the requested conversion
switch (m_Elem->entry_data.type)
{
case MMDB_DATA_TYPE_UTF8_STRING:
return m_Elem->entry_data.utf8_string;
case MMDB_DATA_TYPE_DOUBLE:
return FmtStr("%f", m_Elem->entry_data.double_value);
case MMDB_DATA_TYPE_UINT16:
return FmtStr("%u", m_Elem->entry_data.uint16);
case MMDB_DATA_TYPE_UINT32:
return FmtStr("%u", m_Elem->entry_data.uint32);
case MMDB_DATA_TYPE_INT32:
return FmtStr("%d", m_Elem->entry_data.int32);
case MMDB_DATA_TYPE_UINT64:
return FmtStr("%llu", m_Elem->entry_data.uint64);
case MMDB_DATA_TYPE_BOOLEAN:
return m_Elem->entry_data.boolean ? _SC("true") : _SC("false");
case MMDB_DATA_TYPE_FLOAT:
return FmtStr("%f", m_Elem->entry_data.float_value);
default:
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(_SqVM);
// Push a long integer instance with the requested value on the stack
_SqMod->PushULongObject(_SqVM, longint);
// Get the object from the stack and return it
return Var< Object >(_SqVM, -1).value;
}
// ------------------------------------------------------------------------------------------------
bool EntryDataList::GetBool() const
{
// Validate the database, list and element handle
ValidateData();
// Attempt to perform the requested conversion
switch (m_Elem->entry_data.type)
{
case MMDB_DATA_TYPE_UTF8_STRING:
return !!(m_Elem->entry_data.utf8_string);
case MMDB_DATA_TYPE_DOUBLE:
return EpsGt(m_Elem->entry_data.double_value, 0.0d);
case MMDB_DATA_TYPE_UINT16:
return (m_Elem->entry_data.uint16 > 0);
case MMDB_DATA_TYPE_UINT32:
return (m_Elem->entry_data.uint32 > 0);
case MMDB_DATA_TYPE_INT32:
return (m_Elem->entry_data.int32 > 0);
case MMDB_DATA_TYPE_UINT64:
return (m_Elem->entry_data.uint64 > 0);
case MMDB_DATA_TYPE_BOOLEAN:
return m_Elem->entry_data.boolean;
case MMDB_DATA_TYPE_FLOAT:
return EpsGt(m_Elem->entry_data.float_value, 0.0f);
default:
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();
// Validate the specified file path
if (!filepath || strlen(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));
}
} // Namespace:: SqMod