eq2go/old/common/eq_emu_error.hpp
2025-08-06 19:00:30 -05:00

138 lines
3.8 KiB
C++

// Copyright (C) 2007 EQ2EMulator Development Team, GPL v3
#pragma once
#include <vector>
#include <string>
#include <mutex>
#include <iostream>
#include <memory>
#include <algorithm>
#include <cstdio>
#include "types.hpp"
enum eEQEMuError
{
EQEMuError_NoError,
EQEMuError_Mysql_1405,
EQEMuError_Mysql_2003,
EQEMuError_Mysql_2005,
EQEMuError_Mysql_2007,
EQEMuError_MaxErrorID
};
// Error message lookup table for predefined error codes
const char* EQEMuErrorText[EQEMuError_MaxErrorID] = {
"ErrorID# 0, No Error",
"MySQL Error #1405 or #2001 means your mysql server rejected the username and password you presented it.",
"MySQL Error #2003 means you were unable to connect to the mysql server.",
"MySQL Error #2005 means you there are too many connections on the mysql server. The server is overloaded.",
"MySQL Error #2007 means you the server is out of memory. The server is overloaded.",
};
// Error storage structure to handle both enum and string errors
struct ErrorEntry
{
bool is_enum_error; // True if this is an enum error, false for string error
int32 error_id; // Used only for enum errors
std::string message; // Used for string errors or can store enum converted to string
ErrorEntry(eEQEMuError error) : is_enum_error(true), error_id(error) {}
ErrorEntry(const std::string& msg) : is_enum_error(false), error_id(0), message(msg) {}
};
// Global error list and mutex for thread-safe error collection
std::vector<ErrorEntry> g_error_list;
std::mutex g_error_mutex;
// Forward declaration for signal handling
void CatchSignal(int sig_num);
// Retrieves the error text for a given error ID
// Returns the corresponding error message or out of range message
const char* GetErrorText(int32 iError)
{
if (iError >= EQEMuError_MaxErrorID)
return "ErrorID# out of range";
else
return EQEMuErrorText[iError];
}
// Adds an enumerated error to the error list with optional immediate exit
// Checks for duplicate enum errors before adding to prevent spam
void AddEQEMuError(eEQEMuError iError, bool iExitNow = false)
{
if (!iError)
return;
std::lock_guard<std::mutex> lock(g_error_mutex);
// Check for duplicate enum errors
auto it = std::find_if(g_error_list.begin(), g_error_list.end(),
[iError](const ErrorEntry& entry) {
return entry.is_enum_error && entry.error_id == iError;
});
if (it != g_error_list.end())
return; // Duplicate found, don't add
g_error_list.emplace_back(iError);
if (iExitNow)
CatchSignal(2);
}
// Adds a string-based error to the error list with optional immediate exit
// String errors are not deduplicated as they may contain unique information
void AddEQEMuError(const char* iError, bool iExitNow = false)
{
if (!iError)
return;
std::lock_guard<std::mutex> lock(g_error_mutex);
g_error_list.emplace_back(std::string(iError));
if (iExitNow)
CatchSignal(2);
}
// Checks and displays all accumulated errors, then clears the error list
// Returns the number of errors that were found and displayed
int32 CheckEQEMuError()
{
std::lock_guard<std::mutex> lock(g_error_mutex);
if (g_error_list.empty())
return 0;
bool header_printed = false;
int32 error_count = 0;
for (const auto& entry : g_error_list) {
if (!header_printed) {
std::fprintf(stdout, "===============================\nRuntime errors:\n\n");
header_printed = true;
}
if (entry.is_enum_error) {
std::fprintf(stdout, "%s\n", GetErrorText(entry.error_id));
} else {
std::fprintf(stdout, "%s\n\n", entry.message.c_str());
}
error_count++;
}
g_error_list.clear();
return error_count;
}
// Checks for errors and pauses for user input if any errors were found
// Useful for keeping console windows open to display error messages
void CheckEQEMuErrorAndPause()
{
if (CheckEQEMuError()) {
std::fprintf(stdout, "Hit any key to exit\n");
std::getchar();
}
}