From fbe6ab7f4ec19ad7d17bb78cc525d5e27d245bbb Mon Sep 17 00:00:00 2001 From: DeadlySurprise Date: Fri, 21 Nov 2014 15:11:45 +0100 Subject: [PATCH] Fixed yaml bug with leading spaces --- OpenRA.Game/Map/Map.cs | 2 +- OpenRA.Game/Map/MapCache.cs | 2 + OpenRA.Game/MiniYaml.cs | 59 +++++++++++++++++++------ OpenRA.Game/Platform.cs | 2 + OpenRA.Test/OpenRA.Game/MiniYamlTest.cs | 38 ++++++++++++++++ 5 files changed, 88 insertions(+), 15 deletions(-) diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 5efc58fe10..db7c598f93 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -262,7 +262,7 @@ namespace OpenRA AssertExists("map.yaml"); AssertExists("map.bin"); - var yaml = new MiniYaml(null, MiniYaml.FromStream(Container.GetContent("map.yaml"))); + var yaml = new MiniYaml(null, MiniYaml.FromStream(Container.GetContent("map.yaml"), path)); FieldLoader.Load(this, yaml); // Support for formats 1-3 dropped 2011-02-11. diff --git a/OpenRA.Game/Map/MapCache.cs b/OpenRA.Game/Map/MapCache.cs index 2330152b68..7578308760 100644 --- a/OpenRA.Game/Map/MapCache.cs +++ b/OpenRA.Game/Map/MapCache.cs @@ -60,6 +60,8 @@ namespace OpenRA { Console.WriteLine("Failed to load map: {0}", path); Console.WriteLine("Details: {0}", e); + Log.Write("Debug", "Failed to load map: {0}", path); + Log.Write("Debug", "Details: {0}", e); } } } diff --git a/OpenRA.Game/MiniYaml.cs b/OpenRA.Game/MiniYaml.cs index 639d963baa..ee4381e145 100755 --- a/OpenRA.Game/MiniYaml.cs +++ b/OpenRA.Game/MiniYaml.cs @@ -83,20 +83,20 @@ namespace OpenRA public class MiniYaml { - static readonly Func StringIdentity = s => s; - static readonly Func MiniYamlIdentity = my => my; - + const int SpacesPerLevel = 4; + static Func stringIdentity = s => s; + static Func miniYamlIdentity = my => my; public string Value; public List Nodes; public Dictionary ToDictionary() { - return ToDictionary(MiniYamlIdentity); + return ToDictionary(miniYamlIdentity); } public Dictionary ToDictionary(Func elementSelector) { - return ToDictionary(StringIdentity, elementSelector); + return ToDictionary(stringIdentity, elementSelector); } public Dictionary ToDictionary( @@ -154,13 +154,44 @@ namespace OpenRA { var line = ll; ++lineNo; - var commentIndex = line.IndexOf('#'); - if (commentIndex != -1) - line = line.Substring(0, commentIndex).TrimEnd(' ', '\t'); - var t = line.TrimStart(' ', '\t'); + + if (line.Contains('#')) + line = line.Substring(0, line.IndexOf('#')).TrimEnd(' ', '\t'); + if (line.Length == 0) + continue; + var cp = 0; + var level = 0; + var spaces = 0; + var textStart = false; + var c = line[cp]; + while (!(c == '\n' || c == '\r') && cp < line.Length && !textStart) + { + c = line[cp]; + switch (c) + { + case ' ': + spaces++; + if (spaces >= SpacesPerLevel) + { + spaces = 0; + level++; + } + + cp++; + break; + case '\t': + level++; + cp++; + break; + default: + textStart = true; + break; + } + } + + var t = line.Substring(cp); if (t.Length == 0) continue; - var level = line.Length - t.Length; var location = new MiniYamlNode.SourceLocation { Filename = filename, Line = lineNo }; if (levels.Count <= level) @@ -211,15 +242,15 @@ namespace OpenRA return FromLines(File.ReadAllLines(path), path); } - public static List FromStream(Stream s) + public static List FromStream(Stream s, string fileName = "") { using (var reader = new StreamReader(s)) - return FromString(reader.ReadToEnd()); + return FromString(reader.ReadToEnd(), fileName); } - public static List FromString(string text) + public static List FromString(string text, string fileName = "") { - return FromLines(text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries), ""); + return FromLines(text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries), fileName); } public static List MergeLiberal(List a, List b) diff --git a/OpenRA.Game/Platform.cs b/OpenRA.Game/Platform.cs index 06741d2e1f..de72f717ed 100644 --- a/OpenRA.Game/Platform.cs +++ b/OpenRA.Game/Platform.cs @@ -98,6 +98,8 @@ namespace OpenRA /// Replace special character prefixes with full paths public static string ResolvePath(string path) { + path = path.TrimEnd(new char[] { ' ', '\t' }); + // paths starting with ^ are relative to the support dir if (path.StartsWith("^")) path = SupportDir + path.Substring(1); diff --git a/OpenRA.Test/OpenRA.Game/MiniYamlTest.cs b/OpenRA.Test/OpenRA.Game/MiniYamlTest.cs index 0f41361666..4eb7c3c6ec 100644 --- a/OpenRA.Test/OpenRA.Game/MiniYamlTest.cs +++ b/OpenRA.Test/OpenRA.Game/MiniYamlTest.cs @@ -26,12 +26,40 @@ namespace OpenRA.Test FromParent: FromParentRemove: "; + readonly string yamlForChild = @" Child: Inherits: ^Parent FromChild: -FromParentRemove: "; + + readonly string yamlTabStyle = @" +Root1: + Child1: + Attribute1: Test + Attribute2: Test + Child2: + Attribute1: Test + Attribute2: Test +Root2: + Child1: + Attribute1: Test +"; + + readonly string yamlMixedStyle = @" +Root1: + Child1: + Attribute1: Test + Attribute2: Test + Child2: + Attribute1: Test + Attribute2: Test +Root2: + Child1: + Attribute1: Test +"; + List parentList; List childList; MiniYaml parent; @@ -85,5 +113,15 @@ Child: Assert.That(res.Key, Is.EqualTo("Child")); InheritanceTest(res.Value.Nodes); } + + [TestCase(TestName = "Mixed tabs & spaces indents")] + public void TestIndents() + { + var tabs = MiniYaml.FromString(yamlTabStyle, "yamlTabStyle").WriteToString(); + Console.WriteLine(tabs); + var mixed = MiniYaml.FromString(yamlMixedStyle, "yamlMixedStyle").WriteToString(); + Console.WriteLine(mixed); + Assert.That(tabs, Is.EqualTo(mixed)); + } } }