wshub: fix CalConfig.Normalise parity gaps vs C++ twin and JS client
Finding 1: strip trailing [digits] array-element suffix from Signal so one calibration entry covers an entire array signal, matching the C++ strchr truncation and the JS equivalent. Finding 2: after the 16-byte Unit truncation, drop any trailing partial UTF-8 rune so json.Marshal never emits replacement characters; keeps byte limit in sync with C++ strncpy(u, unit, kMaxUnitLen). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
47f1567a26
commit
66efd74dd5
@@ -4,11 +4,18 @@ import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"math"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// arrayIndexSuffix matches a trailing "[digits]" at the very end of a signal
|
||||
// name, used to strip array-element suffixes so one entry covers the whole
|
||||
// array. Mirrors the C++ `strchr(signal,'[')` truncation and the JS equivalent.
|
||||
var arrayIndexSuffix = regexp.MustCompile(`\[\d+\]$`)
|
||||
|
||||
// maxUnitLen bounds the calibration unit override. Mirrored by kMaxUnitLen in
|
||||
// the C++ StreamHub and MAX_UNIT_LEN in the SPA's calibration.js.
|
||||
const maxUnitLen = 16
|
||||
@@ -37,6 +44,10 @@ func calKey(source, signal string) string { return source + "\x00" + signal }
|
||||
func (c *CalConfig) Normalise() bool {
|
||||
c.Source = strings.TrimSpace(c.Source)
|
||||
c.Signal = strings.TrimSpace(c.Signal)
|
||||
// Strip a trailing "[digits]" suffix so one entry covers an entire array
|
||||
// signal. "Adc[3]" → "Adc". Must run before the empty check below so
|
||||
// that "[0]" → "" → rejected, matching C++ and JS behaviour.
|
||||
c.Signal = arrayIndexSuffix.ReplaceAllString(c.Signal, "")
|
||||
if c.Source == "" || c.Signal == "" {
|
||||
return false
|
||||
}
|
||||
@@ -49,6 +60,16 @@ func (c *CalConfig) Normalise() bool {
|
||||
c.Unit = strings.TrimSpace(c.Unit)
|
||||
if len(c.Unit) > maxUnitLen {
|
||||
c.Unit = c.Unit[:maxUnitLen]
|
||||
// The byte cut may land mid-rune. Drop any trailing partial rune so
|
||||
// the result is always valid UTF-8; json.Marshal would otherwise emit
|
||||
// replacement characters and break the save→load round-trip.
|
||||
for {
|
||||
r, size := utf8.DecodeLastRuneInString(c.Unit)
|
||||
if r != utf8.RuneError || size != 1 {
|
||||
break
|
||||
}
|
||||
c.Unit = c.Unit[:len(c.Unit)-1]
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user