Skip to content

Commit 3a817fb

Browse files
committed
Handle inline comments during parsing instead of trying to preprocess lines
Fixes #40
1 parent 68d8406 commit 3a817fb

File tree

4 files changed

+83
-27
lines changed

4 files changed

+83
-27
lines changed

Sledge.Formats.Bsp.Tests/Sledge.Formats.Bsp.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net6.0</TargetFramework>
4+
<TargetFramework>net8.0</TargetFramework>
55
<Nullable>enable</Nullable>
66

77
<IsPackable>false</IsPackable>

Sledge.Formats.Bsp.Tests/TestEntitiesLump.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Generic;
22
using System.IO;
3+
using System.Text;
34
using Microsoft.VisualStudio.TestTools.UnitTesting;
45
using Sledge.Formats.Bsp.Lumps;
56

@@ -78,4 +79,63 @@ public void TestEntitiesKeyOrdering()
7879
Assert.AreEqual("test3", lump2[0].SortedKeyValues[2].Key);
7980
Assert.AreEqual("789", lump2[0].SortedKeyValues[2].Value);
8081
}
82+
83+
[TestMethod]
84+
public void TestEntitiesWithComments()
85+
{
86+
var data = """
87+
// comment1
88+
{
89+
"test1" "123"
90+
// "test2" "456"
91+
"com//ment" "val//ue"
92+
}
93+
// comment2
94+
""";
95+
using var ms = new MemoryStream();
96+
using var bw = new BinaryWriter(ms);
97+
bw.WriteFixedLengthString(Encoding.ASCII, data.Length, data);
98+
99+
ms.Position = 0;
100+
using var br = new BinaryReader(ms);
101+
var lump2 = new Entities();
102+
lump2.Read(br, new Blob { Offset = 0, Length = (int)ms.Length }, Version.Goldsource);
103+
104+
Assert.AreEqual(1, lump2.Count);
105+
Assert.AreEqual(2, lump2[0].KeyValues.Count);
106+
Assert.AreEqual("test1", lump2[0].SortedKeyValues[0].Key);
107+
Assert.AreEqual("123", lump2[0].SortedKeyValues[0].Value);
108+
Assert.AreEqual("com//ment", lump2[0].SortedKeyValues[1].Key);
109+
Assert.AreEqual("val//ue", lump2[0].SortedKeyValues[1].Value);
110+
}
111+
112+
[TestMethod]
113+
public void TestEntitiesWithDoubleSlashInKeyValue()
114+
{
115+
var lump = new Entities
116+
{
117+
new()
118+
{
119+
SortedKeyValues =
120+
{
121+
new KeyValuePair<string, string>("a//b", "c//d")
122+
}
123+
}
124+
};
125+
Assert.AreEqual(1, lump[0].KeyValues.Count);
126+
127+
using var ms = new MemoryStream();
128+
using var bw = new BinaryWriter(ms);
129+
lump.Write(bw, Version.Goldsource);
130+
131+
ms.Position = 0;
132+
using var br = new BinaryReader(ms);
133+
var lump2 = new Entities();
134+
lump2.Read(br, new Blob { Offset = 0, Length = (int)ms.Length }, Version.Goldsource);
135+
136+
Assert.AreEqual(1, lump2.Count);
137+
Assert.AreEqual(1, lump2[0].KeyValues.Count);
138+
Assert.AreEqual("a//b", lump2[0].SortedKeyValues[0].Key);
139+
Assert.AreEqual("c//d", lump2[0].SortedKeyValues[0].Value);
140+
}
81141
}

Sledge.Formats.Bsp/Lumps/Entities.cs

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,10 @@ public void Read(BinaryReader br, Blob blob, Version version)
2121
{
2222
var text = Encoding.ASCII.GetString(br.ReadBytes(blob.Length));
2323

24-
// Remove comments
25-
var cleaned = new StringBuilder();
26-
foreach (var line in text.Split('\n'))
27-
{
28-
var l = line;
29-
var idx = l.IndexOf("//", StringComparison.Ordinal);
30-
if (idx >= 0) l = l.Substring(0, idx);
31-
l = l.Trim();
32-
cleaned.Append(l).Append('\n');
33-
}
34-
35-
var data = cleaned.ToString();
36-
3724
Entity cur = null;
3825
int i;
3926
string key = null;
40-
for (i = 0; i < data.Length; i++)
27+
for (i = 0; i < text.Length; i++)
4128
{
4229
var token = GetToken();
4330
if (token == "{")
@@ -79,29 +66,38 @@ string GetToken()
7966
{
8067
if (!ScanToNonWhitespace()) return null;
8168

82-
if (data[i] == '{' || data[i] == '}')
69+
if (text[i] == '/' && i + 1 < text.Length && text[i + 1] == '/')
70+
{
71+
// Comment, find end of line and then skip whitespace again
72+
var idx = text.IndexOf('\n', i + 1);
73+
if (idx < 0) return null;
74+
i = idx + 1;
75+
if (!ScanToNonWhitespace()) return null;
76+
}
77+
78+
if (text[i] == '{' || text[i] == '}')
8379
{
8480
// Start/end entity
85-
return data[i].ToString();
81+
return text[i].ToString();
8682
}
8783

88-
if (data[i] == '"')
84+
if (text[i] == '"')
8985
{
9086
// Quoted string, find end quote
91-
var idx = data.IndexOf('"', i + 1);
87+
var idx = text.IndexOf('"', i + 1);
9288
if (idx < 0) return null;
93-
var tok = data.Substring(i + 1, idx - i - 1);
89+
var tok = text.Substring(i + 1, idx - i - 1);
9490
i = idx + 1;
9591
return tok;
9692
}
9793

98-
if (data[i] > 32)
94+
if (text[i] > 32)
9995
{
10096
// Not whitespace
10197
var s = "";
102-
while (data[i] > 32)
98+
while (text[i] > 32)
10399
{
104-
s += data[i++];
100+
s += text[i++];
105101
}
106102
return s;
107103
}
@@ -111,9 +107,9 @@ string GetToken()
111107

112108
bool ScanToNonWhitespace()
113109
{
114-
while (i < data.Length)
110+
while (i < text.Length)
115111
{
116-
if (data[i] == ' ' || data[i] == '\n') i++;
112+
if (text[i] == ' ' || text[i] == '\n') i++;
117113
else return true;
118114
}
119115

Sledge.Formats.Bsp/Sledge.Formats.Bsp.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
<RepositoryUrl>https://github.com/LogicAndTrick/sledge-formats</RepositoryUrl>
1212
<RepositoryType>Git</RepositoryType>
1313
<PackageTags>half-life quake valve bsp</PackageTags>
14-
<PackageReleaseNotes>Add ID to faces, add RawLightmapData to Lighmaps lump</PackageReleaseNotes>
15-
<Version>1.0.15</Version>
14+
<PackageReleaseNotes>Fix issue when entity keyvalues contain double forward slashes</PackageReleaseNotes>
15+
<Version>1.0.16</Version>
1616
</PropertyGroup>
1717

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

0 commit comments

Comments
 (0)