Skip to content

Commit 02687ed

Browse files
authored
Merge pull request #6 from Angel-foxxo/master
code gen for class generation
2 parents 02d3571 + 14a7064 commit 02687ed

17 files changed

Lines changed: 582 additions & 210 deletions

Datamodel.NET.sln

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datamodel.NET", "Datamodel.
66
EndProject
77
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{4C928D60-5E48-4C0D-9C7E-C75D9734CD58}"
88
EndProject
9+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ElementFactoryGenerator", "ElementFactoryGenerator\ElementFactoryGenerator.csproj", "{FE0CDDEB-F817-0758-1DFC-A472CC81F0F3}"
10+
EndProject
911
Global
1012
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1113
Debug|Any CPU = Debug|Any CPU
@@ -25,6 +27,12 @@ Global
2527
{4C928D60-5E48-4C0D-9C7E-C75D9734CD58}.Documentation|Any CPU.Build.0 = Debug|Any CPU
2628
{4C928D60-5E48-4C0D-9C7E-C75D9734CD58}.Release|Any CPU.ActiveCfg = Release|Any CPU
2729
{4C928D60-5E48-4C0D-9C7E-C75D9734CD58}.Release|Any CPU.Build.0 = Release|Any CPU
30+
{FE0CDDEB-F817-0758-1DFC-A472CC81F0F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31+
{FE0CDDEB-F817-0758-1DFC-A472CC81F0F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
32+
{FE0CDDEB-F817-0758-1DFC-A472CC81F0F3}.Documentation|Any CPU.ActiveCfg = Release|Any CPU
33+
{FE0CDDEB-F817-0758-1DFC-A472CC81F0F3}.Documentation|Any CPU.Build.0 = Release|Any CPU
34+
{FE0CDDEB-F817-0758-1DFC-A472CC81F0F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
35+
{FE0CDDEB-F817-0758-1DFC-A472CC81F0F3}.Release|Any CPU.Build.0 = Release|Any CPU
2836
EndGlobalSection
2937
GlobalSection(SolutionProperties) = preSolution
3038
HideSolutionNode = FALSE

Datamodel.NET/Arrays.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@ internal set
181181
if (elem.Owner == null)
182182
{
183183
var importedElement = OwnerDatamodel.ImportElement(elem, Datamodel.ImportRecursionMode.Stubs, Datamodel.ImportOverwriteMode.Stubs);
184-
185-
if(importedElement is not null)
184+
185+
if (importedElement is not null)
186186
{
187187
Inner[i] = importedElement;
188188
}
@@ -201,8 +201,8 @@ protected override void Insert_Internal(int index, Element item)
201201
if (item.Owner == null)
202202
{
203203
var importedElement = OwnerDatamodel.ImportElement(item, Datamodel.ImportRecursionMode.Recursive, Datamodel.ImportOverwriteMode.Stubs);
204-
205-
if(importedElement is not null)
204+
205+
if (importedElement is not null)
206206
{
207207
item = importedElement;
208208
}

Datamodel.NET/AttributeList.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ private ICollection<Attribute> GetPropertyBasedAttributes(bool useSerializationN
2929
var result = new List<Attribute>();
3030
foreach (DictionaryEntry entry in PropertyInfos)
3131
{
32-
if(entry.Value is null)
32+
if (entry.Value is null)
3333
{
3434
throw new InvalidDataException("Property value can not be null");
3535
}
@@ -135,7 +135,7 @@ public void Add(string key, object? value)
135135
{
136136
var attrib = Inner[key];
137137

138-
if(attrib is null)
138+
if (attrib is null)
139139
{
140140
return null;
141141
}
@@ -269,7 +269,7 @@ public virtual object? this[string name]
269269
{
270270
// were actually fine with this being null, it will just set the value to null
271271
// but need to check so the type check doesn't fail if it is null
272-
if(value != null)
272+
if (value != null)
273273
{
274274
var valueType = value.GetType();
275275

@@ -307,7 +307,7 @@ public virtual object? this[string name]
307307

308308
return;
309309
}
310-
310+
311311
Attribute? old_attr;
312312
Attribute? new_attr;
313313
int old_index = -1;
@@ -343,7 +343,7 @@ public AttrKVP this[int index]
343343
{
344344
var attr = (Attribute?)Inner[index];
345345

346-
if(attr is null)
346+
if (attr is null)
347347
{
348348
throw new InvalidOperationException($"attribute at index {index} doesn't exist");
349349
}
@@ -367,7 +367,7 @@ public void RemoveAt(int index)
367367
{
368368
attr = (Attribute?)Inner[index];
369369

370-
if(attr is not null)
370+
if (attr is not null)
371371
{
372372
attr.Owner = null;
373373
Inner.RemoveAt(index);
@@ -571,7 +571,7 @@ public static ValueComparer Default
571571

572572
public new bool Equals(object? x, object? y)
573573
{
574-
if(x is null || y is null)
574+
if (x is null || y is null)
575575
{
576576
return false;
577577
}

Datamodel.NET/Codecs/Binary.cs

Lines changed: 108 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
using System.Numerics;
66
using System.IO;
77
using System.Diagnostics;
8-
using System.Reflection;
98
using System.Runtime.CompilerServices;
9+
using System.Threading;
1010

1111
namespace Datamodel.Codecs
1212
{
@@ -249,96 +249,116 @@ public void Encode(Datamodel dm, string encoding, int encoding_version, Stream s
249249
encoder.Encode();
250250
}
251251

252-
float[] ReadVector(int dim, BinaryReader reader)
252+
private static readonly Dictionary<RuntimeTypeHandle, int> TypeMap = new Dictionary<RuntimeTypeHandle, int>
253253
{
254-
var output = new float[dim];
255-
foreach (int i in Enumerable.Range(0, dim))
256-
output[i] = reader.ReadSingle();
257-
return output;
254+
{ typeof(Element).TypeHandle, 0 },
255+
{ typeof(int).TypeHandle, 1 },
256+
{ typeof(float).TypeHandle, 2 },
257+
{ typeof(bool).TypeHandle, 3 },
258+
{ typeof(string).TypeHandle, 4 },
259+
{ typeof(byte[]).TypeHandle, 5 },
260+
{ typeof(TimeSpan).TypeHandle, 6 },
261+
{ typeof(Color).TypeHandle, 7 },
262+
{ typeof(Vector2).TypeHandle, 8 },
263+
{ typeof(Vector3).TypeHandle, 9 },
264+
{ typeof(QAngle).TypeHandle, 10 },
265+
{ typeof(Vector4).TypeHandle, 11 },
266+
{ typeof(Quaternion).TypeHandle, 12 },
267+
{ typeof(Matrix4x4).TypeHandle, 13 },
268+
{ typeof(byte).TypeHandle, 14 },
269+
{ typeof(UInt64).TypeHandle, 15 }
270+
};
271+
272+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
273+
object? ReadValue(Datamodel dm, int typeIndex, bool raw_string, BinaryReader reader)
274+
{
275+
return typeIndex switch
276+
{
277+
0 => ReadElement(dm, reader),
278+
1 => reader.ReadInt32(),
279+
2 => reader.ReadSingle(),
280+
3 => reader.ReadBoolean(),
281+
4 => raw_string ? ReadString_Raw(reader) : StringDict!.ReadString(reader),
282+
5 => reader.ReadBytes(reader.ReadInt32()),
283+
6 => TimeSpan.FromTicks(reader.ReadInt32() * (TimeSpan.TicksPerSecond / DatamodelTicksPerSecond)),
284+
7 => ReadColor(reader),
285+
8 => ReadVector2(reader),
286+
9 => ReadVector3(reader),
287+
10 => ReadQAngle(reader),
288+
11 => ReadVector4(reader),
289+
12 => ReadQuaternion(reader),
290+
13 => ReadMatrix4x4(reader),
291+
14 => reader.ReadByte(),
292+
15 => reader.ReadUInt64(),
293+
_ => throw new ArgumentException("Cannot read value of type")
294+
};
258295
}
259296

260-
object? ReadValue(Datamodel dm, Type? type, bool raw_string, BinaryReader reader)
297+
// Specialized methods to avoid repeated vector allocations
298+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
299+
private object? ReadElement(Datamodel dm, BinaryReader reader)
261300
{
262-
if (type == typeof(Element))
301+
var index = reader.ReadInt32();
302+
return index switch
263303
{
264-
var index = reader.ReadInt32();
265-
if (index == -1)
266-
return null;
267-
else if (index == -2)
268-
{
269-
var id = new Guid(ReadString_Raw(reader)); // yes, it's in ASCII!
270-
return dm.AllElements[id] ?? new Element(dm, id);
271-
}
272-
else
273-
return dm.AllElements[index];
274-
}
275-
if (type == typeof(int))
276-
return reader.ReadInt32();
277-
if (type == typeof(float))
278-
return reader.ReadSingle();
279-
if (type == typeof(bool))
280-
return reader.ReadBoolean();
281-
if (type == typeof(string))
282-
return raw_string ? ReadString_Raw(reader) : StringDict!.ReadString(reader);
283-
284-
if (type == typeof(byte[]))
285-
return reader.ReadBytes(reader.ReadInt32());
286-
if (type == typeof(TimeSpan))
287-
return TimeSpan.FromTicks(reader.ReadInt32() * (TimeSpan.TicksPerSecond / DatamodelTicksPerSecond));
304+
-1 => null,
305+
-2 => dm.AllElements[new Guid(StringDict.ReadString(reader))] ?? new Element(dm, new Guid(StringDict.ReadString(reader))),
306+
_ => dm.AllElements[index]
307+
};
308+
}
288309

289-
if (type == typeof(Color))
290-
{
291-
var rgba = reader.ReadBytes(4);
292-
return Color.FromBytes(rgba);
293-
}
310+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
311+
private static Color ReadColor(BinaryReader reader)
312+
{
313+
var rgba = reader.ReadBytes(4);
314+
return Color.FromBytes(rgba);
315+
}
294316

295-
if (type == typeof(Vector2))
296-
{
297-
var ords = ReadVector(2, reader);
298-
return new Vector2(ords[0], ords[1]);
299-
}
300-
if (type == typeof(Vector3))
301-
{
302-
var ords = ReadVector(3, reader);
303-
return new Vector3(ords[0], ords[1], ords[2]);
304-
}
305-
if (type == typeof(QAngle))
306-
{
307-
var ords = ReadVector(3, reader);
308-
return new QAngle(ords[0], ords[1], ords[2]);
309-
}
317+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
318+
private static Vector2 ReadVector2(BinaryReader reader)
319+
{
320+
return new Vector2(reader.ReadSingle(), reader.ReadSingle());
321+
}
310322

311-
if (type == typeof(Vector4))
312-
{
313-
var ords = ReadVector(4, reader);
314-
return new Vector4(ords[0], ords[1], ords[2], ords[3]);
315-
}
316-
if (type == typeof(Quaternion))
317-
{
318-
var ords = ReadVector(4, reader);
319-
return new Quaternion(ords[0], ords[1], ords[2], ords[3]);
320-
}
321-
if (type == typeof(Matrix4x4))
322-
{
323-
var ords = ReadVector(4 * 4, reader);
324-
return new Matrix4x4(
325-
ords[0], ords[1], ords[2], ords[3],
326-
ords[4], ords[5], ords[6], ords[7],
327-
ords[8], ords[9], ords[10], ords[11],
328-
ords[12], ords[13], ords[14], ords[15]);
329-
}
323+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
324+
private static Vector3 ReadVector3(BinaryReader reader)
325+
{
326+
return new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
327+
}
330328

331-
if (type == typeof(byte))
332-
return reader.ReadByte();
333-
if (type == typeof(UInt64))
334-
return reader.ReadUInt64();
329+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
330+
private static QAngle ReadQAngle(BinaryReader reader)
331+
{
332+
return new QAngle(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
333+
}
335334

336-
throw new ArgumentException(type == null ? "No type provided to GetValue()" : "Cannot read value of type " + type.Name);
335+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
336+
private static Vector4 ReadVector4(BinaryReader reader)
337+
{
338+
return new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
339+
}
340+
341+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
342+
private static Quaternion ReadQuaternion(BinaryReader reader)
343+
{
344+
return new Quaternion(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
345+
}
346+
347+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
348+
private static Matrix4x4 ReadMatrix4x4(BinaryReader reader)
349+
{
350+
// Read all 16 floats directly without intermediate array
351+
return new Matrix4x4(
352+
reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(),
353+
reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(),
354+
reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(),
355+
reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
337356
}
338357

339358
public Datamodel Decode(string encoding, int encoding_version, string format, int format_version, Stream stream, DeferredMode defer_mode, ReflectionParams reflectionParams)
340359
{
341-
var types = CodecUtilities.GetReflectionTypes(reflectionParams);
360+
var elementFactoryTypes = CodecUtilities.GetIElementFactoryClasses();
361+
var elementFactory = (IElementFactory)Activator.CreateInstance(elementFactoryTypes.First());
342362

343363
stream.Seek(0, SeekOrigin.Begin);
344364
while (true)
@@ -349,7 +369,8 @@ public Datamodel Decode(string encoding, int encoding_version, string format, in
349369
var dm = new Datamodel(format, format_version);
350370

351371
EncodingVersion = encoding_version;
352-
Reader = new BinaryReader(stream, Datamodel.TextEncoding);
372+
373+
Reader = new BinaryReader(stream);
353374

354375
if (EncodingVersion >= 9)
355376
{
@@ -377,13 +398,14 @@ public Datamodel Decode(string encoding, int encoding_version, string format, in
377398
var id_bits = Reader.ReadBytes(16);
378399
var id = new Guid(BitConverter.IsLittleEndian ? id_bits : id_bits.Reverse().ToArray());
379400

380-
if (!CodecUtilities.TryConstructCustomElement(types, dm, type, name, id, out _))
401+
if (!CodecUtilities.TryConstructCustomElement(elementFactory, reflectionParams, dm, type, name, id, out _))
381402
{
382403
// note: constructing an element, adds it to the datamodel.AllElements
383404
_ = new Element(dm, name, id, type);
384405
}
385406
}
386407

408+
387409
// read attributes (or not, if we're deferred)
388410
foreach (var elem in dm.AllElements.ToArray())
389411
{
@@ -414,12 +436,12 @@ public Datamodel Decode(string encoding, int encoding_version, string format, in
414436

415437
public object? DeferredDecodeAttribute(Datamodel dm, long offset)
416438
{
417-
if(Reader is null)
439+
if (Reader is null)
418440
{
419441
throw new InvalidDataException("Tried to read a deferred attribute but the reader is invalid");
420442
}
421443

422-
Reader.BaseStream.Seek(offset, SeekOrigin.Begin);
444+
Reader.BaseStream.Seek((int)offset, SeekOrigin.Begin);
423445
return DecodeAttribute(dm, false, Reader);
424446
}
425447

@@ -428,15 +450,16 @@ public Datamodel Decode(string encoding, int encoding_version, string format, in
428450
var types = IdToType(reader.ReadByte());
429451

430452
if (types.Item2 == null)
431-
return ReadValue(dm, types.Item1, EncodingVersion < 4 || prefix, reader);
453+
return ReadValue(dm, TypeMap[types.Item1.TypeHandle], EncodingVersion < 4 || prefix, reader);
432454
else
433455
{
434456
var count = reader.ReadInt32();
435457
var inner_type = types.Item2;
436458
var array = CodecUtilities.MakeList(inner_type, count);
437459

460+
var typeId = TypeMap[inner_type.TypeHandle];
438461
foreach (var x in Enumerable.Range(0, count))
439-
array.Add(ReadValue(dm, inner_type, true, reader));
462+
array.Add(ReadValue(dm, typeId, true, reader));
440463

441464
return array;
442465
}
@@ -449,7 +472,7 @@ void SkipAttribute(BinaryReader reader)
449472
int count = 1;
450473
Type? type = types.Item1;
451474

452-
if(type is null)
475+
if (type is null)
453476
{
454477
throw new InvalidDataException("Failed to match id to type");
455478
}
@@ -554,7 +577,7 @@ public void Encode()
554577

555578
int CountChildren(Element? elem, HashSet<Element> counter)
556579
{
557-
if(elem is null)
580+
if (elem is null)
558581
{
559582
return 0;
560583
}

0 commit comments

Comments
 (0)