slight refactoring to prep for more array / pointer stuff. Added some insertion points as TODOs

This commit is contained in:
Benjamin Popp
2019-02-12 21:04:11 -06:00
parent 34fd89c243
commit cf828d06f1
4 changed files with 29 additions and 23 deletions

View File

@@ -253,14 +253,6 @@ namespace HavenSoft.HexManiac.Core.Models {
// replace / merge with existing
// if the only thing changed was the anchor, then don't change the format, just merge the anchor
var existingRun = runs[index];
if (existingRun is PointerRun pointerRun1) {
if (ReadValue(pointerRun1.Start) == 0) {
var name = sourceToUnmappedName[pointerRun1.Start];
sourceToUnmappedName.Remove(pointerRun1.Start);
unmappedNameToSources[name].Remove(pointerRun1.Start);
}
}
changeToken.RemoveRun(existingRun);
run = run.MergeAnchor(existingRun.PointerSources);
runs[index] = run;
@@ -285,6 +277,8 @@ namespace HavenSoft.HexManiac.Core.Models {
}
}
// TODO if run is array run, look for pointers in the array to link
if (run is NoInfoRun && run.PointerSources.Count == 0 && !anchorForAddress.ContainsKey(run.Start)) {
// this run has no useful information. Remove it.
changeToken.RemoveRun(runs[index]);
@@ -435,6 +429,8 @@ namespace HavenSoft.HexManiac.Core.Models {
}
ClearAnchorFormat(changeToken, originalStart, run);
// TODO if the run is an array run, look for pointers to unlink
if (alsoClearData) {
for (int i = 0; i < run.Length; i++) changeToken.ChangeData(this, run.Start + i, 0xFF);
}
@@ -668,10 +664,13 @@ namespace HavenSoft.HexManiac.Core.Models {
} else {
return new ErrorInfo($"Ascii runs must include a length.");
}
} else if (TryParse(model, format, dataIndex, null, out var arrayRun)) {
run = arrayRun;
} else if (format != string.Empty) {
return new ErrorInfo($"Format {format} was not understood.");
} else {
var errorInfo = TryParse(model, format, dataIndex, null, out var arrayRun);
if (errorInfo == ErrorInfo.NoError) {
run = arrayRun;
} else if (format != string.Empty) {
return new ErrorInfo($"Format {format} was not understood.");
}
}
return ErrorInfo.NoError;

View File

@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
namespace HavenSoft.HexManiac.Core.Models.Runs {
@@ -94,11 +95,11 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
owner = data;
FormatString = format;
var closeArray = format.LastIndexOf(ArrayEnd.ToString());
if (!format.StartsWith(ArrayStart.ToString()) || closeArray == -1) throw new FormatException($"Array Content must be wrapped in {ArrayStart}{ArrayEnd}.");
if (!format.StartsWith(ArrayStart.ToString()) || closeArray == -1) throw new ArrayRunParseException($"Array Content must be wrapped in {ArrayStart}{ArrayEnd}.");
var segments = format.Substring(1, closeArray - 1);
var length = format.Substring(closeArray + 1);
ElementContent = ParseSegments(segments);
if (ElementContent.Count == 0) throw new FormatException("Array Content must not be empty.");
if (ElementContent.Count == 0) throw new ArrayRunParseException("Array Content must not be empty.");
ElementLength = ElementContent.Sum(e => e.Length);
if (length.Length == 0) {
@@ -132,21 +133,21 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
Length = ElementLength * ElementCount;
}
public static bool TryParse(IDataModel data, string format, int start, IReadOnlyList<int> pointerSources, out ArrayRun self) {
public static ErrorInfo TryParse(IDataModel data, string format, int start, IReadOnlyList<int> pointerSources, out ArrayRun self) {
try {
self = new ArrayRun(data, format, start, pointerSources);
} catch {
} catch (ArrayRunParseException e) {
self = null;
return false;
return new ErrorInfo(e.Message);
}
return true;
return ErrorInfo.NoError;
}
public static bool TrySearch(IDataModel data, string format, out ArrayRun self) {
self = null;
var closeArray = format.LastIndexOf(ArrayEnd.ToString());
if (!format.StartsWith(ArrayStart.ToString()) || closeArray == -1) throw new FormatException($"Array Content must be wrapped in {ArrayStart}{ArrayEnd}");
if (!format.StartsWith(ArrayStart.ToString()) || closeArray == -1) throw new ArrayRunParseException($"Array Content must be wrapped in {ArrayStart}{ArrayEnd}");
var segments = format.Substring(1, closeArray - 1);
var length = format.Substring(closeArray + 1);
var elementContent = ParseSegments(segments);
@@ -208,6 +209,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
}
if (currentSegment.Type == ElementContentType.Pointer) {
// TODO display the pointer in red if it points to outside the data
var destination = data.ReadPointer(offsets.SegmentStart);
var destinationName = data.GetAnchorFromAddress(offsets.SegmentStart, destination);
return new Pointer(offsets.SegmentStart, index - offsets.SegmentStart, destination, destinationName);
@@ -261,7 +263,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
int nameEnd = 0;
while (nameEnd < segments.Length && char.IsLetterOrDigit(segments[nameEnd])) nameEnd++;
var name = segments.Substring(0, nameEnd);
if (name == string.Empty) throw new FormatException("expected name, but none was found: " + segments);
if (name == string.Empty) throw new ArrayRunParseException("expected name, but none was found: " + segments);
segments = segments.Substring(nameEnd);
var format = ElementContentType.Unknown;
int formatLength = 0;
@@ -283,7 +285,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
(format, formatLength, segmentLength) = (ElementContentType.Pointer, 2, 4);
}
if (format == ElementContentType.Unknown) throw new FormatException($"Could not parse format '{segments}'");
if (format == ElementContentType.Unknown) throw new ArrayRunParseException($"Could not parse format '{segments}'");
segments = segments.Substring(formatLength).Trim();
list.Add(new ArrayRunElementSegment(name, format, segmentLength));
}
@@ -339,4 +341,8 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
}
}
}
public class ArrayRunParseException : Exception {
public ArrayRunParseException(string message) : base(message) { }
}
}

View File

@@ -971,6 +971,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
if (fullValue == Pointer.NULL || (0 <= fullValue && fullValue < Model.Count)) {
Model.WritePointer(history.CurrentChange, index, fullValue);
if (!inArray) Model.ObserveRunWritten(history.CurrentChange, new PointerRun(index));
// TODO do something amazing here... we don't need to observe the run being written, but there's still pointer updates to be done
ClearEdits(point);
SilentScroll(index + 4);
} else {

View File

@@ -28,9 +28,9 @@ namespace HavenSoft.HexManiac.Tests {
[Fact]
public void ArrayElementsMustHaveNames() {
var model = new PokemonModel(new byte[0x200]);
var success = ArrayRun.TryParse(model, "[\"\"10]13", 12, null, out var arrayRun); // no name given for the format member
var errorInfo = ArrayRun.TryParse(model, "[\"\"10]13", 12, null, out var arrayRun); // no name given for the format member
Assert.False(success);
Assert.NotEqual(ErrorInfo.NoError, errorInfo);
}
[Fact]