diff options
Diffstat (limited to 'uservars.c')
-rw-r--r-- | uservars.c | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/uservars.c b/uservars.c new file mode 100644 index 0000000..4389e64 --- /dev/null +++ b/uservars.c @@ -0,0 +1,346 @@ +/* +Copyright (C) 2004-2007 Christian Wieninger + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + +The author can be reached at cwieninger@gmx.de + +The project's page is at http://winni.vdr-developer.org/epgsearch +*/ + +#include <algorithm> +#include "uservars.h" +#include "epgsearchcats.h" +#include "epgsearchtools.h" +#include "log.h" + +cUserVars UserVars; + +string cPlugconfdirVar::dir = ""; + +// cUserVar + +cUserVar::cUserVar() +{ + oldEvent = NULL; +} + +string cUserVar::Evaluate(const cEvent* e, bool escapeStrings) +{ + if (oldEvent && oldEvent == e && oldescapeStrings == escapeStrings) + return oldResult; + usedVars.clear(); + string result; + if (IsShellCmd()) + result = EvaluateShellCmd(e); + else if (IsCondExpr()) + result = EvaluateCondExpr(e); + else + result = EvaluateCompExpr(e); + oldResult = result; + oldEvent = e; + oldescapeStrings = escapeStrings; + + // avoid double dir separators + int pos = 0; + while((pos = result.find("~~")) >= 0) + result.replace(pos, 2, "~"); + + return result; +} + +string cUserVar::EvaluateShellCmd(const cEvent* e) +{ + if (!varparser.cmd) return ""; + string cmdArgs; + if (varparser.cmdArgs != "") + { + string args = varparser.cmdArgs; + varparser.compExpr = args; //handle the args as composed expr + cmdArgs = EvaluateCompExpr(e, true); + } + const char* res = varparser.cmd->Execute(cmdArgs.c_str()); + string result = res?res:""; + int crPos = 0; // remove any CR + while((crPos = result.find("\n")) >= 0) + result.replace(crPos, 1, ""); + + return result; +} + +string cUserVar::EvaluateCondExpr(const cEvent* e, bool escapeStrings) +{ + string condresult = ""; + cVarExpr leftExp(varparser.condEqLeft); + string resLeft = leftExp.Evaluate(e); + cVarExpr rightExp(varparser.condEqRight); + string resRight = rightExp.Evaluate(e); + if (varparser.condOp == condEq && resLeft == resRight) condresult = "1"; // assign any value + if (varparser.condOp == condNeq && resLeft != resRight) condresult = "1"; // assign any value + + cUserVar* condVarTrue = UserVars.GetFromName(varparser.condvarTrue); + cUserVar* condVarFalse = UserVars.GetFromName(varparser.condvarFalse); + if (!condVarTrue || !condVarFalse) return ""; + + if (!AddDepVar(condVarTrue)) return ""; + if (!AddDepVar(condVarFalse)) return ""; + + if (condresult != "") + { + LogFile.Log(3, "using case 'true'"); + return condVarTrue->Evaluate(e, escapeStrings); + } + else + { + LogFile.Log(3, "using case 'false'"); + return condVarFalse->Evaluate(e, escapeStrings); + } +} + +string cUserVar::EvaluateCompExpr(const cEvent* e, bool escapeStrings) +{ + string expr = varparser.compExpr; + + string compExprLower = expr; + std::transform(compExprLower.begin(), compExprLower.end(), compExprLower.begin(), tolower); + + // handle internal vars like title and subtitle + expr = EvaluateInternalVars(expr, e, escapeStrings); + + // replace ext. EPG variables + expr = EvaluateExtEPGVars(expr, e, escapeStrings); + + // replace other user vars + expr = EvaluateUserVars(expr, e, escapeStrings); + + return expr; +} + +string cUserVar::EvaluateInternalVars(const string& Expr, const cEvent* e, bool escapeStrings) +{ + string expr = Expr; + + std::map<string, cInternalVar*>::iterator it; + for (it = UserVars.internalVars.begin(); it != UserVars.internalVars.end(); it++) + { + string varName = (it->second)->Name(); + int varPos = 0; + while((varPos = FindIgnoreCase(expr, varName)) >= 0) + { + usedVars.insert(it->second); + expr.replace(varPos, varName.size(), (it->second)->Evaluate(e, escapeStrings)); + } + } + return expr; +} + +string cUserVar::EvaluateExtEPGVars(const string& Expr, const cEvent* e, bool escapeStrings) +{ + string expr = Expr; + + std::map<string, cExtEPGVar*>::iterator evar; + for (evar = UserVars.extEPGVars.begin(); evar != UserVars.extEPGVars.end(); evar++) + { + string varName = evar->second->Name(); + int varPos = 0; + while((varPos = FindIgnoreCase(expr, varName)) >= 0) + { + expr.replace(varPos, varName.size(), evar->second->Evaluate(e, escapeStrings)); + usedVars.insert(evar->second); + } + } + return expr; +} + +string cUserVar::EvaluateUserVars(const string& Expr, const cEvent* e, bool escapeStrings) +{ + string expr = Expr; + + std::set<cUserVar*>::iterator it; + for (it = UserVars.userVars.begin(); it != UserVars.userVars.end(); it++) + { + string varName = (*it)->Name(); + int varPos = 0; + while((varPos = FindIgnoreCase(expr, varName)) >= 0) + { + if (!AddDepVar(*it)) return ""; + expr.replace(varPos, varName.size(), (*it)->Evaluate(e, escapeStrings)); + } + } + return expr; +} + +string cUserVar::EvaluateInternalTimerVars(const string& Expr, const cTimer* t) +{ + string expr = Expr; + + std::map<string, cTimerVar*>::iterator tvar; + for (tvar = UserVars.internalTimerVars.begin(); tvar != UserVars.internalTimerVars.end(); tvar++) + { + string varName = tvar->second->Name(); + int varPos = 0; + while((varPos = FindIgnoreCase(expr, varName)) >= 0) + { + expr.replace(varPos, varName.size(), tvar->second->Evaluate(t)); + } + } + return expr; +} + +string cUserVar::EvaluateInternalSearchVars(const string& Expr, const cSearchExt* s) +{ + string expr = Expr; + + std::map<string, cSearchVar*>::iterator svar; + for (svar = UserVars.internalSearchVars.begin(); svar != UserVars.internalSearchVars.end(); svar++) + { + string varName = svar->second->Name(); + int varPos = 0; + while((varPos = FindIgnoreCase(expr, varName)) >= 0) + { + expr.replace(varPos, varName.size(), svar->second->Evaluate(s)); + } + } + return expr; +} + +bool cUserVar::DependsOnVar(const string& varName) +{ + string VarName = Strip(varName); + cUserVar* var = UserVars.GetFromName(VarName); + if (!var) return false; + return DependsOnVar(var); +} + +bool cUserVar::DependsOnVar(cUserVar* var) +{ + if (!var) return false; + if (usedVars.find(var) != usedVars.end()) return true; + std::set<cUserVar*>::iterator it; + for (it = usedVars.begin(); it != usedVars.end(); it++) + if ((*it)->DependsOnVar(var)) + return true; + return false; +} + +bool cUserVar::AddDepVar(cUserVar* var) +{ + if (var == this || var->DependsOnVar(this)) + { + LogFile.eSysLog("ERROR - found cylic reference to var '%s' in var '%s'", var->Name().c_str(), Name().c_str()); + return false; + } + usedVars.insert(var); + return true; +} + +void cUserVar::ResetCache() +{ + oldEvent = NULL; + oldResult = ""; +} + +// cUserVarLine +bool cUserVarLine::Parse(char *s) +{ + if (s && s[0] == '#') + return true; + char *p = strchr(s, '='); + if (p) + { + cUserVar* userVar = new cUserVar; + if (userVar->varparser.Parse(s)) + { + UserVars.userVars.insert(userVar); + return true; + } + } + return false; +} + +// cUserVars +cUserVar* cUserVars::GetFromName(const string& varName) +{ + string VarName = Strip(varName); + std::transform(VarName.begin(), VarName.end(), VarName.begin(), tolower); + + std::map<string, cInternalVar*>::iterator ivar = internalVars.find(VarName); + if (ivar != internalVars.end()) + return ivar->second; + + std::set<cUserVar*>::iterator uvar; + for (uvar = userVars.begin(); uvar != userVars.end(); uvar++) + if (EqualsNoCase((*uvar)->Name(), VarName)) + return (*uvar); + + std::map<string, cExtEPGVar*>::iterator evar = extEPGVars.find(VarName); + if (evar != extEPGVars.end()) + return evar->second; + + LogFile.eSysLog("var '%s' not defined!", VarName.c_str()); + return NULL; +} + +// cVarExpr +string cVarExpr::Evaluate(const cEvent* e) +{ + // create a dummy user var + cUserVar var; + if (!var.varparser.ParseExp(expr)) + return ""; + + LogFile.Log(3, "start evaluating expression '%s'", expr.c_str()); + string result = var.Evaluate(e); + LogFile.Log(3, "stop evaluating expression '%s' - result: '%s'", expr.c_str(), result.c_str()); + usedVars = var.usedVars; + return result; +} + +string cVarExpr::Evaluate(const cTimer* t) +{ + // create a dummy user var + cUserVar var; + if (!var.varparser.ParseExp(expr)) + return ""; + + usedVars = var.usedVars; + return var.EvaluateInternalTimerVars(expr, t); +} + +string cVarExpr::Evaluate(const cSearchExt* s) +{ + // create a dummy user var + cUserVar var; + if (!var.varparser.ParseExp(expr)) + return ""; + + usedVars = var.usedVars; + return var.EvaluateInternalSearchVars(expr, s); +} + +bool cVarExpr::DependsOnVar(const string& varName, const cEvent* e) +{ + string VarName = Strip(varName); + if (FindIgnoreCase(expr, VarName) >= 0) + return true; + // create a dummy user var + cUserVar var; + var.varparser.varName = expr; + if (!var.varparser.ParseExp(expr)) + return false; + var.Evaluate(e); + return var.DependsOnVar(VarName); +} |