< Summary

Information
Class: MoreStructures.RecImmTrees.Conversions.FullyIterativeStringifier<T1, T2>
Assembly: MoreStructures
File(s): /home/runner/work/MoreStructures/MoreStructures/MoreStructures/RecImmTrees/Conversions/FullyIterativeStringifier.cs
Line coverage
100%
Covered lines: 40
Uncovered lines: 0
Coverable lines: 40
Total lines: 116
Line coverage: 100%
Branch coverage
100%
Covered branches: 20
Total branches: 20
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
get_StopIndentingLevel()100%1100%
get_PrependLevelAfterStopIndenting()100%1100%
.ctor(...)100%1100%
Stringify(...)100%6100%
Stringify(...)100%10100%
Stringify(...)100%4100%

File(s)

/home/runner/work/MoreStructures/MoreStructures/MoreStructures/RecImmTrees/Conversions/FullyIterativeStringifier.cs

#LineLine coverage
 1namespace MoreStructures.RecImmTrees.Conversions;
 2
 3/// <summary>
 4///     <inheritdoc/>
 5///     <br/>
 6///     Iterative implementation.
 7/// </summary>
 8/// <typeparam name="TEdge">The type of edges of the specific structure.</typeparam>
 9/// <typeparam name="TNode">The type of nodes of the specific structure.</typeparam>
 10/// <remarks>
 11///     <inheritdoc cref="IStringifier{TEdge, TNode}" path="/remarks"/>
 12///     <para id="advantages">
 13///     ADVANTAGES AND DISADVANTAGES
 14///     <br/>
 15///     <inheritdoc cref="DocFragments" path="/remarks/para[@id='fully-iterative-advantages']"/>
 16///     </para>
 17/// </remarks>
 18public class FullyIterativeStringifier<TEdge, TNode>
 19    : StringifierBase<TEdge, TNode>, IStringifier<TEdge, TNode>
 20    where TEdge : IRecImmDictIndexedTreeEdge<TEdge, TNode>
 21    where TNode : IRecImmDictIndexedTreeNode<TEdge, TNode>
 22{
 23    /// <summary>
 24    /// The maximum level at which indentation should not be done anymore. Default is <see cref="int.MaxValue"/>.
 25    /// </summary>
 26    /// <remarks>
 27    ///     <para id="complexity">
 28    ///     COMPLEXITY
 29    ///     <br/>
 30    ///     - When trying to render a very deep structure to string, the resulting string can become extremely big due
 31    ///       to indentation.
 32    ///       <br/>
 33    ///     - This can easily happen with structures like <see cref="SuffixTries.SuffixTrieNode"/>. Less with
 34    ///       <see cref="SuffixTrees.SuffixTreeNode"/>, due to their coalescing of paths of nodes with single child.
 35    ///       <br/>
 36    ///     - For example if the structure is a linear chain of n in depth, 4 chars of indentation per line would yield
 37    ///       a string of 2n(n-1) chars = O(n^2).
 38    ///       <br/>
 39    ///     - For n = 10000 nodes the produced string would be ~ 200M.
 40    ///       <br/>
 41    ///     - To avoid that <see cref="StopIndentingLevel"/> can be set to a constant c, limiting the size of the
 42    ///       resulting string by an upper bound of cn = O(n).
 43    ///       <br/>
 44    ///     - For n = 10000 nodes and c = 10 levels the produced string would be 100K.
 45    ///     </para>
 46    /// </remarks>
 1104547    public int StopIndentingLevel { get; set; } = int.MaxValue;
 48
 49    /// <summary>
 50    /// Whether the actual level should be prepended to the line, once the maximum level of indentation defined at
 51    /// <see cref="StopIndentingLevel"/> has been reached. Default is <see langword="true"/>.
 52    /// </summary>
 1104353    public bool PrependLevelAfterStopIndenting { get; set; } = true;
 54
 55    /// <inheritdoc path="//*[not(self::remarks)]"/>
 56    /// <inheritdoc cref="FullyIterativeStringifier{TEdge, TNode}" path="/remarks"/>
 57    public FullyIterativeStringifier(
 58        Func<TNode, string> rootStringifier, Func<TEdge, TNode, string> edgeAndNodeStringifier)
 2059        : base(rootStringifier, edgeAndNodeStringifier)
 2060    {
 2061    }
 62
 63    /// <inheritdoc path="//*[not(self::remarks)]"/>
 64    /// <inheritdoc cref="FullyIterativeStringifier{TEdge, TNode}" path="/remarks"/>
 65    public override string Stringify(TNode node)
 16566    {
 16567        var stringBuilder = new StringBuilder();
 16568        stringBuilder.Append(RootStringifier(node));
 69
 16570        var stack = new Stack<(TEdge edge, TNode node, int level)> { };
 216671        foreach (var (childEdge, childNode) in node.Children.OrderByDescending(c => c.Key))
 55772            stack.Push((childEdge, childNode, 1));
 73
 1118474        while (stack.Count > 0)
 1101975            Stringify(stringBuilder, stack);
 16576        return stringBuilder.ToString();
 16577    }
 78
 79    private void Stringify(StringBuilder stringBuilder, Stack<(TEdge edge, TNode node, int level)> stack)
 1101980    {
 1101981        var (edge, node, level) = stack.Pop();
 82
 1101983        stringBuilder.Append(NewLine);
 1101984        var indentationDepth = Math.Min(StopIndentingLevel, level);
 10003523685        for (int i = 0; i < indentationDepth; i++)
 5000659986            stringBuilder.Append(Indent);
 1101987        if (PrependLevelAfterStopIndenting && level != indentationDepth)
 888            stringBuilder.Append($"[level {level}]");
 89
 1101990        stringBuilder.Append(EdgeAndNodeStringifier(edge, node));
 91
 6444392        foreach (var (childEdge, childNode) in node.Children.OrderByDescending(c => c.Key))
 1046293            stack.Push((childEdge, childNode, level + 1));
 1101994    }
 95
 96    /// <inheritdoc path="//*[not(self::remarks)]"/>
 97    /// <inheritdoc cref="FullyIterativeStringifier{TEdge, TNode}" path="/remarks"/>
 98    public override string Stringify(TreePath<TEdge, TNode> path)
 999    {
 9100        if (!path.PathNodes.Any())
 2101            return string.Empty;
 102
 7103        var stringBuilder = new StringBuilder();
 104
 7105        var (firstEdge, firstNode) = path.PathNodes.First();
 7106        stringBuilder.Append(EdgeAndNodeStringifier(firstEdge, firstNode));
 107
 75108        foreach (var (edge, node) in path.PathNodes.Skip(1))
 27109        {
 27110            stringBuilder.Append(PathSeparator);
 27111            stringBuilder.Append(EdgeAndNodeStringifier(edge, node));
 27112        }
 113
 7114        return stringBuilder.ToString();
 9115    }
 116}