@bitbybit-dev/ifc 0.0.0-stage → 1.5.0-rc.0
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.
- package/LICENSE +21 -0
- package/NOTICE +42 -0
- package/README.md +92 -2
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/lib/api/dto-registry.d.ts +8 -0
- package/lib/api/dto-registry.js +109 -0
- package/lib/api/ifc-service.d.ts +109 -0
- package/lib/api/ifc-service.js +55 -0
- package/lib/api/inputs/base-inputs.d.ts +5 -0
- package/lib/api/inputs/base-inputs.js +5 -0
- package/lib/api/inputs/ifc-inputs.d.ts +2727 -0
- package/lib/api/inputs/ifc-inputs.js +2498 -0
- package/lib/api/inputs/index.d.ts +3 -0
- package/lib/api/inputs/index.js +3 -0
- package/lib/api/resolved-inputs/index.d.ts +70 -0
- package/lib/api/resolved-inputs/index.js +1 -0
- package/lib/api/services/assemblies.d.ts +28 -0
- package/lib/api/services/assemblies.js +49 -0
- package/lib/api/services/beams.d.ts +33 -0
- package/lib/api/services/beams.js +59 -0
- package/lib/api/services/columns.d.ts +26 -0
- package/lib/api/services/columns.js +56 -0
- package/lib/api/services/defaults.constants.d.ts +44 -0
- package/lib/api/services/defaults.constants.js +44 -0
- package/lib/api/services/doors.d.ts +45 -0
- package/lib/api/services/doors.js +94 -0
- package/lib/api/services/geometry.d.ts +51 -0
- package/lib/api/services/geometry.js +87 -0
- package/lib/api/services/index.d.ts +17 -0
- package/lib/api/services/index.js +17 -0
- package/lib/api/services/materials.d.ts +46 -0
- package/lib/api/services/materials.js +86 -0
- package/lib/api/services/member-support.d.ts +7 -0
- package/lib/api/services/member-support.js +29 -0
- package/lib/api/services/members.d.ts +24 -0
- package/lib/api/services/members.js +51 -0
- package/lib/api/services/model.d.ts +244 -0
- package/lib/api/services/model.js +409 -0
- package/lib/api/services/openings.d.ts +57 -0
- package/lib/api/services/openings.js +102 -0
- package/lib/api/services/properties.d.ts +89 -0
- package/lib/api/services/properties.js +142 -0
- package/lib/api/services/quantities.d.ts +38 -0
- package/lib/api/services/quantities.js +51 -0
- package/lib/api/services/roofs.d.ts +24 -0
- package/lib/api/services/roofs.js +52 -0
- package/lib/api/services/service-support.d.ts +8 -0
- package/lib/api/services/service-support.js +37 -0
- package/lib/api/services/service-types.d.ts +3 -0
- package/lib/api/services/service-types.js +1 -0
- package/lib/api/services/site.d.ts +37 -0
- package/lib/api/services/site.js +80 -0
- package/lib/api/services/slabs.d.ts +31 -0
- package/lib/api/services/slabs.js +59 -0
- package/lib/api/services/spaces.d.ts +36 -0
- package/lib/api/services/spaces.js +64 -0
- package/lib/api/services/spatial.d.ts +54 -0
- package/lib/api/services/spatial.js +75 -0
- package/lib/api/services/walls.d.ts +140 -0
- package/lib/api/services/walls.js +268 -0
- package/lib/api/services/windows.d.ts +46 -0
- package/lib/api/services/windows.js +76 -0
- package/lib/build/assemblies.d.ts +4 -0
- package/lib/build/assemblies.js +45 -0
- package/lib/build/build-types.d.ts +345 -0
- package/lib/build/build-types.js +1 -0
- package/lib/build/checks.d.ts +6 -0
- package/lib/build/checks.js +32 -0
- package/lib/build/constants.d.ts +27 -0
- package/lib/build/constants.js +43 -0
- package/lib/build/contexts.d.ts +9 -0
- package/lib/build/contexts.js +52 -0
- package/lib/build/curves.d.ts +3 -0
- package/lib/build/curves.js +23 -0
- package/lib/build/entity-writer.d.ts +23 -0
- package/lib/build/entity-writer.js +97 -0
- package/lib/build/fillings.d.ts +7 -0
- package/lib/build/fillings.js +182 -0
- package/lib/build/georeference.d.ts +5 -0
- package/lib/build/georeference.js +44 -0
- package/lib/build/materials.d.ts +18 -0
- package/lib/build/materials.js +166 -0
- package/lib/build/math.d.ts +10 -0
- package/lib/build/math.js +47 -0
- package/lib/build/measure.d.ts +9 -0
- package/lib/build/measure.js +195 -0
- package/lib/build/moving.d.ts +4 -0
- package/lib/build/moving.js +61 -0
- package/lib/build/openings.d.ts +12 -0
- package/lib/build/openings.js +156 -0
- package/lib/build/outlines.d.ts +4 -0
- package/lib/build/outlines.js +40 -0
- package/lib/build/placement.d.ts +16 -0
- package/lib/build/placement.js +106 -0
- package/lib/build/profiles.d.ts +4 -0
- package/lib/build/profiles.js +35 -0
- package/lib/build/project.d.ts +11 -0
- package/lib/build/project.js +134 -0
- package/lib/build/properties.d.ts +10 -0
- package/lib/build/properties.js +182 -0
- package/lib/build/quantities.d.ts +7 -0
- package/lib/build/quantities.js +262 -0
- package/lib/build/relationships.d.ts +9 -0
- package/lib/build/relationships.js +67 -0
- package/lib/build/removal.d.ts +3 -0
- package/lib/build/removal.js +106 -0
- package/lib/build/representations.d.ts +6 -0
- package/lib/build/representations.js +46 -0
- package/lib/build/roof-clipping.d.ts +5 -0
- package/lib/build/roof-clipping.js +79 -0
- package/lib/build/roofs.d.ts +4 -0
- package/lib/build/roofs.js +131 -0
- package/lib/build/site.d.ts +7 -0
- package/lib/build/site.js +112 -0
- package/lib/build/slab-openings.d.ts +4 -0
- package/lib/build/slab-openings.js +71 -0
- package/lib/build/slabs-columns-beams.d.ts +8 -0
- package/lib/build/slabs-columns-beams.js +73 -0
- package/lib/build/solids.d.ts +5 -0
- package/lib/build/solids.js +33 -0
- package/lib/build/spaces.d.ts +6 -0
- package/lib/build/spaces.js +55 -0
- package/lib/build/spatial.d.ts +17 -0
- package/lib/build/spatial.js +111 -0
- package/lib/build/type-objects.d.ts +4 -0
- package/lib/build/type-objects.js +9 -0
- package/lib/build/wall-edits.d.ts +5 -0
- package/lib/build/wall-edits.js +138 -0
- package/lib/build/wall-geometry.d.ts +15 -0
- package/lib/build/wall-geometry.js +159 -0
- package/lib/build/wall-parameters.d.ts +3 -0
- package/lib/build/wall-parameters.js +47 -0
- package/lib/build/walls.d.ts +12 -0
- package/lib/build/walls.js +238 -0
- package/lib/geometry/advanced.d.ts +27 -0
- package/lib/geometry/advanced.js +292 -0
- package/lib/geometry/colours.d.ts +3 -0
- package/lib/geometry/colours.js +109 -0
- package/lib/geometry/curves.d.ts +32 -0
- package/lib/geometry/curves.js +370 -0
- package/lib/geometry/edges.constants.d.ts +5 -0
- package/lib/geometry/edges.constants.js +5 -0
- package/lib/geometry/edges.d.ts +21 -0
- package/lib/geometry/edges.js +164 -0
- package/lib/geometry/elements.d.ts +3 -0
- package/lib/geometry/elements.js +152 -0
- package/lib/geometry/errors.d.ts +3 -0
- package/lib/geometry/errors.js +6 -0
- package/lib/geometry/faceted.d.ts +31 -0
- package/lib/geometry/faceted.js +214 -0
- package/lib/geometry/geometry-types.d.ts +103 -0
- package/lib/geometry/geometry-types.js +1 -0
- package/lib/geometry/groups.d.ts +21 -0
- package/lib/geometry/groups.js +106 -0
- package/lib/geometry/items.d.ts +34 -0
- package/lib/geometry/items.js +313 -0
- package/lib/geometry/operators.d.ts +3 -0
- package/lib/geometry/operators.js +65 -0
- package/lib/geometry/profiles.d.ts +4 -0
- package/lib/geometry/profiles.js +277 -0
- package/lib/geometry/recipe-builder.d.ts +14 -0
- package/lib/geometry/recipe-builder.js +48 -0
- package/lib/geometry/references.d.ts +4 -0
- package/lib/geometry/references.js +17 -0
- package/lib/geometry/regions.d.ts +4 -0
- package/lib/geometry/regions.js +26 -0
- package/lib/geometry/surfaces.constants.d.ts +17 -0
- package/lib/geometry/surfaces.constants.js +17 -0
- package/lib/geometry/surfaces.d.ts +6 -0
- package/lib/geometry/surfaces.js +306 -0
- package/lib/geometry/swept-solids.constants.d.ts +7 -0
- package/lib/geometry/swept-solids.constants.js +6 -0
- package/lib/geometry/swept-solids.d.ts +25 -0
- package/lib/geometry/swept-solids.js +243 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +6 -0
- package/lib/model/constants.d.ts +30 -0
- package/lib/model/constants.js +30 -0
- package/lib/model/entity-lookup.d.ts +9 -0
- package/lib/model/entity-lookup.js +20 -0
- package/lib/model/guid.d.ts +7 -0
- package/lib/model/guid.js +60 -0
- package/lib/model/id-map.d.ts +10 -0
- package/lib/model/id-map.js +80 -0
- package/lib/model/index.d.ts +4 -0
- package/lib/model/index.js +2 -0
- package/lib/model/io.d.ts +6 -0
- package/lib/model/io.js +136 -0
- package/lib/model/is-model.d.ts +9 -0
- package/lib/model/is-model.js +11 -0
- package/lib/model/model-types.d.ts +111 -0
- package/lib/model/model-types.js +1 -0
- package/lib/model/overlay-indexes.d.ts +17 -0
- package/lib/model/overlay-indexes.js +69 -0
- package/lib/model/references.d.ts +2 -0
- package/lib/model/references.js +51 -0
- package/lib/model/rows-by-id.d.ts +8 -0
- package/lib/model/rows-by-id.js +39 -0
- package/lib/model/snapshot.d.ts +36 -0
- package/lib/model/snapshot.js +144 -0
- package/lib/model/source.d.ts +29 -0
- package/lib/model/source.js +172 -0
- package/lib/model/transaction.d.ts +39 -0
- package/lib/model/transaction.js +250 -0
- package/lib/model/upgrade.d.ts +2 -0
- package/lib/model/upgrade.js +78 -0
- package/lib/schema/constants.d.ts +3 -0
- package/lib/schema/constants.js +3 -0
- package/lib/schema/generated/ifc4.d.ts +2 -0
- package/lib/schema/generated/ifc4.js +1204 -0
- package/lib/schema/generated/ifc4x3.d.ts +2 -0
- package/lib/schema/generated/ifc4x3.js +1325 -0
- package/lib/schema/registry.d.ts +7 -0
- package/lib/schema/registry.js +37 -0
- package/lib/schema/schema-types.d.ts +45 -0
- package/lib/schema/schema-types.js +1 -0
- package/lib/schema/schema.d.ts +23 -0
- package/lib/schema/schema.js +136 -0
- package/lib/step/constants.d.ts +48 -0
- package/lib/step/constants.js +48 -0
- package/lib/step/encoder.d.ts +21 -0
- package/lib/step/encoder.js +321 -0
- package/lib/step/errors.d.ts +39 -0
- package/lib/step/errors.js +45 -0
- package/lib/step/file-index.d.ts +2 -0
- package/lib/step/file-index.js +221 -0
- package/lib/step/header.d.ts +4 -0
- package/lib/step/header.js +52 -0
- package/lib/step/numbers.d.ts +3 -0
- package/lib/step/numbers.js +73 -0
- package/lib/step/reader.d.ts +2 -0
- package/lib/step/reader.js +160 -0
- package/lib/step/scanner.d.ts +13 -0
- package/lib/step/scanner.js +203 -0
- package/lib/step/step-types.d.ts +170 -0
- package/lib/step/step-types.js +1 -0
- package/lib/step/strings.d.ts +2 -0
- package/lib/step/strings.js +150 -0
- package/lib/step/values.d.ts +13 -0
- package/lib/step/values.js +51 -0
- package/package.json +51 -5
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { CHAR_DOT, CHAR_LOWER_E, CHAR_MINUS, CHAR_PLUS, CHAR_UPPER_E, CHAR_ZERO, DECIMAL_RADIX } from "./constants";
|
|
2
|
+
import { isDigit } from "./scanner";
|
|
3
|
+
const MAX_EXACT_DIGITS = 15;
|
|
4
|
+
const MAX_EXACT_POWER = 22;
|
|
5
|
+
const MAX_EXPONENT_DIGITS = 4;
|
|
6
|
+
const EXACT_POWERS = Array.from({ length: MAX_EXACT_POWER + 1 }, (_, power) => Number(`1e${power}`));
|
|
7
|
+
export function formatReal(value) {
|
|
8
|
+
if (!Number.isFinite(value)) {
|
|
9
|
+
throw new RangeError(`An IFC real must be finite, not ${value}`);
|
|
10
|
+
}
|
|
11
|
+
const text = Object.is(value, -0) ? "0" : String(value);
|
|
12
|
+
const exponentAt = text.indexOf("e");
|
|
13
|
+
const mantissa = exponentAt < 0 ? text : text.slice(0, exponentAt);
|
|
14
|
+
const exponent = exponentAt < 0 ? "" : `E${text.slice(exponentAt + 1).replace("+", "")}`;
|
|
15
|
+
return `${mantissa.includes(".") ? mantissa : `${mantissa}.`}${exponent}`;
|
|
16
|
+
}
|
|
17
|
+
export function formatInteger(value) {
|
|
18
|
+
if (!Number.isSafeInteger(value)) {
|
|
19
|
+
throw new RangeError(`An IFC integer must be a whole number within the safe range, not ${value}`);
|
|
20
|
+
}
|
|
21
|
+
return String(value);
|
|
22
|
+
}
|
|
23
|
+
export function exactDecimal(bytes, start, end) {
|
|
24
|
+
let at = start;
|
|
25
|
+
const negative = bytes[at] === CHAR_MINUS;
|
|
26
|
+
if (negative || bytes[at] === CHAR_PLUS) {
|
|
27
|
+
at++;
|
|
28
|
+
}
|
|
29
|
+
let mantissa = 0;
|
|
30
|
+
let digits = 0;
|
|
31
|
+
let significant = 0;
|
|
32
|
+
let scale = 0;
|
|
33
|
+
let fraction = false;
|
|
34
|
+
for (; at < end; at++) {
|
|
35
|
+
const code = bytes[at];
|
|
36
|
+
if (code === CHAR_DOT && !fraction) {
|
|
37
|
+
fraction = true;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (!isDigit(code)) {
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
mantissa = mantissa * DECIMAL_RADIX + (code - CHAR_ZERO);
|
|
44
|
+
digits++;
|
|
45
|
+
significant += mantissa === 0 ? 0 : 1;
|
|
46
|
+
scale += fraction ? 1 : 0;
|
|
47
|
+
}
|
|
48
|
+
if (digits === 0 || significant > MAX_EXACT_DIGITS) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
let exponent = 0;
|
|
52
|
+
if (at < end && (bytes[at] === CHAR_UPPER_E || bytes[at] === CHAR_LOWER_E)) {
|
|
53
|
+
at++;
|
|
54
|
+
const negativeExponent = bytes[at] === CHAR_MINUS;
|
|
55
|
+
if (negativeExponent || bytes[at] === CHAR_PLUS) {
|
|
56
|
+
at++;
|
|
57
|
+
}
|
|
58
|
+
const first = at;
|
|
59
|
+
for (; at < end && at - first < MAX_EXPONENT_DIGITS && isDigit(bytes[at]); at++) {
|
|
60
|
+
exponent = exponent * DECIMAL_RADIX + (bytes[at] - CHAR_ZERO);
|
|
61
|
+
}
|
|
62
|
+
if (at === first) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
exponent = negativeExponent ? -exponent : exponent;
|
|
66
|
+
}
|
|
67
|
+
const power = exponent - scale;
|
|
68
|
+
if (at !== end || power < -MAX_EXACT_POWER || power > MAX_EXACT_POWER) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
const value = power < 0 ? mantissa / EXACT_POWERS[-power] : mantissa * EXACT_POWERS[power];
|
|
72
|
+
return negative ? -value : value;
|
|
73
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { CHAR_APOSTROPHE, CHAR_CLOSE, CHAR_COMMA, CHAR_DOLLAR, CHAR_DOT, CHAR_HASH, CHAR_LOWER_E, CHAR_MINUS, CHAR_OPEN, CHAR_PLUS, CHAR_QUOTE, CHAR_STAR, CHAR_UPPER_E, CHAR_ZERO, DECIMAL_RADIX, MAX_NESTING, } from "./constants";
|
|
2
|
+
import { StepSyntaxError } from "./errors";
|
|
3
|
+
import { exactDecimal } from "./numbers";
|
|
4
|
+
import { asciiText, endOfBinary, endOfString, isDigit, isNameCharacter, skipSpace, textOf } from "./scanner";
|
|
5
|
+
import { decodeString } from "./strings";
|
|
6
|
+
import { DERIVED } from "./values";
|
|
7
|
+
function readNumber(bytes, at, end) {
|
|
8
|
+
var _a;
|
|
9
|
+
let position = at;
|
|
10
|
+
if (bytes[position] === CHAR_MINUS || bytes[position] === CHAR_PLUS) {
|
|
11
|
+
position++;
|
|
12
|
+
}
|
|
13
|
+
while (position < end) {
|
|
14
|
+
const code = bytes[position];
|
|
15
|
+
const signOfExponent = (code === CHAR_MINUS || code === CHAR_PLUS) && (bytes[position - 1] === CHAR_UPPER_E || bytes[position - 1] === CHAR_LOWER_E);
|
|
16
|
+
if (!isDigit(code) && code !== CHAR_DOT && code !== CHAR_UPPER_E && code !== CHAR_LOWER_E && !signOfExponent) {
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
position++;
|
|
20
|
+
}
|
|
21
|
+
const value = (_a = exactDecimal(bytes, at, position)) !== null && _a !== void 0 ? _a : Number(asciiText(bytes, at, position));
|
|
22
|
+
if (Number.isNaN(value)) {
|
|
23
|
+
throw new StepSyntaxError("A malformed number", at);
|
|
24
|
+
}
|
|
25
|
+
if (!Number.isFinite(value)) {
|
|
26
|
+
throw new StepSyntaxError("A number too large to be finite", at);
|
|
27
|
+
}
|
|
28
|
+
return [value, position];
|
|
29
|
+
}
|
|
30
|
+
function readName(bytes, at, end) {
|
|
31
|
+
let position = at;
|
|
32
|
+
while (position < end && isNameCharacter(bytes[position])) {
|
|
33
|
+
position++;
|
|
34
|
+
}
|
|
35
|
+
return position;
|
|
36
|
+
}
|
|
37
|
+
function readReference(bytes, at, end) {
|
|
38
|
+
var _a;
|
|
39
|
+
let close = at + 1;
|
|
40
|
+
let id = 0;
|
|
41
|
+
while (close < end && isDigit(bytes[close])) {
|
|
42
|
+
id = id * DECIMAL_RADIX + (bytes[close] - CHAR_ZERO);
|
|
43
|
+
close++;
|
|
44
|
+
}
|
|
45
|
+
if (close === at + 1 || !Number.isSafeInteger(id) || isNameCharacter((_a = bytes[close]) !== null && _a !== void 0 ? _a : 0)) {
|
|
46
|
+
throw new StepSyntaxError("A reference that is not '#' followed by digits", at);
|
|
47
|
+
}
|
|
48
|
+
return [{ ref: id }, close];
|
|
49
|
+
}
|
|
50
|
+
function readEnumeration(bytes, at, end) {
|
|
51
|
+
const close = readName(bytes, at + 1, end);
|
|
52
|
+
if (bytes[close] !== CHAR_DOT) {
|
|
53
|
+
throw new StepSyntaxError("An enumeration value is never closed", at);
|
|
54
|
+
}
|
|
55
|
+
const name = asciiText(bytes, at + 1, close).toUpperCase();
|
|
56
|
+
const value = name === "T" ? true : name === "F" ? false : { enum: name };
|
|
57
|
+
return [value, close + 1];
|
|
58
|
+
}
|
|
59
|
+
function readScalar(bytes, at, end) {
|
|
60
|
+
const code = bytes[at];
|
|
61
|
+
if (code === CHAR_DOLLAR) {
|
|
62
|
+
return [null, at + 1];
|
|
63
|
+
}
|
|
64
|
+
if (code === CHAR_STAR) {
|
|
65
|
+
return [DERIVED, at + 1];
|
|
66
|
+
}
|
|
67
|
+
if (code === CHAR_HASH) {
|
|
68
|
+
return readReference(bytes, at, end);
|
|
69
|
+
}
|
|
70
|
+
if (code === CHAR_APOSTROPHE) {
|
|
71
|
+
const close = endOfString(bytes, at, end);
|
|
72
|
+
return [decodeString(textOf(bytes, at + 1, close), at), close + 1];
|
|
73
|
+
}
|
|
74
|
+
if (code === CHAR_QUOTE) {
|
|
75
|
+
const close = endOfBinary(bytes, at, end);
|
|
76
|
+
return [{ binary: textOf(bytes, at + 1, close) }, close + 1];
|
|
77
|
+
}
|
|
78
|
+
if (code === CHAR_DOT) {
|
|
79
|
+
return readEnumeration(bytes, at, end);
|
|
80
|
+
}
|
|
81
|
+
if (isDigit(code) || code === CHAR_MINUS || code === CHAR_PLUS) {
|
|
82
|
+
return readNumber(bytes, at, end);
|
|
83
|
+
}
|
|
84
|
+
throw new StepSyntaxError(`An unexpected character '${String.fromCharCode(code)}'`, at);
|
|
85
|
+
}
|
|
86
|
+
function closeFrame(stack, at, spell) {
|
|
87
|
+
const frame = stack.pop();
|
|
88
|
+
if (frame.typeName === undefined) {
|
|
89
|
+
return frame.items;
|
|
90
|
+
}
|
|
91
|
+
if (frame.items.length !== 1) {
|
|
92
|
+
throw new StepSyntaxError(`The typed value ${frame.typeName} holds ${frame.items.length} values instead of one`, at);
|
|
93
|
+
}
|
|
94
|
+
return { type: spell ? spell(frame.typeName) : frame.typeName, value: frame.items[0] };
|
|
95
|
+
}
|
|
96
|
+
function openFrame(bytes, at, end, stack) {
|
|
97
|
+
let typeName;
|
|
98
|
+
let open = at;
|
|
99
|
+
if (bytes[at] !== CHAR_OPEN) {
|
|
100
|
+
const nameEnd = readName(bytes, at, end);
|
|
101
|
+
typeName = asciiText(bytes, at, nameEnd);
|
|
102
|
+
open = skipSpace(bytes, nameEnd, end);
|
|
103
|
+
if (bytes[open] !== CHAR_OPEN) {
|
|
104
|
+
throw new StepSyntaxError(`The typed value ${typeName} has no parentheses`, at);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (stack.length > MAX_NESTING) {
|
|
108
|
+
throw new StepSyntaxError(`Values nested more than ${MAX_NESTING} deep`, at);
|
|
109
|
+
}
|
|
110
|
+
stack.push({ items: [], typeName });
|
|
111
|
+
return skipSpace(bytes, open + 1, end);
|
|
112
|
+
}
|
|
113
|
+
export function decodeArguments(bytes, start, end, spell) {
|
|
114
|
+
const root = { items: [], typeName: undefined };
|
|
115
|
+
const stack = [root];
|
|
116
|
+
let at = skipSpace(bytes, start, end);
|
|
117
|
+
let expectValue = true;
|
|
118
|
+
while (at < end) {
|
|
119
|
+
const code = bytes[at];
|
|
120
|
+
if (code === CHAR_COMMA) {
|
|
121
|
+
if (expectValue) {
|
|
122
|
+
throw new StepSyntaxError("A value is missing before a comma", at);
|
|
123
|
+
}
|
|
124
|
+
expectValue = true;
|
|
125
|
+
at = skipSpace(bytes, at + 1, end);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (code === CHAR_CLOSE) {
|
|
129
|
+
if (stack.length === 1) {
|
|
130
|
+
throw new StepSyntaxError("A closing parenthesis without an opening one", at);
|
|
131
|
+
}
|
|
132
|
+
if (expectValue && stack[stack.length - 1].items.length > 0) {
|
|
133
|
+
throw new StepSyntaxError("A value is missing before a closing parenthesis", at);
|
|
134
|
+
}
|
|
135
|
+
const value = closeFrame(stack, at, spell);
|
|
136
|
+
stack[stack.length - 1].items.push(value);
|
|
137
|
+
expectValue = false;
|
|
138
|
+
at = skipSpace(bytes, at + 1, end);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (!expectValue) {
|
|
142
|
+
throw new StepSyntaxError("Two values without a comma between them", at);
|
|
143
|
+
}
|
|
144
|
+
if (code === CHAR_OPEN || (isNameCharacter(code) && !isDigit(code))) {
|
|
145
|
+
at = openFrame(bytes, at, end, stack);
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
const [value, next] = readScalar(bytes, at, end);
|
|
149
|
+
stack[stack.length - 1].items.push(value);
|
|
150
|
+
expectValue = false;
|
|
151
|
+
at = skipSpace(bytes, next, end);
|
|
152
|
+
}
|
|
153
|
+
if (stack.length !== 1) {
|
|
154
|
+
throw new StepSyntaxError("A parenthesis is never closed", end);
|
|
155
|
+
}
|
|
156
|
+
if (expectValue && root.items.length > 0) {
|
|
157
|
+
throw new StepSyntaxError("A value is missing at the end", end);
|
|
158
|
+
}
|
|
159
|
+
return root.items;
|
|
160
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function isDigit(code: number): boolean;
|
|
2
|
+
export declare function isNameCharacter(code: number): boolean;
|
|
3
|
+
export declare function plainText(bytes: Uint8Array, start: number, end: number): string | undefined;
|
|
4
|
+
export declare function asciiText(bytes: Uint8Array, start: number, end: number): string;
|
|
5
|
+
export declare function textOf(bytes: Uint8Array, start: number, end: number): string;
|
|
6
|
+
export declare function endOfString(bytes: Uint8Array, open: number, end: number): number;
|
|
7
|
+
export declare function endOfBinary(bytes: Uint8Array, open: number, end: number): number;
|
|
8
|
+
export declare function skipSpace(bytes: Uint8Array, at: number, end: number): number;
|
|
9
|
+
export declare function closingParenthesis(bytes: Uint8Array, open: number, end: number): number;
|
|
10
|
+
export declare function referenceCapacity(bytes: Uint8Array, start: number, end: number): number;
|
|
11
|
+
export declare function referencesInto(bytes: Uint8Array, start: number, end: number, into: Int32Array): number;
|
|
12
|
+
export declare function referenceList(bytes: Uint8Array, start: number, end: number): number[] | undefined;
|
|
13
|
+
export declare function firstStringIn(bytes: Uint8Array, start: number, end: number): [number, number] | undefined;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { CHARACTERS_PER_CHUNK, DECIMAL_RADIX, CHAR_APOSTROPHE, CHAR_CLOSE, CHAR_COMMA, CHAR_HASH, CHAR_LOWER_A, CHAR_LOWER_Z, CHAR_NINE, CHAR_OPEN, CHAR_QUOTE, CHAR_SLASH, CHAR_BACKSLASH, CHAR_SPACE, CHAR_STAR, CHAR_TILDE, CHAR_UNDERSCORE, CHAR_UPPER_A, CHAR_UPPER_Z, CHAR_ZERO, MAX_EXPRESS_ID, } from "./constants";
|
|
2
|
+
import { StepSyntaxError } from "./errors";
|
|
3
|
+
const strictUtf8 = new TextDecoder("utf-8", { fatal: true });
|
|
4
|
+
export function isDigit(code) {
|
|
5
|
+
return code >= CHAR_ZERO && code <= CHAR_NINE;
|
|
6
|
+
}
|
|
7
|
+
export function isNameCharacter(code) {
|
|
8
|
+
return (code >= CHAR_UPPER_A && code <= CHAR_UPPER_Z) || (code >= CHAR_LOWER_A && code <= CHAR_LOWER_Z) || isDigit(code) || code === CHAR_UNDERSCORE;
|
|
9
|
+
}
|
|
10
|
+
function latin1(bytes) {
|
|
11
|
+
let out = "";
|
|
12
|
+
for (let at = 0; at < bytes.length; at += CHARACTERS_PER_CHUNK) {
|
|
13
|
+
out += String.fromCharCode(...bytes.subarray(at, at + CHARACTERS_PER_CHUNK));
|
|
14
|
+
}
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
export function plainText(bytes, start, end) {
|
|
18
|
+
if (end - start > CHARACTERS_PER_CHUNK) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
for (let at = start; at < end; at++) {
|
|
22
|
+
const code = bytes[at];
|
|
23
|
+
if (code < CHAR_SPACE || code > CHAR_TILDE || code === CHAR_BACKSLASH || code === CHAR_APOSTROPHE) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return String.fromCharCode(...bytes.subarray(start, end));
|
|
28
|
+
}
|
|
29
|
+
export function asciiText(bytes, start, end) {
|
|
30
|
+
return Reflect.apply(String.fromCharCode, null, bytes.subarray(start, end));
|
|
31
|
+
}
|
|
32
|
+
export function textOf(bytes, start, end) {
|
|
33
|
+
const slice = bytes.subarray(start, end);
|
|
34
|
+
try {
|
|
35
|
+
return strictUtf8.decode(slice);
|
|
36
|
+
}
|
|
37
|
+
catch (_a) {
|
|
38
|
+
return latin1(slice);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function endOfComment(bytes, open, end) {
|
|
42
|
+
for (let at = open + 2; at + 1 < end; at++) {
|
|
43
|
+
if (bytes[at] === CHAR_STAR && bytes[at + 1] === CHAR_SLASH) {
|
|
44
|
+
return at + 2;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
throw new StepSyntaxError("A comment is never closed", open);
|
|
48
|
+
}
|
|
49
|
+
export function endOfString(bytes, open, end) {
|
|
50
|
+
let at = open + 1;
|
|
51
|
+
while (at < end) {
|
|
52
|
+
if (bytes[at] === CHAR_APOSTROPHE) {
|
|
53
|
+
if (bytes[at + 1] === CHAR_APOSTROPHE) {
|
|
54
|
+
at += 2;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
return at;
|
|
58
|
+
}
|
|
59
|
+
at++;
|
|
60
|
+
}
|
|
61
|
+
throw new StepSyntaxError("A string is never closed", open);
|
|
62
|
+
}
|
|
63
|
+
export function endOfBinary(bytes, open, end) {
|
|
64
|
+
const close = bytes.indexOf(CHAR_QUOTE, open + 1);
|
|
65
|
+
if (close < 0 || close >= end) {
|
|
66
|
+
throw new StepSyntaxError("A binary value is never closed", open);
|
|
67
|
+
}
|
|
68
|
+
return close;
|
|
69
|
+
}
|
|
70
|
+
export function skipSpace(bytes, at, end) {
|
|
71
|
+
let position = at;
|
|
72
|
+
while (position < end) {
|
|
73
|
+
const code = bytes[position];
|
|
74
|
+
if (code <= CHAR_SPACE) {
|
|
75
|
+
position++;
|
|
76
|
+
}
|
|
77
|
+
else if (code === CHAR_SLASH && bytes[position + 1] === CHAR_STAR) {
|
|
78
|
+
position = endOfComment(bytes, position, end);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return position;
|
|
85
|
+
}
|
|
86
|
+
function afterQuoted(bytes, at, end) {
|
|
87
|
+
const code = bytes[at];
|
|
88
|
+
if (code === CHAR_APOSTROPHE) {
|
|
89
|
+
return endOfString(bytes, at, end) + 1;
|
|
90
|
+
}
|
|
91
|
+
if (code === CHAR_QUOTE) {
|
|
92
|
+
return endOfBinary(bytes, at, end) + 1;
|
|
93
|
+
}
|
|
94
|
+
if (code === CHAR_SLASH && bytes[at + 1] === CHAR_STAR) {
|
|
95
|
+
return endOfComment(bytes, at, end);
|
|
96
|
+
}
|
|
97
|
+
return at;
|
|
98
|
+
}
|
|
99
|
+
function isQuoteOrSlash(code) {
|
|
100
|
+
return code === CHAR_APOSTROPHE || code === CHAR_QUOTE || code === CHAR_SLASH;
|
|
101
|
+
}
|
|
102
|
+
export function closingParenthesis(bytes, open, end) {
|
|
103
|
+
let depth = 0;
|
|
104
|
+
let at = open;
|
|
105
|
+
while (at < end) {
|
|
106
|
+
const code = bytes[at];
|
|
107
|
+
if (code === CHAR_OPEN) {
|
|
108
|
+
depth++;
|
|
109
|
+
}
|
|
110
|
+
else if (code === CHAR_CLOSE) {
|
|
111
|
+
depth--;
|
|
112
|
+
if (depth === 0) {
|
|
113
|
+
return at;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else if (isQuoteOrSlash(code)) {
|
|
117
|
+
const skipped = afterQuoted(bytes, at, end);
|
|
118
|
+
if (skipped !== at) {
|
|
119
|
+
at = skipped;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
at++;
|
|
124
|
+
}
|
|
125
|
+
throw new StepSyntaxError("A parenthesis is never closed", open);
|
|
126
|
+
}
|
|
127
|
+
export function referenceCapacity(bytes, start, end) {
|
|
128
|
+
let count = 0;
|
|
129
|
+
for (let at = bytes.indexOf(CHAR_HASH, start); at >= 0 && at < end; at = bytes.indexOf(CHAR_HASH, at + 1)) {
|
|
130
|
+
count++;
|
|
131
|
+
}
|
|
132
|
+
return count;
|
|
133
|
+
}
|
|
134
|
+
export function referencesInto(bytes, start, end, into) {
|
|
135
|
+
let count = 0;
|
|
136
|
+
let at = start;
|
|
137
|
+
while (at < end) {
|
|
138
|
+
const code = bytes[at];
|
|
139
|
+
if (code === CHAR_HASH) {
|
|
140
|
+
let digits = at + 1;
|
|
141
|
+
let id = 0;
|
|
142
|
+
while (digits < end && isDigit(bytes[digits])) {
|
|
143
|
+
id = id * DECIMAL_RADIX + bytes[digits] - CHAR_ZERO;
|
|
144
|
+
digits++;
|
|
145
|
+
}
|
|
146
|
+
if (digits > at + 1 && id <= MAX_EXPRESS_ID) {
|
|
147
|
+
into[count++] = id;
|
|
148
|
+
}
|
|
149
|
+
at = digits;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (isQuoteOrSlash(code)) {
|
|
153
|
+
const skipped = afterQuoted(bytes, at, end);
|
|
154
|
+
if (skipped !== at) {
|
|
155
|
+
at = skipped;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
at++;
|
|
160
|
+
}
|
|
161
|
+
return count;
|
|
162
|
+
}
|
|
163
|
+
export function referenceList(bytes, start, end) {
|
|
164
|
+
let at = skipSpace(bytes, start, end);
|
|
165
|
+
if (bytes[at] !== CHAR_OPEN) {
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
at = skipSpace(bytes, at + 1, end);
|
|
169
|
+
const references = [];
|
|
170
|
+
while (at < end && bytes[at] !== CHAR_CLOSE) {
|
|
171
|
+
if (bytes[at] !== CHAR_HASH) {
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
let digits = at + 1;
|
|
175
|
+
let id = 0;
|
|
176
|
+
while (digits < end && isDigit(bytes[digits])) {
|
|
177
|
+
id = id * DECIMAL_RADIX + bytes[digits] - CHAR_ZERO;
|
|
178
|
+
digits++;
|
|
179
|
+
}
|
|
180
|
+
if (digits === at + 1 || id > MAX_EXPRESS_ID) {
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
references.push(id);
|
|
184
|
+
at = skipSpace(bytes, digits, end);
|
|
185
|
+
if (bytes[at] === CHAR_COMMA) {
|
|
186
|
+
at = skipSpace(bytes, at + 1, end);
|
|
187
|
+
if (bytes[at] === CHAR_CLOSE) {
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
else if (bytes[at] !== CHAR_CLOSE) {
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return at < end && skipSpace(bytes, at + 1, end) === end ? references : undefined;
|
|
196
|
+
}
|
|
197
|
+
export function firstStringIn(bytes, start, end) {
|
|
198
|
+
const open = skipSpace(bytes, start, end);
|
|
199
|
+
if (bytes[open] !== CHAR_APOSTROPHE) {
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
return [open + 1, endOfString(bytes, open, end)];
|
|
203
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A reference to another entity of the same file, by its express id: `#12` in the file.
|
|
3
|
+
* @beta
|
|
4
|
+
*/
|
|
5
|
+
export interface IfcReference {
|
|
6
|
+
/**
|
|
7
|
+
* The express id of the entity referred to.
|
|
8
|
+
*/
|
|
9
|
+
readonly ref: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* An enumeration value, written between dots: `.ELEMENT.` in the file.
|
|
13
|
+
* @beta
|
|
14
|
+
*/
|
|
15
|
+
export interface IfcEnumerationValue {
|
|
16
|
+
/**
|
|
17
|
+
* The value, in upper case.
|
|
18
|
+
*/
|
|
19
|
+
readonly enum: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A value carried with its defined type, as a select needs it: `IFCLABEL('Wall')` in the file.
|
|
23
|
+
* @beta
|
|
24
|
+
*/
|
|
25
|
+
export interface IfcTypedValue {
|
|
26
|
+
/**
|
|
27
|
+
* The defined type, in the schema's spelling, such as `IfcLabel`.
|
|
28
|
+
*/
|
|
29
|
+
readonly type: string;
|
|
30
|
+
/**
|
|
31
|
+
* The value itself.
|
|
32
|
+
*/
|
|
33
|
+
readonly value: IfcValue;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A binary value: its bits as hexadecimal digits, after a first digit that counts the unused
|
|
37
|
+
* leading bits.
|
|
38
|
+
* @beta
|
|
39
|
+
*/
|
|
40
|
+
export interface IfcBinaryValue {
|
|
41
|
+
/**
|
|
42
|
+
* The digits as the file writes them.
|
|
43
|
+
*/
|
|
44
|
+
readonly binary: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* An attribute a subtype derives from its other attributes, written `*` in the file.
|
|
48
|
+
* @beta
|
|
49
|
+
*/
|
|
50
|
+
export interface IfcDerivedValue {
|
|
51
|
+
/**
|
|
52
|
+
* Always true.
|
|
53
|
+
*/
|
|
54
|
+
readonly derived: true;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* One attribute value of an IFC entity. `null` is an unset optional attribute (`$` in the file), a
|
|
58
|
+
* number is a real or an integer as the schema says, and a list is an aggregate.
|
|
59
|
+
* @beta
|
|
60
|
+
*/
|
|
61
|
+
export type IfcValue = null | boolean | number | string | IfcReference | IfcEnumerationValue | IfcTypedValue | IfcBinaryValue | IfcDerivedValue | readonly IfcValue[];
|
|
62
|
+
/**
|
|
63
|
+
* One entity instance: its express id, its type in the schema's spelling, and its attribute values
|
|
64
|
+
* in the order the schema lists them.
|
|
65
|
+
* @beta
|
|
66
|
+
*/
|
|
67
|
+
export interface IfcEntity {
|
|
68
|
+
/**
|
|
69
|
+
* The express id, unique within the file.
|
|
70
|
+
*/
|
|
71
|
+
readonly id: number;
|
|
72
|
+
/**
|
|
73
|
+
* The entity type, in the schema's spelling, such as `IfcWall`.
|
|
74
|
+
*/
|
|
75
|
+
readonly type: string;
|
|
76
|
+
/**
|
|
77
|
+
* The attribute values, inherited attributes first, in the order a file writes them.
|
|
78
|
+
*/
|
|
79
|
+
readonly args: readonly IfcValue[];
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The HEADER section of an IFC file: what the file declares about itself.
|
|
83
|
+
* @beta
|
|
84
|
+
*/
|
|
85
|
+
export interface IfcFileHeader {
|
|
86
|
+
/**
|
|
87
|
+
* Free texts describing the file; IFC uses the first to declare the model view, such as
|
|
88
|
+
* `ViewDefinition [ReferenceView_V1.2]`.
|
|
89
|
+
*/
|
|
90
|
+
readonly description: readonly string[];
|
|
91
|
+
/**
|
|
92
|
+
* The conformance level of the file's encoding, `2;1` for files written by this library.
|
|
93
|
+
*/
|
|
94
|
+
readonly implementationLevel: string;
|
|
95
|
+
/**
|
|
96
|
+
* The name of the file.
|
|
97
|
+
*/
|
|
98
|
+
readonly name: string;
|
|
99
|
+
/**
|
|
100
|
+
* When the file was written, as ISO 8601 date and time.
|
|
101
|
+
*/
|
|
102
|
+
readonly timeStamp: string;
|
|
103
|
+
/**
|
|
104
|
+
* The people who wrote the file.
|
|
105
|
+
*/
|
|
106
|
+
readonly author: readonly string[];
|
|
107
|
+
/**
|
|
108
|
+
* The organizations of those people.
|
|
109
|
+
*/
|
|
110
|
+
readonly organization: readonly string[];
|
|
111
|
+
/**
|
|
112
|
+
* The software that encoded the file.
|
|
113
|
+
*/
|
|
114
|
+
readonly preprocessorVersion: string;
|
|
115
|
+
/**
|
|
116
|
+
* The software the data comes from.
|
|
117
|
+
*/
|
|
118
|
+
readonly originatingSystem: string;
|
|
119
|
+
/**
|
|
120
|
+
* Who approved the file.
|
|
121
|
+
*/
|
|
122
|
+
readonly authorization: string;
|
|
123
|
+
/**
|
|
124
|
+
* The schemas the data follows, such as `IFC4`.
|
|
125
|
+
*/
|
|
126
|
+
readonly schemaIdentifiers: readonly string[];
|
|
127
|
+
}
|
|
128
|
+
export interface StepHeaderEntity {
|
|
129
|
+
readonly type: string;
|
|
130
|
+
readonly args: readonly IfcValue[];
|
|
131
|
+
readonly text: string;
|
|
132
|
+
readonly offset: number;
|
|
133
|
+
}
|
|
134
|
+
export interface StepIndex {
|
|
135
|
+
readonly bytes: Uint8Array;
|
|
136
|
+
readonly count: number;
|
|
137
|
+
readonly ids: Int32Array;
|
|
138
|
+
readonly typeCodes: Uint16Array;
|
|
139
|
+
readonly typeTable: readonly string[];
|
|
140
|
+
readonly argStart: Uint32Array;
|
|
141
|
+
readonly argEnd: Uint32Array;
|
|
142
|
+
readonly rowStart: Uint32Array;
|
|
143
|
+
readonly rowEnd: Uint32Array;
|
|
144
|
+
readonly header: readonly StepHeaderEntity[];
|
|
145
|
+
readonly headerEnd: number;
|
|
146
|
+
readonly afterHeader: number;
|
|
147
|
+
readonly sectionStarts: readonly number[];
|
|
148
|
+
}
|
|
149
|
+
export interface StepRows {
|
|
150
|
+
count: number;
|
|
151
|
+
ids: Int32Array;
|
|
152
|
+
typeCodes: Uint16Array;
|
|
153
|
+
readonly typeTable: string[];
|
|
154
|
+
readonly codesOfHash: Map<number, number[]>;
|
|
155
|
+
argStart: Uint32Array;
|
|
156
|
+
argEnd: Uint32Array;
|
|
157
|
+
rowStart: Uint32Array;
|
|
158
|
+
rowEnd: Uint32Array;
|
|
159
|
+
}
|
|
160
|
+
export interface RowSpans {
|
|
161
|
+
readonly rowStart: number;
|
|
162
|
+
readonly argStart: number;
|
|
163
|
+
readonly argEnd: number;
|
|
164
|
+
readonly rowEnd: number;
|
|
165
|
+
}
|
|
166
|
+
export interface ParseFrame {
|
|
167
|
+
readonly items: IfcValue[];
|
|
168
|
+
readonly typeName: string | undefined;
|
|
169
|
+
}
|
|
170
|
+
export type TypeSpelling = (typeName: string) => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|