@ifc-lite/parser 2.1.8 → 2.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/classification-extractor.d.ts +1 -1
  2. package/dist/classification-extractor.d.ts.map +1 -1
  3. package/dist/classification-resolver.d.ts +18 -0
  4. package/dist/classification-resolver.d.ts.map +1 -0
  5. package/dist/classification-resolver.js +126 -0
  6. package/dist/classification-resolver.js.map +1 -0
  7. package/dist/columnar-parser-attributes.d.ts +39 -0
  8. package/dist/columnar-parser-attributes.d.ts.map +1 -0
  9. package/dist/columnar-parser-attributes.js +225 -0
  10. package/dist/columnar-parser-attributes.js.map +1 -0
  11. package/dist/columnar-parser-indexes.d.ts +42 -0
  12. package/dist/columnar-parser-indexes.d.ts.map +1 -0
  13. package/dist/columnar-parser-indexes.js +102 -0
  14. package/dist/columnar-parser-indexes.js.map +1 -0
  15. package/dist/columnar-parser-relationships.d.ts +17 -0
  16. package/dist/columnar-parser-relationships.d.ts.map +1 -0
  17. package/dist/columnar-parser-relationships.js +95 -0
  18. package/dist/columnar-parser-relationships.js.map +1 -0
  19. package/dist/columnar-parser.d.ts +2 -21
  20. package/dist/columnar-parser.d.ts.map +1 -1
  21. package/dist/columnar-parser.js +3 -409
  22. package/dist/columnar-parser.js.map +1 -1
  23. package/dist/georef-extractor.d.ts +7 -1
  24. package/dist/georef-extractor.d.ts.map +1 -1
  25. package/dist/georef-extractor.js +29 -5
  26. package/dist/georef-extractor.js.map +1 -1
  27. package/dist/material-extractor.d.ts +1 -1
  28. package/dist/material-extractor.d.ts.map +1 -1
  29. package/dist/material-resolver.d.ts +37 -0
  30. package/dist/material-resolver.d.ts.map +1 -0
  31. package/dist/material-resolver.js +230 -0
  32. package/dist/material-resolver.js.map +1 -0
  33. package/dist/on-demand-extractors.d.ts +4 -51
  34. package/dist/on-demand-extractors.d.ts.map +1 -1
  35. package/dist/on-demand-extractors.js +17 -341
  36. package/dist/on-demand-extractors.js.map +1 -1
  37. package/dist/style-extractor.js.map +1 -1
  38. package/package.json +3 -3
@@ -0,0 +1,95 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * Relationship extraction for columnar parsing.
6
+ *
7
+ * Byte-level relationship scanners that extract numeric entity IDs
8
+ * from STEP relationship entities without TextDecoder overhead.
9
+ */
10
+ import { skipCommas, readRefId, readRefList } from './columnar-parser-attributes.js';
11
+ /**
12
+ * Extract relatingObject and relatedObjects from a relationship entity using byte-level scanning.
13
+ * No TextDecoder needed - only extracts numeric entity IDs.
14
+ */
15
+ export function extractRelFast(buffer, byteOffset, byteLength, typeUpper) {
16
+ const end = byteOffset + byteLength;
17
+ let pos = byteOffset;
18
+ while (pos < end && buffer[pos] !== 0x28)
19
+ pos++;
20
+ if (pos >= end)
21
+ return null;
22
+ pos++;
23
+ // Skip to attr[4] (all IfcRelationship subtypes have 4 shared IfcRoot+IfcRelationship attrs)
24
+ pos = skipCommas(buffer, pos, end, 4);
25
+ if (typeUpper === 'IFCRELCONTAINEDINSPATIALSTRUCTURE'
26
+ || typeUpper === 'IFCRELREFERENCEDINSPATIALSTRUCTURE'
27
+ || typeUpper === 'IFCRELDEFINESBYPROPERTIES'
28
+ || typeUpper === 'IFCRELDEFINESBYTYPE') {
29
+ // attr[4]=RelatedObjects, attr[5]=RelatingObject
30
+ const [related, rp] = readRefList(buffer, pos, end);
31
+ pos = rp;
32
+ while (pos < end && buffer[pos] !== 0x2C)
33
+ pos++;
34
+ pos++;
35
+ const [relating, _] = readRefId(buffer, pos, end);
36
+ if (relating < 0 || related.length === 0)
37
+ return null;
38
+ return { relatingObject: relating, relatedObjects: related };
39
+ }
40
+ else if (typeUpper === 'IFCRELASSIGNSTOGROUP' || typeUpper === 'IFCRELASSIGNSTOPRODUCT') {
41
+ const [related, rp] = readRefList(buffer, pos, end);
42
+ pos = skipCommas(buffer, rp, end, 2);
43
+ const [relating, _] = readRefId(buffer, pos, end);
44
+ if (relating < 0 || related.length === 0)
45
+ return null;
46
+ return { relatingObject: relating, relatedObjects: related };
47
+ }
48
+ else if (typeUpper === 'IFCRELCONNECTSELEMENTS' || typeUpper === 'IFCRELCONNECTSPATHELEMENTS') {
49
+ pos = skipCommas(buffer, pos, end, 1);
50
+ const [relating, rp2] = readRefId(buffer, pos, end);
51
+ pos = skipCommas(buffer, rp2, end, 1);
52
+ const [related, _] = readRefId(buffer, pos, end);
53
+ if (relating < 0 || related < 0)
54
+ return null;
55
+ return { relatingObject: relating, relatedObjects: [related] };
56
+ }
57
+ else {
58
+ // Default: attr[4]=RelatingObject, attr[5]=RelatedObject(s)
59
+ const [relating, rp] = readRefId(buffer, pos, end);
60
+ if (relating < 0)
61
+ return null;
62
+ pos = rp;
63
+ while (pos < end && buffer[pos] !== 0x2C)
64
+ pos++;
65
+ pos++;
66
+ const [related, _] = readRefList(buffer, pos, end);
67
+ if (related.length === 0)
68
+ return null;
69
+ return { relatingObject: relating, relatedObjects: related };
70
+ }
71
+ }
72
+ /**
73
+ * Extract property rel data: attr[4]=relatedObjects, attr[5]=relatingDef.
74
+ * Numbers only, no TextDecoder.
75
+ */
76
+ export function extractPropertyRelFast(buffer, byteOffset, byteLength) {
77
+ const end = byteOffset + byteLength;
78
+ let pos = byteOffset;
79
+ while (pos < end && buffer[pos] !== 0x28)
80
+ pos++;
81
+ if (pos >= end)
82
+ return null;
83
+ pos++;
84
+ pos = skipCommas(buffer, pos, end, 4);
85
+ const [relatedObjects, rp] = readRefList(buffer, pos, end);
86
+ pos = rp;
87
+ while (pos < end && buffer[pos] !== 0x2C)
88
+ pos++;
89
+ pos++;
90
+ const [relatingDef, _] = readRefId(buffer, pos, end);
91
+ if (relatingDef < 0 || relatedObjects.length === 0)
92
+ return null;
93
+ return { relatedObjects, relatingDef };
94
+ }
95
+ //# sourceMappingURL=columnar-parser-relationships.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"columnar-parser-relationships.js","sourceRoot":"","sources":["../src/columnar-parser-relationships.ts"],"names":[],"mappings":"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"}
@@ -7,27 +7,8 @@
7
7
  import type { EntityRef } from './types.js';
8
8
  import { StringTable, EntityTableBuilder, PropertyTableBuilder, RelationshipGraphBuilder } from '@ifc-lite/data';
9
9
  import type { SpatialHierarchy, QuantityTable, PropertyValue } from '@ifc-lite/data';
10
- export interface SpatialIndex {
11
- queryAABB(bounds: {
12
- min: [number, number, number];
13
- max: [number, number, number];
14
- }): number[];
15
- raycast(origin: [number, number, number], direction: [number, number, number]): number[];
16
- }
17
- /**
18
- * Entity-by-ID lookup interface. Supports both Map<number, EntityRef> (legacy)
19
- * and CompactEntityIndex (memory-optimized typed arrays with LRU cache).
20
- */
21
- export type EntityByIdIndex = {
22
- get(expressId: number): EntityRef | undefined;
23
- has(expressId: number): boolean;
24
- readonly size: number;
25
- keys(): IterableIterator<number>;
26
- values(): IterableIterator<EntityRef>;
27
- entries(): IterableIterator<[number, EntityRef]>;
28
- forEach(callback: (value: EntityRef, key: number) => void): void;
29
- [Symbol.iterator](): IterableIterator<[number, EntityRef]>;
30
- };
10
+ import type { SpatialIndex, EntityByIdIndex } from './columnar-parser-indexes.js';
11
+ export type { SpatialIndex, EntityByIdIndex } from './columnar-parser-indexes.js';
31
12
  export interface IfcDataStore {
32
13
  fileSize: number;
33
14
  schemaVersion: 'IFC2X3' | 'IFC4' | 'IFC4X3' | 'IFC5';
@@ -1 +1 @@
1
- {"version":3,"file":"columnar-parser.d.ts","sourceRoot":"","sources":["../src/columnar-parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"columnar-parser.d.ts","sourceRoot":"","sources":["../src/columnar-parser.ts"],"names":[],"mappings":"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"}
@@ -4,419 +4,13 @@
4
4
  import { SpatialHierarchyBuilder } from './spatial-hierarchy-builder.js';
5
5
  import { EntityExtractor } from './entity-extractor.js';
6
6
  import { extractLengthUnitScale } from './unit-extractor.js';
7
- import { decodeIfcString } from '@ifc-lite/encoding';
8
7
  import { getAttributeNames, getInheritanceChain } from './ifc-schema.js';
9
8
  import { parsePropertyValue } from './on-demand-extractors.js';
10
9
  import { buildCompactEntityIndexAsync } from './compact-entity-index.js';
11
10
  import { StringTable, EntityTableBuilder, PropertyTableBuilder, QuantityTableBuilder, RelationshipGraphBuilder, RelationshipType, QuantityType, } from '@ifc-lite/data';
12
- // Pre-computed type sets for O(1) lookups
13
- const GEOMETRY_TYPES = new Set([
14
- 'IFCWALL', 'IFCWALLSTANDARDCASE', 'IFCDOOR', 'IFCWINDOW', 'IFCSLAB',
15
- 'IFCCOLUMN', 'IFCBEAM', 'IFCROOF', 'IFCSTAIR', 'IFCSTAIRFLIGHT',
16
- 'IFCRAILING', 'IFCRAMP', 'IFCRAMPFLIGHT', 'IFCPLATE', 'IFCMEMBER',
17
- 'IFCCURTAINWALL', 'IFCFOOTING', 'IFCPILE', 'IFCBUILDINGELEMENTPROXY',
18
- 'IFCFURNISHINGELEMENT', 'IFCFLOWSEGMENT', 'IFCFLOWTERMINAL',
19
- 'IFCFLOWCONTROLLER', 'IFCFLOWFITTING', 'IFCSPACE', 'IFCOPENINGELEMENT',
20
- 'IFCSITE', 'IFCBUILDING', 'IFCBUILDINGSTOREY',
21
- ]);
22
- // IMPORTANT: This set MUST include ALL RelationshipType enum values to prevent semantic loss
23
- // Missing types will be skipped during parsing, causing incomplete relationship graphs
24
- const RELATIONSHIP_TYPES = new Set([
25
- 'IFCRELCONTAINEDINSPATIALSTRUCTURE', 'IFCRELAGGREGATES',
26
- 'IFCRELDEFINESBYPROPERTIES', 'IFCRELDEFINESBYTYPE',
27
- 'IFCRELASSOCIATESMATERIAL', 'IFCRELASSOCIATESCLASSIFICATION',
28
- 'IFCRELASSOCIATESDOCUMENT',
29
- 'IFCRELVOIDSELEMENT', 'IFCRELFILLSELEMENT',
30
- 'IFCRELCONNECTSPATHELEMENTS', 'IFCRELCONNECTSELEMENTS',
31
- 'IFCRELSPACEBOUNDARY',
32
- 'IFCRELASSIGNSTOGROUP', 'IFCRELASSIGNSTOPRODUCT',
33
- 'IFCRELREFERENCEDINSPATIALSTRUCTURE',
34
- ]);
35
- // Map IFC relationship type strings to RelationshipType enum
36
- // MUST cover ALL RelationshipType enum values (14 types total)
37
- const REL_TYPE_MAP = {
38
- 'IFCRELCONTAINEDINSPATIALSTRUCTURE': RelationshipType.ContainsElements,
39
- 'IFCRELAGGREGATES': RelationshipType.Aggregates,
40
- 'IFCRELDEFINESBYPROPERTIES': RelationshipType.DefinesByProperties,
41
- 'IFCRELDEFINESBYTYPE': RelationshipType.DefinesByType,
42
- 'IFCRELASSOCIATESMATERIAL': RelationshipType.AssociatesMaterial,
43
- 'IFCRELASSOCIATESCLASSIFICATION': RelationshipType.AssociatesClassification,
44
- 'IFCRELASSOCIATESDOCUMENT': RelationshipType.AssociatesDocument,
45
- 'IFCRELVOIDSELEMENT': RelationshipType.VoidsElement,
46
- 'IFCRELFILLSELEMENT': RelationshipType.FillsElement,
47
- 'IFCRELCONNECTSPATHELEMENTS': RelationshipType.ConnectsPathElements,
48
- 'IFCRELCONNECTSELEMENTS': RelationshipType.ConnectsElements,
49
- 'IFCRELSPACEBOUNDARY': RelationshipType.SpaceBoundary,
50
- 'IFCRELASSIGNSTOGROUP': RelationshipType.AssignsToGroup,
51
- 'IFCRELASSIGNSTOPRODUCT': RelationshipType.AssignsToProduct,
52
- 'IFCRELREFERENCEDINSPATIALSTRUCTURE': RelationshipType.ReferencedInSpatialStructure,
53
- };
54
- const QUANTITY_TYPE_MAP = {
55
- 'IFCQUANTITYLENGTH': QuantityType.Length,
56
- 'IFCQUANTITYAREA': QuantityType.Area,
57
- 'IFCQUANTITYVOLUME': QuantityType.Volume,
58
- 'IFCQUANTITYCOUNT': QuantityType.Count,
59
- 'IFCQUANTITYWEIGHT': QuantityType.Weight,
60
- 'IFCQUANTITYTIME': QuantityType.Time,
61
- };
62
- // Types needed for spatial hierarchy (small subset)
63
- const SPATIAL_TYPES = new Set([
64
- 'IFCPROJECT', 'IFCSITE', 'IFCBUILDING', 'IFCBUILDINGSTOREY', 'IFCSPACE',
65
- 'IFCFACILITY', 'IFCFACILITYPART',
66
- 'IFCBRIDGE', 'IFCBRIDGEPART',
67
- 'IFCROAD', 'IFCROADPART',
68
- 'IFCRAILWAY', 'IFCRAILWAYPART',
69
- 'IFCMARINEFACILITY',
70
- ]);
71
- // Relationship types needed for hierarchy and structural relationships
72
- const HIERARCHY_REL_TYPES = new Set([
73
- 'IFCRELAGGREGATES', 'IFCRELCONTAINEDINSPATIALSTRUCTURE',
74
- 'IFCRELDEFINESBYTYPE',
75
- // Structural relationships (voids, fills, connections, groups)
76
- 'IFCRELVOIDSELEMENT', 'IFCRELFILLSELEMENT',
77
- 'IFCRELCONNECTSPATHELEMENTS', 'IFCRELCONNECTSELEMENTS',
78
- 'IFCRELSPACEBOUNDARY',
79
- 'IFCRELASSIGNSTOGROUP', 'IFCRELASSIGNSTOPRODUCT',
80
- 'IFCRELREFERENCEDINSPATIALSTRUCTURE',
81
- ]);
82
- // Relationship types for on-demand property loading
83
- const PROPERTY_REL_TYPES = new Set([
84
- 'IFCRELDEFINESBYPROPERTIES',
85
- ]);
86
- // Relationship types for on-demand classification/material loading
87
- const ASSOCIATION_REL_TYPES = new Set([
88
- 'IFCRELASSOCIATESCLASSIFICATION', 'IFCRELASSOCIATESMATERIAL',
89
- 'IFCRELASSOCIATESDOCUMENT',
90
- ]);
91
- // Attributes to skip in extractAllEntityAttributes (shown elsewhere or non-displayable)
92
- const SKIP_DISPLAY_ATTRS = new Set(['GlobalId', 'OwnerHistory', 'ObjectPlacement', 'Representation', 'HasPropertySets', 'RepresentationMaps']);
93
- // Property-related entity types for on-demand extraction
94
- const PROPERTY_ENTITY_TYPES = new Set([
95
- 'IFCPROPERTYSET', 'IFCELEMENTQUANTITY',
96
- 'IFCPROPERTYSINGLEVALUE', 'IFCPROPERTYENUMERATEDVALUE',
97
- 'IFCPROPERTYBOUNDEDVALUE', 'IFCPROPERTYTABLEVALUE',
98
- 'IFCPROPERTYLISTVALUE', 'IFCPROPERTYREFERENCEVALUE',
99
- 'IFCQUANTITYLENGTH', 'IFCQUANTITYAREA', 'IFCQUANTITYVOLUME',
100
- 'IFCQUANTITYCOUNT', 'IFCQUANTITYWEIGHT', 'IFCQUANTITYTIME',
101
- ]);
102
- const PROPERTY_CONTAINER_TYPES = new Set([
103
- 'IFCPROPERTYSET',
104
- 'IFCELEMENTQUANTITY',
105
- ]);
106
- function isIfcTypeLikeEntity(typeUpper) {
107
- return typeUpper.endsWith('TYPE') || typeUpper.endsWith('STYLE');
108
- }
109
- // ==========================================
110
- // Byte-level helpers for fast extraction
111
- // These avoid per-entity TextDecoder calls by working on raw bytes.
112
- // ==========================================
113
- /**
114
- * Find the byte range of a quoted string at a specific attribute position in STEP entity bytes.
115
- * Returns [start, end) byte offsets (excluding quotes), or null if not found.
116
- *
117
- * @param buffer - The IFC file buffer
118
- * @param entityStart - byte offset of the entity
119
- * @param entityLen - byte length of the entity
120
- * @param attrIndex - 0-based attribute index (0=GlobalId, 2=Name)
121
- */
122
- function findQuotedAttrRange(buffer, entityStart, entityLen, attrIndex) {
123
- const end = entityStart + entityLen;
124
- let pos = entityStart;
125
- // Skip to opening paren '(' after TYPE name
126
- while (pos < end && buffer[pos] !== 0x28 /* ( */)
127
- pos++;
128
- if (pos >= end)
129
- return null;
130
- pos++; // skip '('
131
- // Skip commas to reach the target attribute
132
- if (attrIndex > 0) {
133
- let toSkip = attrIndex;
134
- let depth = 0;
135
- let inStr = false;
136
- while (pos < end && toSkip > 0) {
137
- const ch = buffer[pos];
138
- if (ch === 0x27 /* ' */) {
139
- if (inStr && pos + 1 < end && buffer[pos + 1] === 0x27) {
140
- pos += 2;
141
- continue;
142
- }
143
- inStr = !inStr;
144
- }
145
- else if (!inStr) {
146
- if (ch === 0x28)
147
- depth++;
148
- else if (ch === 0x29)
149
- depth--;
150
- else if (ch === 0x2C && depth === 0)
151
- toSkip--;
152
- }
153
- pos++;
154
- }
155
- }
156
- // Skip whitespace
157
- while (pos < end && (buffer[pos] === 0x20 || buffer[pos] === 0x09))
158
- pos++;
159
- // Check for quoted string
160
- if (pos >= end || buffer[pos] !== 0x27 /* ' */)
161
- return null;
162
- pos++; // skip opening quote
163
- const start = pos;
164
- // Find closing quote (handle escaped quotes '')
165
- while (pos < end) {
166
- if (buffer[pos] === 0x27) {
167
- if (pos + 1 < end && buffer[pos + 1] === 0x27) {
168
- pos += 2;
169
- continue;
170
- }
171
- break;
172
- }
173
- pos++;
174
- }
175
- return [start, pos];
176
- }
177
- /**
178
- * Batch extract GlobalId (attr[0]) and Name (attr[2]) for many entities using
179
- * only 2 TextDecoder.decode() calls total (one for all GlobalIds, one for all Names).
180
- *
181
- * This is ~100x faster than calling extractEntity() per entity for large batches
182
- * because it eliminates per-entity TextDecoder overhead which is significant in Firefox.
183
- *
184
- * Returns a Map from expressId → { globalId, name }.
185
- */
186
- async function batchExtractGlobalIdAndName(buffer, refs, yieldIfNeeded) {
187
- const result = new Map();
188
- if (refs.length === 0)
189
- return result;
190
- const CHUNK_SIZE = 2048;
191
- // Phase 1: Scan byte ranges for GlobalId and Name positions (no string allocation)
192
- const gidRanges = []; // [start, end) for each entity
193
- const nameRanges = [];
194
- const validIndices = []; // indices into refs for entities with valid ranges
195
- for (let i = 0; i < refs.length; i++) {
196
- if (yieldIfNeeded && (i & (CHUNK_SIZE - 1)) === 0) {
197
- await yieldIfNeeded();
198
- }
199
- const ref = refs[i];
200
- const gidRange = findQuotedAttrRange(buffer, ref.byteOffset, ref.byteLength, 0);
201
- const nameRange = findQuotedAttrRange(buffer, ref.byteOffset, ref.byteLength, 2);
202
- gidRanges.push(gidRange ?? [0, 0]);
203
- nameRanges.push(nameRange ?? [0, 0]);
204
- validIndices.push(i);
205
- }
206
- // Phase 2: Concatenate all GlobalId bytes into one buffer, decode once
207
- // Use null byte (0x00) as separator (never appears in IFC string content)
208
- let totalGidBytes = 0;
209
- let totalNameBytes = 0;
210
- for (let i = 0; i < validIndices.length; i++) {
211
- if (yieldIfNeeded && (i & (CHUNK_SIZE - 1)) === 0) {
212
- await yieldIfNeeded();
213
- }
214
- const [gs, ge] = gidRanges[i];
215
- const [ns, ne] = nameRanges[i];
216
- totalGidBytes += (ge - gs) + 1; // +1 for separator
217
- totalNameBytes += (ne - ns) + 1;
218
- }
219
- const gidBuf = new Uint8Array(totalGidBytes);
220
- const nameBuf = new Uint8Array(totalNameBytes);
221
- let gidOffset = 0;
222
- let nameOffset = 0;
223
- for (let i = 0; i < validIndices.length; i++) {
224
- if (yieldIfNeeded && (i & (CHUNK_SIZE - 1)) === 0) {
225
- await yieldIfNeeded();
226
- }
227
- const [gs, ge] = gidRanges[i];
228
- const [ns, ne] = nameRanges[i];
229
- if (ge > gs) {
230
- gidBuf.set(buffer.subarray(gs, ge), gidOffset);
231
- gidOffset += ge - gs;
232
- }
233
- gidBuf[gidOffset++] = 0; // null separator
234
- if (ne > ns) {
235
- nameBuf.set(buffer.subarray(ns, ne), nameOffset);
236
- nameOffset += ne - ns;
237
- }
238
- nameBuf[nameOffset++] = 0;
239
- }
240
- // Phase 3: Two TextDecoder calls for ALL entities
241
- const decoder = new TextDecoder();
242
- const allGids = decoder.decode(gidBuf.subarray(0, gidOffset));
243
- const allNames = decoder.decode(nameBuf.subarray(0, nameOffset));
244
- const gids = allGids.split('\0');
245
- const names = allNames.split('\0');
246
- // Phase 4: Build result map
247
- for (let i = 0; i < validIndices.length; i++) {
248
- if (yieldIfNeeded && (i & (CHUNK_SIZE - 1)) === 0) {
249
- await yieldIfNeeded();
250
- }
251
- const ref = refs[validIndices[i]];
252
- const rawName = names[i] || '';
253
- result.set(ref.expressId, {
254
- globalId: gids[i] || '',
255
- name: rawName ? decodeIfcString(rawName) : '',
256
- });
257
- }
258
- return result;
259
- }
260
- // ==========================================
261
- // Byte-level relationship scanners (numbers only, no TextDecoder)
262
- // ==========================================
263
- /**
264
- * Skip N commas at depth 0 in STEP bytes.
265
- */
266
- function skipCommas(buffer, start, end, count) {
267
- let pos = start;
268
- let remaining = count;
269
- let depth = 0;
270
- let inString = false;
271
- while (pos < end && remaining > 0) {
272
- const ch = buffer[pos];
273
- if (ch === 0x27) {
274
- if (inString && pos + 1 < end && buffer[pos + 1] === 0x27) {
275
- pos += 2;
276
- continue;
277
- }
278
- inString = !inString;
279
- }
280
- else if (!inString) {
281
- if (ch === 0x28)
282
- depth++;
283
- else if (ch === 0x29)
284
- depth--;
285
- else if (ch === 0x2C && depth === 0)
286
- remaining--;
287
- }
288
- pos++;
289
- }
290
- return pos;
291
- }
292
- /** Read a #ID entity reference as a number. Returns -1 if not an entity ref. */
293
- function readRefId(buffer, pos, end) {
294
- while (pos < end && (buffer[pos] === 0x20 || buffer[pos] === 0x09))
295
- pos++;
296
- if (pos < end && buffer[pos] === 0x23) {
297
- pos++;
298
- let num = 0;
299
- while (pos < end && buffer[pos] >= 0x30 && buffer[pos] <= 0x39) {
300
- num = num * 10 + (buffer[pos] - 0x30);
301
- pos++;
302
- }
303
- return [num, pos];
304
- }
305
- return [-1, pos];
306
- }
307
- /** Read a list of entity refs (#id1,#id2,...) or a single #id. Returns [ids, newPos]. */
308
- function readRefList(buffer, pos, end) {
309
- while (pos < end && (buffer[pos] === 0x20 || buffer[pos] === 0x09))
310
- pos++;
311
- const ids = [];
312
- if (pos < end && buffer[pos] === 0x28) {
313
- pos++;
314
- while (pos < end && buffer[pos] !== 0x29) {
315
- while (pos < end && (buffer[pos] === 0x20 || buffer[pos] === 0x09 || buffer[pos] === 0x2C))
316
- pos++;
317
- if (pos < end && buffer[pos] === 0x23) {
318
- const [id, np] = readRefId(buffer, pos, end);
319
- if (id >= 0)
320
- ids.push(id);
321
- pos = np;
322
- }
323
- else if (pos < end && buffer[pos] !== 0x29) {
324
- pos++;
325
- }
326
- }
327
- }
328
- else if (pos < end && buffer[pos] === 0x23) {
329
- const [id, np] = readRefId(buffer, pos, end);
330
- if (id >= 0)
331
- ids.push(id);
332
- pos = np;
333
- }
334
- return [ids, pos];
335
- }
336
- /**
337
- * Extract relatingObject and relatedObjects from a relationship entity using byte-level scanning.
338
- * No TextDecoder needed - only extracts numeric entity IDs.
339
- */
340
- function extractRelFast(buffer, byteOffset, byteLength, typeUpper) {
341
- const end = byteOffset + byteLength;
342
- let pos = byteOffset;
343
- while (pos < end && buffer[pos] !== 0x28)
344
- pos++;
345
- if (pos >= end)
346
- return null;
347
- pos++;
348
- // Skip to attr[4] (all IfcRelationship subtypes have 4 shared IfcRoot+IfcRelationship attrs)
349
- pos = skipCommas(buffer, pos, end, 4);
350
- if (typeUpper === 'IFCRELCONTAINEDINSPATIALSTRUCTURE'
351
- || typeUpper === 'IFCRELREFERENCEDINSPATIALSTRUCTURE'
352
- || typeUpper === 'IFCRELDEFINESBYPROPERTIES'
353
- || typeUpper === 'IFCRELDEFINESBYTYPE') {
354
- // attr[4]=RelatedObjects, attr[5]=RelatingObject
355
- const [related, rp] = readRefList(buffer, pos, end);
356
- pos = rp;
357
- while (pos < end && buffer[pos] !== 0x2C)
358
- pos++;
359
- pos++;
360
- const [relating, _] = readRefId(buffer, pos, end);
361
- if (relating < 0 || related.length === 0)
362
- return null;
363
- return { relatingObject: relating, relatedObjects: related };
364
- }
365
- else if (typeUpper === 'IFCRELASSIGNSTOGROUP' || typeUpper === 'IFCRELASSIGNSTOPRODUCT') {
366
- const [related, rp] = readRefList(buffer, pos, end);
367
- pos = skipCommas(buffer, rp, end, 2);
368
- const [relating, _] = readRefId(buffer, pos, end);
369
- if (relating < 0 || related.length === 0)
370
- return null;
371
- return { relatingObject: relating, relatedObjects: related };
372
- }
373
- else if (typeUpper === 'IFCRELCONNECTSELEMENTS' || typeUpper === 'IFCRELCONNECTSPATHELEMENTS') {
374
- pos = skipCommas(buffer, pos, end, 1);
375
- const [relating, rp2] = readRefId(buffer, pos, end);
376
- pos = skipCommas(buffer, rp2, end, 1);
377
- const [related, _] = readRefId(buffer, pos, end);
378
- if (relating < 0 || related < 0)
379
- return null;
380
- return { relatingObject: relating, relatedObjects: [related] };
381
- }
382
- else {
383
- // Default: attr[4]=RelatingObject, attr[5]=RelatedObject(s)
384
- const [relating, rp] = readRefId(buffer, pos, end);
385
- if (relating < 0)
386
- return null;
387
- pos = rp;
388
- while (pos < end && buffer[pos] !== 0x2C)
389
- pos++;
390
- pos++;
391
- const [related, _] = readRefList(buffer, pos, end);
392
- if (related.length === 0)
393
- return null;
394
- return { relatingObject: relating, relatedObjects: related };
395
- }
396
- }
397
- /**
398
- * Extract property rel data: attr[4]=relatedObjects, attr[5]=relatingDef.
399
- * Numbers only, no TextDecoder.
400
- */
401
- function extractPropertyRelFast(buffer, byteOffset, byteLength) {
402
- const end = byteOffset + byteLength;
403
- let pos = byteOffset;
404
- while (pos < end && buffer[pos] !== 0x28)
405
- pos++;
406
- if (pos >= end)
407
- return null;
408
- pos++;
409
- pos = skipCommas(buffer, pos, end, 4);
410
- const [relatedObjects, rp] = readRefList(buffer, pos, end);
411
- pos = rp;
412
- while (pos < end && buffer[pos] !== 0x2C)
413
- pos++;
414
- pos++;
415
- const [relatingDef, _] = readRefId(buffer, pos, end);
416
- if (relatingDef < 0 || relatedObjects.length === 0)
417
- return null;
418
- return { relatedObjects, relatingDef };
419
- }
11
+ import { batchExtractGlobalIdAndName } from './columnar-parser-attributes.js';
12
+ import { GEOMETRY_TYPES, REL_TYPE_MAP, QUANTITY_TYPE_MAP, SPATIAL_TYPES, HIERARCHY_REL_TYPES, PROPERTY_REL_TYPES, ASSOCIATION_REL_TYPES, SKIP_DISPLAY_ATTRS, PROPERTY_ENTITY_TYPES, PROPERTY_CONTAINER_TYPES, isIfcTypeLikeEntity, } from './columnar-parser-indexes.js';
13
+ import { extractRelFast, extractPropertyRelFast } from './columnar-parser-relationships.js';
420
14
  function detectSchemaVersion(buffer) {
421
15
  const headerEnd = Math.min(buffer.length, 2000);
422
16
  const headerText = new TextDecoder().decode(buffer.subarray(0, headerEnd)).toUpperCase();