Skip to content

Commit 9df59e2

Browse files
committed
Added support for serializing -0 floats
1 parent a93b492 commit 9df59e2

16 files changed

+141
-93
lines changed

FoxTool/ExtensionMethods.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Globalization;
23
using System.IO;
34
using System.Linq;
45
using FoxTool.Fox.Containers;
@@ -172,5 +173,24 @@ internal static string ToXmlName(this FoxDataType type)
172173
throw new ArgumentOutOfRangeException("type");
173174
}
174175
}
176+
177+
internal static string ToStringRoundtrip(this float value)
178+
{
179+
var bytes = BitConverter.GetBytes(value);
180+
if (value.Equals(0.0f) && bytes[BitConverter.IsLittleEndian ? 3 : 0] == 0x80)
181+
{
182+
return "-0";
183+
}
184+
return value.ToString("r", CultureInfo.InvariantCulture);
185+
}
186+
187+
internal static float ParseFloatRoundtrip(string text)
188+
{
189+
if (text == "-0")
190+
{
191+
return -0f;
192+
}
193+
return float.Parse(text, CultureInfo.InvariantCulture);
194+
}
175195
}
176196
}

FoxTool/Fox/Enums/FoxEnumValue.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ public FoxEnumValue(string name, int value)
99
}
1010

1111
public string Name { get; private set; }
12-
// TODO: Check if there are non int32 enums.
1312
public int Value { get; private set; }
1413
}
1514
}

FoxTool/Fox/FoxEntity.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ public void WriteXml(XmlWriter writer)
9494
writer.WriteAttributeString("class", ClassName);
9595
writer.WriteAttributeString("classVersion", Version.ToString());
9696
writer.WriteAttributeString("addr", String.Format("0x{0:X8}", Address));
97-
// TODO: Rename unknown attributes
9897
writer.WriteAttributeString("unknown", Unknown.ToString());
9998

10099

FoxTool/Fox/FoxStringLiteralBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public override bool Equals(object obj)
4545
if (ReferenceEquals(null, obj)) return false;
4646
if (ReferenceEquals(this, obj)) return true;
4747
if (obj.GetType() != GetType()) return false;
48-
return Equals((FoxStringLookupLiteral) (FoxStringLookupLiteral) obj);
48+
return Equals((FoxStringLookupLiteral) obj);
4949
}
5050

5151
public override int GetHashCode()
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System.Collections.Generic;
2+
3+
namespace FoxTool.Fox
4+
{
5+
public class FoxStringLiteralLookupTable
6+
{
7+
public FoxStringLiteralLookupTable()
8+
: this(new Dictionary<ulong, FoxStringLiteralBase>())
9+
{
10+
}
11+
12+
public FoxStringLiteralLookupTable(Dictionary<ulong, FoxStringLiteralBase> globalLookupTable)
13+
: this(globalLookupTable, new Dictionary<ulong, FoxStringLiteralBase>())
14+
{
15+
}
16+
17+
public FoxStringLiteralLookupTable(Dictionary<ulong, FoxStringLiteralBase> globalLookupTable,
18+
Dictionary<ulong, FoxStringLiteralBase> localLookupTable)
19+
{
20+
GlobalLookupTable = globalLookupTable;
21+
LocalLookupTable = localLookupTable;
22+
}
23+
24+
private Dictionary<ulong, FoxStringLiteralBase> GlobalLookupTable { get; set; }
25+
private Dictionary<ulong, FoxStringLiteralBase> LocalLookupTable { get; set; }
26+
27+
public FoxStringLiteralBase Lookup(ulong hash)
28+
{
29+
FoxStringLiteralBase result;
30+
if (LocalLookupTable.TryGetValue(hash, out result))
31+
return result;
32+
if (GlobalLookupTable.TryGetValue(hash, out result))
33+
return result;
34+
return null;
35+
}
36+
}
37+
}

FoxTool/Fox/FoxStringLookupLiteral.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ public FoxStringLookupLiteral()
1111

1212
public FoxStringLookupLiteral(FoxStringLiteralBase stringLiteral)
1313
{
14-
// TODO: Maybe create a factory method
1514
Literal = stringLiteral.Literal;
1615
Hash = stringLiteral.Hash;
1716
EncryptedLiteral = stringLiteral.EncryptedLiteral;

FoxTool/Fox/Types/Structs/FoxColor.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,21 @@ public override void CollectStringLookupLiterals(List<FoxStringLookupLiteral> li
5151
public override void ReadXml(XmlReader reader)
5252
{
5353
var isEmptyElement = reader.IsEmptyElement;
54-
Red = float.Parse(reader.GetAttribute("r"), CultureInfo.InvariantCulture);
55-
Green = float.Parse(reader.GetAttribute("g"), CultureInfo.InvariantCulture);
56-
Blue = float.Parse(reader.GetAttribute("b"), CultureInfo.InvariantCulture);
57-
Alpha = float.Parse(reader.GetAttribute("a"), CultureInfo.InvariantCulture);
54+
Red = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("r"));
55+
Green = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("g"));
56+
Blue = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("b"));
57+
Alpha = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("a"));
5858
reader.ReadStartElement("value");
5959
if (isEmptyElement == false)
6060
reader.ReadEndElement();
6161
}
6262

6363
public override void WriteXml(XmlWriter writer)
6464
{
65-
writer.WriteAttributeString("r", Red.ToString("r", CultureInfo.InvariantCulture));
66-
writer.WriteAttributeString("g", Green.ToString("r", CultureInfo.InvariantCulture));
67-
writer.WriteAttributeString("b", Blue.ToString("r", CultureInfo.InvariantCulture));
68-
writer.WriteAttributeString("a", Alpha.ToString("r", CultureInfo.InvariantCulture));
65+
writer.WriteAttributeString("r", Red.ToStringRoundtrip());
66+
writer.WriteAttributeString("g", Green.ToStringRoundtrip());
67+
writer.WriteAttributeString("b", Blue.ToStringRoundtrip());
68+
writer.WriteAttributeString("a", Alpha.ToStringRoundtrip());
6969
}
7070

7171
public override string ToString()

FoxTool/Fox/Types/Structs/FoxEntityLink.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ namespace FoxTool.Fox.Types.Structs
1010
public class FoxEntityLink : FoxStruct
1111
{
1212
public ulong EntityHandle { get; set; }
13-
// TODO: 3x StringLiteral
1413
private FoxStringLiteral PackagePathLiteral { get; set; }
1514
private FoxStringLiteral ArchivePathLiteral { get; set; }
1615
private FoxStringLiteral NameInArchiveLiteral { get; set; }

FoxTool/Fox/Types/Structs/FoxMatrix3.cs

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Collections.Generic;
2-
using System.Globalization;
32
using System.IO;
43
using System.Text;
54
using System.Xml;
@@ -69,17 +68,17 @@ public override void ReadXml(XmlReader reader)
6968
reader.ReadStartElement("value");
7069
if (isEmptyElement == false)
7170
{
72-
Row1Value1 = float.Parse(reader.GetAttribute("Column1"), CultureInfo.InvariantCulture);
73-
Row1Value2 = float.Parse(reader.GetAttribute("Column2"), CultureInfo.InvariantCulture);
74-
Row1Value3 = float.Parse(reader.GetAttribute("Column3"), CultureInfo.InvariantCulture);
71+
Row1Value1 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column1"));
72+
Row1Value2 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column2"));
73+
Row1Value3 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column3"));
7574
reader.ReadStartElement("Row1");
76-
Row2Value1 = float.Parse(reader.GetAttribute("Column1"), CultureInfo.InvariantCulture);
77-
Row2Value2 = float.Parse(reader.GetAttribute("Column2"), CultureInfo.InvariantCulture);
78-
Row2Value3 = float.Parse(reader.GetAttribute("Column3"), CultureInfo.InvariantCulture);
75+
Row2Value1 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column1"));
76+
Row2Value2 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column2"));
77+
Row2Value3 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column3"));
7978
reader.ReadStartElement("Row2");
80-
Row3Value1 = float.Parse(reader.GetAttribute("Column1"), CultureInfo.InvariantCulture);
81-
Row3Value2 = float.Parse(reader.GetAttribute("Column2"), CultureInfo.InvariantCulture);
82-
Row3Value3 = float.Parse(reader.GetAttribute("Column3"), CultureInfo.InvariantCulture);
79+
Row3Value1 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column1"));
80+
Row3Value2 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column2"));
81+
Row3Value3 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column3"));
8382
reader.ReadStartElement("Row3");
8483
reader.ReadEndElement();
8584
}
@@ -88,19 +87,19 @@ public override void ReadXml(XmlReader reader)
8887
public override void WriteXml(XmlWriter writer)
8988
{
9089
writer.WriteStartElement("Row1");
91-
writer.WriteAttributeString("Column1", Row1Value1.ToString("r", CultureInfo.InvariantCulture));
92-
writer.WriteAttributeString("Column2", Row1Value2.ToString("r", CultureInfo.InvariantCulture));
93-
writer.WriteAttributeString("Column3", Row1Value3.ToString("r", CultureInfo.InvariantCulture));
90+
writer.WriteAttributeString("Column1", Row1Value1.ToStringRoundtrip());
91+
writer.WriteAttributeString("Column2", Row1Value2.ToStringRoundtrip());
92+
writer.WriteAttributeString("Column3", Row1Value3.ToStringRoundtrip());
9493
writer.WriteEndElement();
9594
writer.WriteStartElement("Row2");
96-
writer.WriteAttributeString("Column1", Row2Value1.ToString("r", CultureInfo.InvariantCulture));
97-
writer.WriteAttributeString("Column2", Row2Value2.ToString("r", CultureInfo.InvariantCulture));
98-
writer.WriteAttributeString("Column3", Row2Value3.ToString("r", CultureInfo.InvariantCulture));
95+
writer.WriteAttributeString("Column1", Row2Value1.ToStringRoundtrip());
96+
writer.WriteAttributeString("Column2", Row2Value2.ToStringRoundtrip());
97+
writer.WriteAttributeString("Column3", Row2Value3.ToStringRoundtrip());
9998
writer.WriteEndElement();
10099
writer.WriteStartElement("Row3");
101-
writer.WriteAttributeString("Column1", Row3Value1.ToString("r", CultureInfo.InvariantCulture));
102-
writer.WriteAttributeString("Column2", Row3Value2.ToString("r", CultureInfo.InvariantCulture));
103-
writer.WriteAttributeString("Column3", Row3Value3.ToString("r", CultureInfo.InvariantCulture));
100+
writer.WriteAttributeString("Column1", Row3Value1.ToStringRoundtrip());
101+
writer.WriteAttributeString("Column2", Row3Value2.ToStringRoundtrip());
102+
writer.WriteAttributeString("Column3", Row3Value3.ToStringRoundtrip());
104103
writer.WriteEndElement();
105104
}
106105

FoxTool/Fox/Types/Structs/FoxMatrix4.cs

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Collections.Generic;
2-
using System.Globalization;
32
using System.IO;
43
using System.Text;
54
using System.Xml;
@@ -90,25 +89,25 @@ public override void ReadXml(XmlReader reader)
9089
reader.ReadStartElement("value");
9190
if (isEmptyElement == false)
9291
{
93-
Row1Value1 = float.Parse(reader.GetAttribute("Column1"), CultureInfo.InvariantCulture);
94-
Row1Value2 = float.Parse(reader.GetAttribute("Column2"), CultureInfo.InvariantCulture);
95-
Row1Value3 = float.Parse(reader.GetAttribute("Column3"), CultureInfo.InvariantCulture);
96-
Row1Value4 = float.Parse(reader.GetAttribute("Column4"), CultureInfo.InvariantCulture);
92+
Row1Value1 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column1"));
93+
Row1Value2 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column2"));
94+
Row1Value3 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column3"));
95+
Row1Value4 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column4"));
9796
reader.ReadStartElement("Row1");
98-
Row2Value1 = float.Parse(reader.GetAttribute("Column1"), CultureInfo.InvariantCulture);
99-
Row2Value2 = float.Parse(reader.GetAttribute("Column2"), CultureInfo.InvariantCulture);
100-
Row2Value3 = float.Parse(reader.GetAttribute("Column3"), CultureInfo.InvariantCulture);
101-
Row2Value4 = float.Parse(reader.GetAttribute("Column4"), CultureInfo.InvariantCulture);
97+
Row2Value1 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column1"));
98+
Row2Value2 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column2"));
99+
Row2Value3 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column3"));
100+
Row2Value4 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column4"));
102101
reader.ReadStartElement("Row2");
103-
Row3Value1 = float.Parse(reader.GetAttribute("Column1"), CultureInfo.InvariantCulture);
104-
Row3Value2 = float.Parse(reader.GetAttribute("Column2"), CultureInfo.InvariantCulture);
105-
Row3Value3 = float.Parse(reader.GetAttribute("Column3"), CultureInfo.InvariantCulture);
106-
Row3Value4 = float.Parse(reader.GetAttribute("Column4"), CultureInfo.InvariantCulture);
102+
Row3Value1 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column1"));
103+
Row3Value2 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column2"));
104+
Row3Value3 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column3"));
105+
Row3Value4 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column4"));
107106
reader.ReadStartElement("Row3");
108-
Row4Value1 = float.Parse(reader.GetAttribute("Column1"), CultureInfo.InvariantCulture);
109-
Row4Value2 = float.Parse(reader.GetAttribute("Column2"), CultureInfo.InvariantCulture);
110-
Row4Value3 = float.Parse(reader.GetAttribute("Column3"), CultureInfo.InvariantCulture);
111-
Row4Value4 = float.Parse(reader.GetAttribute("Column4"), CultureInfo.InvariantCulture);
107+
Row4Value1 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column1"));
108+
Row4Value2 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column2"));
109+
Row4Value3 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column3"));
110+
Row4Value4 = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("Column4"));
112111
reader.ReadStartElement("Row4");
113112
reader.ReadEndElement();
114113
}
@@ -117,28 +116,28 @@ public override void ReadXml(XmlReader reader)
117116
public override void WriteXml(XmlWriter writer)
118117
{
119118
writer.WriteStartElement("Row1");
120-
writer.WriteAttributeString("Column1", Row1Value1.ToString("r", CultureInfo.InvariantCulture));
121-
writer.WriteAttributeString("Column2", Row1Value2.ToString("r", CultureInfo.InvariantCulture));
122-
writer.WriteAttributeString("Column3", Row1Value3.ToString("r", CultureInfo.InvariantCulture));
123-
writer.WriteAttributeString("Column4", Row1Value4.ToString("r", CultureInfo.InvariantCulture));
119+
writer.WriteAttributeString("Column1", Row1Value1.ToStringRoundtrip());
120+
writer.WriteAttributeString("Column2", Row1Value2.ToStringRoundtrip());
121+
writer.WriteAttributeString("Column3", Row1Value3.ToStringRoundtrip());
122+
writer.WriteAttributeString("Column4", Row1Value4.ToStringRoundtrip());
124123
writer.WriteEndElement();
125124
writer.WriteStartElement("Row2");
126-
writer.WriteAttributeString("Column1", Row2Value1.ToString("r", CultureInfo.InvariantCulture));
127-
writer.WriteAttributeString("Column2", Row2Value2.ToString("r", CultureInfo.InvariantCulture));
128-
writer.WriteAttributeString("Column3", Row2Value3.ToString("r", CultureInfo.InvariantCulture));
129-
writer.WriteAttributeString("Column4", Row2Value4.ToString("r", CultureInfo.InvariantCulture));
125+
writer.WriteAttributeString("Column1", Row2Value1.ToStringRoundtrip());
126+
writer.WriteAttributeString("Column2", Row2Value2.ToStringRoundtrip());
127+
writer.WriteAttributeString("Column3", Row2Value3.ToStringRoundtrip());
128+
writer.WriteAttributeString("Column4", Row2Value4.ToStringRoundtrip());
130129
writer.WriteEndElement();
131130
writer.WriteStartElement("Row3");
132-
writer.WriteAttributeString("Column1", Row3Value1.ToString("r", CultureInfo.InvariantCulture));
133-
writer.WriteAttributeString("Column2", Row3Value2.ToString("r", CultureInfo.InvariantCulture));
134-
writer.WriteAttributeString("Column3", Row3Value3.ToString("r", CultureInfo.InvariantCulture));
135-
writer.WriteAttributeString("Column4", Row3Value4.ToString("r", CultureInfo.InvariantCulture));
131+
writer.WriteAttributeString("Column1", Row3Value1.ToStringRoundtrip());
132+
writer.WriteAttributeString("Column2", Row3Value2.ToStringRoundtrip());
133+
writer.WriteAttributeString("Column3", Row3Value3.ToStringRoundtrip());
134+
writer.WriteAttributeString("Column4", Row3Value4.ToStringRoundtrip());
136135
writer.WriteEndElement();
137136
writer.WriteStartElement("Row4");
138-
writer.WriteAttributeString("Column1", Row4Value1.ToString("r", CultureInfo.InvariantCulture));
139-
writer.WriteAttributeString("Column2", Row4Value2.ToString("r", CultureInfo.InvariantCulture));
140-
writer.WriteAttributeString("Column3", Row4Value3.ToString("r", CultureInfo.InvariantCulture));
141-
writer.WriteAttributeString("Column4", Row4Value4.ToString("r", CultureInfo.InvariantCulture));
137+
writer.WriteAttributeString("Column1", Row4Value1.ToStringRoundtrip());
138+
writer.WriteAttributeString("Column2", Row4Value2.ToStringRoundtrip());
139+
writer.WriteAttributeString("Column3", Row4Value3.ToStringRoundtrip());
140+
writer.WriteAttributeString("Column4", Row4Value4.ToStringRoundtrip());
142141
writer.WriteEndElement();
143142
}
144143

FoxTool/Fox/Types/Structs/FoxQuat.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,22 +51,21 @@ public override void CollectStringLookupLiterals(List<FoxStringLookupLiteral> li
5151
public override void ReadXml(XmlReader reader)
5252
{
5353
var isEmptyElement = reader.IsEmptyElement;
54-
X = float.Parse(reader.GetAttribute("x"), CultureInfo.InvariantCulture);
55-
Y = float.Parse(reader.GetAttribute("y"), CultureInfo.InvariantCulture);
56-
Z = float.Parse(reader.GetAttribute("z"), CultureInfo.InvariantCulture);
57-
W = float.Parse(reader.GetAttribute("w"), CultureInfo.InvariantCulture);
54+
X = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("x"));
55+
Y = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("y"));
56+
Z = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("z"));
57+
W = ExtensionMethods.ParseFloatRoundtrip(reader.GetAttribute("w"));
5858
reader.ReadStartElement("value");
5959
if (isEmptyElement == false)
6060
reader.ReadEndElement();
6161
}
6262

6363
public override void WriteXml(XmlWriter writer)
6464
{
65-
// TODO: Correctly format negative zero. The round-trip specifier appears to print -0 as 0 even though their IEEE values are different.
66-
writer.WriteAttributeString("x", X.ToString("r", CultureInfo.InvariantCulture));
67-
writer.WriteAttributeString("y", Y.ToString("r", CultureInfo.InvariantCulture));
68-
writer.WriteAttributeString("z", Z.ToString("r", CultureInfo.InvariantCulture));
69-
writer.WriteAttributeString("w", W.ToString("r", CultureInfo.InvariantCulture));
65+
writer.WriteAttributeString("x", X.ToStringRoundtrip());
66+
writer.WriteAttributeString("y", Y.ToStringRoundtrip());
67+
writer.WriteAttributeString("z", Z.ToStringRoundtrip());
68+
writer.WriteAttributeString("w", W.ToStringRoundtrip());
7069
}
7170

7271
public override string ToString()

0 commit comments

Comments
 (0)