1
0
Fork 0

DBG: performance improvement in ExpressionParser, commands and script

This commit is contained in:
mrexodia 2016-09-06 13:16:00 +02:00
parent 9f17d0aa3b
commit c143d43269
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
6 changed files with 76 additions and 87 deletions

View File

@ -157,39 +157,6 @@ void setalloctrace(const char* file)
}
#endif //ENABLE_MEM_TRACE
/**
\brief A function to determine if a string is contained in a specifically formatted 'array string'.
\param cmd_list Array of strings separated by '\1'.
\param cmd The string to look for.
\return true if \p cmd is contained in \p cmd_list.
*/
bool arraycontains(const char* cmd_list, const char* cmd)
{
//TODO: fix this function a little
if(!cmd_list || !cmd)
return false;
char temp[deflen] = "";
strcpy_s(temp, cmd_list);
int len = (int)strlen(cmd_list);
if(len >= deflen)
return false;
for(int i = 0; i < len; i++)
if(temp[i] == 1)
temp[i] = 0;
if(!_stricmp(temp, cmd))
return true;
for(int i = (int)strlen(temp); i < len; i++)
{
if(!temp[i])
{
if(!_stricmp(temp + i + 1, cmd))
return true;
i += (int)strlen(temp + i + 1);
}
}
return false;
}
/**
\brief Compares two strings without case-sensitivity.
\param a The first string.

View File

@ -76,7 +76,6 @@ void* json_malloc(size_t size);
void json_free(void* ptr);
int memleaks();
void setalloctrace(const char* file);
bool arraycontains(const char* cmd_list, const char* cmd);
bool scmp(const char* a, const char* b);
void formathex(char* string);
void formatdec(char* string);

View File

@ -13,6 +13,14 @@
COMMAND* cmd_list = 0;
static bool vecContains(std::vector<String>* names, const char* name)
{
for(const auto & cmd : *names)
if(!_stricmp(cmd.c_str(), name))
return true;
return false;
}
/**
\brief Finds a ::COMMAND in a command list.
\param [in] command list.
@ -23,12 +31,12 @@ COMMAND* cmd_list = 0;
COMMAND* cmdfind(const char* name, COMMAND** link)
{
COMMAND* cur = cmd_list;
if(!cur->name)
if(!cur->names)
return 0;
COMMAND* prev = 0;
while(cur)
{
if(arraycontains(cur->name, name))
if(vecContains(cur->names, name))
{
if(link)
*link = prev;
@ -60,7 +68,7 @@ void cmdfree()
COMMAND* cur = cmd_list;
while(cur)
{
efree(cur->name, "cmdfree:cur->name");
efree(cur->names, "cmdfree:cur->name");
COMMAND* next = cur->next;
efree(cur, "cmdfree:cur");
cur = next;
@ -81,7 +89,7 @@ bool cmdnew(const char* name, CBCOMMAND cbCommand, bool debugonly)
return false;
COMMAND* cmd;
bool nonext = false;
if(!cmd_list->name)
if(!cmd_list->names)
{
cmd = cmd_list;
nonext = true;
@ -89,8 +97,14 @@ bool cmdnew(const char* name, CBCOMMAND cbCommand, bool debugonly)
else
cmd = (COMMAND*)emalloc(sizeof(COMMAND), "cmdnew:cmd");
memset(cmd, 0, sizeof(COMMAND));
cmd->name = (char*)emalloc(strlen(name) + 1, "cmdnew:cmd->name");
strcpy(cmd->name, name);
cmd->names = new std::vector<String>;
auto split = StringUtils::Split(name, '\1');
for(const auto & s : split)
{
auto trimmed = StringUtils::Trim(s);
if(trimmed.length())
cmd->names->push_back(trimmed);
}
cmd->cbCommand = cbCommand;
cmd->debugonly = debugonly;
COMMAND* cur = cmd_list;
@ -157,7 +171,7 @@ bool cmddel(const char* name)
COMMAND* found = cmdfind(name, &prev);
if(!found)
return false;
efree(found->name, "cmddel:found->name");
delete found->names;
if(found == cmd_list)
{
COMMAND* next = cmd_list->next;

View File

@ -21,7 +21,7 @@ typedef COMMAND* (*CBCOMMANDFINDER)(char*);
struct COMMAND
{
char* name;
std::vector<String>* names;
CBCOMMAND cbCommand;
bool debugonly;
COMMAND* next;

View File

@ -136,6 +136,9 @@ ExpressionParser::ExpressionParser(const String & expression)
: mExpression(fixClosingBrackets(expression)),
mIsValidExpression(true)
{
const size_t r = 50;
mTokens.reserve(r);
mCurToken.reserve(r);
tokenize();
shuntingYard();
}
@ -180,7 +183,7 @@ void ExpressionParser::tokenize()
case '[':
{
stateMemory++;
mCurToken += ch;
mCurToken.push_back(ch);
}
break;
@ -188,14 +191,14 @@ void ExpressionParser::tokenize()
{
if(stateMemory)
stateMemory--;
mCurToken += ch;
mCurToken.push_back(ch);
}
break;
default:
{
if(stateMemory || stateQuote)
mCurToken += ch;
mCurToken.push_back(ch);
else
{
switch(ch)
@ -336,7 +339,7 @@ void ExpressionParser::tokenize()
case '\t': //ignore tabs
break;
default:
mCurToken += ch;
mCurToken.push_back(ch);
break;
}
}
@ -372,19 +375,21 @@ void ExpressionParser::shuntingYard()
{
//Implementation of Dijkstra's Shunting-yard algorithm (https://en.wikipedia.org/wiki/Shunting-yard_algorithm)
std::vector<Token> queue;
std::stack<Token> stack;
std::vector<Token> stack;
auto len = mTokens.size();
queue.reserve(len);
stack.reserve(len);
//process the tokens
for(size_t i = 0; i < len; i++)
{
auto & token = mTokens[i];
const auto & token = mTokens[i];
switch(token.type())
{
case Token::Type::Data:
queue.push_back(token);
break;
case Token::Type::Function:
stack.push(token);
stack.push_back(token);
break;
case Token::Type::Comma:
while(true)
@ -394,68 +399,71 @@ void ExpressionParser::shuntingYard()
mIsValidExpression = false;
return;
}
auto curToken = stack.top();
const auto & curToken = stack[stack.size() - 1];
if(curToken.type() == Token::Type::OpenBracket)
break;
stack.pop();
queue.push_back(curToken);
stack.pop_back();
}
break;
case Token::Type::OpenBracket:
stack.push(token);
stack.push_back(token);
break;
case Token::Type::CloseBracket:
{
while(true)
{
if(stack.empty()) //empty stack = bracket mismatch
if(stack.empty()) //empty stack = bracket mismatch
{
mIsValidExpression = false;
return;
}
auto curToken = stack.top();
stack.pop();
if(curToken.type() == Token::Type::OpenBracket) //the bracket is already popped here
auto curToken = stack[stack.size() - 1];
stack.pop_back();
if(curToken.type() == Token::Type::OpenBracket) //the bracket is already popped here
break;
queue.push_back(curToken);
}
if(!stack.empty() && stack.top().type() == Token::Type::Function)
const auto & top = stack[stack.size() - 1];
if(!stack.empty() && top.type() == Token::Type::Function)
{
queue.push_back(stack.top());
stack.pop();
queue.push_back(top);
stack.pop_back();
}
break;
}
break;
default: //operator
auto & o1 = token;
const auto & o1 = token;
while(!stack.empty())
{
auto o2 = stack.top();
const auto & o2 = stack[stack.size() - 1];
if(o2.isOperator() &&
(o1.associativity() == Token::Associativity::LeftToRight && o1.precedence() >= o2.precedence()) ||
(o1.associativity() == Token::Associativity::RightToLeft && o1.precedence() > o2.precedence()))
{
queue.push_back(o2);
stack.pop();
stack.pop_back();
}
else
break;
}
stack.push(o1);
stack.push_back(o1);
break;
}
}
//pop the remaining operators
while(!stack.empty())
{
auto curToken = stack.top();
stack.pop();
const auto & curToken = stack[stack.size() - 1];
if(curToken.type() == Token::Type::OpenBracket || curToken.type() == Token::Type::CloseBracket) //brackets on the stack means invalid expression
{
mIsValidExpression = false;
return;
}
queue.push_back(curToken);
stack.pop_back();
}
mPrefixTokens = queue;
mPrefixTokens = std::move(queue);
}
#ifdef _WIN64
@ -770,7 +778,8 @@ bool ExpressionParser::Calculate(duint & value, bool signedcalc, bool allowassig
value = 0;
if(!mPrefixTokens.size() || !mIsValidExpression)
return false;
std::stack<EvalValue> stack;
std::vector<EvalValue> stack;
stack.reserve(mPrefixTokens.size());
//calculate the result from the RPN queue
for(const auto & token : mPrefixTokens)
{
@ -793,15 +802,15 @@ bool ExpressionParser::Calculate(duint & value, bool signedcalc, bool allowassig
case Token::Type::OperatorSuffixDec:
if(stack.size() < 1)
return false;
op1 = stack.top();
stack.pop();
op1 = stack[stack.size() - 1];
stack.pop_back();
if(signedcalc)
operationSuccess = signedOperation(type, op1, op2, result, silent, baseonly, allowassign);
else
operationSuccess = unsignedOperation(type, op1, op2, result, silent, baseonly, allowassign);
if(!operationSuccess)
return false;
stack.push(result);
stack.push_back(result);
break;
case Token::Type::OperatorMul:
case Token::Type::OperatorHiMul:
@ -841,17 +850,17 @@ bool ExpressionParser::Calculate(duint & value, bool signedcalc, bool allowassig
case Token::Type::OperatorAssignOr:
if(stack.size() < 2)
return false;
op2 = stack.top();
stack.pop();
op1 = stack.top();
stack.pop();
op2 = stack[stack.size() - 1];
stack.pop_back();
op1 = stack[stack.size() - 1];
stack.pop_back();
if(signedcalc)
operationSuccess = signedOperation(type, op1, op2, result, silent, baseonly, allowassign);
else
operationSuccess = unsignedOperation(type, op1, op2, result, silent, baseonly, allowassign);
if(!operationSuccess)
return false;
stack.push(result);
stack.push_back(result);
break;
case Token::Type::Error:
return false;
@ -872,20 +881,20 @@ bool ExpressionParser::Calculate(duint & value, bool signedcalc, bool allowassig
for(auto i = 0; i < argc; i++)
{
duint arg;
if(!stack.top().DoEvaluate(arg, silent, baseonly))
if(!stack[stack.size() - 1].DoEvaluate(arg, silent, baseonly))
return false;
stack.pop();
stack.pop_back();
argv[argc - i - 1] = arg;
}
duint result;
if(!ExpressionFunctions::Call(name, argv, result))
return false;
stack.push(EvalValue(result));
stack.push_back(EvalValue(result));
}
else
stack.push(EvalValue(token.data()));
stack.push_back(EvalValue(token.data()));
}
if(stack.size() != 1) //there should only be one value left on the stack
return false;
return stack.top().DoEvaluate(value, silent, baseonly, value_size, isvar, hexonly);
return stack[stack.size() - 1].DoEvaluate(value, silent, baseonly, value_size, isvar, hexonly);
}

View File

@ -1632,6 +1632,12 @@ bool valfromstring_noexpr(const char* string, duint* value, bool silent, bool ba
*isvar = true;
return true;
}
else if(varget(string, value, value_size, 0)) //then come variables
{
if(isvar)
*isvar = true;
return true;
}
else if(isregister(string)) //register
{
if(!DbgIsDebugging())
@ -1694,12 +1700,6 @@ bool valfromstring_noexpr(const char* string, duint* value, bool silent, bool ba
inc = 1;
return convertNumber(string + inc, *value, 16);
}
else if(varget(string, value, value_size, 0)) //then come variables
{
if(isvar)
*isvar = true;
return true;
}
if(baseonly)
return false;
else if(valapifromstring(string, value, value_size, true, silent, hexonly)) //then come APIs