// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. using System; using System.IO; namespace Flax.Stats { /// /// Represents single Code Frame captured to the file /// public sealed class CodeFrame : IDisposable { /// /// Root node for code frames /// public CodeFrameNode Root; /// /// Code frame date /// public DateTime Date; /// /// Capture code stats in current working directory /// /// Directory path to capture /// Created code frame public static CodeFrame Capture(string directory) { // Create code frame var frame = new CodeFrame(); // Create root node and all children frame.Root = CodeFrameNode.Capture(new DirectoryInfo(directory)); // Save capture time frame.Date = DateTime.Now; // Return result return frame; } /// /// Load code frame from the file /// /// Path of the file to load /// Loaded code frame public static CodeFrame Load(string path) { // Create and load var frame = new CodeFrame(); using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { frame.load(fs); } return frame; } private void load(Stream stream) { // Clear state if (Root != null) { Root.Dispose(); Root = null; } // Header if (stream.ReadInt() != 1032) { throw new FileLoadException("Invalid Code Frame file."); } // Version int version = stream.ReadInt(); // Switch version switch (version) { case 1: { // Read root node Root = loadNode1(stream); break; } case 2: { // Read date Date = stream.ReadDateTime(); // Read root node Root = loadNode1(stream); break; } case 3: { // Read date Date = stream.ReadDateTime(); // Read root node Root = loadNode3(stream); break; } case 4: { // Read date Date = stream.ReadDateTime(); // Read root node Root = loadNode4(stream); break; } default: throw new FileLoadException("Unknown Code Frame file version."); } // Ending char if(stream.ReadByte() != 99) { throw new FileLoadException("Code Frame file. is corrupted"); } } /// /// Save to the file /// /// File path public void Save(string path) { using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read)) { Save(fs); } } /// /// Save to the stream /// /// Stream to write to private void Save(Stream stream) { // Header stream.Write(1032); // Version stream.Write(4); // Date stream.Write(Date); // Write root node saveNode4(stream, Root); // Ending char stream.WriteByte(99); } #region Version 1 and 2 private void saveNode1(Stream stream, CodeFrameNode node) { // Save node data stream.Write(node.FilesCount); stream.Write(node.LinesOfCode[0]); stream.Write(node.LinesOfCode[1]); stream.WriteUTF8(node.ShortName, 13); stream.Write(node.SizeOnDisk); stream.Write(node.Children.Length); // Save all child nodes for (int i = 0; i < node.Children.Length; i++) { saveNode1(stream, node.Children[i]); } } private CodeFrameNode loadNode1(Stream stream) { // Load node data int files = stream.ReadInt(); long[] lines = { stream.ReadLong(), stream.ReadLong(), 0, 0 }; string name = stream.ReadStringUTF8(13); long size = stream.ReadLong(); int childrenCount = stream.ReadInt(); // Load all child nodes CodeFrameNode[] children = new CodeFrameNode[childrenCount]; for (int i = 0; i < childrenCount; i++) { children[i] = loadNode1(stream); } // Create node return new CodeFrameNode(name, files, lines, size, children); } #endregion #region Version 3 private void saveNode3(Stream stream, CodeFrameNode node) { // Save node data stream.Write(node.FilesCount); stream.Write(node.LinesOfCode[0]); stream.Write(node.LinesOfCode[1]); stream.Write(node.LinesOfCode[2]); stream.WriteUTF8(node.ShortName, 13); stream.Write(node.SizeOnDisk); stream.Write(node.Children.Length); // Save all child nodes for (int i = 0; i < node.Children.Length; i++) { saveNode3(stream, node.Children[i]); } } private CodeFrameNode loadNode3(Stream stream) { // Load node data int files = stream.ReadInt(); long[] lines = { stream.ReadLong(), stream.ReadLong(), stream.ReadLong(), 0, }; string name = stream.ReadStringUTF8(13); long size = stream.ReadLong(); int childrenCount = stream.ReadInt(); // Load all child nodes CodeFrameNode[] children = new CodeFrameNode[childrenCount]; for (int i = 0; i < childrenCount; i++) { children[i] = loadNode3(stream); } // Create node return new CodeFrameNode(name, files, lines, size, children); } #endregion #region Version 4 private void saveNode4(Stream stream, CodeFrameNode node) { // Save node data stream.Write(node.FilesCount); stream.Write(node.LinesOfCode[0]); stream.Write(node.LinesOfCode[1]); stream.Write(node.LinesOfCode[2]); stream.Write(node.LinesOfCode[3]); stream.WriteUTF8(node.ShortName, 13); stream.Write(node.SizeOnDisk); stream.Write(node.Children.Length); // Save all child nodes for (int i = 0; i < node.Children.Length; i++) { saveNode3(stream, node.Children[i]); } } private CodeFrameNode loadNode4(Stream stream) { // Load node data int files = stream.ReadInt(); long[] lines = { stream.ReadLong(), stream.ReadLong(), stream.ReadLong(), stream.ReadLong() }; string name = stream.ReadStringUTF8(13); long size = stream.ReadLong(); int childrenCount = stream.ReadInt(); // Load all child nodes CodeFrameNode[] children = new CodeFrameNode[childrenCount]; for (int i = 0; i < childrenCount; i++) { children[i] = loadNode3(stream); } // Create node return new CodeFrameNode(name, files, lines, size, children); } #endregion /// /// Clean all data /// public void Dispose() { // Dispose root if (Root != null) { Root.Dispose(); Root = null; } } } }