public static void GenerateRangeUsageVisualization(TextWriter writer, PsbReader reader) { RangeUsageAnalyzer analyzer = new RangeUsageAnalyzer(); foreach (var node in reader.GenerateNameNodes().Values) { RegularNameNode regularNode = node as RegularNameNode; if (regularNode != null) { var regularChildren = regularNode.Children.Values.Where(x => x is RegularNameNode).OrderBy(x => x.Index); if (regularChildren.Count() > 0) { var minIndex = regularChildren.First().Index; var maxIndex = regularChildren.Last().Index; analyzer.AddRange(node.Index, minIndex, maxIndex, false); } var terminator = regularNode.Children.Values.Where(x => x is TerminalNameNode).FirstOrDefault(); if (terminator != null) { analyzer.AddRange(node.Index, terminator.Index, terminator.Index, false); } } else { analyzer.AddRange(node.Index, node.Index, node.Index, true); } } analyzer.OrderNodes(); analyzer.WriteVisualization(writer); }
static void WriteRange(IndentedTextWriter writer, NameNode node) { RegularNameNode regularNode = node as RegularNameNode; if (regularNode != null) { string line = $"{node.Index} {(char)node.Character} "; var regularChildren = regularNode.Children.Values.Where(x => x is RegularNameNode).OrderBy(x => x.Index); var terminator = regularNode.Children.Values.Where(x => x is TerminalNameNode).FirstOrDefault(); if (terminator != null) { line += $"[{terminator.Index}] "; } if (regularChildren.Count() > 0) { var minIndex = regularChildren.First().Index; var maxIndex = regularChildren.Last().Index; if (minIndex == maxIndex) { line += $"<{minIndex}> "; } else { line += $"<{minIndex} {maxIndex}> "; } } writer.WriteLine(line.Trim()); ++writer.Indent; foreach (var child in regularNode.Children.Values) { WriteRange(writer, child); } --writer.Indent; } }
public Dictionary <uint, NameNode> GenerateNodes() { if (tree == null) { throw new InvalidOperationException("Names are stored flat, not in a tree."); } Dictionary <uint, NameNode> nodes = new Dictionary <uint, NameNode>(); for (uint i = 0; i < tails.Length; ++i) { TerminalNameNode tailNode = new TerminalNameNode(); tailNode.Index = tails[i]; tailNode.TailIndex = i; // Quick check to ensure if (valueOffsets[tailNode.Index] != i) { throw new Exception(); } tailNode.ParentIndex = tree[tailNode.Index]; tailNode.Character = (byte)(tailNode.Index - valueOffsets[tailNode.ParentIndex]); nodes.Add(tailNode.Index, tailNode); uint parentIndex = tailNode.ParentIndex; while (!nodes.ContainsKey(parentIndex)) { RegularNameNode regularNode = new RegularNameNode(); regularNode.Index = parentIndex; regularNode.ParentIndex = tree[regularNode.Index]; regularNode.ValueOffset = valueOffsets[regularNode.Index]; if (regularNode.Index != 0) { regularNode.Character = (byte)(regularNode.Index - valueOffsets[regularNode.ParentIndex]); } nodes.Add(regularNode.Index, regularNode); parentIndex = regularNode.ParentIndex; } } // Link it up foreach (var node in nodes.Values) { if (node.Index != 0) { node.Parent = nodes[node.ParentIndex]; var parent = node.Parent as RegularNameNode; parent.Children.Add(node.Character, node); } } if (nodes.Count == 0) { // Create root node if we don't have any strings RegularNameNode regularNode = new RegularNameNode(); regularNode.Index = 0; regularNode.ParentIndex = tree[regularNode.Index]; regularNode.ValueOffset = valueOffsets[regularNode.Index]; nodes.Add(regularNode.Index, regularNode); } return(nodes); }