324 lines
8.8 KiB
C#
324 lines
8.8 KiB
C#
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
|
|
|
using System;
|
|
using System.IO;
|
|
|
|
namespace Flax.Stats
|
|
{
|
|
/// <summary>
|
|
/// Represents single Code Frame captured to the file
|
|
/// </summary>
|
|
public sealed class CodeFrame : IDisposable
|
|
{
|
|
/// <summary>
|
|
/// Root node for code frames
|
|
/// </summary>
|
|
public CodeFrameNode Root;
|
|
|
|
/// <summary>
|
|
/// Code frame date
|
|
/// </summary>
|
|
public DateTime Date;
|
|
|
|
/// <summary>
|
|
/// Capture code stats in current working directory
|
|
/// </summary>
|
|
/// <param name="directory">Directory path to capture</param>
|
|
/// <returns>Created code frame</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load code frame from the file
|
|
/// </summary>
|
|
/// <param name="path">Path of the file to load</param>
|
|
/// <returns>Loaded code frame</returns>
|
|
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");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Save to the file
|
|
/// </summary>
|
|
/// <param name="path">File path</param>
|
|
public void Save(string path)
|
|
{
|
|
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
|
|
{
|
|
Save(fs);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Save to the stream
|
|
/// </summary>
|
|
/// <param name="stream">Stream to write to</param>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Clean all data
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
// Dispose root
|
|
if (Root != null)
|
|
{
|
|
Root.Dispose();
|
|
Root = null;
|
|
}
|
|
}
|
|
}
|
|
}
|