117 lines
2.6 KiB
C#
117 lines
2.6 KiB
C#
namespace MkvPropEditWrapper.MkvInfo;
|
|
|
|
public class MkvInfoReader
|
|
{
|
|
public const char LineDelimiter = '\n';
|
|
|
|
private readonly ReadOnlyMemory<char> _memory;
|
|
private ReadOnlyMemory<char> _remainingMemory;
|
|
|
|
private readonly MkvNodeRoot _root;
|
|
private MkvNode _currentNode;
|
|
|
|
private int _currentPosition;
|
|
|
|
public MkvInfoReader(string mkvInfoOutput)
|
|
{
|
|
_memory = mkvInfoOutput.AsMemory();
|
|
_remainingMemory = _memory;
|
|
|
|
_root = new MkvNodeRoot();
|
|
_currentNode = _root;
|
|
|
|
_currentPosition = 0;
|
|
}
|
|
|
|
public MkvNodeRoot Read()
|
|
{
|
|
if (_root.Children.Count > 0)
|
|
{
|
|
return _root;
|
|
}
|
|
|
|
while (_currentPosition < _memory.Length)
|
|
{
|
|
var line = ReadLine();
|
|
|
|
// Skip empty lines
|
|
if (line.Length < 1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ProcessLine(line);
|
|
}
|
|
|
|
return _root;
|
|
}
|
|
|
|
private void ProcessLine(ReadOnlyMemory<char> line)
|
|
{
|
|
var lineSpan = line.Span;
|
|
|
|
// Find depth
|
|
int depth = lineSpan.IndexOf('+');
|
|
|
|
// Climb up the node tree
|
|
while (depth <= _currentNode.Depth)
|
|
{
|
|
_currentNode = _currentNode.Parent!;
|
|
}
|
|
|
|
// Node content
|
|
var content = line[(depth + 2)..];
|
|
var contentSpan = content.Span;
|
|
|
|
// Check for property
|
|
int propertyIndex = contentSpan.IndexOf(':');
|
|
|
|
MkvNode node;
|
|
// Property node
|
|
if (propertyIndex != -1)
|
|
{
|
|
var name = content[..propertyIndex];
|
|
var value = content[(propertyIndex + 1)..];
|
|
|
|
node = new MkvProperty(_currentNode, name, value);
|
|
}
|
|
// Generic node
|
|
else
|
|
{
|
|
node = new MkvNode(_currentNode, content);
|
|
}
|
|
|
|
_currentNode.Children.Add(node);
|
|
|
|
_currentNode = node;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read in the span till next \n or EOF while incrementing _currentPosition
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private ReadOnlyMemory<char> ReadLine()
|
|
{
|
|
var remainingSpan = _remainingMemory.Span;
|
|
ReadOnlyMemory<char> line;
|
|
|
|
int index = remainingSpan.IndexOf(LineDelimiter);
|
|
|
|
// Reach the end
|
|
if (index == -1)
|
|
{
|
|
line = _remainingMemory;
|
|
_currentPosition = _memory.Length;
|
|
}
|
|
else
|
|
{
|
|
line = _remainingMemory[..(index - 1)]; // -1 to skip \r
|
|
_currentPosition += index + 1; // Skip \n
|
|
}
|
|
|
|
// Move forward in the span
|
|
_remainingMemory = _memory[_currentPosition..];
|
|
|
|
return line;
|
|
}
|
|
} |