diff options
author | Max Horn | 2009-05-11 18:02:27 +0000 |
---|---|---|
committer | Max Horn | 2009-05-11 18:02:27 +0000 |
commit | 95a4b26efedbb4e7f15b7417f54064df95c40775 (patch) | |
tree | ca4cc23bb5899c1e307543eceb2059e934454de6 | |
parent | e3e3fbd7d1d5f358515fc0d28b2c0abd715e5b79 (diff) | |
download | scummvm-rg350-95a4b26efedbb4e7f15b7417f54064df95c40775.tar.gz scummvm-rg350-95a4b26efedbb4e7f15b7417f54064df95c40775.tar.bz2 scummvm-rg350-95a4b26efedbb4e7f15b7417f54064df95c40775.zip |
Turned fixed-size lists of debugger/console commands and variables into more flexible data structures
svn-id: r40458
-rw-r--r-- | gui/console.cpp | 5 | ||||
-rw-r--r-- | gui/console.h | 4 | ||||
-rw-r--r-- | gui/debugger.cpp | 125 | ||||
-rw-r--r-- | gui/debugger.h | 31 |
4 files changed, 81 insertions, 84 deletions
diff --git a/gui/console.cpp b/gui/console.cpp index cf274b3ebd..e33aa9d9fe 100644 --- a/gui/console.cpp +++ b/gui/console.cpp @@ -327,14 +327,13 @@ void ConsoleDialog::handleKeyDown(Common::KeyState state) { str[i] = buffer(_promptStartPos + i); str[len] = '\0'; - char *completion = 0; + Common::String completion; if ((*_completionCallbackProc)(this, str, completion, _callbackRefCon)) { if (_caretVisible) drawCaret(true); - insertIntoPrompt(completion); + insertIntoPrompt(completion.c_str()); scrollToCurrent(); drawLine(pos2line(_currentPos)); - delete[] completion; } delete[] str; } diff --git a/gui/console.h b/gui/console.h index cf86e40bc8..ae38d1d690 100644 --- a/gui/console.h +++ b/gui/console.h @@ -46,7 +46,7 @@ class ScrollBarWidget; implement this simple rewrapping -- we currently don't do that at all!). Or, one can go and implement a more complete console, by replacing the - _buffer by a real line buffer -- an arrach of char* pointers. + _buffer by a real line buffer -- an array of char* pointers. This will allow one to implement resizing perfectly, but has the drawback of making things like scrolling, drawing etc. more complicated. @@ -67,7 +67,7 @@ class ScrollBarWidget; class ConsoleDialog : public Dialog { public: typedef bool (*InputCallbackProc)(ConsoleDialog *console, const char *input, void *refCon); - typedef bool (*CompletionCallbackProc)(ConsoleDialog* console, const char *input, char*& completion, void *refCon); + typedef bool (*CompletionCallbackProc)(ConsoleDialog* console, const char *input, Common::String &completion, void *refCon); protected: enum { diff --git a/gui/debugger.cpp b/gui/debugger.cpp index 637443836b..c32b68f3de 100644 --- a/gui/debugger.cpp +++ b/gui/debugger.cpp @@ -35,8 +35,6 @@ namespace GUI { Debugger::Debugger() { _frame_countdown = 0; - _dvar_count = 0; - _dcmd_count = 0; _detach_now = false; _isAttached = false; _errStr = NULL; @@ -57,10 +55,6 @@ Debugger::Debugger() { } Debugger::~Debugger() { - for (int i = 0; i < _dcmd_count; i++) { - delete _dcmds[i].debuglet; - _dcmds[i].debuglet = 0; - } delete _debuggerDialog; } @@ -167,13 +161,11 @@ void Debugger::enter() { } bool Debugger::handleCommand(int argc, const char **argv, bool &result) { - for (int i = 0; i < _dcmd_count; ++i) { - if (!strcmp(_dcmds[i].name, argv[0])) { - Debuglet *debuglet = _dcmds[i].debuglet; - assert(debuglet); - result = (*debuglet)(argc, argv); - return true; - } + if (_cmds.contains(argv[0])) { + Debuglet *debuglet = _cmds[argv[0]].get(); + assert(debuglet); + result = (*debuglet)(argc, argv); + return true; } return false; @@ -181,7 +173,7 @@ bool Debugger::handleCommand(int argc, const char **argv, bool &result) { // Command execution loop bool Debugger::parseCommand(const char *inputOrig) { - int i = 0, num_params = 0; + int num_params = 0; const char *param[256]; char *input = strdup(inputOrig); // One of the rare occasions using strdup is OK (although avoiding strtok might be more elegant here). @@ -203,8 +195,8 @@ bool Debugger::parseCommand(const char *inputOrig) { } // It's not a command, so things get a little tricky for variables. Do fuzzy matching to ignore things like subscripts. - for (i = 0; i < _dvar_count; i++) { - if (!strncmp(_dvars[i].name, param[0], strlen(_dvars[i].name))) { + for (uint i = 0; i < _dvars.size(); i++) { + if (!strncmp(_dvars[i].name.c_str(), param[0], _dvars[i].name.size())) { if (num_params > 1) { // Alright, we need to check the TYPE of the variable to deref and stuff... the array stuff is a bit ugly :) switch (_dvars[i].type) { @@ -235,7 +227,7 @@ bool Debugger::parseCommand(const char *inputOrig) { } break; default: - DebugPrintf("Failed to set variable %s to %s - unknown type\n", _dvars[i].name, param[1]); + DebugPrintf("Failed to set variable %s to %s - unknown type\n", _dvars[i].name.c_str(), param[1]); break; } } else { @@ -286,7 +278,7 @@ bool Debugger::parseCommand(const char *inputOrig) { // returns true if something has been completed // completion has to be delete[]-ed then -bool Debugger::tabComplete(const char *input, char*& completion) { +bool Debugger::tabComplete(const char *input, Common::String &completion) const { // very basic tab completion // for now it just supports command completions @@ -297,63 +289,61 @@ bool Debugger::tabComplete(const char *input, char*& completion) { if (strchr(input, ' ')) return false; // already finished the first word - unsigned int inputlen = strlen(input); + const uint inputlen = strlen(input); - unsigned int matchlen = 0; - char match[30]; // the max. command name is 30 chars + completion.clear(); - for (int i = 0; i < _dcmd_count; i++) { - if (!strncmp(_dcmds[i].name, input, inputlen)) { - unsigned int commandlen = strlen(_dcmds[i].name); - if (commandlen == inputlen) { // perfect match + CommandsMap::const_iterator i, e = _cmds.end(); + for (i = _cmds.begin(); i != e; ++i) { + if (i->_key.hasPrefix(input)) { + uint commandlen = i->_key.size(); + if (commandlen == inputlen) { // perfect match, so no tab completion possible return false; } if (commandlen > inputlen) { // possible match // no previous match - if (matchlen == 0) { - strcpy(match, _dcmds[i].name + inputlen); - matchlen = commandlen - inputlen; + if (completion.empty()) { + completion = i->_key.c_str() + inputlen; } else { // take common prefix of previous match and this command - unsigned int j; - for (j = 0; j < matchlen; j++) { - if (match[j] != _dcmds[i].name[inputlen + j]) break; + for (uint j = 0; j < completion.size(); j++) { + if (completion[j] != i->_key[inputlen + j]) { + completion = Common::String(completion.begin(), completion.begin() + j); + // If there is no unambiguous completion, abort + if (completion.empty()) + return false; + break; + } } - matchlen = j; } - if (matchlen == 0) - return false; } } } - if (matchlen == 0) + if (completion.empty()) return false; - completion = new char[matchlen + 1]; - memcpy(completion, match, matchlen); - completion[matchlen] = 0; return true; } // Variable registration function -void Debugger::DVar_Register(const char *varname, void *pointer, int type, int optional) { - assert(_dvar_count < ARRAYSIZE(_dvars)); - strcpy(_dvars[_dvar_count].name, varname); - _dvars[_dvar_count].type = type; - _dvars[_dvar_count].variable = pointer; - _dvars[_dvar_count].optional = optional; - - _dvar_count++; +void Debugger::DVar_Register(const Common::String &varname, void *pointer, int type, int optional) { + // TODO: Filter out duplicates + // TODO: Sort this list? Then we can do binary search later on when doing lookups. + assert(pointer); + + DVar tmp; + tmp.name = varname; + tmp.type = type; + tmp.variable = pointer; + tmp.optional = optional; + + _dvars.push_back(tmp); } // Command registration function -void Debugger::DCmd_Register(const char *cmdname, Debuglet *debuglet) { - assert(debuglet->isValid()); - assert(_dcmd_count < ARRAYSIZE(_dcmds)); - strcpy(_dcmds[_dcmd_count].name, cmdname); - _dcmds[_dcmd_count].debuglet = debuglet; - - _dcmd_count++; +void Debugger::DCmd_Register(const Common::String &cmdname, Debuglet *debuglet) { + assert(debuglet && debuglet->isValid()); + _cmds[cmdname] = Common::SharedPtr<Debuglet>(debuglet); } @@ -368,12 +358,23 @@ bool Debugger::Cmd_Exit(int argc, const char **argv) { bool Debugger::Cmd_Help(int argc, const char **argv) { const int charsPerLine = _debuggerDialog->getCharsPerLine(); - int width, size, i; + int width, size; + uint i; DebugPrintf("Commands are:\n"); + + // Obtain a list of sorted command names + Common::StringList cmds; + CommandsMap::const_iterator iter, e = _cmds.end(); + for (iter = _cmds.begin(); iter != e; ++iter) { + cmds.push_back(iter->_key); + } + sort(cmds.begin(), cmds.end()); + + // Print them all width = 0; - for (i = 0; i < _dcmd_count; i++) { - size = strlen(_dcmds[i].name) + 1; + for (i = 0; i < cmds.size(); i++) { + size = cmds[i].size() + 1; if ((width + size) >= charsPerLine) { DebugPrintf("\n"); @@ -381,16 +382,16 @@ bool Debugger::Cmd_Help(int argc, const char **argv) { } else width += size; - DebugPrintf("%s ", _dcmds[i].name); + DebugPrintf("%s ", cmds[i].c_str()); } DebugPrintf("\n"); - if (_dvar_count > 0) { + if (!_dvars.empty()) { DebugPrintf("\n"); DebugPrintf("Variables are:\n"); width = 0; - for (i = 0; i < _dvar_count; i++) { - size = strlen(_dvars[i].name) + 1; + for (i = 0; i < _dvars.size(); i++) { + size = _dvars[i].name.size() + 1; if ((width + size) >= charsPerLine) { DebugPrintf("\n"); @@ -398,7 +399,7 @@ bool Debugger::Cmd_Help(int argc, const char **argv) { } else width += size; - DebugPrintf("%s ", _dvars[i].name); + DebugPrintf("%s ", _dvars[i].name.c_str()); } DebugPrintf("\n"); } @@ -459,7 +460,7 @@ bool Debugger::debuggerInputCallback(GUI::ConsoleDialog *console, const char *in } -bool Debugger::debuggerCompletionCallback(GUI::ConsoleDialog *console, const char *input, char*& completion, void *refCon) { +bool Debugger::debuggerCompletionCallback(GUI::ConsoleDialog *console, const char *input, Common::String &completion, void *refCon) { Debugger *debugger = (Debugger *)refCon; return debugger->tabComplete(input, completion); diff --git a/gui/debugger.h b/gui/debugger.h index 0e48f384de..e84da594be 100644 --- a/gui/debugger.h +++ b/gui/debugger.h @@ -26,6 +26,9 @@ #define GUI_DEBUGGER_H #include "common/func.h" +#include "common/ptr.h" +#include "common/hashmap.h" +#include "common/hash-str.h" namespace GUI { @@ -51,7 +54,7 @@ public: protected: typedef Common::Functor2<int, const char **, bool> Debuglet; - // Convenicence macro for registering a method of a debugger class + // Convenience macro for registering a method of a debugger class // as the current command. #define WRAP_METHOD(cls, method) \ new Common::Functor2Mem<int, const char **, bool, cls>(this, &cls::method) @@ -65,26 +68,20 @@ protected: }; struct DVar { - char name[30]; + Common::String name; void *variable; - int type, optional; - }; - - struct DCmd { - char name[30]; - Debuglet *debuglet; + int type; + int optional; }; int _frame_countdown; bool _detach_now; private: - // TODO: Consider replacing the following two arrays by a Hashmap - int _dvar_count; - DVar _dvars[256]; + Common::Array<DVar> _dvars; - int _dcmd_count; - DCmd _dcmds[256]; + typedef Common::HashMap<Common::String, Common::SharedPtr<Debuglet>, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> CommandsMap; + CommandsMap _cmds; bool _isAttached; char *_errStr; @@ -109,11 +106,11 @@ private: void enter(); bool parseCommand(const char *input); - bool tabComplete(const char *input, char*& completion); + bool tabComplete(const char *input, Common::String &completion) const; protected: - void DVar_Register(const char *varname, void *pointer, int type, int optional); - void DCmd_Register(const char *cmdname, Debuglet *debuglet); + void DVar_Register(const Common::String &varname, void *pointer, int type, int optional); + void DCmd_Register(const Common::String &cmdname, Debuglet *debuglet); bool Cmd_Exit(int argc, const char **argv); bool Cmd_Help(int argc, const char **argv); @@ -124,7 +121,7 @@ protected: #if USE_CONSOLE private: static bool debuggerInputCallback(GUI::ConsoleDialog *console, const char *input, void *refCon); - static bool debuggerCompletionCallback(GUI::ConsoleDialog *console, const char *input, char*& completion, void *refCon); + static bool debuggerCompletionCallback(GUI::ConsoleDialog *console, const char *input, Common::String &completion, void *refCon); #endif }; |