public bool?CheckConditions(List <Condition> fel, ConditionVariables values, out string errlist, List <Condition> passed = null, ConditionFunctions cf = null) { errlist = null; bool?outerres = null; foreach (Condition fe in fel) // find all values needed { bool?innerres = null; foreach (ConditionEntry f in fe.fields) { bool matched = false; if (f.matchtype == ConditionEntry.MatchType.AlwaysTrue || f.matchtype == ConditionEntry.MatchType.AlwaysFalse) { if (f.itemname.Length == 0 || f.itemname.Equals("Condition", StringComparison.InvariantCultureIgnoreCase)) // empty (legacy) or { if (f.matchtype == ConditionEntry.MatchType.AlwaysTrue) { matched = true; // matched, else if false, leave as false. } } else { errlist += "AlwaysFalse/True does not have left side text of Condition"; innerres = false; break; } } else { string leftside = null; ConditionFunctions.ExpandResult er = ConditionFunctions.ExpandResult.NoExpansion; if (cf != null) // if we have a string expander, try the left side { er = cf.ExpandString(f.itemname, out leftside); if (er == ConditionFunctions.ExpandResult.Failed) // stop on error { errlist += leftside; // add on errors.. innerres = false; // stop loop, false break; } } if (f.matchtype == ConditionEntry.MatchType.IsPresent) // these use f.itemname without any expansion { if (leftside == null || er == ConditionFunctions.ExpandResult.NoExpansion) // no expansion, must be a variable name { leftside = f.itemname; } if (values.Exists(leftside) && values[leftside] != null) { matched = true; } } else if (f.matchtype == ConditionEntry.MatchType.IsNotPresent) { if (leftside == null || er == ConditionFunctions.ExpandResult.NoExpansion) // no expansion, must be a variable name { leftside = f.itemname; } if (!values.Exists(leftside) || values[leftside] == null) { matched = true; } } else { if (er == ConditionFunctions.ExpandResult.NoExpansion) // no expansion, must be a variable name { leftside = values.Exists(f.itemname) ? values[f.itemname] : null; if (leftside == null) { errlist += "Item " + f.itemname + " is not available" + Environment.NewLine; innerres = false; break; // stop the loop, its a false } } string rightside; if (cf != null) // if we have a string expander, pass it thru { er = cf.ExpandString(f.matchstring, out rightside); if (er == ConditionFunctions.ExpandResult.Failed) // if error, abort { errlist += rightside; // add on errors.. innerres = false; // stop loop, false break; } } else { rightside = f.matchstring; } if (f.matchtype == ConditionEntry.MatchType.DateBefore || f.matchtype == ConditionEntry.MatchType.DateAfter) { DateTime tmevalue, tmecontent; if (!DateTime.TryParse(leftside, System.Globalization.CultureInfo.CreateSpecificCulture("en-US"), System.Globalization.DateTimeStyles.None, out tmevalue)) { errlist += "Date time not in correct format on left side" + Environment.NewLine; innerres = false; break; } else if (!DateTime.TryParse(rightside, System.Globalization.CultureInfo.CreateSpecificCulture("en-US"), System.Globalization.DateTimeStyles.None, out tmecontent)) { errlist += "Date time not in correct format on right side" + Environment.NewLine; innerres = false; break; } else { if (f.matchtype == ConditionEntry.MatchType.DateBefore) { matched = tmevalue.CompareTo(tmecontent) < 0; } else { matched = tmevalue.CompareTo(tmecontent) >= 0; } } } else if (f.matchtype == ConditionEntry.MatchType.Equals) { matched = leftside.Equals(rightside, StringComparison.InvariantCultureIgnoreCase); } else if (f.matchtype == ConditionEntry.MatchType.EqualsCaseSensitive) { matched = leftside.Equals(rightside); } else if (f.matchtype == ConditionEntry.MatchType.NotEqual) { matched = !leftside.Equals(rightside, StringComparison.InvariantCultureIgnoreCase); } else if (f.matchtype == ConditionEntry.MatchType.NotEqualCaseSensitive) { matched = !leftside.Equals(rightside); } else if (f.matchtype == ConditionEntry.MatchType.Contains) { matched = leftside.IndexOf(rightside, StringComparison.InvariantCultureIgnoreCase) >= 0; } else if (f.matchtype == ConditionEntry.MatchType.ContainsCaseSensitive) { matched = leftside.Contains(rightside); } else if (f.matchtype == ConditionEntry.MatchType.DoesNotContain) { matched = leftside.IndexOf(rightside, StringComparison.InvariantCultureIgnoreCase) < 0; } else if (f.matchtype == ConditionEntry.MatchType.DoesNotContainCaseSensitive) { matched = !leftside.Contains(rightside); } else if (f.matchtype == ConditionEntry.MatchType.IsOneOf) { StringParser p = new StringParser(rightside); List <string> ret = p.NextQuotedWordList(); if (ret == null) { errlist += "IsOneOf value list is not in a optionally quoted comma separated form" + Environment.NewLine; innerres = false; break; // stop the loop, its a false } else { matched = ret.Contains(leftside, StringComparer.InvariantCultureIgnoreCase); } } else if (f.matchtype == ConditionEntry.MatchType.AnyOfAny) { StringParser l = new StringParser(leftside); List <string> ll = l.NextQuotedWordList(); StringParser r = new StringParser(rightside); List <string> rl = r.NextQuotedWordList(); if (ll == null || rl == null) { errlist += "AnyOfAny value list is not in a optionally quoted comma separated form on both sides" + Environment.NewLine; innerres = false; break; // stop the loop, its a false } else { foreach (string s in ll) // for all left strings { if (rl.Contains(s, StringComparer.InvariantCultureIgnoreCase)) // if right has it.. { matched = true; // matched and break break; } } } } else if (f.matchtype == ConditionEntry.MatchType.IsEmpty) { matched = leftside.Length == 0; } else if (f.matchtype == ConditionEntry.MatchType.IsNotEmpty) { matched = leftside.Length > 0; } else if (f.matchtype == ConditionEntry.MatchType.IsTrue || f.matchtype == ConditionEntry.MatchType.IsFalse) { int inum = 0; if (leftside.InvariantParse(out inum)) { matched = (f.matchtype == ConditionEntry.MatchType.IsTrue) ? (inum != 0) : (inum == 0); } else { errlist += "True/False value is not an integer on left side" + Environment.NewLine; innerres = false; break; } } else { double fnum = 0, num = 0; if (!leftside.InvariantParse(out num)) { errlist += "Number not in correct format on left side" + Environment.NewLine; innerres = false; break; } else if (!rightside.InvariantParse(out fnum)) { errlist += "Number not in correct format on right side" + Environment.NewLine; innerres = false; break; } else { if (f.matchtype == ConditionEntry.MatchType.NumericEquals) { matched = Math.Abs(num - fnum) < 0.0000000001; // allow for rounding } else if (f.matchtype == ConditionEntry.MatchType.NumericNotEquals) { matched = Math.Abs(num - fnum) >= 0.0000000001; } else if (f.matchtype == ConditionEntry.MatchType.NumericGreater) { matched = num > fnum; } else if (f.matchtype == ConditionEntry.MatchType.NumericGreaterEqual) { matched = num >= fnum; } else if (f.matchtype == ConditionEntry.MatchType.NumericLessThan) { matched = num < fnum; } else if (f.matchtype == ConditionEntry.MatchType.NumericLessThanEqual) { matched = num <= fnum; } else { System.Diagnostics.Debug.Assert(false); } } } } } // System.Diagnostics.Debug.WriteLine(fe.eventname + ":Compare " + f.matchtype + " '" + f.contentmatch + "' with '" + vr.value + "' res " + matched + " IC " + fe.innercondition); if (fe.innercondition == ConditionEntry.LogicalCondition.And) // Short cut, if AND, all must pass, and it did not { if (!matched) { innerres = false; break; } } else if (fe.innercondition == ConditionEntry.LogicalCondition.Nand) // Short cut, if NAND, and not matched { if (!matched) { innerres = true; // positive non match - NAND produces a true break; } } else if (fe.innercondition == ConditionEntry.LogicalCondition.Or) // Short cut, if OR, and matched { if (matched) { innerres = true; break; } } else { // short cut, if NOR, and matched, its false if (matched) { innerres = false; break; } } } if (!innerres.HasValue) // All tests executed, without a short cut, we set it to a definitive state { if (fe.innercondition == ConditionEntry.LogicalCondition.And) // none did not match, producing a false, so therefore AND is true { innerres = true; } else if (fe.innercondition == ConditionEntry.LogicalCondition.Or) // none did match, producing a true, so therefore OR must be false { innerres = false; } else if (fe.innercondition == ConditionEntry.LogicalCondition.Nor) // none did match, producing a false, so therefore NOR must be true { innerres = true; } else // NAND none did match, producing a true, so therefore NAND must be false { innerres = false; } } if (innerres.Value && passed != null) // if want a list of passes, do it { passed.Add(fe); } if (!outerres.HasValue) // if first time, its just the value { outerres = innerres.Value; } else if (fe.outercondition == ConditionEntry.LogicalCondition.Or) { outerres |= innerres.Value; } else if (fe.outercondition == ConditionEntry.LogicalCondition.And) { outerres &= innerres.Value; } else if (fe.outercondition == ConditionEntry.LogicalCondition.Nor) { outerres = !(outerres | innerres.Value); } else if (fe.outercondition == ConditionEntry.LogicalCondition.Nand) { outerres = !(outerres & innerres.Value); } } return(outerres); }
// backstop standard functions static public ConditionFunctionHandlers DefaultGetCFH(ConditionFunctions c, ConditionVariables vars, ConditionPersistentData handles, int recdepth) { return(new ConditionFunctionsBase(c, vars, handles, recdepth)); }
// check all conditions against these values. public bool?CheckAll(ConditionVariables values, out string errlist, List <Condition> passed = null, ConditionFunctions cf = null) // Check all conditions.. { if (conditionlist.Count == 0) // no filters match, null { errlist = null; return(null); } return(CheckConditions(conditionlist, values, out errlist, passed, cf)); }
public ConditionFunctionsBase(ConditionFunctions c, ConditionVariables v, ConditionFileHandles h, int recd) : base(c, v, h, recd) { if (functions == null) // one time init, done like this cause can't do it in {} { functions = new Dictionary <string, FuncEntry>(); functions.Add("abs", new FuncEntry(Abs, 2, 2, 1, 0)); // first is var or literal or string functions.Add("alt", new FuncEntry(Alt, 2, 20, 0xfffffff, 0xfffffff)); // first is var or literal or string, etc. functions.Add("closefile", new FuncEntry(CloseFile, 1, 1, 1, 0)); // first is a var functions.Add("datetimenow", new FuncEntry(DateTimeNow, 1, 1, 0)); // literal type functions.Add("datehour", new FuncEntry(DateHour, 1, 1, 1, 1)); // first is a var or string functions.Add("date", new FuncEntry(Date, 2, 2, 1, 1)); // first is a var or string, second is literal functions.Add("direxists", new FuncEntry(DirExists, 1, 20, 0xfffffff, 0xfffffff)); // check var, can be string functions.Add("escapechar", new FuncEntry(EscapeChar, 1, 1, 1, 1)); // check var, can be string functions.Add("eval", new FuncEntry(Eval, 1, 2, 1, 1)); // can be string, can be variable, p2 is not a variable, and can't be a string functions.Add("exist", new FuncEntry(Exists, 1, 20, 0, 0xfffffff)); functions.Add("existsdefault", new FuncEntry(ExistsDefault, 2, 2, 2, 3)); // first is a macro but can not exist, second is a string or macro which must exist functions.Add("expand", new FuncEntry(Expand, 1, 20, 0xfffffff, 0xfffffff)); // check var, can be string (if so expanded) functions.Add("expandarray", new FuncEntry(ExpandArray, 4, 5, 2, 3 + 16)); // var 1 is text root/string, not var, not string, var 2 can be var or string, var 3/4 is integers or variables, checked in function functions.Add("expandvars", new FuncEntry(ExpandVars, 4, 5, 2, 3 + 16)); // var 1 is text root/string, not var, not string, var 2 can be var or string, var 3/4 is integers or variables, checked in function functions.Add("filelength", new FuncEntry(FileLength, 1, 1, 1, 1)); // check var, can be string functions.Add("fileexists", new FuncEntry(FileExists, 1, 20, 0xfffffff, 0xfffffff)); // check var, can be string functions.Add("findline", new FuncEntry(FindLine, 2, 2, 3, 2)); //check var1 and var2, second can be a string functions.Add("floor", new FuncEntry(Floor, 2, 2, 1)); // check var1, not var 2 no strings functions.Add("ifnotempty", new FuncEntry(Ifnotempty, 2, 3, 7, 7)); // check var1-3, allow strings var1-3 functions.Add("ifempty", new FuncEntry(Ifempty, 2, 3, 7, 7)); functions.Add("iftrue", new FuncEntry(Iftrue, 2, 3, 7, 7)); // check var1-3, allow strings var1-3 functions.Add("iffalse", new FuncEntry(Iffalse, 2, 3, 7, 7)); functions.Add("ifzero", new FuncEntry(Ifzero, 2, 3, 7, 7)); // check var1-3, allow strings var1-3 functions.Add("ifnonzero", new FuncEntry(Ifnonzero, 2, 3, 7, 7)); // check var1-3, allow strings var1-3 functions.Add("ifcontains", new FuncEntry(Ifcontains, 3, 5, 31, 31)); // check var1-5, allow strings var1-5 functions.Add("ifnotcontains", new FuncEntry(Ifnotcontains, 3, 5, 31, 31)); functions.Add("ifequal", new FuncEntry(Ifequal, 3, 5, 31, 31)); functions.Add("ifnotequal", new FuncEntry(Ifnotequal, 3, 5, 31, 31)); functions.Add("ifgt", new FuncEntry(Ifnumgreater, 3, 5, 31, 31)); // check var1-5, allow strings var1-5 functions.Add("iflt", new FuncEntry(Ifnumless, 3, 5, 31, 31)); functions.Add("ifge", new FuncEntry(Ifnumgreaterequal, 3, 5, 31, 31)); functions.Add("ifle", new FuncEntry(Ifnumlessequal, 3, 5, 31, 31)); functions.Add("ifeq", new FuncEntry(Ifnumequal, 3, 5, 31, 31)); functions.Add("ifne", new FuncEntry(Ifnumnotequal, 3, 5, 31, 31)); functions.Add("indexof", new FuncEntry(IndexOf, 2, 2, 3, 3)); // check var1 and 2 if normal, allow string in 1 and 2 functions.Add("indirect", new FuncEntry(Indirect, 1, 20, 0xfffffff, 0xfffffff)); // check var, no strings functions.Add("ispresent", new FuncEntry(Ispresent, 2, 3, 2, 2)); // 1 may not be there, 2 either a macro or can be string. 3 is optional and a var or literal functions.Add("join", new FuncEntry(Join, 3, 20, 0xfffffff, 0xfffffff)); // all can be string, check var functions.Add("length", new FuncEntry(Length, 1, 1, 1, 1)); functions.Add("lower", new FuncEntry(Lower, 1, 20, 0xfffffff, 0xfffffff)); // all can be string, check var functions.Add("mkdir", new FuncEntry(MkDir, 1, 1, 1, 1)); // check var, can be string functions.Add("openfile", new FuncEntry(OpenFile, 3, 3, 2, 2)); functions.Add("phrase", new FuncEntry(Phrase, 1, 1, 1, 1)); functions.Add("random", new FuncEntry(Random, 1, 1, 0, 0)); // no change var, not string functions.Add("readline", new FuncEntry(ReadLineFile, 2, 2, 1, 0)); // first must be a macro, second is a literal varname only functions.Add("replace", new FuncEntry(Replace, 3, 3, 7, 7)); // var/string for all functions.Add("replaceescapechar", new FuncEntry(ReplaceEscapeChar, 1, 1, 1, 1)); // check var, can be string functions.Add("replacevar", new FuncEntry(ReplaceVar, 2, 2, 1, 3)); // var/string, literal/var/string functions.Add("round", new FuncEntry(RoundCommon, 3, 3, 1)); functions.Add("roundnz", new FuncEntry(RoundCommon, 4, 4, 1)); functions.Add("roundscale", new FuncEntry(RoundCommon, 5, 5, 1)); functions.Add("rs", new FuncEntry(ReplaceVarSC, 2, 2, 1, 3)); // var/string, literal/var/string functions.Add("rv", new FuncEntry(ReplaceVar, 2, 2, 1, 3)); // var/string, literal/var/string functions.Add("seek", new FuncEntry(SeekFile, 2, 2, 1, 0)); //first is macro, second is literal or macro functions.Add("safevarname", new FuncEntry(SafeVarName, 1, 1, 1, 1)); //macro/string functions.Add("sc", new FuncEntry(SplitCaps, 1, 1, 1, 1)); //shorter alias functions.Add("ship", new FuncEntry(Ship, 1, 1, 1, 1)); //ship translator functions.Add("splitcaps", new FuncEntry(SplitCaps, 1, 1, 1, 1)); //check var, allow strings functions.Add("substring", new FuncEntry(SubString, 3, 3, 1, 1)); // check var1, var1 can be string, var 2 and 3 can either be macro or ints not strings functions.Add("systempath", new FuncEntry(SystemPath, 1, 1, 0, 0)); // literal functions.Add("tell", new FuncEntry(TellFile, 1, 1, 1, 0)); //first is macro functions.Add("tickcount", new FuncEntry(TickCount, 0, 0, 0, 0)); // no paras functions.Add("trim", new FuncEntry(Trim, 1, 2, 1, 1)); functions.Add("upper", new FuncEntry(Upper, 1, 20, 0xfffffff, 0xfffffff)); // all can be string, check var functions.Add("wordlistcount", new FuncEntry(WordListCount, 1, 1, 1)); // first is a var or string functions.Add("wordlistentry", new FuncEntry(WordListEntry, 2, 2, 1, 1)); // first is a var or string, second is a var or literal functions.Add("wordof", new FuncEntry(WordOf, 2, 3, 1 + 4, 1 + 4)); // first is a var or string, second is a var or literal, third is a macro or string functions.Add("write", new FuncEntry(WriteFile, 2, 2, 3, 2)); // first must be a var, second can be macro or string functions.Add("writeline", new FuncEntry(WriteLineFile, 2, 2, 3, 2)); // first must be a var, second can be macro or string } }