// ------------------------------------------------------------------------------------------------ #include "SearchNode.hpp" #include "EntryData.hpp" #include "EntryDataList.hpp" #include "Database.hpp" // ------------------------------------------------------------------------------------------------ #include #include #include // ------------------------------------------------------------------------------------------------ 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) const DbRef & SearchNode::GetValid(CCStr file, Int32 line) const { Validate(file, line); return m_Handle; } #else const DbRef & SearchNode::GetValid() const { Validate(); return m_Handle; } #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() { // Validate the managed handles SQMOD_VALIDATE(*this); // 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(&m_Node.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() { // Validate the managed handles SQMOD_VALIDATE(*this); // 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(&m_Node.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