/
CommandArgsParser.h
188 lines (157 loc) · 7.63 KB
/
CommandArgsParser.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#ifndef COMMAND_ARGS_PARSER_H
#define COMMAND_ARGS_PARSER_H
#include <unordered_map>
#include <cstdint>
/// Tagged variant variable type
namespace CommandArgVariableType {
enum Type {
None,
Integer,
Float,
Boolean,
CString
};
}
/// Flags for the CommandArgVariable class
namespace CommandArgVariableFlags {
enum Flags {
OwnsCString = 1
};
}
/// Tagged variant class used for command line variables
/// Might own the cstring if OwnsCString flag is set
/// Must be placed in static memory - will register the command on construction
class CommandArgVariable {
public:
CommandArgVariable() = delete;
~CommandArgVariable();
CommandArgVariable(const char * pVariableName, const CommandArgVariableType::Type nType, const int defaultIntValue, const uint8_t flags = 0);
CommandArgVariable(const char * pVariableName, const CommandArgVariableType::Type nType, const bool defaultBoolValue, const uint8_t flags = 0);
CommandArgVariable(const char * pVariableName, const CommandArgVariableType::Type nType, const float defaultFloatValue, const uint8_t flags = 0);
CommandArgVariable(const char * pVariableName, const CommandArgVariableType::Type nType, const char * defaultCStringValue, const uint8_t flags = 0);
CommandArgVariable(const uint32_t variableHash, const CommandArgVariableType::Type nType, const int defaultIntValue, const uint8_t flags = 0);
CommandArgVariable(const uint32_t variableHash, const CommandArgVariableType::Type nType, const bool defaultBoolValue, const uint8_t flags = 0);
CommandArgVariable(const uint32_t variableHash, const CommandArgVariableType::Type nType, const float defaultFloatValue, const uint8_t flags = 0);
CommandArgVariable(const uint32_t variableHash, const CommandArgVariableType::Type nType, const char * defaultCStringValue, const uint8_t flags = 0);
int GetInt() const;
float GetFloat() const;
bool GetBool() const;
const char * GetCString() const;
void SetInt(const int i);
void SetFloat(const float f);
void SetBool(const bool b);
void SetCString(const char * pString);
CommandArgVariableType::Type GetType() const { return static_cast<CommandArgVariableType::Type>(m_Type); }
void SetFlags(const uint8_t flags) { m_Flags = flags; }
uint8_t GetFlags() const { return m_Flags; }
private:
union {
int m_AsInt;
float m_AsFloat;
bool m_AsBool;
const char * m_AsCString;
} m_Data; // 8 bytes for char * ptr. Use memset to be safe.
int8_t m_Type; // CommandArgType::Type
uint8_t m_Flags; // CommandArgVariableFlags::Flags
};
#define VALIDATE_HASH_COMMAND ( 0 )
#if VALIDATE_HASH_COMMAND
#define HASH_COMMAND_VARIABLE( str, hashValue ) CommandArgsMgr::ValidateHashCommandValue((str), (hashValue))
#else
#define HASH_COMMAND_VARIABLE( str, hashValue ) ( hashValue )
#endif //
// If enabled, we make a deep copy of the input string
// The advantage of doing this is that after making IncrementToken
// calls m_pInputString is still unmodified
#define COMMANDS_ARGS_PARSER_MAKES_COPY_OF_INPUT_STRING (0)
class CommandArgsParser {
public:
static const char * ms_DefaultDelimeters;
static bool Parse_Bool(const char * pString, bool & rInOutBool);
static bool Parse_Integer(const char * pString, int & rInOutInt);
static bool Parse_Float(const char * pString, float & rInOutFloat);
CommandArgsParser();
~CommandArgsParser();
char * GetInputString() const { return m_pInputString; }
char * GetCurrentToken() const { return m_pCurrentToken; }
void InitWithArgs(char * pFullString);
char * IncrementToken(const char * pDelimeters = ms_DefaultDelimeters);
bool CompareToken(const char * pCurToken, const char * pToCompareTo) const;
bool IncrementTokenAndParseInt(int & rInOutInt, const char * pDelimeters = ms_DefaultDelimeters);
bool IncrementTokenAndParseFloat(float & rInOutFloat, const char * pDelimeters = ms_DefaultDelimeters);
bool IncrementTokenAndParseVector2(float & fx, float & fy, const char * pDelimeters = ms_DefaultDelimeters);
bool IncrementTokenAndParseVector3(float & fx, float & fy, float & fz, const char * pDelimeters = ms_DefaultDelimeters);
void Reset();
private:
char * m_pInputString;
char * m_pInputStringTokenize;
char * m_pCurrentToken;
char * m_pNextToken;
bool m_bHasProcessedFirstToken;
};
typedef int(*ConsoleCommandFunc)(CommandArgsParser & args);
/// Helper class that allows REGISTER_CONSOLE_COMMAND_FUNCTION to effectively be called
/// as part of the CONSOLE_COMMAND_FUNCTION macro
class RegisterCommandArgFunctionAuto {
public:
RegisterCommandArgFunctionAuto() = delete;
RegisterCommandArgFunctionAuto(const char * pCommandName, const ConsoleCommandFunc pFunc);
RegisterCommandArgFunctionAuto(const uint32_t commandHashValue, const ConsoleCommandFunc pFunc);
};
#define CONSOLE_COMMAND_FUNCTION_NAME( commandName ) int Command_##commandName(CommandArgsParser & ); \
RegisterCommandArgFunctionAuto s_auto##commandName(#commandName, &Command_##commandName); \
int Command_##commandName
#define CONSOLE_COMMAND_FUNCTION_HASH( commandName, hashValue ) int Command_##commandName(CommandArgsParser & ); \
RegisterCommandArgFunctionAuto s_auto##commandName(hashValue, &Command_##commandName); \
int Command_##commandName
namespace CommandArgEntryType {
enum Type {
Variable,
Function
};
}
/// Each entry is either a command or a variable this tagged variant holds
/// one or the other
class CommandArgEntry {
public:
CommandArgEntry();
const ConsoleCommandFunc GetFunction() const;
CommandArgVariable * GetVariable() const;
void SetFunction(const ConsoleCommandFunc pFunc);
void SetVariable(CommandArgVariable * pVariable);
void SetType(const CommandArgEntryType::Type nType);
unsigned int GetType() const { return m_Type; }
private:
union {
CommandArgVariable * m_pVariable;
ConsoleCommandFunc m_pFunction;
} m_Data;
uint8_t m_Type; // CommandArgEntryType::Type
};
/// Singleton interface for command arg functions and variables
/// Initialize with SetupAllCommandArgs()
/// Invoke with Execute()
class CommandArgsMgr {
public:
static CommandArgsMgr & GetInstance() { return ms_Instance; }
static uint32_t HashCommandLineArg(const char * pString);
static uint32_t HashCommandLineArg_StartEnd(const char * pStart, const char * pEnd);
static uint32_t ValidateHashCommandValue(const char * pString, const uint32_t precalculatedHashValue);
static char * FindFirstNonWhitespaceCharacter(const char * pString, const char * pWhitespaceCharacters = CommandArgsParser::ms_DefaultDelimeters);
static char * FindFirstWhitespaceCharacterAfterFirstToken(const char * pString, const char * pWhitespaceCharacters = CommandArgsParser::ms_DefaultDelimeters);
void RegisterCommandArgVariableByName(const char * pArgName, CommandArgVariable * ptr);
void RegisterCommandArgVariableByHash(const uint32_t argHashValue, CommandArgVariable * ptr);
void RegisterCommandArgFunctionByName(const char * pArgName, const ConsoleCommandFunc pFunc);
void RegisterCommandArgFunctionByHash(const uint32_t commandHashValue, const ConsoleCommandFunc pFunc);
int GetIntegerForKey(const uint32_t key);
float GetFloatForKey(const uint32_t key);
bool GetBoolForKey(const uint32_t key);
const char * GetCStringForKey(const uint32_t key);
void SetupAllCommandArgs(const int argc, char * argv[]);
int Execute(const char * pCommand);
private:
bool FindCommandArgEntry(std::unordered_map<uint32_t, CommandArgEntry>::iterator & inOutIterator, const uint32_t key);
std::unordered_map<uint32_t, CommandArgEntry> m_CommandArgsMap;
static CommandArgsMgr ms_Instance;
};
#endif // COMMAND_ARGS_PARSER_H