ReChecker/common/commandline.cpp
2022-09-25 00:01:43 +07:00

355 lines
6.7 KiB
C++

#include "precompiled.h"
class CCommandLine: public ICommandLine {
public:
CCommandLine();
virtual ~CCommandLine();
void CreateCmdLine(const char *commandline);
void CreateCmdLine(int argc, const char *argv[]);
const char *GetCmdLine() const;
// Check whether a particular parameter exists
const char *CheckParm(const char *psz, char **ppszValue = nullptr) const;
void RemoveParm(const char *pszParm);
void AppendParm(const char *pszParm, const char *pszValues);
void SetParm(const char *pszParm, const char *pszValues);
void SetParm(const char *pszParm, int iValue);
// When the commandline contains @name, it reads the parameters from that file
void LoadParametersFromFile(const char *&pSrc, char *&pDst, int maxDestLen);
private:
// Copy of actual command line
char *m_pszCmdLine;
};
CCommandLine g_CmdLine;
ICommandLine *cmdline = &g_CmdLine;
ICommandLine *CommandLine()
{
return &g_CmdLine;
}
CCommandLine::CCommandLine()
{
m_pszCmdLine = nullptr;
}
CCommandLine::~CCommandLine()
{
if (m_pszCmdLine)
{
delete [] m_pszCmdLine;
m_pszCmdLine = nullptr;
}
}
char *CopyString(const char *src)
{
if (!src)
return nullptr;
char *out = (char *)new char[strlen(src) + 1];
strcpy(out, src);
return out;
}
// Creates a command line from the arguments passed in
void CCommandLine::CreateCmdLine(int argc, const char *argv[])
{
char cmdline[4096] = "";
const int MAX_CHARS = sizeof(cmdline) - 1;
for (int i = 0; i < argc; ++i)
{
if (strchr(argv[i], ' '))
{
strncat(cmdline, "\"", MAX_CHARS);
strncat(cmdline, argv[i], MAX_CHARS);
strncat(cmdline, "\"", MAX_CHARS);
}
else
{
strncat(cmdline, argv[i], MAX_CHARS);
}
strncat(cmdline, " ", MAX_CHARS);
}
cmdline[strlen(cmdline)] = '\0';
CreateCmdLine(cmdline);
}
void CCommandLine::LoadParametersFromFile(const char *&pSrc, char *&pDst, int maxDestLen)
{
// Suck out the file name
char szFileName[ MAX_PATH ];
char *pOut;
char *pDestStart = pDst;
// Skip the @ sign
pSrc++;
pOut = szFileName;
while (*pSrc && *pSrc != ' ')
{
*pOut++ = *pSrc++;
#if 0
if ((pOut - szFileName) >= (MAX_PATH - 1))
break;
#endif
}
*pOut = '\0';
// Skip the space after the file name
if (*pSrc)
pSrc++;
// Now read in parameters from file
FILE *fp = fopen(szFileName, "r");
if (fp)
{
char c;
c = (char)fgetc(fp);
while (c != EOF)
{
// Turn return characters into spaces
if (c == '\n')
c = ' ';
*pDst++ = c;
#if 0
// Don't go past the end, and allow for our terminating space character AND a terminating null character.
if ((pDst - pDestStart) >= (maxDestLen - 2))
break;
#endif
// Get the next character, if there are more
c = (char)fgetc(fp);
}
// Add a terminating space character
*pDst++ = ' ';
fclose(fp);
}
else
{
printf("Parameter file '%s' not found, skipping...", szFileName);
}
}
// Purpose: Create a command line from the passed in string
// Note that if you pass in a @filename, then the routine will read settings from a file instead of the command line
void CCommandLine::CreateCmdLine(const char *commandline)
{
if (m_pszCmdLine)
{
delete[] m_pszCmdLine;
m_pszCmdLine = nullptr;
}
char szFull[4096];
char *pDst = szFull;
const char *pSrc = commandline;
bool allowAtSign = true;
while (*pSrc)
{
if (*pSrc == '@')
{
if (allowAtSign)
{
LoadParametersFromFile(pSrc, pDst, sizeof(szFull) - (pDst - szFull));
continue;
}
}
allowAtSign = isspace(*pSrc) != 0;
#if 0
// Don't go past the end.
if ((pDst - szFull) >= (sizeof(szFull) - 1))
break;
#endif
*pDst++ = *pSrc++;
}
*pDst = '\0';
int len = strlen(szFull) + 1;
m_pszCmdLine = new char[len];
memcpy(m_pszCmdLine, szFull, len);
}
// Purpose: Remove specified string ( and any args attached to it ) from command line
void CCommandLine::RemoveParm(const char *pszParm)
{
if (!m_pszCmdLine)
return;
if (!pszParm || *pszParm == '\0')
return;
// Search for first occurrence of pszParm
char *p, *found;
char *pnextparam;
int n;
int curlen;
p = m_pszCmdLine;
while (*p)
{
curlen = strlen(p);
found = strstr(p, pszParm);
if (!found)
break;
pnextparam = found + 1;
while (pnextparam && *pnextparam && (*pnextparam != '-') && (*pnextparam != '+'))
pnextparam++;
if (pnextparam && *pnextparam)
{
// We are either at the end of the string, or at the next param. Just chop out the current param.
// # of characters after this param.
n = curlen - (pnextparam - p);
memcpy(found, pnextparam, n);
found[n] = '\0';
}
else
{
// Clear out rest of string.
n = pnextparam - found;
memset(found, 0, n);
}
}
// Strip and trailing ' ' characters left over.
while (1)
{
int curpos = strlen(m_pszCmdLine);
if (curpos == 0 || m_pszCmdLine[ curpos - 1 ] != ' ')
break;
m_pszCmdLine[curpos - 1] = '\0';
}
}
// Purpose: Append parameter and argument values to command line
void CCommandLine::AppendParm(const char *pszParm, const char *pszValues)
{
int nNewLength = 0;
char *pCmdString;
// Parameter.
nNewLength = strlen(pszParm);
// Values + leading space character.
if (pszValues)
nNewLength += strlen(pszValues) + 1;
// Terminal 0;
nNewLength++;
if (!m_pszCmdLine)
{
m_pszCmdLine = new char[ nNewLength ];
strcpy(m_pszCmdLine, pszParm);
if (pszValues)
{
strcat(m_pszCmdLine, " ");
strcat(m_pszCmdLine, pszValues);
}
return;
}
// Remove any remnants from the current Cmd Line.
RemoveParm(pszParm);
nNewLength += strlen(m_pszCmdLine) + 1 + 1;
pCmdString = new char[ nNewLength ];
memset(pCmdString, 0, nNewLength);
strcpy(pCmdString, m_pszCmdLine); // Copy old command line.
strcat(pCmdString, " "); // Put in a space
strcat(pCmdString, pszParm);
if (pszValues)
{
strcat(pCmdString, " ");
strcat(pCmdString, pszValues);
}
// Kill off the old one
delete[] m_pszCmdLine;
// Point at the new command line.
m_pszCmdLine = pCmdString;
}
void CCommandLine::SetParm(const char *pszParm, const char *pszValues)
{
RemoveParm(pszParm);
AppendParm(pszParm, pszValues);
}
void CCommandLine::SetParm(const char *pszParm, int iValue)
{
char buf[64];
_snprintf(buf, sizeof(buf), "%d", iValue);
SetParm(pszParm, buf);
}
// Purpose: Search for the parameter in the current commandline
const char *CCommandLine::CheckParm(const char *psz, char **ppszValue) const
{
static char sz[128] = "";
if (!m_pszCmdLine)
return nullptr;
char *pret = strstr(m_pszCmdLine, psz);
if (!pret || !ppszValue)
return pret;
*ppszValue = nullptr;
// find the next whitespace
char *p1 = pret;
do {
++p1;
} while (*p1 != ' ' && *p1);
int i = 0;
char *p2 = p1 + 1;
do {
if (p2[i] == '\0' || p2[i] == ' ')
break;
sz[i++] = p2[i];
} while (i < sizeof(sz));
sz[i] = '\0';
*ppszValue = sz;
return pret;
}
const char *CCommandLine::GetCmdLine() const
{
return m_pszCmdLine;
}