Files
MkvLang/MkvToolnixWrapper/MkvInfo/MkvInfoReader.cs
2022-03-12 17:12:52 +01:00

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