Skip to content

Commit

Permalink
Introduce separate (I)EDFLoaderService for loading EDF file content. …
Browse files Browse the repository at this point in the history
…Make IEDFFile immutable
  • Loading branch information
ethanmoffat committed Mar 12, 2022
1 parent fc1f1f7 commit 19384e4
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 73 deletions.
9 changes: 5 additions & 4 deletions EOLib.Localization/DataFileLoadActions.cs
Expand Up @@ -8,10 +8,13 @@ namespace EOLib.Localization
public class DataFileLoadActions : IDataFileLoadActions
{
private readonly IDataFileRepository _dataFileRepository;
private readonly IEDFLoaderService _edfLoaderService;

public DataFileLoadActions(IDataFileRepository dataFileRepository)
public DataFileLoadActions(IDataFileRepository dataFileRepository,
IEDFLoaderService edfLoaderService)
{
_dataFileRepository = dataFileRepository;
_edfLoaderService = edfLoaderService;
}

public void LoadDataFiles()
Expand All @@ -32,9 +35,7 @@ public void LoadDataFiles()
throw new DataFileLoadException();

var fileToLoad = (DataFiles)i;
var loadedFile = new EDFFile(files[i - 1], fileToLoad);

_dataFileRepository.DataFiles.Add(fileToLoad, loadedFile);
_dataFileRepository.DataFiles[fileToLoad] = _edfLoaderService.LoadFile(files[i - 1], fileToLoad);
}
}

Expand Down
93 changes: 24 additions & 69 deletions EOLib.Localization/EDFFile.cs
@@ -1,88 +1,43 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Collections.Generic;

namespace EOLib.Localization
{
public class EDFFile : IEDFFile
{
public Dictionary<int, string> Data { get; }
private readonly Dictionary<int, string> _data;

public EDFFile(string fileName, DataFiles whichFile)
{
if (!File.Exists(fileName))
throw new FileNotFoundException("File does not exist!", fileName);
public IReadOnlyDictionary<int, string> Data => _data;

Data = new Dictionary<int, string>();
public DataFiles WhichFile { get; private set; }

if (whichFile == DataFiles.CurseFilter)
{
string[] lines = File.ReadAllLines(fileName);
int i = 0;
foreach (string encoded in lines)
{
string decoded = _decodeDatString(encoded, whichFile);
string[] curses = decoded.Split(':');
foreach (string curse in curses)
Data.Add(i++, curse);
}
}
else
{
string[] lines = File.ReadAllLines(fileName, Encoding.Default);
int i = 0;
foreach (string encoded in lines)
Data.Add(i++, _decodeDatString(encoded, whichFile));
}
}
public EDFFile(DataFiles whichFile)
: this(whichFile, new Dictionary<int, string>()) { }

private string _decodeDatString(string input, DataFiles whichFile)
public EDFFile(DataFiles whichFile, Dictionary<int, string> data)
{
//unencrypted
if (whichFile == DataFiles.Credits || whichFile == DataFiles.Checksum)
return input;

string ret = "";

for (int i = 0; i < input.Length; i += 2)
ret += input[i];

//if there are an even number of characters start with the last one
//otherwise start with the second to last one
int startIndex = input.Length - (input.Length % 2 == 0 ? 1 : 2);
for (int i = startIndex; i >= 0; i -= 2)
ret += input[i];

if (whichFile == DataFiles.CurseFilter)
return ret;

StringBuilder sb = new StringBuilder(ret);

//adjacent ascii char values that are multiples of 7 should be flipped
for (int i = 0; i < sb.Length; ++i)
{
int next = i + 1;
if (next < sb.Length)
{
char c1 = sb[i], c2 = sb[next];
int ch1 = Convert.ToInt32(c1);
int ch2 = Convert.ToInt32(c2);
WhichFile = whichFile;
_data = data;
}

if (ch1 % 7 == 0 && ch2 % 7 == 0)
{
sb[i] = c2;
sb[next] = c1;
}
}
}
public IEDFFile WithDataEntry(int key, string data)
{
var copy = MakeCopy(this);
copy._data[key] = data;
return copy;
}

return sb.ToString();
private EDFFile MakeCopy(EDFFile input)
{
return new EDFFile(WhichFile, new Dictionary<int, string>(input._data));
}
}

public interface IEDFFile
{
Dictionary<int, string> Data { get; }
IReadOnlyDictionary<int, string> Data { get; }

DataFiles WhichFile { get; }

IEDFFile WithDataEntry(int key, string data);
}
}
1 change: 1 addition & 0 deletions EOLib.Localization/EOLib.Localization.csproj
Expand Up @@ -14,6 +14,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\EOLib.Config\EOLib.Config.csproj" />
<ProjectReference Include="..\EOLib.IO\EOLib.IO.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AutomaticTypeMapper" Version="1.4.1" />
Expand Down
125 changes: 125 additions & 0 deletions EOLib.Localization/Services/EDFLoaderService.cs
@@ -0,0 +1,125 @@
using AutomaticTypeMapper;
using EOLib.IO.Services;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace EOLib.Localization
{
[AutoMappedType]
public class EDFLoaderService : IEDFLoaderService
{
private readonly IDataEncoderService _dataEncoderService;

public EDFLoaderService(IDataEncoderService dataEncoderService)
{
_dataEncoderService = dataEncoderService;
}

public IEDFFile LoadFile(string fileName, DataFiles whichFile)
{
switch (whichFile)
{
case DataFiles.CurseFilter:
return LoadCurseFilter(fileName);
case DataFiles.Checksum:
case DataFiles.Credits:
return LoadUnencodedFile(fileName, whichFile);
default:
return LoadEncodedFile(fileName, whichFile);
}
}

public void SaveFile(string fileName, IEDFFile file)
{
switch(file.WhichFile)
{
case DataFiles.CurseFilter:
{
var data = string.Join(":", file.Data.Values);
var encoded = EncodeDatString(data, DataFiles.CurseFilter);
File.WriteAllText(fileName, encoded);
break;
}
case DataFiles.Checksum:
case DataFiles.Credits:
{
File.WriteAllLines(fileName, file.Data.Values.ToArray());
break;
}
default:
{
var data = file.Data.Values
.Select(x => EncodeDatString(x, file.WhichFile))
.ToArray();
File.WriteAllLines(fileName, data);
break;
}
}
}

private IEDFFile LoadCurseFilter(string fileName)
{
var data = new Dictionary<int, string>();
var lines = File.ReadAllLines(fileName);

var i = 0;
foreach (string encoded in lines)
{
string decoded = DecodeDatString(encoded, DataFiles.CurseFilter);
string[] curses = decoded.Split(':');
foreach (string curse in curses)
data.Add(i++, curse);
}

return new EDFFile(DataFiles.CurseFilter, data);
}

private IEDFFile LoadEncodedFile(string fileName, DataFiles whichFile)
{
var data = new Dictionary<int, string>();
var lines = File.ReadAllLines(fileName, Encoding.Default);

var i = 0;
foreach (string encoded in lines)
data.Add(i++, DecodeDatString(encoded, whichFile));

return new EDFFile(whichFile, data);
}

private IEDFFile LoadUnencodedFile(string fileName, DataFiles whichFile)
{
var data = new Dictionary<int, string>();
var lines = File.ReadAllLines(fileName, Encoding.Default);

var i = 0;
foreach (string decoded in lines)
data.Add(i++, decoded);

return new EDFFile(whichFile, data);
}

private string DecodeDatString(string content, DataFiles whichFile)
{
var res = _dataEncoderService.Deinterleave(Encoding.ASCII.GetBytes(content));

if (whichFile != DataFiles.CurseFilter)
res = _dataEncoderService.SwapMultiples(res, 7);

return Encoding.ASCII.GetString(res.ToArray());
}

private string EncodeDatString(string content, DataFiles whichFile)
{
List<byte> res = null;

if (whichFile != DataFiles.CurseFilter)
res = _dataEncoderService.SwapMultiples(res, 7);

res = _dataEncoderService.Interleave(res ?? Encoding.ASCII.GetBytes(content).ToList());

return Encoding.ASCII.GetString(res.ToArray());
}
}
}
9 changes: 9 additions & 0 deletions EOLib.Localization/Services/IEDFLoaderService.cs
@@ -0,0 +1,9 @@
namespace EOLib.Localization
{
public interface IEDFLoaderService
{
IEDFFile LoadFile(string fileName, DataFiles whichFile);

void SaveFile(string fileName, IEDFFile file);
}
}

0 comments on commit 19384e4

Please sign in to comment.