mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 08:47:17 +01:00
215 lines
7.1 KiB
C++
215 lines
7.1 KiB
C++
// ------------------------------------------------------------------------------------------------
|
|
#include "SearchNode.hpp"
|
|
#include "EntryData.hpp"
|
|
#include "EntryDataList.hpp"
|
|
#include "Database.hpp"
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
#include <vector>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
namespace SqMod {
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SQInteger SearchNode::Typename(HSQUIRRELVM vm)
|
|
{
|
|
static const SQChar name[] = _SC("SqMMSearchNode");
|
|
sq_pushstring(vm, name, sizeof(name));
|
|
return 1;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
void SearchNode::Validate(CCStr file, Int32 line) const
|
|
{
|
|
if (!m_Handle)
|
|
{
|
|
SqThrowF("Invalid Maxmind database reference =>[%s:%d]", file, line);
|
|
}
|
|
}
|
|
#else
|
|
void SearchNode::Validate() const
|
|
{
|
|
if (!m_Handle)
|
|
{
|
|
SqThrowF("Invalid Maxmind database reference");
|
|
}
|
|
}
|
|
#endif // _DEBUG
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
SearchNode::Reference SearchNode::GetValid(CCStr file, Int32 line)
|
|
{
|
|
Validate(file, line);
|
|
return m_Node;
|
|
}
|
|
#else
|
|
SearchNode::Reference SearchNode::GetValid()
|
|
{
|
|
Validate();
|
|
return m_Node;
|
|
}
|
|
#endif // _DEBUG
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SearchNode::SearchNode()
|
|
: m_Handle(), m_Node()
|
|
{
|
|
std::memset(&m_Node, 0, sizeof(Type));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void SearchNode::Release()
|
|
{
|
|
std::memset(&m_Node, 0, sizeof(Type));
|
|
m_Handle.Reset();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
Database SearchNode::GetDatabase() const
|
|
{
|
|
return Database(m_Handle);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
Object SearchNode::GetLeftRecordEntryDataList()
|
|
{
|
|
// Prepare a temporary entry data list pointer
|
|
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(&(SQMOD_GET_VALID(*this).left_record_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));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
Object SearchNode::GetRightRecordEntryDataList()
|
|
{
|
|
// Prepare a temporary entry data list pointer
|
|
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(&(SQMOD_GET_VALID(*this).right_record_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 SearchNode::GetRecordEntryData(HSQUIRRELVM vm, bool right)
|
|
{
|
|
const Int32 top = sq_gettop(vm);
|
|
// The search node result instance
|
|
SearchNode * node = nullptr;
|
|
// Attempt to extract the search node result instance
|
|
try
|
|
{
|
|
node = Var< SearchNode * >(vm, 1).value;
|
|
}
|
|
catch (const Sqrat::Exception & e)
|
|
{
|
|
return sq_throwerror(vm, e.what());
|
|
}
|
|
// Do we have a valid search node result instance?
|
|
if (!node)
|
|
{
|
|
return sq_throwerror(vm, "Invalid search node result instance");
|
|
}
|
|
// See if there's a handle
|
|
else if (!node->m_Handle)
|
|
{
|
|
return sq_throwerror(vm, "Invalid Maxmind database reference");
|
|
}
|
|
|
|
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);
|
|
|
|
// Grab the requested entry
|
|
MMDB_entry_s * entry = &(right ? node->m_Node.right_record_entry : node->m_Node.left_record_entry);
|
|
|
|
MMDB_entry_data_s entry_data;
|
|
// Attempt to retrieve the specified entry data
|
|
const int status = MMDB_aget_value(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(node->m_Handle, entry_data));
|
|
}
|
|
catch (const Sqrat::Exception & e)
|
|
{
|
|
return sq_throwerror(vm, e.what());
|
|
}
|
|
|
|
// Specify that we returned a value
|
|
return 1;
|
|
}
|
|
|
|
// ================================================================================================
|
|
void Register_SearchNode(Table & mmns)
|
|
{
|
|
mmns.Bind(_SC("SearchNode"),
|
|
Class< SearchNode >(mmns.GetVM(), _SC("SqMMSearchNode"))
|
|
// Constructors
|
|
.Ctor()
|
|
.Ctor< const SearchNode & >()
|
|
// Meta-methods
|
|
.SquirrelFunc(_SC("_typename"), &SearchNode::Typename)
|
|
.Func(_SC("_tostring"), &SearchNode::ToString)
|
|
// Properties
|
|
.Prop(_SC("IsValid"), &SearchNode::IsValid)
|
|
.Prop(_SC("Database"), &SearchNode::GetDatabase)
|
|
.Prop(_SC("References"), &SearchNode::GetRefCount)
|
|
.Prop(_SC("LeftRecord"), &SearchNode::GetLeftRecord)
|
|
.Prop(_SC("RightRecord"), &SearchNode::GetRightRecord)
|
|
.Prop(_SC("LeftRecordType"), &SearchNode::GetLeftRecordType)
|
|
.Prop(_SC("RightRecordType"), &SearchNode::GetRightRecordType)
|
|
.Prop(_SC("LeftRecordEntryDataList"), &SearchNode::GetLeftRecordEntryDataList)
|
|
.Prop(_SC("RightRecordEntryDataList"), &SearchNode::GetRightRecordEntryDataList)
|
|
// Member methods
|
|
.Func(_SC("Release"), &SearchNode::Release)
|
|
// Squirrel methods
|
|
.SquirrelFunc(_SC("GetLeftRecordValue"), &SearchNode::GetLeftRecordEntryData)
|
|
.SquirrelFunc(_SC("GetRightRecordValue"), &SearchNode::GetRightRecordEntryData)
|
|
);
|
|
}
|
|
|
|
} // Namespace:: SqMod
|