Improve type and length safety of commands taking binary data
This commit is contained in:
@@ -260,7 +260,7 @@ CommandProc CmdRenamePlan;
|
||||
|
||||
CommandProc CmdDesyncCheck;
|
||||
|
||||
#define DEF_CMD(proc, flags, type) {proc, #proc, (CommandFlags)flags, type}
|
||||
#define DEF_CMD(proc, flags, type) Command(proc, #proc, (CommandFlags)flags, type)
|
||||
|
||||
/**
|
||||
* The master command table
|
||||
@@ -638,7 +638,7 @@ static int _docommand_recursive = 0;
|
||||
*/
|
||||
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
|
||||
{
|
||||
return DoCommand(container->tile, container->p1, container->p2, flags, container->cmd & CMD_ID_MASK, container->text.c_str());
|
||||
return DoCommand(container->tile, container->p1, container->p2, flags, container->cmd & CMD_ID_MASK, container->text.c_str(), container->binary_length);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -651,10 +651,11 @@ CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
|
||||
* @param flags Flags for the command and how to execute the command
|
||||
* @param cmd The command-id to execute (a value of the CMD_* enums)
|
||||
* @param text The text to pass
|
||||
* @param binary_length The length of binary data in text
|
||||
* @see CommandProc
|
||||
* @return the cost
|
||||
*/
|
||||
CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text)
|
||||
CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text, uint32 binary_length)
|
||||
{
|
||||
SCOPE_INFO_FMT([=], "DoCommand: tile: %X (%d x %d), p1: 0x%X, p2: 0x%X, flags: 0x%X, company: %s, cmd: 0x%X (%s)",
|
||||
tile, TileX(tile), TileY(tile), p1, p2, flags, scope_dumper().CompanyInfo(_current_company), cmd, GetCommandName(cmd));
|
||||
@@ -665,7 +666,7 @@ CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags,
|
||||
if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (flags & DC_ALL_TILES) == 0))) return CMD_ERROR;
|
||||
|
||||
/* Chop of any CMD_MSG or other flags; we don't need those here */
|
||||
CommandProc *proc = _command_proc_table[cmd & CMD_ID_MASK].proc;
|
||||
const Command &command = _command_proc_table[cmd & CMD_ID_MASK];
|
||||
|
||||
_docommand_recursive++;
|
||||
|
||||
@@ -673,7 +674,7 @@ CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags,
|
||||
if (_docommand_recursive == 1 || !(flags & DC_EXEC) ) {
|
||||
if (_docommand_recursive == 1) _cleared_object_areas.Clear();
|
||||
SetTownRatingTestMode(true);
|
||||
res = proc(tile, flags & ~DC_EXEC, p1, p2, text);
|
||||
res = command.Execute(tile, flags & ~DC_EXEC, p1, p2, text, binary_length);
|
||||
SetTownRatingTestMode(false);
|
||||
if (res.Failed()) {
|
||||
goto error;
|
||||
@@ -695,7 +696,7 @@ CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags,
|
||||
/* Execute the command here. All cost-relevant functions set the expenses type
|
||||
* themselves to the cost object at some point */
|
||||
if (_docommand_recursive == 1) _cleared_object_areas.Clear();
|
||||
res = proc(tile, flags, p1, p2, text);
|
||||
res = command.Execute(tile, flags, p1, p2, text, binary_length);
|
||||
if (res.Failed()) {
|
||||
error:
|
||||
_docommand_recursive--;
|
||||
@@ -732,7 +733,7 @@ Money GetAvailableMoneyForCommand()
|
||||
*/
|
||||
bool DoCommandP(const CommandContainer *container, bool my_cmd)
|
||||
{
|
||||
return DoCommandP(container->tile, container->p1, container->p2, container->cmd, container->callback, container->text.c_str(), my_cmd);
|
||||
return DoCommandP(container->tile, container->p1, container->p2, container->cmd, container->callback, container->text.c_str(), my_cmd, container->binary_length);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -748,7 +749,7 @@ bool DoCommandP(const CommandContainer *container, bool my_cmd)
|
||||
* @param callback A callback function to call after the command is finished
|
||||
* @param text The text to pass
|
||||
* @param my_cmd indicator if the command is from a company or server (to display error messages for a user)
|
||||
* @param binary_length The quantity of binary data in text
|
||||
* @param binary_length The length of binary data in text
|
||||
* @return \c true if the command succeeded, else \c false.
|
||||
*/
|
||||
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, uint32 binary_length)
|
||||
@@ -853,10 +854,10 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd,
|
||||
byte cmd_id = cmd & CMD_ID_MASK;
|
||||
assert(cmd_id < lengthof(_command_proc_table));
|
||||
|
||||
CommandProc *proc = _command_proc_table[cmd_id].proc;
|
||||
const Command &command = _command_proc_table[cmd_id];
|
||||
/* Shouldn't happen, but you never know when someone adds
|
||||
* NULLs to the _command_proc_table. */
|
||||
assert(proc != NULL);
|
||||
assert(command.proc != NULL);
|
||||
|
||||
/* Command flags are used internally */
|
||||
CommandFlags cmd_flags = GetCommandFlags(cmd);
|
||||
@@ -890,7 +891,7 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd,
|
||||
_cleared_object_areas.Clear();
|
||||
SetTownRatingTestMode(true);
|
||||
BasePersistentStorageArray::SwitchMode(PSM_ENTER_TESTMODE);
|
||||
CommandCost res = proc(tile, flags, p1, p2, text);
|
||||
CommandCost res = command.Execute(tile, flags, p1, p2, text, binary_length);
|
||||
BasePersistentStorageArray::SwitchMode(PSM_LEAVE_TESTMODE);
|
||||
SetTownRatingTestMode(false);
|
||||
|
||||
@@ -935,7 +936,7 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd,
|
||||
* use the construction one */
|
||||
_cleared_object_areas.Clear();
|
||||
BasePersistentStorageArray::SwitchMode(PSM_ENTER_COMMAND);
|
||||
CommandCost res2 = proc(tile, flags | DC_EXEC, p1, p2, text);
|
||||
CommandCost res2 = command.Execute(tile, flags | DC_EXEC, p1, p2, text, binary_length);
|
||||
BasePersistentStorageArray::SwitchMode(PSM_LEAVE_COMMAND);
|
||||
|
||||
if (cmd_id == CMD_COMPANY_CTRL) {
|
||||
|
@@ -34,7 +34,7 @@ static const CommandCost CMD_ERROR = CommandCost(INVALID_STRING_ID);
|
||||
*/
|
||||
#define return_cmd_error(errcode) return CommandCost(errcode);
|
||||
|
||||
CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text = NULL);
|
||||
CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text = NULL, uint32 binary_length = 0);
|
||||
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags);
|
||||
|
||||
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback = NULL, const char *text = NULL, bool my_cmd = true, uint32 binary_length = 0);
|
||||
|
@@ -492,6 +492,7 @@ enum CommandFlags {
|
||||
CMD_DEITY = 0x100, ///< the command may be executed by COMPANY_DEITY
|
||||
CMD_STR_CTRL = 0x200, ///< the command's string may contain control strings
|
||||
CMD_NO_EST = 0x400, ///< the command is never estimated.
|
||||
CMD_PROCEX = 0x800, ///< the command proc function has extended parameters
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(CommandFlags)
|
||||
|
||||
@@ -537,6 +538,7 @@ enum CommandPauseLevel {
|
||||
* @return The CommandCost of the command, which can be succeeded or failed.
|
||||
*/
|
||||
typedef CommandCost CommandProc(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text);
|
||||
typedef CommandCost CommandProcEx(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text, uint32 binary_length);
|
||||
|
||||
/**
|
||||
* Define a command with the flags which belongs to it.
|
||||
@@ -545,10 +547,26 @@ typedef CommandCost CommandProc(TileIndex tile, DoCommandFlag flags, uint32 p1,
|
||||
* the #CMD_AUTO, #CMD_OFFLINE and #CMD_SERVER values.
|
||||
*/
|
||||
struct Command {
|
||||
CommandProc *proc; ///< The procedure to actually executing
|
||||
union {
|
||||
CommandProc *proc; ///< The procedure to actually execute
|
||||
CommandProcEx *procex; ///< The procedure to actually execute, extended parameters
|
||||
};
|
||||
const char *name; ///< A human readable name for the procedure
|
||||
CommandFlags flags; ///< The (command) flags to that apply to this command
|
||||
CommandType type; ///< The type of command.
|
||||
|
||||
Command(CommandProc *proc, const char *name, CommandFlags flags, CommandType type)
|
||||
: proc(proc), name(name), flags(flags & ~CMD_PROCEX), type(type) {}
|
||||
Command(CommandProcEx *procex, const char *name, CommandFlags flags, CommandType type)
|
||||
: procex(procex), name(name), flags(flags | CMD_PROCEX), type(type) {}
|
||||
|
||||
inline CommandCost Execute(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text, uint32 binary_length) const {
|
||||
if (this->flags & CMD_PROCEX) {
|
||||
return this->procex(tile, flags, p1, p2, text, binary_length);
|
||||
} else {
|
||||
return this->proc(tile, flags, p1, p2, text);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user