fix(calibration.js): cap unit at 16 UTF-8 bytes, matching both hubs
normaliseCal was using String.length/.slice() (UTF-16 code units), so multi-byte characters like °, Ω, µ could slip through oversized. Now uses TextEncoder to slice at 16 bytes, then repairs any incomplete trailing UTF-8 sequence by walking back over continuation bytes to find the lead byte and dropping the incomplete rune — exactly mirroring Go's utf8.DecodeLastRuneInString loop and the C++ walk-back in StreamHub::SetCalibrationEntry. Adds 4 new test cases covering the non-ASCII/boundary scenarios, and corrects the canonical test command in the task-6 report to 'cd Client/udpstreamer && node --test'. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
21d084d2ea
commit
48d62c1f80
@@ -41,7 +41,42 @@
|
||||
if (!isFiniteNum(scale) || scale === 0) return null;
|
||||
if (!isFiniteNum(offset)) return null;
|
||||
var unit = String(obj.unit == null ? '' : obj.unit).trim();
|
||||
if (unit.length > MAX_UNIT_LEN) unit = unit.slice(0, MAX_UNIT_LEN);
|
||||
// Cap at MAX_UNIT_LEN UTF-8 bytes, matching both hubs' Normalise() exactly.
|
||||
// TextEncoder/TextDecoder are available natively in all modern browsers and
|
||||
// Node v11+; no build step or bundler is needed.
|
||||
var enc = new TextEncoder();
|
||||
var bytes = enc.encode(unit);
|
||||
if (bytes.length > MAX_UNIT_LEN) {
|
||||
// Truncate to MAX_UNIT_LEN bytes, then repair any split UTF-8 rune at the
|
||||
// tail. Mirrors Go's utf8.DecodeLastRuneInString walk-back loop and the
|
||||
// C++ repair loop in StreamHub::SetCalibrationEntry:
|
||||
// Drop continuation bytes (10xxxxxx) from the tail until the last byte
|
||||
// is either an ASCII byte (< 0x80) or a lead byte whose sequence is
|
||||
// complete (i.e. all expected continuation bytes are present).
|
||||
var b = bytes.slice(0, MAX_UNIT_LEN);
|
||||
var len = b.length;
|
||||
// Walk back over continuation bytes (up to 3) to find the lead byte of
|
||||
// the last sequence.
|
||||
var cont = 0;
|
||||
while (cont < 3 && cont < len && (b[len - 1 - cont] & 0xC0) === 0x80) {
|
||||
cont++;
|
||||
}
|
||||
if (cont < len) {
|
||||
var lead = b[len - 1 - cont];
|
||||
// Determine expected sequence length from the lead byte.
|
||||
var seqLen = lead < 0x80 ? 1 : // 0xxxxxxx ASCII
|
||||
(lead & 0xE0) === 0xC0 ? 2 : // 110xxxxx
|
||||
(lead & 0xF0) === 0xE0 ? 3 : // 1110xxxx
|
||||
(lead & 0xF8) === 0xF0 ? 4 : // 11110xxx
|
||||
1; // orphaned continuation byte — treat as 1
|
||||
var haveBytes = cont + 1; // lead + continuation bytes present
|
||||
if (haveBytes < seqLen) {
|
||||
// Incomplete sequence: drop the lead byte and all its continuations.
|
||||
len = len - haveBytes;
|
||||
}
|
||||
}
|
||||
unit = new TextDecoder().decode(b.slice(0, len));
|
||||
}
|
||||
return {source: source, signal: signal, scale: scale, offset: offset, unit: unit};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user