コード例 #1
0
        /// <summary>
        /// Clone <paramref name="line"/>.
        /// </summary>
        /// <param name="factory"></param>
        /// <param name="line"></param>
        /// <returns></returns>
        /// <exception cref="LineException">on append error</exception>
        public static ILine Clone(this ILineFactory factory, ILine line)
        {
            ILine result = null;
            StructList16 <ILine> args = new StructList16 <ILine>();

            for (ILine l = line; l != null; l = l.GetPreviousPart())
            {
                if (l is ILineArgument || l is ILineArgumentEnumerable)
                {
                    args.Add(l);
                }
            }
            for (int i = args.Count - 1; i >= 0; i--)
            {
                ILine l = args[i];
                if (l is ILineArgumentEnumerable enumr)
                {
                    foreach (ILineArgument args_ in enumr)
                    {
                        result = factory.Create(result, args_);
                    }
                }

                if (l is ILineArgument arg)
                {
                    result = factory.Create(result, arg);
                }
            }
            return(result);
        }
コード例 #2
0
        /// <summary>
        /// Clone <see cref="ILineKey"/> parts.
        /// </summary>
        /// <param name="line"></param>
        /// <param name="appender">(optional) appender to use for clone. If null uses the appender of <paramref name="line"/></param>
        /// <param name="parameterInfos">(optional) for checking which parameters are keys</param>
        /// <returns>clone of key parts</returns>
        /// <exception cref="LineException">If cloning failed.</exception>
        public static ILine CloneKey(this ILine line, ILineFactory appender = default, IParameterInfos parameterInfos = null)
        {
            if (appender == null)
            {
                appender = line.GetAppender();
            }
            ILine result = null;

            if (parameterInfos == null)
            {
                appender.TryGetParameterInfos(out parameterInfos);
            }

            StructList16 <ILine> args = new StructList16 <ILine>();

            for (ILine l = line; l != null; l = l.GetPreviousPart())
            {
                if (l is ILineArgument || l is ILineArgumentEnumerable)
                {
                    args.Add(l);
                }
            }

            for (int i = args.Count - 1; i >= 0; i--)
            {
                ILine l = args[i];
                if (l is ILineParameterEnumerable lineParameters)
                {
                    foreach (ILineParameter lineParameter in lineParameters)
                    {
                        if (lineParameter.IsCanonicalKey(parameterInfos))
                        {
                            result = appender.Create <ILineCanonicalKey, string, string>(result, lineParameter.ParameterName, lineParameter.ParameterValue);
                        }
                        else if (lineParameter.IsNonCanonicalKey(parameterInfos))
                        {
                            result = appender.Create <ILineNonCanonicalKey, string, string>(result, lineParameter.ParameterName, lineParameter.ParameterValue);
                        }
                    }
                }
                if (l is ILineParameter parameter)
                {
                    if (parameter.IsCanonicalKey(parameterInfos))
                    {
                        result = appender.Create <ILineCanonicalKey, string, string>(result, parameter.ParameterName, parameter.ParameterValue);
                    }
                    else if (parameter.IsNonCanonicalKey(parameterInfos))
                    {
                        result = appender.Create <ILineNonCanonicalKey, string, string>(result, parameter.ParameterName, parameter.ParameterValue);
                    }
                }
            }
            return(result ?? appender.Create <ILinePart>(null));
        }
コード例 #3
0
        /// <summary>
        /// Append <paramref name="right"/> to <paramref name="left"/>.
        /// </summary>
        /// <param name="factory"></param>
        /// <param name="left">part to append to</param>
        /// <param name="right"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        /// <exception cref="LineException">on append error</exception>
        public static bool TryConcat(this ILineFactory factory, ILine left, ILine right, out ILine result)
        {
            if (factory == null)
            {
                result = left; return(false);
            }
            ILine _result = left;
            StructList16 <ILine> _args = new StructList16 <ILine>();

            for (ILine l = right; l != null; l = l.GetPreviousPart())
            {
                if (l is ILineArgument || l is ILineArgumentEnumerable)
                {
                    _args.Add(l);
                }
            }
            for (int i = _args.Count - 1; i >= 0; i--)
            {
                ILine l = _args[i];
                if (l is ILineArgumentEnumerable enumr)
                {
                    foreach (ILineArgument args_ in enumr)
                    {
                        if (!factory.TryCreate(args_, out _result))
                        {
                            result = null; return(false);
                        }
                    }
                }


                if (l is ILineArgument args)
                {
                    if (!factory.TryCreate(args, out _result))
                    {
                        result = null; return(false);
                    }
                }
            }
            result = _result;
            return(false);
        }
コード例 #4
0
        /// <summary>
        /// Try to clone <paramref name="line"/>.
        /// </summary>
        /// <param name="factory"></param>
        /// <param name="line"></param>
        /// <param name="clone"></param>
        /// <returns></returns>
        public static bool TryClone(this ILineFactory factory, ILine line, out ILine clone)
        {
            if (factory == null)
            {
                clone = line; return(false);
            }
            ILine result = null;
            StructList16 <ILine> args = new StructList16 <ILine>();

            for (ILine l = line; l != null; l = l.GetPreviousPart())
            {
                if (l is ILineArgument || l is ILineArgumentEnumerable)
                {
                    args.Add(l);
                }
            }
            for (int i = args.Count - 1; i >= 0; i--)
            {
                ILine l = args[i];
                if (l is ILineArgumentEnumerable enumr)
                {
                    foreach (ILineArgument args_ in enumr)
                    {
                        if (!factory.TryCreate(result, args_, out result))
                        {
                            clone = default; return(false);
                        }
                    }
                }

                if (l is ILineArgument arg)
                {
                    if (!factory.TryCreate(result, args, out result))
                    {
                        clone = default; return(false);
                    }
                }
            }
            clone = result;
            return(true);
        }
コード例 #5
0
        /// <summary>
        /// Add an enumeration of key,value pairs. Each key will constructed a new node.
        ///
        /// If <paramref name="groupingRule"/> the nodes are laid out in the order occurance of name pattern parts.
        ///
        /// For example grouping pattern "{Type}/{Culture}{anysection}{Key}" would order nodes as following:
        /// <code>
        ///  "type:MyController": {
        ///      "key:Success": "Success",
        ///      "culture:en:key:Success": "Success",
        ///  }
        /// </code>
        ///
        /// Non-capture parts such as "/" in pattern "{Section}/{Culture}", specify separator of tree node levels.
        ///
        /// </summary>
        /// <param name="tree"></param>
        /// <param name="lines"></param>
        /// <param name="groupingRule"></param>
        /// <param name="parameterInfos"></param>
        /// <returns></returns>
        public static ILineTree AddRange(this ILineTree tree, IEnumerable <ILine> lines, ILinePattern groupingRule, IParameterInfos parameterInfos) // Todo separate to sortRule + groupingRule
        {
            // Use another method
            //if (groupingRule == null) { node.AddRange(lines); return node; }
            StructList16 <ILineParameter> parameters = new StructList16 <ILineParameter>(null);

            foreach (var line in lines)
            {
                parameters.Clear();
                line.GetParameterParts(ref parameters);
                parameterListSorter.Reverse(ref parameters);

                // Key for the current level.
                ILine levelKey = null;
                // Build levels with this collection
                List <ILine> key_levels = new List <ILine>();
                // Visit both lists concurrently
                ILineParameter next_parameter = default;
                if (groupingRule != null)
                {
                    foreach (var part in groupingRule.AllParts)
                    {
                        // Is not a capture part
                        if (part.CaptureIndex < 0)
                        {
                            // Non-capture part has "/", go to next level. eg. "{nn}/{nn}"
                            if (part.Text != null && part.Text.Contains("/"))
                            {
                                if (levelKey != null)
                                {
                                    key_levels.Add(levelKey);
                                }
                                levelKey = null;
                            }
                            // Next part
                            continue;
                        }
                        // Capture part has "/" in prefix, start next level
                        if (levelKey != null && part.PrefixSeparator.Contains("/"))
                        {
                            if (levelKey != null)
                            {
                                key_levels.Add(levelKey);
                            }
                            levelKey = null;
                        }

                        // Look ahead to see if there is a parameter that matches this capture part
                        int next_parameter_ix = -1;
                        for (int ix = 0; ix < parameters.Count; ix++)
                        {
                            // Copy
                            next_parameter = parameters[ix];
                            // Already added before
                            if (next_parameter.ParameterName == null)
                            {
                                continue;
                            }
                            // Get name
                            string parameter_name = next_parameter.ParameterName;
                            // Parameter matches the name in the pattern's capture part
                            if (parameter_name == part.ParameterName)
                            {
                                next_parameter_ix = ix; break;
                            }
                            // Matches with "anysection"
                            //IParameterInfo info;
                            //if (part.ParameterName == "anysection" && ParameterInfos.Default.TryGetValue(parameter_name, out info) && info.IsSection) { next_parameter_ix = ix; break; }
                        }
                        // No matching parameter for this capture part
                        if (next_parameter_ix < 0)
                        {
                            continue;
                        }

                        // This part is canonical, hint, or parameter.
                        if (!next_parameter.IsNonCanonicalKey(parameterInfos))
                        {
                            // There (may be) are other canonical parts between part_ix and next_part_is. We have to add them here.
                            for (int ix = 0; ix < next_parameter_ix; ix++)
                            {
                                // Copy
                                ILineParameter parameter = parameters[ix];
                                // Has been added before
                                if ((parameter.ParameterName == null) || parameter.IsNonCanonicalKey(parameterInfos))
                                {
                                    continue;
                                }
                                // Append to level's key
                                levelKey = LineAppender.NonResolving.Create(levelKey, LineArgument.ToArgument(parameter));
                                // Mark handled
                                parameters[ix] = unused;
                            }
                        }
                        // Append to level's key
                        levelKey = LineAppender.NonResolving.Create(levelKey, LineArgument.ToArgument(next_parameter));
                        // Mark handled
                        parameters[next_parameter_ix] = unused;
                        // Yield level
                        if (part.PostfixSeparator.Contains("/"))
                        {
                            key_levels.Add(levelKey); levelKey = null;
                        }
                    }
                }

                // Append rest of the parameters
                for (int ix = 0; ix < parameters.Count; ix++)
                {
                    // Copy
                    ILineParameter parameter = parameters[ix];
                    if (parameter.ParameterName != null && parameter.ParameterName != "String")
                    {
                        levelKey = LineAppender.NonResolving.Create(levelKey, LineArgument.ToArgument(parameter));
                    }
                }

                // yield levelKey
                if (levelKey != null)
                {
                    key_levels.Add(levelKey); levelKey = null;
                }

                // Yield line
                tree.AddRecursive(key_levels, line.GetString());
                key_levels.Clear();
                parameters.Clear();
            }

            return(tree);
        }
コード例 #6
0
        /// <summary>
        /// Build key into a string.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string Print(ILine key)
        {
            // List for parts
            StructList16 <Part> parts = new StructList16 <Part>(Part.Comparer.Default);

            // Iterate key
            int occuranceIndex = 1;

            for (ILine part = key; part != null; part = part.GetPreviousPart())
            {
                if (part is ILineParameter parametrized)
                {
                    // Read parameter name and value
                    string parameterName = parametrized.ParameterName, parameterValue = part.GetParameterValue();
                    if (string.IsNullOrEmpty(parameterName) || parameterValue == null)
                    {
                        continue;
                    }

                    // Get description
                    _Rule desc = null;
                    if (parameters.TryGetValue(parameterName, out desc) && !desc.IsIncluded)
                    {
                        continue;
                    }

                    // Try default descriptions
                    if (desc == null && part is ILineCanonicalKey)
                    {
                        parameters.TryGetValue("canonical", out desc);
                    }
                    if (desc == null && part is ILineNonCanonicalKey)
                    {
                        parameters.TryGetValue("noncanonical", out desc);
                    }
                    if (desc == null)
                    {
                        parameters.TryGetValue("", out desc);
                    }

                    // No description
                    if (desc == null)
                    {
                        continue;
                    }

                    // This parameter is disabled
                    if (!desc.IsIncluded)
                    {
                        continue;
                    }

                    // Count occurance index
                    occuranceIndex--;

                    // Add to list
                    parts.Add(new Part {
                        ParameterName = parameterName, ParameterValue = parameterValue, Policy = desc, Order = desc.Order + occuranceIndex
                    });
                }
            }

            // Sort list
            sorter.Sort(ref parts);

            // Calculate char count
            int len = 0;

            for (int i = 0; i < parts.Count; i++)
            {
                len += parts[i].ParameterValue.Length;
                // Count in separator
                if (i > 0)
                {
                    string separator = parts[i - 1].Policy.PostfixSeparator;
                    if (separator != null)
                    {
                        len += separator.Length;
                    }
                    else
                    {
                        separator = parts[i].Policy.PrefixSeparator;
                        if (separator != null)
                        {
                            len += separator.Length;
                        }
                    }
                }
            }
            // Put together a string
            char[] chars = new char[len];
            int    ix    = 0;

            for (int i = 0; i < parts.Count; i++)
            {
                string s;
                // Add separator
                if (i > 0)
                {
                    s = parts[i - 1].Policy.PostfixSeparator;
                    if (s != null)
                    {
                        s.CopyTo(0, chars, ix, s.Length);
                        ix += s.Length;
                    }
                    else
                    {
                        s = parts[i].Policy.PrefixSeparator;
                        if (s != null)
                        {
                            s.CopyTo(0, chars, ix, s.Length);
                            ix += s.Length;
                        }
                    }
                }

                // Add text
                s = parts[i].ParameterValue;
                s.CopyTo(0, chars, ix, s.Length);
                ix += s.Length;
            }

            return(new string(chars));
        }
コード例 #7
0
        /// <summary>
        /// Concatenate <paramref name="right"/> to <paramref name="left"/>.
        /// </summary>
        /// <param name="factory"></param>
        /// <param name="left">part to append to</param>
        /// <param name="right"></param>
        /// <returns></returns>
        /// <exception cref="LineException">on append error</exception>
        public static ILine ConcatIfNew(this ILineFactory factory, ILine left, ILine right)
        {
            ILine result = left;

            KeyValuePair <string, string>[] parameters = null;

            StructList16 <ILine> _args = new StructList16 <ILine>();

            for (ILine l = right; l != null; l = l.GetPreviousPart())
            {
                if (l is ILineArgument || l is ILineArgumentEnumerable)
                {
                    _args.Add(l);
                }
            }
            for (int i = _args.Count - 1; i >= 0; i--)
            {
                ILine l = _args[i];
                if (l is ILineArgumentEnumerable enumr)
                {
                    foreach (ILineArgument args_ in enumr)
                    {
                        if (args_ is ILineArgument <ILineParameter, string, string> paramArgs && ContainsParameter(paramArgs.Argument0, paramArgs.Argument1))
                        {
                            continue;
                        }
                        if (args_ is ILineArgument <ILineNonCanonicalKey, string, string> paramArgs_ && ContainsParameter(paramArgs_.Argument0, paramArgs_.Argument1))
                        {
                            continue;
                        }
                        if (args_ is ILineArgument <ILineCanonicalKey, string, string> paramArgs__ && ContainsParameter(paramArgs__.Argument0, paramArgs__.Argument1))
                        {
                            continue;
                        }
                        result = factory.Create(result, args_);
                    }
                }

                if (l is ILineArgument args)
                {
                    if (args is ILineArgument <ILineParameter, string, string> paramArgs && ContainsParameter(paramArgs.Argument0, paramArgs.Argument1))
                    {
                        continue;
                    }
                    if (args is ILineArgument <ILineNonCanonicalKey, string, string> paramArgs_ && ContainsParameter(paramArgs_.Argument0, paramArgs_.Argument1))
                    {
                        continue;
                    }
                    if (args is ILineArgument <ILineCanonicalKey, string, string> paramArgs__ && ContainsParameter(paramArgs__.Argument0, paramArgs__.Argument1))
                    {
                        continue;
                    }
                    result = factory.Create(result, args);
                }
            }
            return(result);

            bool ContainsParameter(string parameterName, string parameterValue)
            {
                if (parameters == null)
                {
                    parameters = left.GetParameterAsKeyValues();
                }
                for (int i = 0; i < parameters.Length; i++)
                {
                    var p = parameters[i];
                    if (p.Key == parameterName && p.Value == parameterValue)
                    {
                        return(true);
                    }
                }
                return(false);
            }
        }