فهرست منبع

Improved performance of str/array buffer conversions

n1474335 2 سال پیش
والد
کامیت
659325c85a

+ 18 - 11
src/core/Utils.mjs

@@ -474,6 +474,7 @@ class Utils {
     static strToArrayBuffer(str) {
         log.debug(`Converting string[${str?.length}] to array buffer`);
         if (!str) return new ArrayBuffer;
+
         const arr = new Uint8Array(str.length);
         let i = str.length, b;
         while (i--) {
@@ -502,9 +503,10 @@ class Utils {
     static strToUtf8ArrayBuffer(str) {
         log.debug(`Converting string[${str?.length}] to UTF8 array buffer`);
         if (!str) return new ArrayBuffer;
-        const utf8Str = utf8.encode(str);
 
-        if (str.length !== utf8Str.length) {
+        const buffer = new TextEncoder("utf-8").encode(str);
+
+        if (str.length !== buffer.length) {
             if (isWorkerEnvironment() && self && typeof self.setOption === "function") {
                 self.setOption("attemptHighlight", false);
             } else if (isWebEnvironment()) {
@@ -512,7 +514,7 @@ class Utils {
             }
         }
 
-        return Utils.strToArrayBuffer(utf8Str);
+        return buffer.buffer;
     }
 
 
@@ -627,20 +629,24 @@ class Utils {
     static byteArrayToUtf8(byteArray) {
         log.debug(`Converting byte array[${byteArray?.length}] to UTF8`);
         if (!byteArray || !byteArray.length) return "";
-        const str = Utils.byteArrayToChars(byteArray);
+        if (!(byteArray instanceof Uint8Array))
+            byteArray = new Uint8Array(byteArray);
+
         try {
-            const utf8Str = utf8.decode(str);
-            if (str.length !== utf8Str.length) {
+            const str = new TextDecoder("utf-8", {fatal: true}).decode(byteArray);
+
+            if (str.length !== byteArray.length) {
                 if (isWorkerEnvironment()) {
                     self.setOption("attemptHighlight", false);
                 } else if (isWebEnvironment()) {
                     window.app.options.attemptHighlight = false;
                 }
             }
-            return utf8Str;
+
+            return str;
         } catch (err) {
             // If it fails, treat it as ANSI
-            return str;
+            return Utils.byteArrayToChars(byteArray);
         }
     }
 
@@ -662,9 +668,10 @@ class Utils {
         log.debug(`Converting byte array[${byteArray?.length}] to chars`);
         if (!byteArray || !byteArray.length) return "";
         let str = "";
-        // String concatenation appears to be faster than an array join
-        for (let i = 0; i < byteArray.length;) {
-            str += String.fromCharCode(byteArray[i++]);
+        // Maxiumum arg length for fromCharCode is 65535, but the stack may already be fairly deep,
+        // so don't get too near it.
+        for (let i = 0; i < byteArray.length; i += 20000) {
+            str += String.fromCharCode(...(byteArray.slice(i, i+20000)));
         }
         return str;
     }

+ 3 - 3
src/core/lib/Base64.mjs

@@ -25,12 +25,12 @@ import OperationError from "../errors/OperationError.mjs";
  */
 export function toBase64(data, alphabet="A-Za-z0-9+/=") {
     if (!data) return "";
+    if (typeof data == "string") {
+        data = Utils.strToArrayBuffer(data);
+    }
     if (data instanceof ArrayBuffer) {
         data = new Uint8Array(data);
     }
-    if (typeof data == "string") {
-        data = Utils.strToByteArray(data);
-    }
 
     alphabet = Utils.expandAlphRange(alphabet).join("");
     if (alphabet.length !== 64 && alphabet.length !== 65) { // Allow for padding

+ 1 - 1
src/core/operations/FromBCD.mjs

@@ -84,7 +84,7 @@ class FromBCD extends Operation {
                 break;
             case "Raw":
             default:
-                byteArray = Utils.strToByteArray(input);
+                byteArray = new Uint8Array(Utils.strToArrayBuffer(input));
                 byteArray.forEach(b => {
                     nibbles.push(b >>> 4);
                     nibbles.push(b & 15);

+ 3 - 3
src/core/operations/FromCharcode.mjs

@@ -26,7 +26,7 @@ class FromCharcode extends Operation {
         this.description = "Converts unicode character codes back into text.<br><br>e.g. <code>0393 03b5 03b9 03ac 20 03c3 03bf 03c5</code> becomes <code>Γειά σου</code>";
         this.infoURL = "https://wikipedia.org/wiki/Plane_(Unicode)";
         this.inputType = "string";
-        this.outputType = "byteArray";
+        this.outputType = "ArrayBuffer";
         this.args = [
             {
                 "name": "Delimiter",
@@ -44,7 +44,7 @@ class FromCharcode extends Operation {
     /**
      * @param {string} input
      * @param {Object[]} args
-     * @returns {byteArray}
+     * @returns {ArrayBuffer}
      *
      * @throws {OperationError} if base out of range
      */
@@ -77,7 +77,7 @@ class FromCharcode extends Operation {
         for (i = 0; i < bites.length; i++) {
             latin1 += Utils.chr(parseInt(bites[i], base));
         }
-        return Utils.strToByteArray(latin1);
+        return Utils.strToArrayBuffer(latin1);
     }
 
 }

+ 2 - 2
src/core/operations/HammingDistance.mjs

@@ -68,8 +68,8 @@ class HammingDistance extends Operation {
             samples[0] = fromHex(samples[0]);
             samples[1] = fromHex(samples[1]);
         } else {
-            samples[0] = Utils.strToByteArray(samples[0]);
-            samples[1] = Utils.strToByteArray(samples[1]);
+            samples[0] = new Uint8Array(Utils.strToArrayBuffer(samples[0]));
+            samples[1] = new Uint8Array(Utils.strToArrayBuffer(samples[1]));
         }
 
         let dist = 0;

+ 1 - 1
src/core/operations/ParseIPv4Header.mjs

@@ -49,7 +49,7 @@ class ParseIPv4Header extends Operation {
         if (format === "Hex") {
             input = fromHex(input);
         } else if (format === "Raw") {
-            input = Utils.strToByteArray(input);
+            input = new Uint8Array(Utils.strToArrayBuffer(input));
         } else {
             throw new OperationError("Unrecognised input format.");
         }

+ 1 - 1
src/core/operations/ParseX509Certificate.mjs

@@ -71,7 +71,7 @@ class ParseX509Certificate extends Operation {
                     cert.readCertHex(toHex(fromBase64(input, null, "byteArray"), ""));
                     break;
                 case "Raw":
-                    cert.readCertHex(toHex(Utils.strToByteArray(input), ""));
+                    cert.readCertHex(toHex(Utils.strToArrayBuffer(input), ""));
                     break;
                 default:
                     undefinedInputFormat = true;

+ 1 - 1
src/core/operations/PlayMedia.mjs

@@ -77,7 +77,7 @@ class PlayMedia extends Operation {
      * Displays an audio or video element that may be able to play the media
      * file.
      *
-     * @param data {byteArray} Data containing an audio or video file.
+     * @param {byteArray} data Data containing an audio or video file.
      * @returns {string} Markup to display a media player.
      */
     async present(data) {