CCommand improvements

Add constructor and work-in-progress tokenizer.
This commit is contained in:
Kawe Mazidjatari 2022-07-29 17:30:05 +02:00
parent f3555104a2
commit 9556b05209
10 changed files with 291 additions and 5 deletions

View File

@ -0,0 +1,40 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include <string.h>
#include "characterset.h"
// memdbgon must be the last include file in a .cpp file!!!
//#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: builds a simple lookup table of a group of important characters
// Input : *pParseGroup - pointer to the buffer for the group
// *pGroupString - null terminated list of characters to flag
//-----------------------------------------------------------------------------
void CharacterSetBuild(characterset_t* pSetBuffer, const char* pszSetString)
{
int i = 0;
// Test our pointers
if (!pSetBuffer || !pszSetString)
return;
memset(pSetBuffer->set, 0, sizeof(pSetBuffer->set));
while (pszSetString[i])
{
pSetBuffer->set[pszSetString[i]] = 1;
i++;
}
}

View File

@ -0,0 +1,43 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Shared code for parsing / searching for characters in a string
// using lookup tables
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//===========================================================================//
#ifndef CHARACTERSET_H
#define CHARACTERSET_H
#ifdef _WIN32
#pragma once
#endif
struct characterset_t
{
char set[256];
};
// This is essentially a strpbrk() using a precalculated lookup table
//-----------------------------------------------------------------------------
// Purpose: builds a simple lookup table of a group of important characters
// Input : *pSetBuffer - pointer to the buffer for the group
// *pSetString - list of characters to flag
//-----------------------------------------------------------------------------
extern void CharacterSetBuild(characterset_t* pSetBuffer, const char* pSetString);
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pSetBuffer - pre-build group buffer
// character - character to lookup
// Output : int - 1 if the character was in the set
//-----------------------------------------------------------------------------
#define IN_CHARACTERSET( SetBuffer, character ) ((SetBuffer).set[(character)])
#endif // CHARACTERSET_H

View File

@ -9,14 +9,169 @@
#include "tier0/memstd.h"
#include "tier1/cmd.h"
#include "tier1/cvar.h"
#include "tier1/characterset.h"
#include "vstdlib/callback.h"
//-----------------------------------------------------------------------------
// Purpose: returns max command lenght
// Global methods
//-----------------------------------------------------------------------------
int CCommand::MaxCommandLength(void)
static characterset_t s_BreakSet;
static bool s_bBuiltBreakSet = false;
//-----------------------------------------------------------------------------
// Tokenizer class
//-----------------------------------------------------------------------------
CCommand::CCommand()
{
return COMMAND_MAX_LENGTH - 1;
if (!s_bBuiltBreakSet)
{
s_bBuiltBreakSet = true;
CharacterSetBuild(&s_BreakSet, "{}()':");
}
Reset();
}
//-----------------------------------------------------------------------------
// Purpose: constructor
// Input : nArgC -
// **ppArgV -
// source -
//-----------------------------------------------------------------------------
CCommand::CCommand(int nArgC, const char** ppArgV, cmd_source_t source)
{
Assert(nArgC > 0);
if (!s_bBuiltBreakSet)
{
s_bBuiltBreakSet = true;
CharacterSetBuild(&s_BreakSet, "{}()':");
}
Reset();
char* pBuf = m_pArgvBuffer;
char* pSBuf = m_pArgSBuffer;
m_nArgc = nArgC;
for (int i = 0; i < nArgC; ++i)
{
m_ppArgv[i] = pBuf;
int nLen = strlen(ppArgV[i]);
memcpy(pBuf, ppArgV[i], nLen + 1);
if (i == 0)
{
m_nArgv0Size = nLen;
}
pBuf += nLen + 1;
bool bContainsSpace = strchr(ppArgV[i], ' ') != NULL;
if (bContainsSpace)
{
*pSBuf++ = '\"';
}
memcpy(pSBuf, ppArgV[i], nLen);
pSBuf += nLen;
if (bContainsSpace)
{
*pSBuf++ = '\"';
}
if (i != nArgC - 1)
{
*pSBuf++ = ' ';
}
}
m_nQueuedVal = source;
}
//-----------------------------------------------------------------------------
// Purpose: tokenizer
// Input : *pCommand -
// source -
// *pBreakSet -
// Output : true on success, false on failure
//-----------------------------------------------------------------------------
bool CCommand::Tokenize(const char* pCommand, cmd_source_t source, characterset_t* pBreakSet)
{
/* !TODO (CUtlBuffer).
Reset();
m_nQueuedVal = source;
if (!pCommand)
return false;
// Use default break set
if (!pBreakSet)
{
pBreakSet = &s_BreakSet;
}
// Copy the current command into a temp buffer
// NOTE: This is here to avoid the pointers returned by DequeueNextCommand
// to become invalid by calling AddText. Is there a way we can avoid the memcpy?
int nLen = Q_strlen(pCommand);
if (nLen >= COMMAND_MAX_LENGTH - 1)
{
Warning(eDLL_T::ENGINE, "%s: Encountered command which overflows the tokenizer buffer.. Skipping!\n", __FUNCTION__);
return false;
}
memcpy(m_pArgSBuffer, pCommand, nLen + 1);
// Parse the current command into the current command buffer
CUtlBuffer bufParse(m_pArgSBuffer, nLen, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY);
int nArgvBufferSize = 0;
while (bufParse.IsValid() && (m_nArgc < COMMAND_MAX_ARGC))
{
char* pArgvBuf = &m_pArgvBuffer[nArgvBufferSize];
int nMaxLen = COMMAND_MAX_LENGTH - nArgvBufferSize;
int nStartGet = bufParse.TellGet();
int nSize = bufParse.ParseToken(pBreakSet, pArgvBuf, nMaxLen);
if (nSize < 0)
break;
// Check for overflow condition
if (nMaxLen == nSize)
{
Reset();
return false;
}
if (m_nArgc == 1)
{
// Deal with the case where the arguments were quoted
m_nArgv0Size = bufParse.TellGet();
bool bFoundEndQuote = m_pArgSBuffer[m_nArgv0Size - 1] == '\"';
if (bFoundEndQuote)
{
--m_nArgv0Size;
}
m_nArgv0Size -= nSize;
Assert(m_nArgv0Size != 0);
// The StartGet check is to handle this case: "foo"bar
// which will parse into 2 different args. ArgS should point to bar.
bool bFoundStartQuote = (m_nArgv0Size > nStartGet) && (m_pArgSBuffer[m_nArgv0Size - 1] == '\"');
Assert(bFoundEndQuote == bFoundStartQuote);
if (bFoundStartQuote)
{
--m_nArgv0Size;
}
}
m_ppArgv[m_nArgc++] = pArgvBuf;
if (m_nArgc >= COMMAND_MAX_ARGC)
{
Warning(eDLL_T::ENGINE, "%s: Encountered command which overflows the argument buffer.. Clamped!\n", __FUNCTION__);
}
nArgvBufferSize += nSize + 1;
Assert(nArgvBufferSize <= COMMAND_MAX_LENGTH);
}*/
return true;
}
//-----------------------------------------------------------------------------
@ -76,6 +231,15 @@ const char* CCommand::operator[](int nIndex) const
return Arg(nIndex);
}
//-----------------------------------------------------------------------------
// Purpose: returns max command lenght
//-----------------------------------------------------------------------------
int CCommand::MaxCommandLength(void) const
{
return COMMAND_MAX_LENGTH - 1;
}
//-----------------------------------------------------------------------------
// Purpose: return boolean depending on if the string only has digits in it
// Input : svString -
@ -93,6 +257,17 @@ bool CCommand::HasOnlyDigits(int nIndex) const
return true;
}
//-----------------------------------------------------------------------------
// Purpose: reset
//-----------------------------------------------------------------------------
void CCommand::Reset()
{
m_nArgc = 0;
m_nArgv0Size = 0;
m_pArgSBuffer[0] = 0;
m_nQueuedVal = cmd_source_t::kCommandSrcInvalid;
}
//-----------------------------------------------------------------------------
// Purpose: construct/allocate
//-----------------------------------------------------------------------------

View File

@ -1,4 +1,5 @@
#pragma once
#include "tier1/characterset.h"
#include "public/include/iconcommand.h"
//-----------------------------------------------------------------------------
@ -58,8 +59,9 @@ private:
public:
CCommand() = delete;
CCommand(int nArgC, const char** ppArgV, cmd_source_t source);
bool Tokenize(const char* pCommand, cmd_source_t source, characterset_t* pBreakSet);
int MaxCommandLength();
int64_t ArgC(void) const;
const char** ArgV(void) const;
const char* ArgS(void) const;
@ -67,10 +69,12 @@ public:
const char* Arg(int nIndex) const;
const char* operator[](int nIndex) const;
void Reset();
int MaxCommandLength(void) const;
bool HasOnlyDigits(int nIndex) const;
private:
int m_nQueuedVal;
cmd_source_t m_nQueuedVal;
int m_nArgc;
int64_t m_nArgv0Size;
char m_pArgSBuffer[COMMAND_MAX_LENGTH];

View File

@ -108,6 +108,7 @@
<ClCompile Include="..\tier0\platform.cpp" />
<ClCompile Include="..\tier0\threadtools.cpp" />
<ClCompile Include="..\tier1\bitbuf.cpp" />
<ClCompile Include="..\tier1\characterset.cpp" />
<ClCompile Include="..\tier1\cmd.cpp" />
<ClCompile Include="..\tier1\cvar.cpp" />
<ClCompile Include="..\tier1\IConVar.cpp" />
@ -468,6 +469,7 @@
<ClInclude Include="..\tier0\valve_on.h" />
<ClInclude Include="..\tier0\wchartypes.h" />
<ClInclude Include="..\tier1\bitbuf.h" />
<ClInclude Include="..\tier1\characterset.h" />
<ClInclude Include="..\tier1\cmd.h" />
<ClInclude Include="..\tier1\cvar.h" />
<ClInclude Include="..\tier1\IConVar.h" />

View File

@ -561,6 +561,9 @@
<ClCompile Include="..\game\client\view.cpp">
<Filter>sdk\game\client</Filter>
</ClCompile>
<ClCompile Include="..\tier1\characterset.cpp">
<Filter>sdk\tier1</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\client\cdll_engine_int.h">
@ -1652,6 +1655,9 @@
<ClInclude Include="..\public\include\iconvar.h">
<Filter>sdk\public\include</Filter>
</ClInclude>
<ClInclude Include="..\tier1\characterset.h">
<Filter>sdk\tier1</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="..\shared\resource\lockedserver.png">

View File

@ -431,6 +431,7 @@
<ClInclude Include="..\tier0\valve_on.h" />
<ClInclude Include="..\tier0\wchartypes.h" />
<ClInclude Include="..\tier1\bitbuf.h" />
<ClInclude Include="..\tier1\characterset.h" />
<ClInclude Include="..\tier1\cmd.h" />
<ClInclude Include="..\tier1\cvar.h" />
<ClInclude Include="..\tier1\IConVar.h" />
@ -545,6 +546,7 @@
<ClCompile Include="..\tier0\platform.cpp" />
<ClCompile Include="..\tier0\threadtools.cpp" />
<ClCompile Include="..\tier1\bitbuf.cpp" />
<ClCompile Include="..\tier1\characterset.cpp" />
<ClCompile Include="..\tier1\cmd.cpp" />
<ClCompile Include="..\tier1\cvar.cpp" />
<ClCompile Include="..\tier1\IConVar.cpp" />

View File

@ -1185,6 +1185,9 @@
<ClInclude Include="..\public\include\icvar.h">
<Filter>sdk\public\include</Filter>
</ClInclude>
<ClInclude Include="..\tier1\characterset.h">
<Filter>sdk\tier1</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\common\opcodes.cpp">
@ -1484,6 +1487,9 @@
<ClCompile Include="..\server\persistence.cpp">
<Filter>sdk\server</Filter>
</ClCompile>
<ClCompile Include="..\tier1\characterset.cpp">
<Filter>sdk\tier1</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\Dedicated.def" />

View File

@ -118,6 +118,7 @@
<ClCompile Include="..\tier0\platform.cpp" />
<ClCompile Include="..\tier0\threadtools.cpp" />
<ClCompile Include="..\tier1\bitbuf.cpp" />
<ClCompile Include="..\tier1\characterset.cpp" />
<ClCompile Include="..\tier1\cmd.cpp" />
<ClCompile Include="..\tier1\cvar.cpp" />
<ClCompile Include="..\tier1\IConVar.cpp" />
@ -496,6 +497,7 @@
<ClInclude Include="..\tier0\valve_on.h" />
<ClInclude Include="..\tier0\wchartypes.h" />
<ClInclude Include="..\tier1\bitbuf.h" />
<ClInclude Include="..\tier1\characterset.h" />
<ClInclude Include="..\tier1\cmd.h" />
<ClInclude Include="..\tier1\cvar.h" />
<ClInclude Include="..\tier1\IConVar.h" />

View File

@ -600,6 +600,9 @@
<ClCompile Include="..\game\shared\ai_utility_shared.cpp">
<Filter>sdk\game\shared</Filter>
</ClCompile>
<ClCompile Include="..\tier1\characterset.cpp">
<Filter>sdk\tier1</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\client\cdll_engine_int.h">
@ -1745,6 +1748,9 @@
<ClInclude Include="..\public\include\icvar.h">
<Filter>sdk\public\include</Filter>
</ClInclude>
<ClInclude Include="..\tier1\characterset.h">
<Filter>sdk\tier1</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="..\shared\resource\lockedserver.png">