82 lines
2.9 KiB
C#
82 lines
2.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using GameOfLife.Entities;
|
|
|
|
namespace GameOfLife.IO
|
|
{
|
|
public class RleDecoder
|
|
{
|
|
public Pattern Pattern { get; }
|
|
public PatternMetadata Metadata { get; }
|
|
|
|
public RleDecoder(string filename) : this(new FileInfo(filename)) { }
|
|
|
|
public RleDecoder(FileSystemInfo fi) : this(GetLines(fi)) { }
|
|
|
|
public RleDecoder(IEnumerable<string> encodedRle)
|
|
{
|
|
var groups =
|
|
(from line in encodedRle
|
|
let trimmed = line.Trim()
|
|
where
|
|
!string.IsNullOrEmpty(trimmed)
|
|
group line by line.StartsWith("#") into g
|
|
select g
|
|
).ToArray();
|
|
|
|
var comments = groups.First(g => g.Key);
|
|
var nonComments = groups.First(g => !g.Key).ToArray();
|
|
|
|
Metadata = new RlePatternMetaData(nonComments.First(), comments);
|
|
var rleData = string.Join("", nonComments.Skip(1));
|
|
Pattern = Pattern.Extract(ExpandRle(rleData).ToArray());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns RLE encoded string into decoded expansion, breaking lines into an enumeration
|
|
/// </summary>
|
|
private static IEnumerable<string> ExpandRle(string rleData)
|
|
{
|
|
if (!rleData.Contains("!"))
|
|
throw new ArgumentException("RLE pattern did not contain terminating character '!'");
|
|
|
|
var encodedRle
|
|
= rleData.Substring(0, rleData.IndexOf("!", StringComparison.Ordinal));
|
|
|
|
var rleDecodingRegex = new Regex(@"(?<count>\d*)(?<char>[a-z$])");
|
|
|
|
var matches = rleDecodingRegex.Matches(encodedRle);
|
|
var decoded = string.Empty;
|
|
foreach (Match match in matches)
|
|
{
|
|
var countStr = match.Groups["count"].Value;
|
|
var count = string.IsNullOrEmpty(countStr) ? 1 : int.Parse(countStr);
|
|
var c = match.Groups["char"].Value.First();
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
switch (c)
|
|
{
|
|
case '$':
|
|
yield return decoded;
|
|
decoded = string.Empty;
|
|
break;
|
|
default:
|
|
decoded += c;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
yield return decoded;
|
|
}
|
|
|
|
private static IEnumerable<string> GetLines(FileSystemInfo fi)
|
|
{
|
|
if (!fi.Exists)
|
|
throw new FileNotFoundException(fi.FullName);
|
|
return File.ReadAllLines(fi.FullName);
|
|
}
|
|
}
|
|
} |