Skip to content

Commit

Permalink
Treat names and strings the same in the SerialisedObjectFormatter
Browse files Browse the repository at this point in the history
Fixes #41
  • Loading branch information
LogicAndTrick committed Jan 20, 2025
1 parent 3a817fb commit 3ec496e
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 8 deletions.
40 changes: 40 additions & 0 deletions Sledge.Formats.Tests/Valve/TestSerialisedObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,4 +211,44 @@ public void TestNestedObjectsWithQuotedNames()
Assert.AreEqual("Three", output[0].Children[0].Children[0].Name);
Assert.AreEqual("Value", output[0].Children[0].Children[0].Get<string>("Key"));
}

[TestMethod]
public void TestSpecialCharactersInKeyValues()
{
var input = """
One
{
$key1 "$value1"
$key2 $value2
!key3 &value3
!@#$%^&*()_+ value4
A B
"C" D
E "F"
"G" "H"
$I { }
"$J" { }
}
""";

using var stream = new MemoryStream(Encoding.UTF8.GetBytes(input));
var fmt = new SerialisedObjectFormatter();
var output = fmt.Deserialize(stream).ToList();

Assert.AreEqual(1, output.Count);
Assert.AreEqual("One", output[0].Name);
Assert.AreEqual("$value1", output[0].Get<string>("$key1"));
Assert.AreEqual("$value2", output[0].Get<string>("$key2"));
Assert.AreEqual("&value3", output[0].Get<string>("!key3"));
Assert.AreEqual("value4", output[0].Get<string>("!@#$%^&*()_+"));
Assert.AreEqual("B", output[0].Get<string>("A"));
Assert.AreEqual("D", output[0].Get<string>("C"));
Assert.AreEqual("F", output[0].Get<string>("E"));
Assert.AreEqual("H", output[0].Get<string>("G"));
Assert.AreEqual(2, output[0].Children.Count);
Assert.AreEqual("$I", output[0].Children[0].Name);
Assert.AreEqual(0, output[0].Children[0].Children.Count);
Assert.AreEqual("$J", output[0].Children[1].Name);
Assert.AreEqual(0, output[0].Children[1].Children.Count);
}
}
4 changes: 2 additions & 2 deletions Sledge.Formats/Sledge.Formats.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
<RepositoryUrl>https://github.com/LogicAndTrick/sledge-formats</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<PackageTags>half-life quake valve liblist vdf</PackageTags>
<PackageReleaseNotes>Additions to the IFileSystem interface</PackageReleaseNotes>
<PackageReleaseNotes>Fix parsing issues when serialised object keys/values are unquoted and contain special characters</PackageReleaseNotes>
<PackageLicenseFile></PackageLicenseFile>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Version>1.3.0</Version>
<Version>1.3.1</Version>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
Expand Down
25 changes: 19 additions & 6 deletions Sledge.Formats/Valve/SerialisedObjectFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using System.Text;
using Sledge.Formats.Tokens;
using Sledge.Formats.Tokens.Readers;

namespace Sledge.Formats.Valve
{
Expand Down Expand Up @@ -112,7 +113,23 @@ public static void Print(SerialisedObject obj, TextWriter tw, int tabs = 0)
Tokens.Symbols.CloseBrace
};

private static readonly Tokeniser Tokeniser = new Tokeniser(Symbols);
private static readonly Tokeniser Tokeniser;

static SerialisedObjectFormatter()
{
Tokeniser = new Tokeniser(
new SingleLineCommentTokenReader(),
new StringTokenReader(),
new UnsignedIntegerTokenReader(),
new SymbolTokenReader(Symbols),
new NameTokenReader(IsValidNameCharacter, IsValidNameCharacter)
);
}

private static bool IsValidNameCharacter(char c)
{
return c != '"' && c != '{' && c != '}' && !char.IsWhiteSpace(c) && !char.IsControl(c);
}

/// <summary>
/// Parse a structure from a stream
Expand Down Expand Up @@ -182,7 +199,7 @@ public static IEnumerable<SerialisedObject> Parse(TextReader reader)

break;
}
else if (t.Type == TokenType.String && it.Current.Type == TokenType.String)
else if (it.Current.Type == TokenType.String || it.Current.Type == TokenType.Name)
{
if (current == null) throw new TokenParsingException(t, "No structure to add key/values to");

Expand All @@ -192,10 +209,6 @@ public static IEnumerable<SerialisedObject> Parse(TextReader reader)

break;
}
else if (t.Type == TokenType.Name)
{
throw new TokenParsingException(t, "Expected structure open brace");
}
else
{
throw new TokenParsingException(t, "Expected string value or open brace to follow string key");
Expand Down

0 comments on commit 3ec496e

Please sign in to comment.