-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathStepDocument.cs
112 lines (91 loc) · 3.98 KB
/
StepDocument.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Intrinsics;
using Ara3D.Buffers;
using Ara3D.Logging;
using Ara3D.Utils;
namespace Ara3D.StepParser
{
public unsafe class StepDocument : IDisposable
{
public readonly FilePath FilePath;
public readonly byte* DataStart;
public readonly byte* DataEnd;
public readonly AlignedMemory Data;
/// <summary>
/// This is a list of raw step instance information.
/// Each one has only a type and an ID.
/// </summary>
public readonly StepRawInstance[] RawInstances;
/// <summary>
/// The number of raw instance
/// </summary>
public readonly int NumRawInstances;
/// <summary>
/// This gives us a fast way to look up a StepInstance by their ID
/// </summary>
public readonly Dictionary<uint, int> InstanceIdToIndex = new();
/// <summary>
/// This tells us the byte offset of the start of each line in the file
/// </summary>
public readonly List<int> LineOffsets;
public StepDocument(FilePath filePath, ILogger logger = null)
{
FilePath = filePath;
logger = logger ?? Logger.Null;
logger.Log($"Loading {filePath.GetFileSizeAsString()} of data from {filePath.GetFileName()}");
Data = AlignedMemoryReader.ReadAllBytes(filePath);
DataStart = Data.BytePtr;
DataEnd = DataStart + Data.NumBytes;
logger.Log($"Computing the start of each line");
// NOTE: this estimates that the average line length is at least 32 characters.
// This minimize the number of allocations that happen
var cap = Data.NumBytes / 32;
LineOffsets = new List<int>(cap);
// We are going to report the beginning of the lines, while the "ComputeLines" function
// will compute the ends of lines.
var currentLine = 1;
for (var i = 0; i < Data.NumVectors; i++)
{
StepLineParser.ComputeOffsets(
((Vector256<byte>*)Data.BytePtr)[i], ref currentLine, LineOffsets);
}
logger.Log($"Found {LineOffsets.Count} lines");
logger.Log($"Creating instance records");
RawInstances = new StepRawInstance[LineOffsets.Count];
for (var i = 0; i < LineOffsets.Count - 1; i++)
{
var lineStart = LineOffsets[i];
var lineEnd = LineOffsets[i + 1];
var inst = StepLineParser.ParseLine(DataStart + lineStart, DataStart + lineEnd);
if (inst.IsValid())
{
InstanceIdToIndex.Add(inst.Id, NumRawInstances);
RawInstances[NumRawInstances++] = inst;
}
}
logger.Log($"Completed creation of STEP document from {filePath.GetFileName()}");
}
public void Dispose()
=> Data.Dispose();
public StepInstance GetInstanceWithData(uint id)
=> GetInstanceWithDataFromIndex(InstanceIdToIndex[id]);
public StepInstance GetInstanceWithDataFromIndex(int index)
=> GetInstanceWithData(RawInstances[index]);
public StepInstance GetInstanceWithData(StepRawInstance inst)
{
var attr = inst.GetAttributes(DataEnd);
var se = new StepEntity(inst.Type, attr);
return new StepInstance(inst.Id, se);
}
public static StepDocument Create(FilePath fp)
=> new(fp);
public IEnumerable<StepRawInstance> GetRawInstances(string typeCode)
=> RawInstances.Where(inst => inst.Type.Equals(typeCode));
public IEnumerable<StepInstance> GetInstances()
=> RawInstances.Select(GetInstanceWithData);
public IEnumerable<StepInstance> GetInstances(string typeCode)
=> GetRawInstances(typeCode).Select(GetInstanceWithData);
}
}