11/*
2- * Copyright 2021-2021 Samuel Hellawell. All rights reserved.
3- * License: https://github.com/SamHellawell /deusconsole/blob/master/LICENSE
2+ * Copyright 2021-2025 Samuel Hellawell. All rights reserved.
3+ * License: https://github.com/cykoder /deusconsole/blob/master/LICENSE
44 */
55
66#ifndef DEUS_CONSOLE_MGR
77#define DEUS_CONSOLE_MGR
88
9- #include < iostream>
109#include < unordered_map>
1110#include < deque>
1211#include < functional>
1716#include < cassert>
1817#include < string.h>
1918#include < type_traits>
19+ #include < cstdint>
2020
2121#define TEXT (txt ) txt \
2222
2323// Base exception helper
2424struct DeusConsoleException : public std ::exception {
2525 std::string s;
26- DeusConsoleException (std::string ss) : s(ss) {}
26+ DeusConsoleException (const std::string& ss) : s(ss) {}
2727 ~DeusConsoleException () throw () {}
2828 const char * what () const throw() {
2929 return s.c_str ();
@@ -33,9 +33,9 @@ struct DeusConsoleException : public std::exception {
3333// Flags that can be set on defined console variables
3434enum EDeusCVarFlags {
3535 DEUS_CVAR_DEFAULT = 0 , // Default, no flags are set, the value is set by the constructor
36- DEUS_CVAR_DEVELOPER = (1 << 1 ), // Console variables marked with this flag cant be changed in a final build
36+ DEUS_CVAR_DEVELOPER = (1 << 1 ), // Console variables marked with this flag can't be changed in a final build
3737 DEUS_CVAR_READONLY = (1 << 2 ), // Console variables cannot be changed by the user
38- DEUS_CVAR_UNREGISTERED = (1 << 3 ), // Doesnt get registered to console manager
38+ DEUS_CVAR_UNREGISTERED = (1 << 3 ), // doesn't get registered to console manager
3939};
4040
4141// Flags that can be set on defined console variables
@@ -94,11 +94,11 @@ inline int isNumericStr(char* str, size_t len) {
9494 return 0 ;
9595 }
9696 bool hasPeriod = false ;
97- for (int i = 0 ; i < len; i++) {
97+ for (size_t i = 0 ; i < len; i++) {
9898 char cChar = str[i];
9999 if (cChar == ' .' ) { // check if is a decimal number
100100 if (hasPeriod) {
101- return 0 ; // cannot be a numberic string with two periods
101+ return 0 ; // cannot be a numeric string with two periods
102102 } else {
103103 hasPeriod = true ;
104104 }
@@ -155,38 +155,30 @@ struct TConsoleTypeHelper<std::string> {
155155 }
156156};
157157
158-
159-
160158// Class to manage all console variables and commands
161159// Does not do any input processing
162160class IDeusConsoleManager {
163161 private:
164- std::unordered_map<const char * , DeusConsoleVariable> variableTable;
165- std::unordered_map<const char * , TDeusConsoleFunc> methodTable;
166- DeusConsoleHelpTable helpTable;
162+ std::unordered_map<std::string , DeusConsoleVariable> variableTable;
163+ std::unordered_map<std::string , TDeusConsoleFunc> methodTable;
164+ std::unordered_map<std::string, std::string> helpTable;
167165
168166 // Gets a variable reference by name
169- DeusConsoleVariable& getVariable (const char * name) {
170- for (auto kv : this ->variableTable ) {
171- if (strcmp (kv.first , name) == 0 ) {
172- return this ->variableTable [kv.first ];
173- }
167+ DeusConsoleVariable& getVariable (const std::string& name) {
168+ auto it = this ->variableTable .find (name);
169+ if (it != this ->variableTable .end ()) {
170+ return it->second ;
174171 }
175-
176- throw DeusConsoleException (" Console variable does not exist: " + (std::string)(name));
177- return this ->variableTable [name];
172+ throw DeusConsoleException (" Console variable does not exist: " + name);
178173 }
179174
180175 // Gets a method function object reference by name
181- TDeusConsoleFunc& getMethod (const char * name) {
182- for (auto kv : this ->methodTable ) {
183- if (strcmp (kv.first , name) == 0 ) {
184- return this ->methodTable [kv.first ];
185- }
176+ TDeusConsoleFunc& getMethod (const std::string& name) {
177+ auto it = this ->methodTable .find (name);
178+ if (it != this ->methodTable .end ()) {
179+ return it->second ;
186180 }
187-
188- throw DeusConsoleException (" Console method does not exist: " + (std::string)(name));
189- return this ->methodTable [name];
181+ throw DeusConsoleException (" Console method does not exist: " + name);
190182 }
191183
192184 public:
@@ -196,45 +188,39 @@ class IDeusConsoleManager {
196188 void bindBaseCommands () {
197189 this ->registerMethod (" help" , [this ](DeusCommandType& cmd) {
198190 std::string result = " Method/variable list:\n " ;
199- for (auto kv : this ->helpTable ) {
200- result += (std::string)( kv.first ) + " \t\t " + (std::string)( kv.second ) + " \n " ;
191+ for (auto & kv : this ->helpTable ) {
192+ result += kv.first + " \t\t " + kv.second + " \n " ;
201193 }
202194 cmd.returnStr = result;
203195 }, " Returns a list of variables/methods and their descriptions" );
204196 }
205197
206198 // Returns a reference to the help table itself, useful for iterating over potential cmds
207- DeusConsoleHelpTable & getHelpTable () {
199+ std::unordered_map<std::string, std::string> & getHelpTable () {
208200 return this ->helpTable ;
209201 }
210202
211203 // Returns help text for a specific variable or method
212- const char * getHelp (const char * key) {
213- return this ->helpTable [key];
204+ std::string getHelp (const std::string& key) {
205+ auto it = this ->helpTable .find (key);
206+ if (it != this ->helpTable .end ()) {
207+ return it->second .c_str ();
208+ }
209+ return nullptr ;
214210 }
215211
216212 // Checks whether a variable with that name exists in the table
217- bool variableExists (const char * name) {
218- for (auto kv : this ->variableTable ) {
219- if (strcmp (kv.first , name) == 0 ) {
220- return true ;
221- }
222- }
223- return false ;
213+ bool variableExists (const std::string& name) {
214+ return this ->variableTable .find (name) != this ->variableTable .end ();
224215 }
225216
226217 // Checks whether a method with that name exists in the table
227- bool methodExists (const char * name) {
228- for (auto kv : this ->methodTable ) {
229- if (strcmp (kv.first , name) == 0 ) {
230- return true ;
231- }
232- }
233- return false ;
218+ bool methodExists (const std::string& name) {
219+ return this ->methodTable .find (name) != this ->methodTable .end ();
234220 }
235221
236222 // Registers a void function object that takes DeusCommandType as its only argument
237- void registerMethod (const char * name, TDeusConsoleFunc func, const char * description = " " ) {
223+ void registerMethod (const std::string& name, TDeusConsoleFunc func, const std::string& description = " " ) {
238224 if (this ->methodTable .find (name) == this ->methodTable .end ()) {
239225 this ->methodTable [name] = func;
240226 this ->helpTable [name] = description;
@@ -244,7 +230,7 @@ class IDeusConsoleManager {
244230 // This method will take a name, value reference, help description and flags for a console variable
245231 // and will assign it to the various tables required for reading/writing/remembering arguments
246232 template <typename T>
247- void registerCVar (const char * name, T& value, const char * description = " " , int flags = DEUS_CVAR_DEFAULT, TDeusConsoleFuncVoid onUpdate = NULL ) {
233+ void registerCVar (const std::string& name, T& value, const std::string& description = " " , int flags = DEUS_CVAR_DEFAULT, TDeusConsoleFuncVoid onUpdate = nullptr ) {
248234 // Skip registration if flag defined
249235 if (flags & DEUS_CVAR_UNREGISTERED) {
250236 return ;
@@ -273,11 +259,11 @@ class IDeusConsoleManager {
273259 template <typename T, std::enable_if_t <std::is_arithmetic_v<std::remove_reference_t <T>>> * = nullptr > inline
274260 void bindWriteMethods (T& value, DeusConsoleVariable& variable) {
275261 variable.writeDecimalFromBuffer = [&value](char * data) {
276- T tokenValue = atof (data);
262+ T tokenValue = static_cast <T>( atof (data) );
277263 value = tokenValue;
278264 };
279265 variable.writeIntFromBuffer = [&value](char * data) {
280- T tokenValue = atol (data);
266+ T tokenValue = static_cast <T>( atol (data) );
281267 value = tokenValue;
282268 };
283269 variable.write = [&value](void * data) {
@@ -291,11 +277,17 @@ class IDeusConsoleManager {
291277 variable.write = [&value](void * data) {
292278 value = *static_cast <T*>(data);
293279 };
280+ variable.writeIntFromBuffer = [&value](char * data) {
281+ value = T (data);
282+ };
283+ variable.writeDecimalFromBuffer = [&value](char * data) {
284+ value = T (data);
285+ };
294286 }
295287
296288 // This method will take the ptr of the value and cast to its native type as a reference
297289 template <typename T>
298- T& getCVar (const char * name) {
290+ T& getCVar (const std::string& name) {
299291 DeusConsoleVariable& variable = this ->getVariable (name);
300292 TDeusConsoleFuncRead& readFunc = variable.read ;
301293 return *static_cast <T*>(readFunc ());
@@ -409,13 +401,13 @@ class IDeusConsoleManager {
409401 template <typename T>
410402 T runCommandAs (const char * command, DeusCommandType& commandResult) {
411403 this ->parseCommand (command, commandResult);
412- const char * cmdTarget = ( const char *) commandResult.target ;
404+ std::string cmdTarget = commandResult.target ;
413405 const bool methodExists = this ->methodExists (cmdTarget);
414406
415407 // Check if target is a variable to write/read
416408 if (this ->variableExists (cmdTarget)) {
417409 if (commandResult.argc == 0 ) { // Zero tokens is a read op
418- // TODO: FIX: Reading variable doesnt add its value to returnStr
410+ // TODO: FIX: Reading variable doesn't add its value to returnStr
419411 DeusConsoleVariable& variable = this ->getVariable (cmdTarget);
420412 commandResult.returnStr = variable.toString ();
421413 return this ->getCVar <T>(cmdTarget);
@@ -424,7 +416,6 @@ class IDeusConsoleManager {
424416 DeusConsoleVariable& variable = this ->getVariable (cmdTarget);
425417
426418 // Disallow writing to constants
427- // TODO: disallow writing if production mode
428419 if (variable.flags & DEUS_CVAR_READONLY) {
429420 throw DeusConsoleException (" Cannot write to a constant variable" );
430421 }
@@ -453,7 +444,7 @@ class IDeusConsoleManager {
453444
454445 // Fire on update hook
455446 if (variable.onUpdate ) {
456- variable.onUpdate (& variable);
447+ variable.onUpdate (variable. read () );
457448 }
458449
459450 // Return new value
@@ -463,15 +454,15 @@ class IDeusConsoleManager {
463454 }
464455 }
465456
466- // Check if a method exists, since variable read/write didnt pass
457+ // Check if a method exists, since variable read/write didn't pass
467458 if (methodExists) {
468459 TDeusConsoleFunc& method = this ->getMethod (cmdTarget);
469460 method (commandResult);
470461 } else {
471- throw DeusConsoleException (" No variable or method found: " + (std::string) cmdTarget);
462+ throw DeusConsoleException (" No variable or method found: " + cmdTarget);
472463 }
473464
474- return static_cast <T>( NULL ) ;
465+ return T{} ;
475466 }
476467
477468 // This method will take a command string and return its result typecasted to the supplied type
0 commit comments