| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- const {
- formatFixedValue
- } = require('../../utils/number-format.js')
- const {
- getDataType,
- isHexRegister
- } = require('./value-types.js')
- function padWordHex(value) {
- return Number(value || 0).toString(16).toUpperCase().padStart(4, '0')
- }
- function formatIntegerValue(value, dataType) {
- const type = getDataType(dataType).key
- const numberValue = Number(value)
- if (!Number.isFinite(numberValue)) return '--'
- if (type === 'int8_t') return String(((Math.round(numberValue) << 24) >> 24))
- if (type === 'uint8_t') return String(Math.round(numberValue) & 0xFF)
- if (type === 'int16_t') return String(((Math.round(numberValue) << 16) >> 16))
- if (type === 'uint16_t') return String(Math.round(numberValue) & 0xFFFF)
- if (type === 'int32_t') return String((Math.round(numberValue) | 0))
- if (type === 'uint32_t') return String(Math.round(numberValue) >>> 0)
- return String(Math.round(numberValue))
- }
- function formatHexValue(value) {
- const numberValue = Number(value)
- if (!Number.isFinite(numberValue)) return '--'
- return `0x${padWordHex(Math.round(numberValue) & 0xFFFF)}`
- }
- function formatFloatValue(value) {
- return formatFixedValue(value, 6).replace(/(\.\d*?)0+$/, '$1').replace(/\.$/, '')
- }
- function parseIntegerText(value) {
- const text = String(value === undefined || value === null ? '' : value).trim()
- if (!text) return null
- const isHex = /^[-+]?0x[0-9a-f]+$/i.test(text) || /^0x[0-9a-f]+$/i.test(text)
- const parsed = isHex ? parseInt(text, 16) : Number(text)
- return Number.isFinite(parsed) ? parsed : null
- }
- function parseHexText(value) {
- const text = String(value === undefined || value === null ? '' : value).trim()
- if (!text) return null
- const hexText = text.toUpperCase().startsWith('0X') ? text.slice(2) : text
- if (/^[0-9A-F]{1,4}$/i.test(hexText)) {
- const parsedHex = parseInt(hexText, 16)
- return Number.isFinite(parsedHex) ? parsedHex : null
- }
- return null
- }
- function getNumericRange(dataType) {
- const type = getDataType(dataType).key
- if (type === 'int8_t') return { max: 127, min: -128 }
- if (type === 'uint8_t') return { max: 0xFF, min: 0 }
- if (type === 'int16_t') return { max: 32767, min: -32768 }
- if (type === 'uint16_t') return { max: 0xFFFF, min: 0 }
- if (type === 'int32_t') return { max: 2147483647, min: -2147483648 }
- if (type === 'uint32_t') return { max: 0xFFFFFFFF, min: 0 }
- if (type === 'hex') return { max: 0xFFFF, min: 0 }
- return { max: Number.POSITIVE_INFINITY, min: Number.NEGATIVE_INFINITY }
- }
- function parseNumberText(value, dataType) {
- const text = String(value === undefined || value === null ? '' : value).trim()
- if (!text || text === '--') return null
- if (getDataType(dataType).key === 'float') {
- const parsed = Number(text)
- return Number.isFinite(parsed) ? parsed : null
- }
- if (isHexRegister(dataType)) return parseHexText(text)
- return parseIntegerText(text)
- }
- function parseRangeBoundary(value, dataType, label) {
- const text = String(value === undefined || value === null ? '' : value).trim()
- if (!text) return null
- const parsed = parseNumberText(text, dataType)
- if (parsed === null) {
- throw new Error(`${label}无效`)
- }
- return parsed
- }
- function validateNumericValue(register, value) {
- const dataType = getDataType(register.dataType).key
- const range = getNumericRange(dataType)
- const numberValue = Number(value)
- if (!Number.isFinite(numberValue)) return false
- if (dataType !== 'float' && Math.round(numberValue) !== numberValue) {
- throw new Error(`${register.name || '寄存器'} 需要整数`)
- }
- if (numberValue < range.min || numberValue > range.max) {
- throw new Error(`${register.name || '寄存器'} 超出 ${dataType} 范围`)
- }
- const minValue = parseRangeBoundary(register.minValue, dataType, `${register.name || '寄存器'} 最小值`)
- const maxValue = parseRangeBoundary(register.maxValue, dataType, `${register.name || '寄存器'} 最大值`)
- if (minValue !== null && numberValue < minValue) {
- throw new Error(`${register.name || '寄存器'} 小于限制最小值`)
- }
- if (maxValue !== null && numberValue > maxValue) {
- throw new Error(`${register.name || '寄存器'} 大于限制最大值`)
- }
- return true
- }
- function floatToBytes(value) {
- const buffer = new ArrayBuffer(4)
- const view = new DataView(buffer)
- view.setFloat32(0, Number(value), false)
- return [
- view.getUint8(0),
- view.getUint8(1),
- view.getUint8(2),
- view.getUint8(3)
- ]
- }
- function bytesToFloatValue(bytes) {
- if (!Array.isArray(bytes) || bytes.length < 4) return null
- const buffer = new ArrayBuffer(4)
- const view = new DataView(buffer)
- for (let index = 0; index < 4; index += 1) {
- view.setUint8(index, Number(bytes[index]) & 0xFF)
- }
- return view.getFloat32(0, false)
- }
- function unsignedIntegerToBytes(value, byteLength) {
- let numberValue = Math.round(Number(value) || 0)
- const bytes = []
- if (numberValue < 0) {
- numberValue += Math.pow(2, byteLength * 8)
- }
- for (let index = byteLength - 1; index >= 0; index -= 1) {
- bytes[index] = numberValue & 0xFF
- numberValue = Math.floor(numberValue / 0x100)
- }
- return bytes
- }
- function bytesToUnsignedInteger(bytes) {
- return bytes.reduce((value, byte) => ((value * 0x100) + (Number(byte) & 0xFF)), 0)
- }
- function bytesToSignedInteger(bytes) {
- const unsignedValue = bytesToUnsignedInteger(bytes)
- const signLimit = Math.pow(2, bytes.length * 8 - 1)
- const fullRange = Math.pow(2, bytes.length * 8)
- return unsignedValue >= signLimit ? unsignedValue - fullRange : unsignedValue
- }
- module.exports = {
- bytesToFloatValue,
- bytesToSignedInteger,
- bytesToUnsignedInteger,
- floatToBytes,
- formatFloatValue,
- formatHexValue,
- formatIntegerValue,
- getNumericRange,
- parseHexText,
- parseIntegerText,
- parseNumberText,
- parseRangeBoundary,
- unsignedIntegerToBytes,
- validateNumericValue
- }
|