summaryrefslogtreecommitdiff
path: root/uservars.c
diff options
context:
space:
mode:
Diffstat (limited to 'uservars.c')
-rw-r--r--uservars.c346
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);
+}