// 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;
}
}
}
}