Beispiel #1
0
        public ExpandResult ExpandStringFull(string line, out string result, int recdepth)
        {
            int noexpansion = 0;
            int pos         = 0;

            do
            {
                pos = line.IndexOf('%', pos);

                if (pos >= 0)
                {
                    pos++;                                                  // move on, if it fails, next pos= will be past this point

                    int startexpression = pos;

                    int apos = pos;

                    while (apos < line.Length && char.IsLetter(line[apos]))
                    {
                        apos++;
                    }

                    if (apos < line.Length && line[apos] == '(')     // now must be bracket..  if not, its not in form, ignore %, or its past the EOL
                    {
                        string funcname = line.Substring(pos, apos - pos);
                        apos++;     // past the (

                        ConditionFunctionHandlers cfh = GetCFH(this, vars, persistentdata, recdepth);

                        while (true)
                        {
                            while (apos < line.Length && char.IsWhiteSpace(line[apos])) // remove white space
                            {
                                apos++;
                            }

                            if (apos < line.Length && line[apos] == ')' && cfh.paras.Count == 0) // ) here must be on first only, and is valid
                            {
                                apos++;                                                          // skip by
                                break;
                            }

                            int start = apos;

                            if (apos < line.Length && (line[apos] == '"' || line[apos] == '\''))
                            {
                                char quote = line[apos++];

                                string res = "";

                                while (apos < line.Length && line[apos] != quote)
                                {
                                    if (line[apos] == '\\' && (apos + 1) < line.Length && line[apos + 1] == quote)  // if \"
                                    {
                                        apos++;
                                    }

                                    res += line[apos++];
                                }

                                if (apos >= line.Length)
                                {
                                    result = "Terminal quote missing at '" + line.Substring(startexpression, apos - startexpression) + "'";
                                    return(ExpandResult.Failed);
                                }

                                apos++;              // remove quote

                                string       resexp; // expand out any strings.. recursion
                                ExpandResult sexpresult = ExpandStringFull(res, out resexp, recdepth + 1);

                                if (sexpresult == ExpandResult.Failed)
                                {
                                    result = resexp;
                                    return(sexpresult);
                                }

                                cfh.paras.Add(new ConditionFunctionHandlers.Parameter()
                                {
                                    value = resexp, isstring = true
                                });
                            }
                            else
                            {
                                if (funcname.Length > 0)        // functions can have () embedded .. in literals
                                {
                                    int blevel = 0;
                                    while (apos < line.Length && (blevel > 0 || "), ".IndexOf(line[apos]) == -1))
                                    {
                                        if (line[apos] == '(')
                                        {
                                            blevel++;
                                        }
                                        else if (line[apos] == ')')
                                        {
                                            blevel--;
                                        }

                                        apos++;
                                    }
                                }
                                else
                                {
                                    while (apos < line.Length && "), ".IndexOf(line[apos]) == -1)
                                    {
                                        apos++;
                                    }
                                }

                                if (apos == start)
                                {
                                    result = "Missing variable name at '" + line.Substring(startexpression, apos - startexpression) + "'";
                                    return(ExpandResult.Failed);
                                }

                                string res = line.Substring(start, apos - start);

                                if (funcname.Length > 0 && line.Contains("%")) // function paramters can be expanded if they have a %
                                {
                                    string       resexp;                       // expand out any strings.. recursion
                                    ExpandResult sexpresult = ExpandStringFull(res, out resexp, recdepth + 1);

                                    if (sexpresult == ExpandResult.Failed)
                                    {
                                        result = resexp;
                                        return(sexpresult);
                                    }

                                    res = resexp;
                                }
                                else
                                {                   // not an expansion.. see if it needs mangling
                                    res = vars.Qualify(res);
                                }

                                cfh.paras.Add(new ConditionFunctionHandlers.Parameter()
                                {
                                    value = res, isstring = false
                                });
                            }

                            while (apos < line.Length && char.IsWhiteSpace(line[apos]))
                            {
                                apos++;
                            }

                            char c = (apos < line.Length) ? line[apos++] : '-';

                            if (c == ')')     // must be )
                            {
                                break;
                            }

                            if (c != ',')     // must be ,
                            {
                                result = "Incorrectly formed parameter list at '" + line.Substring(startexpression, apos - startexpression) + "'";
                                return(ExpandResult.Failed);
                            }
                        }

                        string expand = null;

                        if (funcname.Length > 0)        // functions!
                        {
                            if (!cfh.RunFunction(funcname, out expand))
                            {
                                result = "Function " + funcname + ": " + expand;
                                return(ExpandResult.Failed);
                            }
                        }
                        else if (cfh.paras.Count != 1)   // only 1
                        {
                            result = "Variable name missing between () at '" + line.Substring(startexpression, apos - startexpression) + "'";
                            return(ExpandResult.Failed);
                        }
                        else
                        {                               // variables
                            if (cfh.paras[0].isstring)
                            {
                                result = "Must be a variable not a string for non function expansions";
                                return(ExpandResult.Failed);
                            }
                            else if (vars.Exists(cfh.paras[0].value))
                            {
                                expand = vars[cfh.paras[0].value];
                            }
                            else
                            {
                                result = "Variable '" + cfh.paras[0].value + "' does not exist";
                                return(ExpandResult.Failed);
                            }
                        }

                        noexpansion++;
                        line = line.Substring(0, pos - 1) + expand + line.Substring(apos);

                        pos = (pos - 1) + expand.Length;

                        //                            System.Diagnostics.Debug.WriteLine("<" + funcname + "> var <" + varnames[0] + ">" + "  line <" + line + "> left <" + line.Substring(pos) + ">");
                    }
                }
            } while (pos != -1);

            result = line;
            return((noexpansion > 0) ? ExpandResult.Expansion : ExpandResult.NoExpansion);
        }
Beispiel #2
0
        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 = values.Qualify(f.itemname);                                 // its a straight variable name, allow any special formatting
                            }
                            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 = values.Qualify(f.itemname);                                 // its a straight variable name, allow any special formatting
                            }
                            if (!values.Exists(leftside) || values[leftside] == null)
                            {
                                matched = true;
                            }
                        }
                        else
                        {
                            if (er == ConditionFunctions.ExpandResult.NoExpansion)     // no expansion, must be a variable name
                            {
                                leftside = values.Qualify(f.itemname);
                                leftside = values.Exists(leftside) ? values[leftside] : null;   // then lookup

                                if (leftside == null)
                                {
                                    errlist += "Item " + leftside + " 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.MatchSemicolon)
                            {
                                string[] list = rightside.Split(';').Select(x => x.Trim()).ToArray();                // split and trim
                                matched = list.Contains(leftside.Trim(), StringComparer.InvariantCultureIgnoreCase); // compare, trimmed, case insensitive
                            }
                            else if (f.matchtype == ConditionEntry.MatchType.MatchCommaList)
                            {
                                StringCombinations sc = new StringCombinations(',');
                                sc.ParseString(rightside);                                                                      // parse, give all combinations
                                matched = sc.Permutations.Contains(leftside.Trim(), StringComparer.InvariantCultureIgnoreCase); // compare, trimmed, case insensitive
                            }
                            else if (f.matchtype == ConditionEntry.MatchType.MatchSemicolonList)
                            {
                                StringCombinations sc = new StringCombinations(';');
                                sc.ParseString(rightside);                                                                      // parse, give all combinations
                                matched = sc.Permutations.Contains(leftside.Trim(), StringComparer.InvariantCultureIgnoreCase); // compare, trimmed, case insensitive
                            }
                            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);
        }