Browse Source

ESM: Ported Tidy operations. Updated portOperation script to attempt to find the run function and list related constants.

n1474335 7 years ago
parent
commit
66c768fe31

+ 32 - 6
src/core/config/scripts/portOperation.mjs

@@ -62,6 +62,25 @@ function main() {
     const esc = new EscapeString();
     const desc = esc.run(op.description, ["Special chars", "Double"]);
 
+    // Attempt to find the operation run function based on the JSDoc comment
+    const regex = `\\* ${opName} operation[^:]+:(?: function ?\\(input, args\\))? ?{([\\s\\S]+?)\n    }`;
+    let runFunc = "\n";
+    try {
+        runFunc = legacyFile.match(new RegExp(regex, "im"))[1];
+    } catch (err) {}
+
+
+    // List all constants in legacyFile
+    const constants = [];
+    try {
+        const constantsRegex = /\* @constant[^/]+\/\s+([^\n]+)/gim;
+        let m;
+
+        while ((m = constantsRegex.exec(legacyFile)) !== null) {
+            constants.push(m[1]);
+        }
+    } catch (err) {}
+
     const template = `/**
  * ${author}
  * ${copyright}
@@ -94,8 +113,7 @@ class ${moduleName} extends Operation {
      * @param {Object[]} args
      * @returns {${op.outputType}}
      */
-    run(input, args) {
-
+    run(input, args) {${runFunc}
     }
 ${op.highlight ? `
     /**
@@ -130,18 +148,26 @@ export default ${moduleName};
 `;
 
     console.log("\nLegacy operation config\n-----------------------\n");
-    console.log(template);
     console.log(JSON.stringify(op, null, 4));
     console.log("\n-----------------------\n");
+    console.log("\nPotentially related constants\n-----------------------\n");
+    console.log(constants.join("\n"));
+    console.log("\n-----------------------\n");
 
     const filename = path.join(dir, `../operations/${moduleName}.mjs`);
     if (fs.existsSync(filename)) {
-        console.log(`\u274c ${filename} already exists. It has NOT been overwritten.`);
+        console.log(`\x1b[31m\u274c ${filename} already exists. It has NOT been overwritten.\x1b[0m`);
         process.exit(0);
     }
     fs.writeFileSync(filename, template);
-    console.log("\u2714 Written to " + filename);
-    console.log(`Open ${legacyFilename} and copy the relevant code over. Make sure you check imports, args and highlights.`);
+
+    console.log("\x1b[32m\u2714\x1b[0m Operation written to \x1b[32m" + filename + "\x1b[0m");
+    if (runFunc === "\n") {
+        console.log("\x1b[31m\u274c The run function could not be located automatically.\x1b[0m You will have to copy it accross manually.");
+    } else {
+        console.log("\x1b[32m\u2714\x1b[0m The run function was copied across. Double check that it was copied correctly. It may rely on other functions which have not been copied.");
+    }
+    console.log(`\nOpen \x1b[32m${legacyFilename}\x1b[0m and copy any relevant code over. Make sure you check imports, args and highlights. Code required by multiple operations should be stored in /src/core/lib/`);
 }
 
 

+ 92 - 0
src/core/operations/DropBytes.mjs

@@ -0,0 +1,92 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+
+/**
+ * Drop bytes operation
+ */
+class DropBytes extends Operation {
+
+    /**
+     * DropBytes constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "Drop bytes";
+        this.module = "Default";
+        this.description = "Cuts a slice of the specified number of bytes out of the data.";
+        this.inputType = "ArrayBuffer";
+        this.outputType = "ArrayBuffer";
+        this.args = [
+            {
+                "name": "Start",
+                "type": "number",
+                "value": 0
+            },
+            {
+                "name": "Length",
+                "type": "number",
+                "value": 5
+            },
+            {
+                "name": "Apply to each line",
+                "type": "boolean",
+                "value": false
+            }
+        ];
+    }
+
+    /**
+     * @param {ArrayBuffer} input
+     * @param {Object[]} args
+     * @returns {ArrayBuffer}
+     */
+    run(input, args) {
+        const start = args[0],
+            length = args[1],
+            applyToEachLine = args[2];
+
+        if (start < 0 || length < 0)
+            throw "Error: Invalid value";
+
+        if (!applyToEachLine) {
+            const left = input.slice(0, start),
+                right = input.slice(start + length, input.byteLength);
+            const result = new Uint8Array(left.byteLength + right.byteLength);
+            result.set(new Uint8Array(left), 0);
+            result.set(new Uint8Array(right), left.byteLength);
+            return result.buffer;
+        }
+
+        // Split input into lines
+        const data = new Uint8Array(input);
+        const lines = [];
+        let line = [],
+            i;
+
+        for (i = 0; i < data.length; i++) {
+            if (data[i] === 0x0a) {
+                lines.push(line);
+                line = [];
+            } else {
+                line.push(data[i]);
+            }
+        }
+        lines.push(line);
+
+        let output = [];
+        for (i = 0; i < lines.length; i++) {
+            output = output.concat(lines[i].slice(0, start).concat(lines[i].slice(start+length, lines[i].length)));
+            output.push(0x0a);
+        }
+        return new Uint8Array(output.slice(0, output.length-1)).buffer;
+    }
+
+}
+
+export default DropBytes;

+ 70 - 0
src/core/operations/PadLines.mjs

@@ -0,0 +1,70 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+
+/**
+ * Pad lines operation
+ */
+class PadLines extends Operation {
+
+    /**
+     * PadLines constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "Pad lines";
+        this.module = "Default";
+        this.description = "Add the specified number of the specified character to the beginning or end of each line";
+        this.inputType = "string";
+        this.outputType = "string";
+        this.args = [
+            {
+                "name": "Position",
+                "type": "option",
+                "value": ["Start", "End"]
+            },
+            {
+                "name": "Length",
+                "type": "number",
+                "value": 5
+            },
+            {
+                "name": "Character",
+                "type": "binaryShortString",
+                "value": " "
+            }
+        ];
+    }
+
+    /**
+     * @param {string} input
+     * @param {Object[]} args
+     * @returns {string}
+     */
+    run(input, args) {
+        const [position, len, chr] = args,
+            lines = input.split("\n");
+        let output = "",
+            i = 0;
+
+        if (position === "Start") {
+            for (i = 0; i < lines.length; i++) {
+                output += lines[i].padStart(lines[i].length+len, chr) + "\n";
+            }
+        } else if (position === "End") {
+            for (i = 0; i < lines.length; i++) {
+                output += lines[i].padEnd(lines[i].length+len, chr) + "\n";
+            }
+        }
+
+        return output.slice(0, output.length-1);
+    }
+
+}
+
+export default PadLines;

+ 43 - 0
src/core/operations/RemoveNullBytes.mjs

@@ -0,0 +1,43 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+
+/**
+ * Remove null bytes operation
+ */
+class RemoveNullBytes extends Operation {
+
+    /**
+     * RemoveNullBytes constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "Remove null bytes";
+        this.module = "Default";
+        this.description = "Removes all null bytes (<code>0x00</code>) from the input.";
+        this.inputType = "byteArray";
+        this.outputType = "byteArray";
+        this.args = [];
+    }
+
+    /**
+     * @param {byteArray} input
+     * @param {Object[]} args
+     * @returns {byteArray}
+     */
+    run(input, args) {
+        const output = [];
+        for (let i = 0; i < input.length; i++) {
+            if (input[i] !== 0) output.push(input[i]);
+        }
+        return output;
+    }
+
+}
+
+export default RemoveNullBytes;

+ 86 - 0
src/core/operations/RemoveWhitespace.mjs

@@ -0,0 +1,86 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+
+/**
+ * Remove whitespace operation
+ */
+class RemoveWhitespace extends Operation {
+
+    /**
+     * RemoveWhitespace constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "Remove whitespace";
+        this.module = "Default";
+        this.description = "Optionally removes all spaces, carriage returns, line feeds, tabs and form feeds from the input data.<br><br>This operation also supports the removal of full stops which are sometimes used to represent non-printable bytes in ASCII output.";
+        this.inputType = "string";
+        this.outputType = "string";
+        this.args = [
+            {
+                "name": "Spaces",
+                "type": "boolean",
+                "value": true
+            },
+            {
+                "name": "Carriage returns (\\r)",
+                "type": "boolean",
+                "value": true
+            },
+            {
+                "name": "Line feeds (\\n)",
+                "type": "boolean",
+                "value": true
+            },
+            {
+                "name": "Tabs",
+                "type": "boolean",
+                "value": true
+            },
+            {
+                "name": "Form feeds (\\f)",
+                "type": "boolean",
+                "value": true
+            },
+            {
+                "name": "Full stops",
+                "type": "boolean",
+                "value": false
+            }
+        ];
+    }
+
+    /**
+     * @param {string} input
+     * @param {Object[]} args
+     * @returns {string}
+     */
+    run(input, args) {
+        const [
+            removeSpaces,
+            removeCariageReturns,
+            removeLineFeeds,
+            removeTabs,
+            removeFormFeeds,
+            removeFullStops
+        ] = args;
+        let data = input;
+
+        if (removeSpaces) data = data.replace(/ /g, "");
+        if (removeCariageReturns) data = data.replace(/\r/g, "");
+        if (removeLineFeeds) data = data.replace(/\n/g, "");
+        if (removeTabs) data = data.replace(/\t/g, "");
+        if (removeFormFeeds) data = data.replace(/\f/g, "");
+        if (removeFullStops) data = data.replace(/\./g, "");
+        return data;
+    }
+
+}
+
+export default RemoveWhitespace;

+ 86 - 0
src/core/operations/TakeBytes.mjs

@@ -0,0 +1,86 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+
+/**
+ * Take bytes operation
+ */
+class TakeBytes extends Operation {
+
+    /**
+     * TakeBytes constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "Take bytes";
+        this.module = "Default";
+        this.description = "Takes a slice of the specified number of bytes from the data.";
+        this.inputType = "ArrayBuffer";
+        this.outputType = "ArrayBuffer";
+        this.args = [
+            {
+                "name": "Start",
+                "type": "number",
+                "value": 0
+            },
+            {
+                "name": "Length",
+                "type": "number",
+                "value": 5
+            },
+            {
+                "name": "Apply to each line",
+                "type": "boolean",
+                "value": false
+            }
+        ];
+    }
+
+    /**
+     * @param {ArrayBuffer} input
+     * @param {Object[]} args
+     * @returns {ArrayBuffer}
+     */
+    run(input, args) {
+        const start = args[0],
+            length = args[1],
+            applyToEachLine = args[2];
+
+        if (start < 0 || length < 0)
+            throw "Error: Invalid value";
+
+        if (!applyToEachLine)
+            return input.slice(start, start+length);
+
+        // Split input into lines
+        const data = new Uint8Array(input);
+        const lines = [];
+        let line = [],
+            i;
+
+        for (i = 0; i < data.length; i++) {
+            if (data[i] === 0x0a) {
+                lines.push(line);
+                line = [];
+            } else {
+                line.push(data[i]);
+            }
+        }
+        lines.push(line);
+
+        let output = [];
+        for (i = 0; i < lines.length; i++) {
+            output = output.concat(lines[i].slice(start, start+length));
+            output.push(0x0a);
+        }
+        return new Uint8Array(output.slice(0, output.length-1)).buffer;
+    }
+
+}
+
+export default TakeBytes;