Optimizations from LJ and generic functions

This commit is contained in:
James R 2019-11-13 14:26:28 -08:00
parent c9aad2d186
commit 359d8a2c25
3 changed files with 70 additions and 110 deletions

View File

@ -345,6 +345,40 @@ size_t COM_CheckParm(const char *check)
return 0;
}
/** \brief COM_CheckParm, but checks only the start of each argument.
* E.g. checking for "-no" would match "-noerror" too.
*/
size_t COM_CheckPartialParm(const char *check)
{
int len;
size_t i;
len = strlen(check);
for (i = 1; i < com_argc; i++)
{
if (strncasecmp(check, com_argv[i], len) == 0)
return i;
}
return 0;
}
/** Find the first argument that starts with a hyphen (-).
* \return The index of the argument, or 0
* if there are no such arguments.
*/
size_t COM_FirstOption(void)
{
size_t i;
for (i = 1; i < com_argc; i++)
{
if (com_argv[i][0] == '-')/* options start with a hyphen */
return i;
}
return 0;
}
/** Parses a string into command-line tokens.
*
* \param ptext A null-terminated string. Does not need to be

View File

@ -29,6 +29,8 @@ size_t COM_Argc(void);
const char *COM_Argv(size_t arg); // if argv > argc, returns empty string
char *COM_Args(void);
size_t COM_CheckParm(const char *check); // like M_CheckParm :)
size_t COM_CheckPartialParm(const char *check);
size_t COM_FirstOption(void);
// match existing command or NULL
const char *COM_CompleteCommand(const char *partial, INT32 skips);

View File

@ -1719,56 +1719,6 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
}
}
enum
{
MAP_COMMAND_FORCE_OPTION,
MAP_COMMAND_GAMETYPE_OPTION,
MAP_COMMAND_NORESETPLAYERS_OPTION,
NUM_MAP_COMMAND_OPTIONS
};
static size_t CheckOptions(
int num_options,
size_t *first_argumentp,
size_t *user_options,
const char ***option_names,
int *option_num_arguments
)
{
int arguments_used;
size_t first_argument;
int i;
const char **pp;
const char *name;
size_t n;
arguments_used = 0;
first_argument = COM_Argc();
for (i = 0; i < num_options; ++i)
{
pp = option_names[i];
name = *pp;
do
{
if (( n = COM_CheckParm(name) ))
{
user_options[i] = n;
arguments_used += 1 + option_num_arguments[i];
if (n < first_argument)
first_argument = n;
}
}
while (( name = *++pp )) ;
}
(*first_argumentp) = first_argument;
return arguments_used;
}
static char *
ConcatCommandArgv (int start, int end)
{
@ -1812,43 +1762,10 @@ ConcatCommandArgv (int start, int end)
//
static void Command_Map_f(void)
{
const char *force_option_names[] =
{
"-force",
"-f",
NULL
};
const char *gametype_option_names[] =
{
"-gametype",
"-g",
"-gt",
NULL
};
const char *noresetplayers_option_names[] =
{
"-noresetplayers",
NULL
};
const char **option_names[] =
{
force_option_names,
gametype_option_names,
noresetplayers_option_names,
};
int option_num_arguments[] =
{
0,/* -force */
1,/* -gametype */
0,/* -noresetplayers */
};
size_t acceptableargc;/* (this includes the command name itself!) */
size_t first_argument;
size_t user_options [NUM_MAP_COMMAND_OPTIONS] = {0};
const char *arg_gametype;
size_t first_option;
size_t option_force;
size_t option_gametype;
const char *gametypename;
boolean newresetplayers;
boolean mustmodifygame;
@ -1871,18 +1788,15 @@ static void Command_Map_f(void)
return;
}
/* map name + options */
acceptableargc = 2 + CheckOptions(NUM_MAP_COMMAND_OPTIONS,
&first_argument,
user_options, option_names, option_num_arguments);
newresetplayers = !user_options[MAP_COMMAND_NORESETPLAYERS_OPTION];
option_force = COM_CheckPartialParm("-f");
option_gametype = COM_CheckPartialParm("-g");
newresetplayers = ! COM_CheckParm("-noresetplayers");
mustmodifygame =
!( netgame || multiplayer ) &&
(!modifiedgame || savemoddata );
if (mustmodifygame && !user_options[MAP_COMMAND_FORCE_OPTION])
if (mustmodifygame && !option_force)
{
/* May want to be more descriptive? */
CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n"));
@ -1895,26 +1809,37 @@ static void Command_Map_f(void)
return;
}
if (user_options[MAP_COMMAND_GAMETYPE_OPTION] && !multiplayer)
if (option_gametype)
{
CONS_Printf(M_GetText("You can't switch gametypes in single player!\n"));
return;
if (!multiplayer)
{
CONS_Printf(M_GetText(
"You can't switch gametypes in single player!\n"));
return;
}
else if (COM_Argc() < option_gametype + 2)/* no argument after? */
{
CONS_Alert(CONS_ERROR,
"No gametype name follows parameter '%s'.\n",
COM_Argv(option_gametype));
return;
}
}
/* If the first argument is an option, you fucked up. */
if (COM_Argc() < acceptableargc || first_argument == 1)
if (!( first_option = COM_FirstOption() ))
first_option = COM_Argc();
if (first_option < 2)
{
/* I'm going over the fucking lines and I DON'T CAREEEEE */
CONS_Printf("map <name / [MAP]code / number> [-gametype <type>] [-force]:\n");
CONS_Printf(M_GetText(
"Warp to a map, by its name, two character code, with optional \"MAP\" prefix, or by its number (though why would you).\n"
"All parameters are case-insensitive.\n"
"* \"-force\" may be shortened to \"-f\".\n"
"* \"-gametype\" may be shortened to \"-g\" or \"-gt\".\n"));
"All parameters are case-insensitive and may be abbreviated.\n"));
return;
}
mapname = ConcatCommandArgv(1, first_argument);
mapname = ConcatCommandArgv(1, first_option);
mapnamelen = strlen(mapname);
if (mapnamelen == 2)/* maybe two digit code */
@ -1965,22 +1890,22 @@ static void Command_Map_f(void)
realmapname = G_BuildMapTitle(newmapnum);
}
if (mustmodifygame && user_options[MAP_COMMAND_FORCE_OPTION])
if (mustmodifygame && option_force)
{
G_SetGameModified(false);
}
// new gametype value
// use current one by default
if (user_options[MAP_COMMAND_GAMETYPE_OPTION])
if (option_gametype)
{
arg_gametype = COM_Argv(user_options[MAP_COMMAND_GAMETYPE_OPTION] + 1);
gametypename = COM_Argv(option_gametype + 1);
newgametype = G_GetGametypeByName(arg_gametype);
newgametype = G_GetGametypeByName(gametypename);
if (newgametype == -1) // reached end of the list with no match
{
d = atoi(arg_gametype);
d = atoi(gametypename);
// assume they gave us a gametype number, which is okay too
if (d >= 0 && d < NUMGAMETYPES)
newgametype = d;
@ -1988,7 +1913,7 @@ static void Command_Map_f(void)
}
// don't use a gametype the map doesn't support
if (cv_debug || user_options[MAP_COMMAND_FORCE_OPTION] || cv_skipmapcheck.value)
if (cv_debug || option_force || cv_skipmapcheck.value)
fromlevelselect = false; // The player wants us to trek on anyway. Do so.
// G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer
else
@ -2043,7 +1968,6 @@ static void Command_Map_f(void)
Z_Free(realmapname);
}
#undef CHECKPARM
/** Receives a map command and changes the map.
*