| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- const BYTE_MIN = 0
- const BYTE_MAX = 0xFF
- const CONTROL_LABELS = {
- 0x00: 'NUL',
- 0x01: 'SOH',
- 0x02: 'STX',
- 0x03: 'ETX',
- 0x04: 'EOT',
- 0x05: 'ENQ',
- 0x06: 'ACK',
- 0x07: 'BEL',
- 0x08: 'BS',
- 0x09: '\\t',
- 0x0A: '\\n',
- 0x0B: 'VT',
- 0x0C: '\\f',
- 0x0D: '\\r',
- 0x0E: 'SO',
- 0x0F: 'SI',
- 0x10: 'DLE',
- 0x11: 'DC1',
- 0x12: 'DC2',
- 0x13: 'DC3',
- 0x14: 'DC4',
- 0x15: 'NAK',
- 0x16: 'SYN',
- 0x17: 'ETB',
- 0x18: 'CAN',
- 0x19: 'EM',
- 0x1A: 'SUB',
- 0x1B: 'ESC',
- 0x1C: 'FS',
- 0x1D: 'GS',
- 0x1E: 'RS',
- 0x1F: 'US',
- 0x20: 'SP',
- 0x7F: 'DEL'
- }
- function formatHexByte(value) {
- return `0x${(Number(value) & BYTE_MAX).toString(16).toUpperCase().padStart(2, '0')}`
- }
- function getDefaultRows() {
- return [
- { label: '字符', meta: '', value: '--', copyValue: '' },
- { label: 'HEX', meta: '', value: '--', copyValue: '' },
- { label: 'DEC', meta: '', value: '--', copyValue: '' }
- ]
- }
- function createEmptyResultState() {
- return {
- asciiCodeErrorText: '',
- asciiCodeResultRows: getDefaultRows()
- }
- }
- function splitValueTokens(text) {
- return String(text || '')
- .trim()
- .split(/[\s,;,;]+/)
- .map((token) => token.trim())
- .filter(Boolean)
- }
- function tokenLooksNumeric(token) {
- return /^0x/i.test(token) || /^\d+$/.test(token)
- }
- function tokenIsValidNumeric(token) {
- return /^0x[0-9a-f]+$/i.test(token) || /^\d+$/.test(token)
- }
- function shouldParseAsNumeric(text) {
- const tokens = splitValueTokens(text)
- if (!tokens.length) return false
- return tokens.every(tokenLooksNumeric)
- }
- function parseNumericToken(token) {
- if (!tokenIsValidNumeric(token)) {
- throw new Error('数值格式无效')
- }
- const value = /^0x/i.test(token)
- ? parseInt(token.slice(2), 16)
- : Number(token)
- if (!Number.isInteger(value) || value < BYTE_MIN || value > BYTE_MAX) {
- throw new Error('数值范围需为 0 - 255')
- }
- return value
- }
- function parseNumericBytes(text) {
- return splitValueTokens(text).map(parseNumericToken)
- }
- function parseTextBytes(text) {
- const bytes = []
- Array.from(String(text || '')).forEach((char) => {
- const value = char.codePointAt(0)
- if (!Number.isInteger(value) || value < BYTE_MIN || value > BYTE_MAX) {
- throw new Error('字符需在 0 - 255 范围内')
- }
- bytes.push(value)
- })
- return bytes
- }
- function formatChar(value) {
- const byte = Number(value) & BYTE_MAX
- if (Object.prototype.hasOwnProperty.call(CONTROL_LABELS, byte)) return CONTROL_LABELS[byte]
- if (byte >= 0x21 && byte <= 0x7E) return String.fromCharCode(byte)
- return `\\x${byte.toString(16).toUpperCase().padStart(2, '0')}`
- }
- function formatDisplayText(bytes = []) {
- if (!bytes.length) return '--'
- if (bytes.every((byte) => {
- const value = Number(byte) & BYTE_MAX
- return value >= 0x21 && value <= 0x7E
- })) {
- return bytes.map((byte) => String.fromCharCode(Number(byte) & BYTE_MAX)).join('')
- }
- return bytes.map(formatChar).join(' ')
- }
- function bytesToText(bytes = []) {
- return bytes.map((byte) => String.fromCharCode(Number(byte) & BYTE_MAX)).join('')
- }
- function createResultRows(bytes = []) {
- if (!bytes.length) return getDefaultRows()
- const hexText = bytes.map(formatHexByte).join(' ')
- const decText = bytes.map((byte) => String(Number(byte) & BYTE_MAX)).join(' ')
- const charText = formatDisplayText(bytes)
- return [
- {
- copyValue: bytesToText(bytes),
- label: '字符',
- value: charText
- },
- {
- copyValue: hexText,
- label: 'HEX',
- value: hexText
- },
- {
- copyValue: decText,
- label: 'DEC',
- value: decText
- }
- ]
- }
- function buildState(source = {}) {
- const inputText = String(source.asciiCodeInputText || '')
- const trimmedText = inputText.trim()
- if (!trimmedText) {
- return {
- asciiCodeInputText: inputText,
- ...createEmptyResultState()
- }
- }
- try {
- const numericMode = shouldParseAsNumeric(trimmedText)
- const bytes = numericMode ? parseNumericBytes(trimmedText) : parseTextBytes(inputText)
- return {
- asciiCodeErrorText: '',
- asciiCodeInputText: inputText,
- asciiCodeResultRows: createResultRows(bytes)
- }
- } catch (error) {
- return {
- asciiCodeErrorText: error && error.message ? error.message : '转换失败',
- asciiCodeInputText: inputText,
- asciiCodeResultRows: getDefaultRows()
- }
- }
- }
- function createInitialState() {
- return buildState({
- asciiCodeInputText: ''
- })
- }
- function updateState(state, changedData = {}) {
- return buildState({
- ...state,
- ...changedData
- })
- }
- function clearInput(state = {}) {
- return updateState(state, {
- asciiCodeInputText: ''
- })
- }
- module.exports = {
- clearInput,
- createInitialState,
- formatHexByte,
- updateState
- }
|