Skip to content

Commit

Permalink
Handle inline comments during parsing instead of trying to preprocess…
Browse files Browse the repository at this point in the history
… lines

Fixes #40
  • Loading branch information
LogicAndTrick committed Jan 4, 2025
1 parent 68d8406 commit 3a817fb
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 27 deletions.
2 changes: 1 addition & 1 deletion Sledge.Formats.Bsp.Tests/Sledge.Formats.Bsp.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
Expand Down
60 changes: 60 additions & 0 deletions Sledge.Formats.Bsp.Tests/TestEntitiesLump.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Sledge.Formats.Bsp.Lumps;

Expand Down Expand Up @@ -78,4 +79,63 @@ public void TestEntitiesKeyOrdering()
Assert.AreEqual("test3", lump2[0].SortedKeyValues[2].Key);
Assert.AreEqual("789", lump2[0].SortedKeyValues[2].Value);
}

[TestMethod]
public void TestEntitiesWithComments()
{
var data = """
// comment1
{
"test1" "123"
// "test2" "456"
"com//ment" "val//ue"
}
// comment2
""";
using var ms = new MemoryStream();
using var bw = new BinaryWriter(ms);
bw.WriteFixedLengthString(Encoding.ASCII, data.Length, data);

ms.Position = 0;
using var br = new BinaryReader(ms);
var lump2 = new Entities();
lump2.Read(br, new Blob { Offset = 0, Length = (int)ms.Length }, Version.Goldsource);

Assert.AreEqual(1, lump2.Count);
Assert.AreEqual(2, lump2[0].KeyValues.Count);
Assert.AreEqual("test1", lump2[0].SortedKeyValues[0].Key);
Assert.AreEqual("123", lump2[0].SortedKeyValues[0].Value);
Assert.AreEqual("com//ment", lump2[0].SortedKeyValues[1].Key);
Assert.AreEqual("val//ue", lump2[0].SortedKeyValues[1].Value);
}

[TestMethod]
public void TestEntitiesWithDoubleSlashInKeyValue()
{
var lump = new Entities
{
new()
{
SortedKeyValues =
{
new KeyValuePair<string, string>("a//b", "c//d")
}
}
};
Assert.AreEqual(1, lump[0].KeyValues.Count);

using var ms = new MemoryStream();
using var bw = new BinaryWriter(ms);
lump.Write(bw, Version.Goldsource);

ms.Position = 0;
using var br = new BinaryReader(ms);
var lump2 = new Entities();
lump2.Read(br, new Blob { Offset = 0, Length = (int)ms.Length }, Version.Goldsource);

Assert.AreEqual(1, lump2.Count);
Assert.AreEqual(1, lump2[0].KeyValues.Count);
Assert.AreEqual("a//b", lump2[0].SortedKeyValues[0].Key);
Assert.AreEqual("c//d", lump2[0].SortedKeyValues[0].Value);
}
}
44 changes: 20 additions & 24 deletions Sledge.Formats.Bsp/Lumps/Entities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,10 @@ public void Read(BinaryReader br, Blob blob, Version version)
{
var text = Encoding.ASCII.GetString(br.ReadBytes(blob.Length));

// Remove comments
var cleaned = new StringBuilder();
foreach (var line in text.Split('\n'))
{
var l = line;
var idx = l.IndexOf("//", StringComparison.Ordinal);
if (idx >= 0) l = l.Substring(0, idx);
l = l.Trim();
cleaned.Append(l).Append('\n');
}

var data = cleaned.ToString();

Entity cur = null;
int i;
string key = null;
for (i = 0; i < data.Length; i++)
for (i = 0; i < text.Length; i++)
{
var token = GetToken();
if (token == "{")
Expand Down Expand Up @@ -79,29 +66,38 @@ string GetToken()
{
if (!ScanToNonWhitespace()) return null;

if (data[i] == '{' || data[i] == '}')
if (text[i] == '/' && i + 1 < text.Length && text[i + 1] == '/')
{
// Comment, find end of line and then skip whitespace again
var idx = text.IndexOf('\n', i + 1);
if (idx < 0) return null;
i = idx + 1;
if (!ScanToNonWhitespace()) return null;
}

if (text[i] == '{' || text[i] == '}')
{
// Start/end entity
return data[i].ToString();
return text[i].ToString();
}

if (data[i] == '"')
if (text[i] == '"')
{
// Quoted string, find end quote
var idx = data.IndexOf('"', i + 1);
var idx = text.IndexOf('"', i + 1);
if (idx < 0) return null;
var tok = data.Substring(i + 1, idx - i - 1);
var tok = text.Substring(i + 1, idx - i - 1);
i = idx + 1;
return tok;
}

if (data[i] > 32)
if (text[i] > 32)
{
// Not whitespace
var s = "";
while (data[i] > 32)
while (text[i] > 32)
{
s += data[i++];
s += text[i++];
}
return s;
}
Expand All @@ -111,9 +107,9 @@ string GetToken()

bool ScanToNonWhitespace()
{
while (i < data.Length)
while (i < text.Length)
{
if (data[i] == ' ' || data[i] == '\n') i++;
if (text[i] == ' ' || text[i] == '\n') i++;
else return true;
}

Expand Down
4 changes: 2 additions & 2 deletions Sledge.Formats.Bsp/Sledge.Formats.Bsp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
<RepositoryUrl>https://github.com/LogicAndTrick/sledge-formats</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<PackageTags>half-life quake valve bsp</PackageTags>
<PackageReleaseNotes>Add ID to faces, add RawLightmapData to Lighmaps lump</PackageReleaseNotes>
<Version>1.0.15</Version>
<PackageReleaseNotes>Fix issue when entity keyvalues contain double forward slashes</PackageReleaseNotes>
<Version>1.0.16</Version>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
Expand Down

0 comments on commit 3a817fb

Please sign in to comment.