Core/Commands: Refactored chat command script hook, fixes a crash when building with gcc 5

Closes #15616
Closes #15740
This commit is contained in:
Shauren
2015-10-22 20:26:56 +02:00
parent 935c93e099
commit 2d942ddcc5
46 changed files with 776 additions and 1025 deletions

View File

@@ -35,54 +35,16 @@
bool ChatHandler::load_command_table = true;
// get number of commands in table
static size_t getCommandTableSize(const ChatCommand* commands)
std::vector<ChatCommand> const& ChatHandler::getCommandTable()
{
if (!commands)
return 0;
size_t count = 0;
while (commands[count].Name != NULL)
count++;
return count;
}
// append source command table to target, return number of appended commands
static size_t appendCommandTable(ChatCommand* target, const ChatCommand* source)
{
const size_t count = getCommandTableSize(source);
if (count)
memcpy(target, source, count * sizeof(ChatCommand));
return count;
}
ChatCommand* ChatHandler::getCommandTable()
{
// cache for commands, needed because some commands are loaded dynamically through ScriptMgr
// cache is never freed and will show as a memory leak in diagnostic tools
// can't use vector as vector storage is implementation-dependent, eg, there can be alignment gaps between elements
static ChatCommand* commandTableCache = NULL;
static std::vector<ChatCommand> commandTableCache;
if (LoadCommandTable())
{
SetLoadCommandTable(false);
{
// count total number of top-level commands
size_t total = 0;
std::vector<ChatCommand*> const& dynamic = sScriptMgr->GetChatCommands();
for (std::vector<ChatCommand*>::const_iterator it = dynamic.begin(); it != dynamic.end(); ++it)
total += getCommandTableSize(*it);
total += 1; // ending zero
// cache top-level commands
size_t added = 0;
free(commandTableCache);
commandTableCache = (ChatCommand*)malloc(sizeof(ChatCommand) * total);
ASSERT(commandTableCache);
memset(commandTableCache, 0, sizeof(ChatCommand) * total);
for (std::vector<ChatCommand*>::const_iterator it = dynamic.begin(); it != dynamic.end(); ++it)
added += appendCommandTable(commandTableCache + added, *it);
}
std::vector<ChatCommand> cmds = sScriptMgr->GetChatCommands();
commandTableCache.swap(cmds);
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_COMMANDS);
PreparedQueryResult result = WorldDatabase.Query(stmt);
@@ -265,7 +227,7 @@ void ChatHandler::SendSysMessage(uint32 entry)
SendSysMessage(GetTrinityString(entry));
}
bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, std::string const& fullcmd)
bool ChatHandler::ExecuteCommandInTable(std::vector<ChatCommand> const& table, const char* text, std::string const& fullcmd)
{
char const* oldtext = text;
std::string cmd = "";
@@ -278,7 +240,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st
while (*text == ' ') ++text;
for (uint32 i = 0; table[i].Name != NULL; ++i)
for (uint32 i = 0; i < table.size(); ++i)
{
if (!hasStringAbbr(table[i].Name, cmd.c_str()))
continue;
@@ -286,7 +248,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st
bool match = false;
if (strlen(table[i].Name) > cmd.length())
{
for (uint32 j = 0; table[j].Name != NULL; ++j)
for (uint32 j = 0; j < table.size(); ++j)
{
if (!hasStringAbbr(table[j].Name, cmd.c_str()))
continue;
@@ -302,7 +264,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st
continue;
// select subcommand from child commands list
if (table[i].ChildCommands != NULL)
if (!table[i].ChildCommands.empty())
{
if (!ExecuteCommandInTable(table[i].ChildCommands, text, fullcmd))
{
@@ -367,7 +329,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st
return false;
}
bool ChatHandler::SetDataForCommandInTable(ChatCommand* table, char const* text, uint32 permission, std::string const& help, std::string const& fullcommand)
bool ChatHandler::SetDataForCommandInTable(std::vector<ChatCommand>& table, char const* text, uint32 permission, std::string const& help, std::string const& fullcommand)
{
std::string cmd = "";
@@ -379,14 +341,14 @@ bool ChatHandler::SetDataForCommandInTable(ChatCommand* table, char const* text,
while (*text == ' ') ++text;
for (uint32 i = 0; table[i].Name != NULL; i++)
for (uint32 i = 0; i < table.size(); i++)
{
// for data fill use full explicit command names
if (table[i].Name != cmd)
continue;
// select subcommand from child commands list (including "")
if (table[i].ChildCommands != NULL)
if (!table[i].ChildCommands.empty())
{
if (SetDataForCommandInTable(table[i].ChildCommands, text, permission, help, fullcommand))
return true;
@@ -413,7 +375,7 @@ bool ChatHandler::SetDataForCommandInTable(ChatCommand* table, char const* text,
// in case "" command let process by caller
if (!cmd.empty())
{
if (table == getCommandTable())
if (&table == &getCommandTable())
TC_LOG_ERROR("sql.sql", "Table `command` have not existed command '%s', skip.", cmd.c_str());
else
TC_LOG_ERROR("sql.sql", "Table `command` have not existed subcommand '%s' in command '%s', skip.", cmd.c_str(), fullcommand.c_str());
@@ -519,10 +481,10 @@ Valid examples:
return LinkExtractor(message).IsValidMessage();
}
bool ChatHandler::ShowHelpForSubCommands(ChatCommand* table, char const* cmd, char const* subcmd)
bool ChatHandler::ShowHelpForSubCommands(std::vector<ChatCommand> const& table, char const* cmd, char const* subcmd)
{
std::string list;
for (uint32 i = 0; table[i].Name != NULL; ++i)
for (uint32 i = 0; i < table.size(); ++i)
{
// must be available (ignore handler existence for show command with possible available subcommands)
if (!isAvailable(table[i]))
@@ -539,14 +501,14 @@ bool ChatHandler::ShowHelpForSubCommands(ChatCommand* table, char const* cmd, ch
list += table[i].Name;
if (table[i].ChildCommands)
if (!table[i].ChildCommands.empty())
list += " ...";
}
if (list.empty())
return false;
if (table == getCommandTable())
if (&table == &getCommandTable())
{
SendSysMessage(LANG_AVIABLE_CMD);
PSendSysMessage("%s", list.c_str());
@@ -557,11 +519,11 @@ bool ChatHandler::ShowHelpForSubCommands(ChatCommand* table, char const* cmd, ch
return true;
}
bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd)
bool ChatHandler::ShowHelpForCommand(std::vector<ChatCommand> const& table, const char* cmd)
{
if (*cmd)
{
for (uint32 i = 0; table[i].Name != NULL; ++i)
for (uint32 i = 0; i < table.size(); ++i)
{
// must be available (ignore handler existence for show command with possible available subcommands)
if (!isAvailable(table[i]))
@@ -573,7 +535,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd)
// have subcommand
char const* subcmd = (*cmd) ? strtok(NULL, " ") : "";
if (table[i].ChildCommands && subcmd && *subcmd)
if (!table[i].ChildCommands.empty() && subcmd && *subcmd)
{
if (ShowHelpForCommand(table[i].ChildCommands, subcmd))
return true;
@@ -582,7 +544,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd)
if (!table[i].Help.empty())
SendSysMessage(table[i].Help.c_str());
if (table[i].ChildCommands)
if (!table[i].ChildCommands.empty())
if (ShowHelpForSubCommands(table[i].ChildCommands, table[i].Name, subcmd ? subcmd : ""))
return true;
@@ -591,7 +553,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd)
}
else
{
for (uint32 i = 0; table[i].Name != NULL; ++i)
for (uint32 i = 0; i < table.size(); ++i)
{
// must be available (ignore handler existence for show command with possible available subcommands)
if (!isAvailable(table[i]))
@@ -603,7 +565,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd)
if (!table[i].Help.empty())
SendSysMessage(table[i].Help.c_str());
if (table[i].ChildCommands)
if (!table[i].ChildCommands.empty())
if (ShowHelpForSubCommands(table[i].ChildCommands, "", ""))
return true;