UNPKG

string-encode

Version:

Convert different types of JavaScript String to/from Uint8Array

274 lines (232 loc) 7.72 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.stringEncode = {})); }(this, (function (exports) { 'use strict'; /** * Convert different types of JavaScript String to/from Uint8Array. * * @author Dumitru Uzun (DUzun.Me) * @version 0.2.2 */ /*requires Uint8Array*/ /*globals escape, unescape, encodeURI, decodeURIComponent, btoa*/ var chr = String.fromCharCode; function ord(chr) { return chr.charCodeAt(0); } function buffer2bin(buf) { buf = view8(buf); return chr.apply(String, buf); } /** * Get the hex representation of a buffer (TypedArray) * * @requires String.prototype.padStart() * * @param {TypedArray} buf Uint8Array is desirable, cause it is consistent regardless of the endianness * * @return {String} The hex representation of the buf */ function buffer2hex(buf) { var bpe = buf.BYTES_PER_ELEMENT << 1; return buf.reduce(function (r, c) { return r += (c >>> 0).toString(16).padStart(bpe, '0'); }, ''); } function buffer2str(buf, asUtf8) { if (typeof buf == 'string') return buf; buf = buffer2bin(buf); if (asUtf8 !== false && !isASCII(buf)) { if (asUtf8) { buf = utf8Decode(buf); } else if (asUtf8 == undefined) { try { buf = utf8Decode(buf); } catch (err) {} } } return buf; } function str2buffer(str, asUtf8) { str = String(str); if (asUtf8 == undefined) { // Some guessing asUtf8 = hasMultibyte(str); // || !isASCII(str) } if (asUtf8) { str = utf8Encode(str); } // Smaller x2 // return new Uint8Array(String(str).split('').map(ord)); // Faster x3-4 var len = str.length; var buf = new Uint8Array(len); while (len--) { buf[len] = str.charCodeAt(len); } return buf; } var nonHexDigitRE = /[^0-9a-f]/g; /** * Read a hex string into a buffer (Uint8Array), ignoring non-hex chars. * * @param {String} str * * @return {Uint8Array} */ function hex2buffer(str) { str = str.replace(nonHexDigitRE, ''); var len = str.length; var ret = new Uint8Array(len + 1 >>> 1); for (var i = 0; i < len; i += 2) { ret[i >>> 1] = parseInt(str.slice(i, i + 2), 16); } return ret; } /** * This method is a replacement of Buffer.toString(enc) * for Browser, where Buffer is not available. * * @requires btoa * * @this {Uint8Array} * * @param {String} enc 'binary' | 'hex' | 'base64' | 'utf8' | undefined * * @return {String} */ function toString(enc) { // The Node.js equivalent would be something like: // if(typeof Buffer == 'function') { // if(enc === false) enc = 'binary'; // if(enc === true) enc = 'utf8'; // return Buffer.from(this.buffer, this.byteOffset, this.byteLength).toString(enc); // } switch (enc) { case false: case 'binary': return buffer2bin(this); case 'hex': return buffer2hex(this); case 'base64': return btoa(buffer2bin(this)); case 'utf8': enc = true; break; } return buffer2str(this, enc); } function view8(buf, start, len) { // If buf is a Buffer, we still want to make it an Uint8Array if (!start && !len && buf instanceof Uint8Array && !buf.copy) return buf; start = start >>> 0; if (len == undefined) len = buf.byteLength - start; return new Uint8Array(buf.buffer, buf.byteOffset + start, len); } var _isLittleEndian; function isLittleEndian() { if (_isLittleEndian !== undefined) return _isLittleEndian; _isLittleEndian = !!new Uint8Array(new Uint16Array([1]).buffer)[0]; isLittleEndian = function isLittleEndian() { return _isLittleEndian; }; return _isLittleEndian; } function switchEndianness32(i) { return (i & 0xFF) << 24 | (i & 0xFF00) << 8 | i >> 8 & 0xFF00 | i >> 24 & 0xFF; } function guessEncoding(str) { if (hasMultibyte(str)) return 'mb'; // @todo: test which is faster, utf8bytes() or RegExp if (isHEX(str)) return 'hex'; // if(isASCII(str)) return 'ascii'; // if(isUTF8(str)) return 'utf8'; var mbLen = utf8bytes(str); if (mbLen) return 'utf8'; if (mbLen === 0) return 'ascii'; if (mbLen === false) { mbLen = utf8bytes(str, true); if (mbLen) return '~utf8'; // UTF8, but with async characters at the edges } return 'binary'; } var hasMultibyteRE = /([^\x00-\xFF])/; var isHEXRE = /^[0-9a-f\s]*$/i; var isASCIIRE = /^[\x00-\x7F]*$/; var isUTF8RE = /^(?:[\x00-\x7F]|[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF][\x80-\xBF]|[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF])*$/; function hasMultibyte(str) { var m = hasMultibyteRE.exec(str); return m ? m[1] : false; } function isBinary(str) { return !hasMultibyte(str); } function isASCII(str) { return isASCIIRE.test(str); } function isUTF8(str) { return isUTF8RE.test(str); } function isHEX(str) { return isHEXRE.test(str); } function utf8bytes(str, allowAsyncChars) { var l = str.length, i = 0, u = 0, c, a = -1, asy = +!!allowAsyncChars; for (; i < l;) { c = str.charCodeAt(i++); if (c < 0x80) continue; // ASCII if (0xFF <= c) return false; // has multi-byte // async UTF8 character if ((c & 0xC0) == 0x80) { // Ignore async UTF8 characters at the beginning if (asy == i) { ++u; ++asy; continue; } return false; } // Check sync UTF8 bytes a = (c & 0xE0) !== 0xC0 ? (c & 0xF0) !== 0xE0 ? (c & 0xF8) !== 0xF0 ? false : 3 : 2 : 1; if (!a) return false; // Not an ASCII, nor sync UTF8 bytes for (; (u += 1) && a-- && i < l;) { c = str.charCodeAt(i++); if ((c & 0xC0) !== 0x80) { return false; // Not an ASCII, nor sync UTF8 bytes } } } // Ignore async UTF8 characters at the end if (~a && !allowAsyncChars) return false; return u; } function utf8Encode(str) { return unescape(encodeURI(str)); } function utf8Decode(str) { return decodeURIComponent(escape(str)); } exports.buffer2bin = buffer2bin; exports.buffer2hex = buffer2hex; exports.buffer2str = buffer2str; exports.chr = chr; exports.guessEncoding = guessEncoding; exports.hasMultibyte = hasMultibyte; exports.hex2buffer = hex2buffer; exports.isASCII = isASCII; exports.isBinary = isBinary; exports.isHEX = isHEX; exports.isLittleEndian = isLittleEndian; exports.isUTF8 = isUTF8; exports.ord = ord; exports.str2buffer = str2buffer; exports.switchEndianness32 = switchEndianness32; exports.toString = toString; exports.utf8Decode = utf8Decode; exports.utf8Encode = utf8Encode; exports.utf8bytes = utf8bytes; exports.view8 = view8; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=string-encode.js.map