예제 #1
0
        void InsertNode(PathTreeNode node, PathTreeNode parentNode, PathTreeNode previousNode)
        {
            parentNode.ChildrenCount += 1;

            node.Parent = parentNode;
            if (previousNode == null)
            {
                // We're inserting at the beginning.
                node.Next             = parentNode.FirstChild;
                parentNode.FirstChild = node;
                return;
            }

            // We are appending inbetween other nodes
            var next = previousNode.Next;

            previousNode.Next = node;
            node.Previous     = previousNode;

            node.Next = next;
            if (next != null)
            {
                next.Previous = node;
            }
        }
예제 #2
0
        internal static (PathTreeNode root, PathTreeNode leaf) CreateSubTree(string path, int start)
        {
            PathTreeNode lastNode = null, rootNode = null;

            while (start < path.Length)
            {
                var nextSep = path.IndexOf(Path.DirectorySeparatorChar, start);
                int length  = nextSep == -1 ? path.Length - start : nextSep - start;

                if (length != 0)
                {
                    var node = new PathTreeNode(path, start, length);

                    if (lastNode != null)
                    {
                        lastNode.FirstChild    = node;
                        node.Parent            = lastNode;
                        lastNode.ChildrenCount = 1;
                    }
                    else
                    {
                        rootNode = node;
                    }

                    lastNode = node;
                }

                start = start + length + 1;
            }

            return(rootNode, lastNode);
        }
예제 #3
0
        bool IsDeadSubtree(PathTreeNode node)
        {
            // We do a DFS here, looking for any live node in a tree.
            // We know that leaves are live, so DFS works better here.
            var stack = new Stack <PathTreeNode>();

            stack.Push(node);

            while (stack.Count != 0)
            {
                node = stack.Pop();
                if (node.IsLive)
                {
                    return(false);
                }

                var child = node.FirstChild;

                while (child != null)
                {
                    stack.Push(child);
                    child = child.Next;
                }
            }
            return(true);
        }
예제 #4
0
 public PathTree()
 {
     rootNode = new PathTreeNode("", 0, 1);
     if (!Platform.IsWindows)
     {
         rootNode.FirstChild = new PathTreeNode("/", 0, 0)
         {
             Parent = rootNode,
         };
     }
 }
예제 #5
0
        bool TryFind(string path, out PathTreeNode result, out PathTreeNode parent, out PathTreeNode previousNode, out int lastIndex)
        {
            lastIndex = 0;

            parent = rootNode;
            var currentNode = parent.FirstChild;

            previousNode = null;

            while (currentNode != null)
            {
                int currentIndex     = path.IndexOf(Path.DirectorySeparatorChar, lastIndex);
                int comparisonResult = string.Compare(currentNode.FullPath, currentNode.Start, path, lastIndex, currentNode.Length);

                // We need to insert in this node's position.
                if (comparisonResult > 0)
                {
                    break;
                }

                // Keep searching.
                if (comparisonResult < 0)
                {
                    previousNode = currentNode;
                    currentNode  = currentNode.Next;
                    continue;
                }

                // We found this segment in the tree.
                lastIndex = currentIndex + 1;

                // We found the node already, register the ID.
                if (currentIndex == -1 || lastIndex == path.Length)
                {
                    result = currentNode;
                    return(true);
                }

                // We go to the first child of this segment and repeat the algorithm.
                parent       = currentNode;
                previousNode = null;
                currentNode  = parent.FirstChild;
            }

            result = null;
            return(false);
        }
예제 #6
0
        public static void Dump(this PathTreeNode rootNode)
        {
            var firstStack = new List <PathTreeNode> {
                rootNode
            };
            var childListStack = new List <List <PathTreeNode> > {
                firstStack
            };

            while (childListStack.Count > 0)
            {
                var childStack = childListStack[childListStack.Count - 1];

                if (childStack.Count == 0)
                {
                    childListStack.RemoveAt(childListStack.Count - 1);
                }
                else
                {
                    var tree = childStack[0];
                    childStack.RemoveAt(0);

                    string indent = "";
                    for (int i = 0; i < childListStack.Count - 1; i++)
                    {
                        indent += (childListStack[i].Count > 0) ? "|  " : "   ";
                    }

                    Console.WriteLine(indent + "+- " + tree.Segment);

                    if (tree.FirstChild != null)
                    {
                        var treeChildren = new List <PathTreeNode>();
                        var child        = tree.FirstChild;
                        while (child != null)
                        {
                            treeChildren.Add(child);
                            child = child.Next;
                        }
                        childListStack.Add(treeChildren);
                    }
                }
            }
        }
예제 #7
0
        public void CreateSubTree(string sep)
        {
            var path = MakePath("a", "b", "c") + sep;

            var(first, leaf) = PathTreeNode.CreateSubTree(path, 0);

            PathTreeNode a;

            if (Platform.IsWindows)
            {
                AssertPathTreeSubtree(first, "C:");
                Assert.AreEqual(1, first.ChildrenCount);
                a = first.FirstChild;
            }
            else
            {
                a = first;
            }

            AssertPathTreeSubtree(a, "a");
            Assert.AreEqual(1, a.ChildrenCount);

            var b = a.FirstChild;

            Assert.AreSame(a, b.Parent);
            AssertPathTreeSubtree(b, "b");
            Assert.AreEqual(1, b.ChildrenCount);

            var c = b.FirstChild;

            Assert.AreSame(b, c.Parent);
            AssertPathTreeSubtree(c, "c");
            Assert.AreEqual(0, c.ChildrenCount);
            Assert.AreSame(c, leaf);

            Assert.IsNull(c.FirstChild);

            void AssertPathTreeSubtree(PathTreeNode node, string segment)
            {
                Assert.AreEqual(segment, node.Segment);
                Assert.IsNull(node.Next);
                Assert.AreSame(node.FirstChild, node.LastChild);
            }
        }
예제 #8
0
        public PathTreeNode AddNode(string path, object id)
        {
            if (TryFind(path, out var result, out var parent, out var previousNode, out var lastIndex))
            {
                result.RegisterId(id);
                return(result);
            }

            // At this point, we need to create a new node.
            var(first, leaf) = PathTreeNode.CreateSubTree(path, lastIndex);
            if (id != null)
            {
                leaf.RegisterId(id);
            }

            InsertNode(first, parent, previousNode);

            return(leaf);
        }
예제 #9
0
 public void JustSlash()
 {
     var(node, leaf) = PathTreeNode.CreateSubTree(Path.DirectorySeparatorChar.ToString(), 0);
     Assert.IsNull(node);
     Assert.IsNull(leaf);
 }
예제 #10
0
 [TestCase(1)]         // Should not crash
 public void EmptySubTrie(int startIndex)
 {
     var(node, leaf) = PathTreeNode.CreateSubTree(string.Empty, startIndex);
     Assert.IsNull(node);
     Assert.IsNull(leaf);
 }