diff options
author | louis <louis.braun@gmx.de> | 2014-09-27 09:25:14 +0200 |
---|---|---|
committer | louis <louis.braun@gmx.de> | 2014-09-27 09:25:14 +0200 |
commit | b0509b5182b6e0d04f05e6b3d5676b0d21f51966 (patch) | |
tree | 22b302342f22843e0815eb5f516c85f1478cbf0b /libtemplate/parameter.c | |
download | vdr-plugin-skindesigner-0.0.1.tar.gz vdr-plugin-skindesigner-0.0.1.tar.bz2 |
initial commit version 0.0.10.0.1
Diffstat (limited to 'libtemplate/parameter.c')
-rw-r--r-- | libtemplate/parameter.c | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/libtemplate/parameter.c b/libtemplate/parameter.c new file mode 100644 index 0000000..e7dd30a --- /dev/null +++ b/libtemplate/parameter.c @@ -0,0 +1,394 @@ +#include "parameter.h" + +using namespace std; + +// --- cNumericParameter ------------------------------------------------------------- + +cNumericParameter::cNumericParameter(string value) { + this->value = value; + globals = NULL; + isValid = false; + width = 0; + height = 0; + columnWidth = -1; + rowHeight = -1; + hor = true; + defaultValue = 0; +} + +cNumericParameter::~cNumericParameter(void) { +} + +void cNumericParameter::SetAreaSize(int w, int h) { + width = w; + height = h; +} + +int cNumericParameter::Parse(string &parsedValue) { + int retVal = defaultValue; + + if (IsNumber(value)) { + isValid = true; + retVal = atoi(value.c_str()); + return retVal; + } + + //checking for percent value + bool isPercentValue = CheckPercentValue(retVal); + if (isPercentValue) { + isValid = true; + return retVal; + } + + //checking for expression + bool isValidExpression = CheckExpression(retVal, parsedValue); + if (isValidExpression) { + isValid = true; + return retVal; + } + + return retVal; +} + +bool cNumericParameter::IsNumber(const string& s) { + string::const_iterator it = s.begin(); + while (it != s.end() && isdigit(*it)) ++it; + return !s.empty() && it == s.end(); +} + +bool cNumericParameter::CheckPercentValue(int &val) { + bool ok = false; + size_t posPercent = value.find('%'); + if (posPercent != string::npos) { + string strPerc = value.substr(0, posPercent); + if (!IsNumber(strPerc)) { + return ok; + } + int perc = atoi(strPerc.c_str()); + if (hor) { + val = width * perc / 100; + } else { + val = height * perc / 100; + } + ok = true; + } + return ok; +} + +bool cNumericParameter::CheckExpression(int &val, string &parsedVal) { + bool ok = false; + string parsedValue = value; + //remove white spaces + parsedValue.erase( std::remove_if( parsedValue.begin(), parsedValue.end(), ::isspace ), parsedValue.end() ); + + //check and replace {areawidth} and {areaheight} tokens + string tokenWidth = "{areawidth}"; + string tokenHeight = "{areaheight}"; + + stringstream sw; + sw << width; + string strWidth = sw.str(); + stringstream sh; + sh << height; + string strHeight = sh.str(); + + bool foundToken = true; + while(foundToken) { + size_t foundTokenWidth = parsedValue.find(tokenWidth); + if (foundTokenWidth != string::npos) { + parsedValue = parsedValue.replace(foundTokenWidth, tokenWidth.size(), strWidth); + } else { + foundToken = false; + } + } + + foundToken = true; + while(foundToken) { + size_t foundTokenHeight = parsedValue.find(tokenHeight); + if (foundTokenHeight != string::npos) { + parsedValue = parsedValue.replace(foundTokenHeight, tokenHeight.size(), strHeight); + } else { + foundToken = false; + } + } + + //check and replace {columnwidth} and {rowheight} tokens for loop functions + if (columnWidth > 0 || rowHeight > 0) { + tokenWidth = "{columnwidth}"; + tokenHeight = "{rowheight}"; + stringstream cw; + cw << columnWidth; + strWidth = cw.str(); + stringstream rh; + rh << rowHeight; + strHeight = rh.str(); + + foundToken = true; + while(foundToken) { + size_t foundTokenWidth = parsedValue.find(tokenWidth); + if (foundTokenWidth != string::npos) { + parsedValue = parsedValue.replace(foundTokenWidth, tokenWidth.size(), strWidth); + } else { + foundToken = false; + } + } + + foundToken = true; + while(foundToken) { + size_t foundTokenHeight = parsedValue.find(tokenHeight); + if (foundTokenHeight != string::npos) { + parsedValue = parsedValue.replace(foundTokenHeight, tokenHeight.size(), strHeight); + } else { + foundToken = false; + } + } + } + + if (globals) { + for (map<string, int>::iterator globInt = globals->intVars.begin(); globInt != globals->intVars.end(); globInt++) { + stringstream sToken; + sToken << "{" << globInt->first << "}"; + string token = sToken.str(); + size_t foundToken = parsedValue.find(token); + if (foundToken != string::npos) { + stringstream st; + st << globInt->second; + parsedValue = parsedValue.replace(foundToken, token.size(), st.str()); + } + } + } + + if (IsNumber(parsedValue)) { + ok = true; + val = atoi(parsedValue.c_str()); + return ok; + } + + if (!ValidNumericExpression(parsedValue)) { + parsedVal = parsedValue; + return ok; + } + ok = true; + char * expression = new char[parsedValue.size() + 1]; + std::copy(parsedValue.begin(), parsedValue.end(), expression); + expression[parsedValue.size()] = '\0'; + int expRes = EvaluateTheExpression(expression); + val = expRes; + delete[] expression; + return ok; +} + +bool cNumericParameter::ValidNumericExpression(string &parsedValue) { + string::const_iterator it = parsedValue.begin(); + while (it != parsedValue.end() && (isdigit(*it) || *it == '.' || *it == ',' || *it == '+' || *it == '-' || *it == '*' || *it == '/')) ++it; + return !parsedValue.empty() && it == parsedValue.end(); +} + +int cNumericParameter::EvaluateTheExpression(char* expr) { + return round(ParseSummands(expr)); +} + +double cNumericParameter::ParseAtom(char*& expr) { + // Read the number from string + char* end_ptr; + double res = strtod(expr, &end_ptr); + // Advance the pointer and return the result + expr = end_ptr; + return res; +} + +// Parse multiplication and division +double cNumericParameter::ParseFactors(char*& expr) { + double num1 = ParseAtom(expr); + for(;;) { + // Save the operation + char op = *expr; + if(op != '/' && op != '*') + return num1; + expr++; + double num2 = ParseAtom(expr); + // Perform the saved operation + if(op == '/') { + if (num2 != 0) { + num1 /= num2; + } + } else + num1 *= num2; + } +} + +// Parse addition and subtraction +double cNumericParameter::ParseSummands(char*& expr) { + double num1 = ParseFactors(expr); + for(;;) { + char op = *expr; + if(op != '-' && op != '+') + return num1; + expr++; + double num2 = ParseFactors(expr); + if(op == '-') + num1 -= num2; + else + num1 += num2; + } +} + +// --- cConditionalParameter ------------------------------------------------------------- + +cConditionalParameter::cConditionalParameter(cGlobals *globals, string value) { + this->globals = globals; + isTrue = false; + this->value = value; + type = cpNone; +} + +cConditionalParameter::~cConditionalParameter(void) { +} + +void cConditionalParameter::Tokenize(void) { + size_t posAnd = value.find("++"); + if (posAnd != string::npos) { + type = cpAnd; + TokenizeValue("++"); + } else { + size_t posOr = value.find("||"); + if (posOr != string::npos) { + type = cpOr; + TokenizeValue("||"); + } + } + if (type == cpNone) { + InsertCondition(value); + } +} + +bool cConditionalParameter::Evaluate(map < string, int > *intTokens, map < string, string > *stringTokens) { + isTrue = false; + bool first = true; + for (vector<sCondition>::iterator cond = conditions.begin(); cond != conditions.end(); cond++) { + bool tokenTrue = false; + + if (cond->type == ctStringSet) { + if (stringTokens) { + map < string, string >::iterator hit = stringTokens->find(cond->tokenName); + if (hit != stringTokens->end()) { + string value = hit->second; + if (value.size() > 0) + tokenTrue = true; + } + } + } else { + int tokenValue = EvaluateParameter(cond->tokenName, intTokens, stringTokens); + if (cond->type == ctBool) { + tokenTrue = tokenValue; + } else if (cond->type == ctGreater) { + tokenTrue = (tokenValue > cond->compareValue) ? true : false; + } else if (cond->type == ctLower) { + tokenTrue = (tokenValue < cond->compareValue) ? true : false; + } else if (cond->type == ctEquals) { + tokenTrue = (tokenValue == cond->compareValue) ? true : false; + } + } + + if (cond->isNegated) + tokenTrue = !tokenTrue; + if (type == cpAnd) { + if (first) + isTrue = tokenTrue; + else + isTrue = isTrue && tokenTrue; + } else if (type == cpOr) { + isTrue = isTrue || tokenTrue; + } else { + isTrue = tokenTrue; + } + first = false; + } +} + +int cConditionalParameter::EvaluateParameter(string token, map < string, int > *intTokens, map < string, string > *stringTokens) { + //first check globals + map < string, int >::iterator hitGlobals = globals->intVars.find(token); + if (hitGlobals != globals->intVars.end()) { + return hitGlobals->second; + } else { + //then check tokens + if (intTokens) { + map < string, int >::iterator hit = intTokens->find(token); + if (hit != intTokens->end()) { + return hit->second; + } + } + if (stringTokens) { + map < string, string >::iterator hit = stringTokens->find(token); + if (hit != stringTokens->end()) { + string value = hit->second; + return atoi(value.c_str()); + } + } + } + return 0; +} + +void cConditionalParameter::TokenizeValue(string sep) { + string buffer = value; + bool sepFound = true; + while (sepFound) { + size_t posSep = buffer.find(sep); + if (posSep == string::npos) { + InsertCondition(buffer); + sepFound = false; + } + string token = buffer.substr(0, posSep); + buffer = buffer.replace(0, posSep + sep.size(), ""); + InsertCondition(token); + } +} + +void cConditionalParameter::InsertCondition(string cond) { + cond.erase( std::remove_if( cond.begin(), cond.end(), ::isspace ), cond.end() ); + + if (cond.size() < 1) + return; + + size_t tokenStart = cond.find('{'); + size_t tokenEnd = cond.find('}'); + + if (tokenStart == string::npos || tokenEnd == string::npos || tokenStart > tokenEnd) + return; + + string tokenName = cond.substr(tokenStart + 1, tokenEnd - tokenStart - 1); + string rest = cond.replace(tokenStart, tokenEnd - tokenStart + 1, ""); + + sCondition sCond; + sCond.tokenName = tokenName; + sCond.type = ctBool; + sCond.compareValue = 0; + sCond.isNegated = false; + if (!rest.compare("not")) { + sCond.isNegated = true; + } else if (!rest.compare("isset")) { + sCond.type = ctStringSet; + } else if (startswith(rest.c_str(), "gt(")) { + string compVal = rest.substr(4, rest.size() - 5); + sCond.compareValue = atoi(compVal.c_str()); + sCond.type = ctGreater; + } else if (startswith(rest.c_str(), "lt(")) { + string compVal = rest.substr(4, rest.size() - 5); + sCond.compareValue = atoi(compVal.c_str()); + sCond.type = ctLower; + } else if (startswith(rest.c_str(), "eq(")) { + string compVal = rest.substr(4, rest.size() - 5); + sCond.compareValue = atoi(compVal.c_str()); + sCond.type = ctEquals; + } + + conditions.push_back(sCond); +} + +void cConditionalParameter::Debug(void) { + dsyslog("skindesigner: Condition %s, Type: %s, cond is %s", value.c_str(), (type == cpAnd)?"and combination":((type == cpOr)?"or combination":"single param") , isTrue?"true":"false"); + for (vector<sCondition>::iterator it = conditions.begin(); it != conditions.end(); it++) { + dsyslog("skindesigner: cond token %s, type: %d, compareValue %d, negated: %d", it->tokenName.c_str(), it->type, it->compareValue, it->isNegated); + } +}
\ No newline at end of file |