From 6987e6b1b9e666ccac53708c9573d84535433e2f Mon Sep 17 00:00:00 2001 From: n1474335 Date: Mon, 7 May 2018 12:12:58 +0100 Subject: [PATCH] ESM: Ported Bit shift, MAC address and Morse Code operations. --- package-lock.json | 4 +- src/core/config/scripts/portOperation.mjs | 4 +- src/core/lib/Delim.mjs | 10 ++ src/core/operations/BitShiftLeft.mjs | 75 ++++++++++ src/core/operations/BitShiftRight.mjs | 82 +++++++++++ src/core/operations/FormatMACAddresses.mjs | 121 ++++++++++++++++ src/core/operations/FromMorseCode.mjs | 145 +++++++++++++++++++ src/core/operations/ToMorseCode.mjs | 153 +++++++++++++++++++++ 8 files changed, 591 insertions(+), 3 deletions(-) create mode 100644 src/core/operations/BitShiftLeft.mjs create mode 100644 src/core/operations/BitShiftRight.mjs create mode 100644 src/core/operations/FormatMACAddresses.mjs create mode 100644 src/core/operations/FromMorseCode.mjs create mode 100644 src/core/operations/ToMorseCode.mjs diff --git a/package-lock.json b/package-lock.json index 4c0a4842..5a573bcd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -725,8 +725,8 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-builtin-extend/-/babel-plugin-transform-builtin-extend-1.1.2.tgz", "integrity": "sha1-Xpb+z1i4+h7XTvytiEdbKvPJEW4=", "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" + "babel-runtime": "^6.2.0", + "babel-template": "^6.3.0" } }, "babel-plugin-transform-es2015-arrow-functions": { diff --git a/src/core/config/scripts/portOperation.mjs b/src/core/config/scripts/portOperation.mjs index 2fcdc707..c187707a 100644 --- a/src/core/config/scripts/portOperation.mjs +++ b/src/core/config/scripts/portOperation.mjs @@ -40,7 +40,9 @@ function main() { } const op = OP_CONFIG[opName]; - const moduleName = opName.replace(/\s/g, ""); + const moduleName = opName.replace(/\w\S*/g, txt => { + return txt.charAt(0).toUpperCase() + txt.substr(1); + }).replace(/\s/g, ""); let legacyFile = ""; diff --git a/src/core/lib/Delim.mjs b/src/core/lib/Delim.mjs index ab84f276..73f86685 100644 --- a/src/core/lib/Delim.mjs +++ b/src/core/lib/Delim.mjs @@ -15,3 +15,13 @@ export const DELIM_OPTIONS = ["Space", "Comma", "Semi-colon", "Colon", "Line fee * Binary sequence delimiters. */ export const BIN_DELIM_OPTIONS = ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "None"]; + +/** + * Letter sequence delimiters. + */ +export const LETTER_DELIM_OPTIONS = ["Space", "Line feed", "CRLF", "Forward slash", "Backslash", "Comma", "Semi-colon", "Colon"]; + +/** + * Word sequence delimiters. + */ +export const WORD_DELIM_OPTIONS = ["Line feed", "CRLF", "Forward slash", "Backslash", "Comma", "Semi-colon", "Colon"]; diff --git a/src/core/operations/BitShiftLeft.mjs b/src/core/operations/BitShiftLeft.mjs new file mode 100644 index 00000000..59c740f2 --- /dev/null +++ b/src/core/operations/BitShiftLeft.mjs @@ -0,0 +1,75 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; + +/** + * Bit shift left operation + */ +class BitShiftLeft extends Operation { + + /** + * BitShiftLeft constructor + */ + constructor() { + super(); + + this.name = "Bit shift left"; + this.module = "Default"; + this.description = "Shifts the bits in each byte towards the left by the specified amount."; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "Amount", + "type": "number", + "value": 1 + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const amount = args[0]; + + return input.map(b => { + return (b << amount) & 0xff; + }); + } + + /** + * Highlight Bit shift left + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight Bit shift left in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default BitShiftLeft; diff --git a/src/core/operations/BitShiftRight.mjs b/src/core/operations/BitShiftRight.mjs new file mode 100644 index 00000000..8207f353 --- /dev/null +++ b/src/core/operations/BitShiftRight.mjs @@ -0,0 +1,82 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; + +/** + * Bit shift right operation + */ +class BitShiftRight extends Operation { + + /** + * BitShiftRight constructor + */ + constructor() { + super(); + + this.name = "Bit shift right"; + this.module = "Default"; + this.description = "Shifts the bits in each byte towards the right by the specified amount.

Logical shifts replace the leftmost bits with zeros.
Arithmetic shifts preserve the most significant bit (MSB) of the original byte keeping the sign the same (positive or negative)."; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "Amount", + "type": "number", + "value": 1 + }, + { + "name": "Type", + "type": "option", + "value": ["Logical shift", "Arithmetic shift"] + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const amount = args[0], + type = args[1], + mask = type === "Logical shift" ? 0 : 0x80; + + return input.map(b => { + return (b >>> amount) ^ (b & mask); + }); + } + + /** + * Highlight Bit shift right + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight Bit shift right in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default BitShiftRight; diff --git a/src/core/operations/FormatMACAddresses.mjs b/src/core/operations/FormatMACAddresses.mjs new file mode 100644 index 00000000..b10fc15c --- /dev/null +++ b/src/core/operations/FormatMACAddresses.mjs @@ -0,0 +1,121 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; + +/** + * Format MAC addresses operation + */ +class FormatMACAddresses extends Operation { + + /** + * FormatMACAddresses constructor + */ + constructor() { + super(); + + this.name = "Format MAC addresses"; + this.module = "Default"; + this.description = "Displays given MAC addresses in multiple different formats.

Expects addresses in a list separated by newlines, spaces or commas.

WARNING: There are no validity checks."; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Output case", + "type": "option", + "value": ["Both", "Upper only", "Lower only"] + }, + { + "name": "No delimiter", + "type": "boolean", + "value": true + }, + { + "name": "Dash delimiter", + "type": "boolean", + "value": true + }, + { + "name": "Colon delimiter", + "type": "boolean", + "value": true + }, + { + "name": "Cisco style", + "type": "boolean", + "value": false + }, + { + "name": "IPv6 interface ID", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (!input) return ""; + + const [ + outputCase, + noDelim, + dashDelim, + colonDelim, + ciscoStyle, + ipv6IntID + ] = args, + outputList = [], + macs = input.toLowerCase().split(/[,\s\r\n]+/); + + macs.forEach(function(mac) { + const cleanMac = mac.replace(/[:.-]+/g, ""), + macHyphen = cleanMac.replace(/(.{2}(?=.))/g, "$1-"), + macColon = cleanMac.replace(/(.{2}(?=.))/g, "$1:"), + macCisco = cleanMac.replace(/(.{4}(?=.))/g, "$1."); + let macIPv6 = cleanMac.slice(0, 6) + "fffe" + cleanMac.slice(6); + + macIPv6 = macIPv6.replace(/(.{4}(?=.))/g, "$1:"); + let bite = parseInt(macIPv6.slice(0, 2), 16) ^ 2; + bite = bite.toString(16).padStart(2, "0"); + macIPv6 = bite + macIPv6.slice(2); + + if (outputCase === "Lower only") { + if (noDelim) outputList.push(cleanMac); + if (dashDelim) outputList.push(macHyphen); + if (colonDelim) outputList.push(macColon); + if (ciscoStyle) outputList.push(macCisco); + if (ipv6IntID) outputList.push(macIPv6); + } else if (outputCase === "Upper only") { + if (noDelim) outputList.push(cleanMac.toUpperCase()); + if (dashDelim) outputList.push(macHyphen.toUpperCase()); + if (colonDelim) outputList.push(macColon.toUpperCase()); + if (ciscoStyle) outputList.push(macCisco.toUpperCase()); + if (ipv6IntID) outputList.push(macIPv6.toUpperCase()); + } else { + if (noDelim) outputList.push(cleanMac, cleanMac.toUpperCase()); + if (dashDelim) outputList.push(macHyphen, macHyphen.toUpperCase()); + if (colonDelim) outputList.push(macColon, macColon.toUpperCase()); + if (ciscoStyle) outputList.push(macCisco, macCisco.toUpperCase()); + if (ipv6IntID) outputList.push(macIPv6, macIPv6.toUpperCase()); + } + + outputList.push( + "" // Empty line to delimit groups + ); + }); + + // Return the data as a string + return outputList.join("\n"); + } + +} + +export default FormatMACAddresses; diff --git a/src/core/operations/FromMorseCode.mjs b/src/core/operations/FromMorseCode.mjs new file mode 100644 index 00000000..d2361485 --- /dev/null +++ b/src/core/operations/FromMorseCode.mjs @@ -0,0 +1,145 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {LETTER_DELIM_OPTIONS, WORD_DELIM_OPTIONS} from "../lib/Delim"; + +/** + * From Morse Code operation + */ +class FromMorseCode extends Operation { + + /** + * FromMorseCode constructor + */ + constructor() { + super(); + + this.name = "From Morse Code"; + this.module = "Default"; + this.description = "Translates Morse Code into (upper case) alphanumeric characters."; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Letter delimiter", + "type": "option", + "value": LETTER_DELIM_OPTIONS + }, + { + "name": "Word delimiter", + "type": "option", + "value": WORD_DELIM_OPTIONS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (!this.reversedTable) { + this.reverseTable(); + } + + const letterDelim = Utils.charRep(args[0]); + const wordDelim = Utils.charRep(args[1]); + + input = input.replace(/-|‐|−|_|–|—|dash/ig, ""); //hyphen-minus|hyphen|minus-sign|undersore|en-dash|em-dash + input = input.replace(/\.|·|dot/ig, ""); + + let words = input.split(wordDelim); + const self = this; + words = Array.prototype.map.call(words, function(word) { + const signals = word.split(letterDelim); + + const letters = signals.map(function(signal) { + return self.reversedTable[signal]; + }); + + return letters.join(""); + }); + words = words.join(" "); + + return words; + } + + + /** + * Reverses the Morse Code lookup table + */ + reverseTable() { + this.reversedTable = {}; + + for (const letter in MORSE_TABLE) { + const signal = MORSE_TABLE[letter]; + this.reversedTable[signal] = letter; + } + } + +} + +const MORSE_TABLE = { + "A": "", + "B": "", + "C": "", + "D": "", + "E": "", + "F": "", + "G": "", + "H": "", + "I": "", + "J": "", + "K": "", + "L": "", + "M": "", + "N": "", + "O": "", + "P": "", + "Q": "", + "R": "", + "S": "", + "T": "", + "U": "", + "V": "", + "W": "", + "X": "", + "Y": "", + "Z": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "", + "6": "", + "7": "", + "8": "", + "9": "", + "0": "", + ".": "", + ",": "", + ":": "", + ";": "", + "!": "", + "?": "", + "'": "", + "\"": "", + "/": "", + "-": "", + "+": "", + "(": "", + ")": "", + "@": "", + "=": "", + "&": "", + "_": "", + "$": "" +}; + +export default FromMorseCode; diff --git a/src/core/operations/ToMorseCode.mjs b/src/core/operations/ToMorseCode.mjs new file mode 100644 index 00000000..3146a114 --- /dev/null +++ b/src/core/operations/ToMorseCode.mjs @@ -0,0 +1,153 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {LETTER_DELIM_OPTIONS, WORD_DELIM_OPTIONS} from "../lib/Delim"; + +/** + * To Morse Code operation + */ +class ToMorseCode extends Operation { + + /** + * ToMorseCode constructor + */ + constructor() { + super(); + + this.name = "To Morse Code"; + this.module = "Default"; + this.description = "Translates alphanumeric characters into International Morse Code.

Ignores non-Morse characters.

e.g. SOS becomes ... --- ..."; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Format options", + "type": "option", + "value": ["-/.", "_/.", "Dash/Dot", "DASH/DOT", "dash/dot"] + }, + { + "name": "Letter delimiter", + "type": "option", + "value": LETTER_DELIM_OPTIONS + }, + { + "name": "Word delimiter", + "type": "option", + "value": WORD_DELIM_OPTIONS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const format = args[0].split("/"); + const dash = format[0]; + const dot = format[1]; + + const letterDelim = Utils.charRep(args[1]); + const wordDelim = Utils.charRep(args[2]); + + input = input.split(/\r?\n/); + input = Array.prototype.map.call(input, function(line) { + let words = line.split(/ +/); + words = Array.prototype.map.call(words, function(word) { + const letters = Array.prototype.map.call(word, function(character) { + const letter = character.toUpperCase(); + if (typeof MORSE_TABLE[letter] == "undefined") { + return ""; + } + + return MORSE_TABLE[letter]; + }); + + return letters.join(""); + }); + line = words.join(""); + return line; + }); + input = input.join("\n"); + + input = input.replace( + /|||/g, + function(match) { + switch (match) { + case "": return dash; + case "": return dot; + case "": return letterDelim; + case "": return wordDelim; + } + } + ); + + return input; + } + +} + +const MORSE_TABLE = { + "A": "", + "B": "", + "C": "", + "D": "", + "E": "", + "F": "", + "G": "", + "H": "", + "I": "", + "J": "", + "K": "", + "L": "", + "M": "", + "N": "", + "O": "", + "P": "", + "Q": "", + "R": "", + "S": "", + "T": "", + "U": "", + "V": "", + "W": "", + "X": "", + "Y": "", + "Z": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "", + "6": "", + "7": "", + "8": "", + "9": "", + "0": "", + ".": "", + ",": "", + ":": "", + ";": "", + "!": "", + "?": "", + "'": "", + "\"": "", + "/": "", + "-": "", + "+": "", + "(": "", + ")": "", + "@": "", + "=": "", + "&": "", + "_": "", + "$": "" +}; + +export default ToMorseCode;