@cosyte/dicom 0.1.3 → 0.1.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.4
4
+
5
+ ### Patch Changes
6
+
7
+ - d21f159: Decoding a string value now takes time linear in its length, so a long run of spaces, digits, or pad bytes no longer stalls `Element.value` or `parseSpecificCharacterSet()` for seconds.
8
+
9
+ Three checks on file-controlled text used patterns that backtracked quadratically on such a run: the trim of each value of a multi-valued string VR, the DS number grammar, and the trim of each Specific Character Set term. Each now scans the value once from each end and returns the same result as before. De-identification also strips every asterisk from the conditional action branch it takes, not only the first; no row of the Annex E table puts one there today, so no output changes.
10
+
3
11
  ## 0.1.3
4
12
 
5
13
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -11,7 +11,7 @@ var __export = (target, all) => {
11
11
  };
12
12
 
13
13
  // src/version.ts
14
- var VERSION = "0.1.3";
14
+ var VERSION = "0.1.4";
15
15
 
16
16
  // src/dictionary/index.ts
17
17
  var dictionary_exports = {};
@@ -13223,7 +13223,18 @@ var MULTIBYTE_LABELS = /* @__PURE__ */ new Set([
13223
13223
  ]);
13224
13224
  function parseSpecificCharacterSet(bytes) {
13225
13225
  const raw = bytes.toString("latin1");
13226
- return raw.split("\\").map((t) => t.replace(/[ ]+$/u, "").replace(/^[ ]+/u, "")).map((t) => t === "" || TERM_TO_LABEL.has(t) ? t : WITHHELD);
13226
+ return raw.split("\\").map(trimTermPad).map((t) => t === "" || TERM_TO_LABEL.has(t) ? t : WITHHELD);
13227
+ }
13228
+ function trimTermPad(term) {
13229
+ let end = term.length;
13230
+ while (end > 0) {
13231
+ const code = term.charCodeAt(end - 1);
13232
+ if (code !== 0 && code !== 32) break;
13233
+ end--;
13234
+ }
13235
+ let start = 0;
13236
+ while (start < end && term.charCodeAt(start) === 32) start++;
13237
+ return term.slice(start, end);
13227
13238
  }
13228
13239
  function isKnownCharsetTerm(term) {
13229
13240
  return TERM_TO_LABEL.has(term);
@@ -13790,6 +13801,14 @@ function stripPad(bytes, tag, vr, position, warnings) {
13790
13801
  }
13791
13802
  return bytes.subarray(0, end);
13792
13803
  }
13804
+ function trimSpaces(value) {
13805
+ let start = 0;
13806
+ let end = value.length;
13807
+ while (start < end && value.charCodeAt(start) === SPACE2) start++;
13808
+ while (end > start && value.charCodeAt(end - 1) === SPACE2) end--;
13809
+ return value.slice(start, end);
13810
+ }
13811
+ var DECIMAL_STRING = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/u;
13793
13812
  function attachWarnings(value, warnings) {
13794
13813
  return warnings.length > 0 ? { ...value, warnings } : value;
13795
13814
  }
@@ -13841,7 +13860,7 @@ function decodeElementValue(element) {
13841
13860
  }
13842
13861
  if (vr === "LO" || vr === "SH" || vr === "UC") {
13843
13862
  const text = decodeCharsetString(trimmed, tag, vr, charset, position, warnings);
13844
- const values = text.split("\\").map((v) => v.replace(/^ +| +$/gu, ""));
13863
+ const values = text.split("\\").map(trimSpaces);
13845
13864
  return attachWarnings({ kind: "strings", values }, warnings);
13846
13865
  }
13847
13866
  if (vr === "LT" || vr === "ST" || vr === "UT") {
@@ -13854,7 +13873,7 @@ function decodeElementValue(element) {
13854
13873
  }
13855
13874
  if (vr === "AE" || vr === "CS" || vr === "AS" || vr === "UI") {
13856
13875
  const text = decodeAsciiString(trimmed, tag, vr, position, warnings);
13857
- const values = text.split("\\").map((v) => v.replace(/^ +| +$/gu, ""));
13876
+ const values = text.split("\\").map(trimSpaces);
13858
13877
  return attachWarnings({ kind: "strings", values }, warnings);
13859
13878
  }
13860
13879
  if (vr === "DS") {
@@ -13862,7 +13881,7 @@ function decodeElementValue(element) {
13862
13881
  const values = text.split("\\").map((v) => {
13863
13882
  const t = v.trim();
13864
13883
  if (t.length === 0) return null;
13865
- if (!/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/u.test(t)) return null;
13884
+ if (!DECIMAL_STRING.test(t)) return null;
13866
13885
  const n = Number(t);
13867
13886
  return Number.isFinite(n) ? n : null;
13868
13887
  });
@@ -16695,7 +16714,7 @@ function effectiveCode(action, active) {
16695
16714
  return action.basicProfile;
16696
16715
  }
16697
16716
  function resolveAction(code) {
16698
- const first = code.split("/", 1)[0]?.replace("*", "") ?? "K";
16717
+ const first = code.split("/", 1)[0]?.replaceAll("*", "") ?? "K";
16699
16718
  return first;
16700
16719
  }
16701
16720
  var TEXT_DUMMIES = {