示例#1
0
        /// <summary>
        /// Add the parameters of <paramref name="qualifierKey"/> as criteria for qualifier.
        ///
        /// Every parameter of <paramref name="qualifierKey"/> will be required to match in the lines that will be compared with this qualifier.
        /// If a parameterValue in the <paramref name="qualifierKey"/> is "", then the compared key must not have that parameter, or it must be "".
        ///
        /// (Does not expect canoncials to be in same order in relation to different ParameterNames.)
        /// </summary>
        /// <param name="qualifier">configurable qualifier composition</param>
        /// <param name="qualifierKey">parameters</param>
        /// <param name="parameterInfos">(optional) infos for determining which keys are non-canonical</param>
        /// <returns><paramref name="qualifier"/></returns>
        public static ILineQualifier Rule(this ILineQualifier qualifier, ILine qualifierKey, IParameterInfos parameterInfos = null)
        {
            // Break qualifierKey into effective non-canonical parameters, and to canonical parameters and occurance index
            StructList12 <(ILineParameter, int)> list = new StructList12 <(ILineParameter, int)>();

            qualifierKey.GetParameterPartsWithOccurance(ref list);

            // Add rules
            foreach ((ILineParameter parameter, int occuranceIndex) in list)
            {
                // Parameter with null is to be ignored
                if (parameter.ParameterName == null || parameter.ParameterValue == null)
                {
                    continue;
                }
                // Ineffective key
                if (occuranceIndex > 0 && parameter.IsNonCanonicalKey(parameterInfos))
                {
                    continue;
                }
                // parameter with "" is expectation of empty or non-existant value.
                if (parameter.ParameterValue == "")
                {
                    qualifier.Add(new LineParameterQualifier.IsEmpty(parameter.ParameterName, occuranceIndex));
                }
                else
                {
                    qualifier.Add(new LineParameterQualifier.IsEqualTo(parameter.ParameterName, occuranceIndex, parameter.ParameterValue));
                }
            }

            return(qualifier);
        }
示例#2
0
 /// <summary>
 /// Add expected value rule.
 /// </summary>
 /// <param name="qualifier"></param>
 /// <param name="parameterName">parameter name this rule applies to</param>
 /// <param name="occuranceIndex">occurance index this rule applies to, or -1 to apply to every occurance of the parameter name</param>
 /// <param name="expectedParameterValue">expected value, or if "", then expects value to not occur</param>
 /// <returns><paramref name="qualifier"/></returns>
 public static ILineQualifier Rule(this ILineQualifier qualifier, string parameterName, int occuranceIndex, string expectedParameterValue)
 {
     if (expectedParameterValue == null)
     {
         throw new ArgumentNullException(nameof(expectedParameterValue));
     }
     if (expectedParameterValue == "")
     {
         qualifier.Add(new LineParameterQualifier.IsEmpty(parameterName, occuranceIndex));
     }
     else
     {
         qualifier.Add(new LineParameterQualifier.IsEqualTo(parameterName, occuranceIndex, expectedParameterValue));
     }
     return(qualifier);
 }
示例#3
0
 /// <summary>
 /// Add expected value rule.
 /// </summary>
 /// <param name="qualifier"></param>
 /// <param name="parameterName">parameter name this rule applies to</param>
 /// <param name="occuranceIndex">occurnace index this rule applies to, or -1 to apply to every occurance of the parameter name</param>
 /// <param name="acceptedParameterValues">group of accepted parameter values</param>
 /// <returns><paramref name="qualifier"/></returns>
 public static ILineQualifier Rule(this ILineQualifier qualifier, string parameterName, int occuranceIndex, params string[] acceptedParameterValues)
 {
     if (acceptedParameterValues == null || acceptedParameterValues.Length == 0)
     {
         return(qualifier);
     }
     if (acceptedParameterValues.Length == 1)
     {
         qualifier.Rule(parameterName, occuranceIndex, acceptedParameterValues[0]);
     }
     else
     {
         qualifier.Add(new LineParameterQualifier.IsInGroup(parameterName, occuranceIndex, acceptedParameterValues));
     }
     return(qualifier);
 }
        /// <summary>
        /// Qualify <paramref name="line"/> against the qualifier rules.
        /// </summary>
        /// <param name="qualifier">(optional) qualifier</param>
        /// <param name="line"></param>
        /// <returns>true if line is qualified, false if disqualified</returns>
        public static bool Qualify(this ILineQualifier qualifier, ILine line)
        {
            // Evaluate whole line
            if (qualifier is ILineQualifierEvaluatable eval)
            {
                return(eval.Qualify(line));
            }

            // Evaluate argument
            if (qualifier is ILineArgumentQualifier argumentQualifier)
            {
                if (argumentQualifier.NeedsOccuranceIndex)
                {
                    // Break key into effective parameters with occurance index
                    StructList12 <(ILineArgument, int)> list1 = new StructList12 <(ILineArgument, int)>();
                    line.GetArgumentPartsWithOccurance(ref list1);
                    for (int i = 0; i < list1.Count; i++)
                    {
                        if (!argumentQualifier.QualifyArgument(list1[i].Item1, list1[i].Item2))
                        {
                            return(false);
                        }
                    }
                }
                else
                {
                    // Break key into parameters
                    StructList12 <ILineArgument> list2 = new StructList12 <ILineArgument>();
                    line.GetArgumentParts(ref list2);
                    for (int i = 0; i < list2.Count; i++)
                    {
                        if (!argumentQualifier.QualifyArgument(list2[i], -1))
                        {
                            return(false);
                        }
                    }
                }
            }

            // no criteria, accept all
            return(true);
        }
示例#5
0
        /// <summary>
        /// Prune out arguments that are disqualified by <paramref name="qualifier"/>.
        /// </summary>
        /// <param name="line"></param>
        /// <param name="qualifier">Argument qualifier that is used for determining which parts to keep in the line</param>
        /// <param name="lineFactory">(optional) extra line factory</param>
        /// <returns>a modified <paramref name="line"/></returns>
        /// <exception cref="LineException"></exception>
        public static ILine Prune(this ILine line, ILineQualifier qualifier, ILineFactory lineFactory = null)
        {
            // Qualified parts to append. Order: tail to root.
            StructList12 <ILineArgument> list = new StructList12 <ILineArgument>();

            ILineArgumentQualifier lineArgumentQualifier = qualifier as ILineArgumentQualifier;

            // Earliest qualified line part. The start tail, where to start appending qualified parts
            ILine startTail = line;

            // Line part's arguments. Order: root to tail
            StructList8 <ILineArgument> tmp = new StructList8 <ILineArgument>();
            // Start tail buffered args. Order: root to tail
            StructList8 <ILineArgument> startTailArgsBuffer = new StructList8 <ILineArgument>();

            // Add parts
            for (ILine l = line; l != null; l = l.GetPreviousPart())
            {
                tmp.Clear();
                if (l is ILineArgumentEnumerable lineArguments)
                {
                    foreach (ILineArgument lineArgument in lineArguments)
                    {
                        tmp.Add(lineArgument);
                    }
                }
                if (l is ILineArgument argument)
                {
                    tmp.Add(argument);
                }

                // Now qualify
                bool   linePartQualifies = true;
                string parameterName, parameterValue;
                for (int i = tmp.Count - 1; i >= 0; i--)
                {
                    ILineArgument a = tmp[i];

                    bool argumentQualifies = true;
                    if (lineArgumentQualifier != null)
                    {
                        // Qualify as an argument.
                        if (!a.IsNonCanonicalKey())
                        {
                            argumentQualifies = lineArgumentQualifier.QualifyArgument(a);
                        }
                        // Qualify as non-canonical parameter
                        else if (a.TryGetParameter(out parameterName, out parameterValue))
                        {
                            // Calculate occurance index
                            int occIx = -1;
                            if (lineArgumentQualifier.NeedsOccuranceIndex)
                            {
                                occIx = 0;
                                for (int j = i - 1; j >= 0; j--)
                                {
                                    ILineArgument b = list[j];
                                    string        parameterName2, parameterValue2;
                                    if (b.TryGetParameter(out parameterName2, out parameterValue2))
                                    {
                                        continue;
                                    }
                                    if (parameterValue2 != null && parameterName == parameterName2)
                                    {
                                        occIx++;
                                    }
                                }
                            }
                            argumentQualifies = lineArgumentQualifier.QualifyArgument(a, occIx);
                        }
                    }
                    if (!argumentQualifies)
                    {
                        tmp.RemoveAt(i);
                    }
                    linePartQualifies &= argumentQualifies;
                }

                // This part didn't qualify
                if (!linePartQualifies)
                {
                    // Append previous start tail to append args
                    if (startTailArgsBuffer.Count > 0)
                    {
                        for (int i = 0; i < startTailArgsBuffer.Count; i++)
                        {
                            list.Add(startTailArgsBuffer[i]);
                        }
                        startTailArgsBuffer.Clear();
                        startTail = null;
                    }
                    // Add parts that did qualify to append list
                    for (int i = 0; i < tmp.Count; i++)
                    {
                        list.Add(tmp[i]);
                    }
                    // preceding part might be better for start tail
                    startTail = l.GetPreviousPart();
                }
                else
                // This part qualified
                {
                    // Add to start tail buffer, in case preceding startTail fails qualifications
                    for (int i = 0; i < tmp.Count; i++)
                    {
                        startTailArgsBuffer.Add(tmp[i]);
                    }
                }
            }


            // Append qualified parts.
            ILineFactory appender1 = null;

            line.TryGetAppender(out appender1);

            // Nothing qualified, no start, create dummy
            if (startTail == null && list.Count == 0)
            {
                // Create dummy
                ILineFactory appender2 = null;
                line.TryGetAppender(out appender2);
                ILinePart dummy = null;
                if (lineFactory == null || !lineFactory.TryCreate(null, out dummy))
                {
                    if (appender2 == null || !appender2.TryCreate(null, out dummy))
                    {
                        throw new LineException(line, $"LineFactory doesn't have capability to create {nameof(ILinePart)}");
                    }
                }
                return(dummy);
            }

            // Append parts
            ILine result = startTail;

            for (int i = list.Count - 1; i >= 0; i--)
            {
                ILineArgument arg = list[i];
                if (lineFactory == null || !lineFactory.TryCreate(result, arg, out result))
                {
                    if (appender1 == null || !appender1.TryCreate(result, arg, out result))
                    {
                        throw new LineException(line, $"LineFactory doesn't have capability to concat {arg}");
                    }
                }
            }
            return(result);
        }
 /// <summary>
 /// Qualifies lines against qualifier rules.
 /// </summary>
 /// <param name="qualifier">(optional) qualifier</param>
 /// <param name="lines"></param>
 /// <returns>all lines that were qualified</returns>
 public static IEnumerable <ILine> Qualify(this ILineQualifier qualifier, IEnumerable <ILine> lines)
 => qualifier is ILineQualifierLinesEvaluatable linesEval?linesEval.Qualify(lines) :
示例#7
0
 /// <summary>
 /// Add regular expression matching rule.
 /// </summary>
 /// <param name="qualifier"></param>
 /// <param name="parameterName">parameter name this rule applies to</param>
 /// <param name="occuranceIndex">occurnace index this rule applies to, or -1 to apply to every occurance of the parameter name</param>
 /// <param name="pattern">pattern</param>
 /// <returns><paramref name="qualifier"/></returns>
 public static ILineQualifier Rule(this ILineQualifier qualifier, string parameterName, int occuranceIndex, Regex pattern)
 {
     qualifier.Add(new LineParameterQualifier.Regex(parameterName, occuranceIndex, pattern));
     return(qualifier);
 }
示例#8
0
 /// <summary>
 /// Qualifier by <paramref name="keyMatch"/>.
 ///
 /// If <see cref="ILinePatternMatch.Success"/> is false then return false.
 ///
 /// The whole <paramref name="keyMatch"/> is matched against every qualifier, if one disqualifies then returns false.
 /// </summary>
 /// <param name="qualifier"></param>
 /// <param name="keyMatch">(optional) </param>
 /// <returns>true if line is qualified, false if disqualified</returns>
 public static bool Qualify(this ILineQualifier qualifier, ILinePatternMatch keyMatch)
 => keyMatch != null && keyMatch.Success && qualifier.Qualify(keyMatch.ToLine());
 /// <summary>
 /// Put all argument parts to <paramref name="list"/> with parameter occurance.
 ///
 /// If <paramref name="argumentQualifier"/> is provided, then filters out non-qualified arguments.
 /// </summary>
 /// <param name="line">(optional) line to read parameters of</param>
 /// <param name="list">list to add parts in order of from tail to root</param>
 /// <param name="argumentQualifier">(optional) parameter qualifier that validates each parameter</param>
 /// <param name="pruneIneffectiveParameters">(optional) If true, removes parameters that are not effetive: a null value, or reoccurance of non-canonical key</param>
 /// <param name="parameterInfos">(optional) extra parameter infos, used by <paramref name="pruneIneffectiveParameters"/> feature to detect which parameters are non-canonical keys.</param>
 /// <returns>array of parameters</returns>
 public static void GetArgumentPartsWithOccurance <LIST>(this ILine line, ref LIST list, ILineQualifier argumentQualifier = null, bool pruneIneffectiveParameters = false, IParameterInfos parameterInfos = null) where LIST : IList <(ILineArgument, int)>
示例#10
0
        /// <summary>
        /// Create new string serializer
        /// </summary>
        /// <param name="escapeCharacters">list of characters that are to be escaped</param>
        /// <param name="escapeControlCharacters">Escape characters 0x00 - 0x1f</param>
        /// <param name="unescapeCharacters">list of characters that are to be unescaped</param>
        /// <param name="unescapeControlCharacters">Unescape tnab0f</param>
        /// <param name="lineAppender">line appender that can append <see cref="ILineParameter"/> and <see cref="ILineString"/></param>
        /// <param name="qualifier">(optional) qualifier</param>
        public LineFormat(string escapeCharacters, bool escapeControlCharacters, string unescapeCharacters, bool unescapeControlCharacters, ILineFactory lineAppender, ILineQualifier qualifier) : base(lineAppender, qualifier)
        {
            // Regex.Escape doen't work for brackets []
            //string escapeCharactersEscaped = Regex.Escape(escapeCharacters);
            string escapeCharactersEscaped = escapeCharacters.Select(c => c == ']' ? "\\]" : Regex.Escape("" + c)).Aggregate((a, b) => a + b);

            if (escapeControlCharacters)
            {
                LiteralEscape = new Regex("[" + escapeCharactersEscaped + "]|[\\x00-\\x1f]", opts);
            }
            else
            {
                LiteralEscape = new Regex("[" + escapeCharactersEscaped + "]", opts);
            }
            escapeChar = EscapeChar;

            string unescapeCharactersEscaped = unescapeCharacters.Select(c => c == ']' ? "\\]" : Regex.Escape("" + c)).Aggregate((a, b) => a + b);

            LiteralUnescape = new Regex(
                unescapeControlCharacters ?
                "\\\\([0abtfnrv" + unescapeCharactersEscaped + "]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})" :
                "\\\\[" + unescapeCharactersEscaped + "]"
                , opts);
            unescapeChar = UnescapeChar;
        }