Initial commit
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user