| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- function toByteArray(bytes) {
- if (!bytes) return []
- if (bytes instanceof ArrayBuffer) return Array.prototype.slice.call(new Uint8Array(bytes))
- if (ArrayBuffer.isView(bytes)) return Array.prototype.slice.call(new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength))
- return Array.prototype.slice.call(bytes)
- }
- function bytesToBase64(bytes) {
- const source = toByteArray(bytes)
- const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
- let output = ''
- for (let index = 0; index < source.length; index += 3) {
- const first = source[index] & 0xFF
- const second = index + 1 < source.length ? source[index + 1] & 0xFF : 0
- const third = index + 2 < source.length ? source[index + 2] & 0xFF : 0
- const triple = (first << 16) | (second << 8) | third
- output += alphabet[(triple >> 18) & 0x3F]
- output += alphabet[(triple >> 12) & 0x3F]
- output += index + 1 < source.length ? alphabet[(triple >> 6) & 0x3F] : '='
- output += index + 2 < source.length ? alphabet[triple & 0x3F] : '='
- }
- return output
- }
- function bytesToBin(bytes) {
- return toByteArray(bytes).map((byte) => (byte & 0xFF).toString(2).padStart(8, '0')).join('')
- }
- function bytesToHex(bytes, separator = '') {
- return toByteArray(bytes).map((byte) => (byte & 0xFF).toString(16).toUpperCase().padStart(2, '0')).join(separator)
- }
- function readByte(bytes, offset) {
- if (!bytes) return 0
- if (bytes instanceof ArrayBuffer) return (new Uint8Array(bytes)[offset] || 0) & 0xFF
- return (bytes[offset] || 0) & 0xFF
- }
- function formatHexNumber(value, length = 2) {
- const numberValue = Math.max(0, Math.floor(Number(value) || 0))
- return numberValue.toString(16).toUpperCase().padStart(length, '0')
- }
- function readUint16BE(bytes = [], offset = 0) {
- return ((readByte(bytes, offset) << 8) | readByte(bytes, offset + 1)) & 0xFFFF
- }
- function readUint16LE(bytes = [], offset = 0) {
- return (readByte(bytes, offset) | (readByte(bytes, offset + 1) << 8)) & 0xFFFF
- }
- function readUint32BE(bytes = [], offset = 0) {
- return (
- (readByte(bytes, offset) * 0x1000000)
- + ((readByte(bytes, offset + 1) << 16) >>> 0)
- + ((readByte(bytes, offset + 2) << 8) >>> 0)
- + readByte(bytes, offset + 3)
- ) >>> 0
- }
- function readUint32LE(bytes = [], offset = 0) {
- return (
- readByte(bytes, offset)
- + ((readByte(bytes, offset + 1) << 8) >>> 0)
- + ((readByte(bytes, offset + 2) << 16) >>> 0)
- + (readByte(bytes, offset + 3) * 0x1000000)
- ) >>> 0
- }
- function splitUint16BE(value) {
- const numberValue = Number(value) & 0xFFFF
- return [(numberValue >> 8) & 0xFF, numberValue & 0xFF]
- }
- function splitUint16LE(value) {
- const numberValue = Number(value) & 0xFFFF
- return [numberValue & 0xFF, (numberValue >> 8) & 0xFF]
- }
- function splitUint32BE(value) {
- const numberValue = Number(value) >>> 0
- return [
- (numberValue >>> 24) & 0xFF,
- (numberValue >>> 16) & 0xFF,
- (numberValue >>> 8) & 0xFF,
- numberValue & 0xFF
- ]
- }
- function splitUint32LE(value) {
- const numberValue = Number(value) >>> 0
- return [
- numberValue & 0xFF,
- (numberValue >>> 8) & 0xFF,
- (numberValue >>> 16) & 0xFF,
- (numberValue >>> 24) & 0xFF
- ]
- }
- function bytesToAsciiText(bytes = []) {
- return String.fromCharCode.apply(null, trimTrailingNullBytes(bytes).map((byte) => byte & 0xFF))
- }
- function bytesToUtf8Text(bytes = []) {
- const trimmed = trimTrailingNullBytes(bytes)
- if (!trimmed.length) return ''
- let encoded = ''
- trimmed.forEach((byte) => {
- encoded += `%${(byte & 0xFF).toString(16).padStart(2, '0').toUpperCase()}`
- })
- try {
- return decodeURIComponent(encoded)
- } catch (error) {
- return bytesToAsciiText(trimmed)
- }
- }
- function decodeBytesWithTextDecoder(bytes = [], encoding) {
- if (typeof TextDecoder === 'undefined') return null
- try {
- const decoder = new TextDecoder(encoding, { fatal: true })
- return decoder.decode(new Uint8Array(bytes))
- } catch (error) {
- return null
- }
- }
- function decodeUtf8Strict(bytes = []) {
- if (!bytes.length) return ''
- let encoded = ''
- bytes.forEach((byte) => {
- encoded += `%${(byte & 0xFF).toString(16).padStart(2, '0').toUpperCase()}`
- })
- try {
- return decodeURIComponent(encoded)
- } catch (error) {
- return null
- }
- }
- function bytesToAutoText(bytes = []) {
- const trimmed = trimTrailingNullBytes(bytes)
- if (!trimmed.length) return ''
- const utf8Text = decodeBytesWithTextDecoder(trimmed, 'utf-8')
- || decodeUtf8Strict(trimmed)
- if (utf8Text !== null) return utf8Text
- const gbkText = decodeBytesWithTextDecoder(trimmed, 'gbk')
- || decodeBytesWithTextDecoder(trimmed, 'gb18030')
- if (gbkText !== null) return gbkText
- return bytesToAsciiText(trimmed)
- }
- function formatBytes(byteLength) {
- const length = Number(byteLength) || 0
- if (length >= 1024 && length % 1024 === 0) return `${length / 1024} KB`
- if (length >= 1024) return `${(length / 1024).toFixed(2)} KB`
- return `${length} bytes`
- }
- function bytesToWords(bytes = []) {
- const words = []
- for (let index = 0; index + 1 < bytes.length; index += 2) {
- const highByte = bytes[index] || 0
- const lowByte = bytes[index + 1] || 0
- words.push(((highByte << 8) | lowByte) & 0xFFFF)
- }
- return words
- }
- function bytesToWordsLE(bytes = []) {
- const words = []
- for (let index = 0; index + 1 < bytes.length; index += 2) {
- const lowByte = bytes[index] || 0
- const highByte = bytes[index + 1] || 0
- words.push(((highByte << 8) | lowByte) & 0xFFFF)
- }
- return words
- }
- function getByteFromWord(word, byteOffset = 0) {
- const value = Number(word) & 0xFFFF
- return byteOffset === 0 ? ((value >> 8) & 0xFF) : (value & 0xFF)
- }
- function stringToUtf8Bytes(text) {
- const bytes = []
- const encoded = encodeURIComponent(String(text || ''))
- for (let index = 0; index < encoded.length; index += 1) {
- const char = encoded[index]
- if (char === '%') {
- bytes.push(parseInt(encoded.slice(index + 1, index + 3), 16) & 0xFF)
- index += 2
- } else {
- bytes.push(char.charCodeAt(0) & 0xFF)
- }
- }
- return bytes
- }
- function trimTrailingNullBytes(bytes = []) {
- let end = bytes.length
- while (end > 0 && bytes[end - 1] === 0x00) {
- end -= 1
- }
- return bytes.slice(0, end)
- }
- function wordsToBytes(words = [], byteLength = words.length * 2) {
- const bytes = []
- for (let index = 0; index < words.length; index += 1) {
- const word = Number(words[index]) & 0xFFFF
- bytes.push((word >> 8) & 0xFF, word & 0xFF)
- }
- return bytes.slice(0, Math.max(0, byteLength))
- }
- function wordsToBytesLE(words = [], byteLength = words.length * 2) {
- const bytes = []
- for (let index = 0; index < words.length; index += 1) {
- const word = Number(words[index]) & 0xFFFF
- bytes.push(word & 0xFF, (word >> 8) & 0xFF)
- }
- return bytes.slice(0, Math.max(0, byteLength))
- }
- module.exports = {
- bytesToAutoText,
- bytesToBase64,
- bytesToBin,
- bytesToHex,
- bytesToAsciiText,
- bytesToUtf8Text,
- bytesToWords,
- bytesToWordsLE,
- formatBytes,
- formatHexNumber,
- getByteFromWord,
- readByte,
- readUint16BE,
- readUint16LE,
- readUint32BE,
- readUint32LE,
- splitUint16BE,
- splitUint16LE,
- splitUint32BE,
- splitUint32LE,
- stringToUtf8Bytes,
- toByteArray,
- trimTrailingNullBytes,
- wordsToBytes,
- wordsToBytesLE
- }
|