diff --git a/src/core/operations/FromBase45.mjs b/src/core/operations/FromBase45.mjs index 2625d782..8cb202bc 100644 --- a/src/core/operations/FromBase45.mjs +++ b/src/core/operations/FromBase45.mjs @@ -32,7 +32,12 @@ class FromBase45 extends Operation { name: "Alphabet", type: "string", value: ALPHABET - } + }, + { + name: "Remove non-alphabet chars", + type: "boolean", + value: true + }, ]; this.highlight = highlightFromBase45; @@ -46,10 +51,17 @@ class FromBase45 extends Operation { */ run(input, args) { if (!input) return []; - const alphabet = Utils.expandAlphRange(args[0]); + const alphabet = Utils.expandAlphRange(args[0]).join(""); + const removeNonAlphChars = args[1]; const res = []; + // Remove non-alphabet characters + if (removeNonAlphChars) { + const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g"); + input = input.replace(re, ""); + } + for (const triple of Utils.chunked(input, 3)) { triple.reverse(); let b = 0; diff --git a/src/core/operations/FromBase85.mjs b/src/core/operations/FromBase85.mjs index c874d5dc..31f00efc 100644 --- a/src/core/operations/FromBase85.mjs +++ b/src/core/operations/FromBase85.mjs @@ -32,6 +32,11 @@ class FromBase85 extends Operation { type: "editableOption", value: ALPHABET_OPTIONS }, + { + name: "Remove non-alphabet chars", + type: "boolean", + value: true + }, ]; } @@ -43,6 +48,7 @@ class FromBase85 extends Operation { run(input, args) { const alphabet = Utils.expandAlphRange(args[0]).join(""), encoding = alphabetName(alphabet), + removeNonAlphChars = args[1], result = []; if (alphabet.length !== 85 || @@ -50,6 +56,12 @@ class FromBase85 extends Operation { throw new OperationError("Alphabet must be of length 85"); } + // Remove non-alphabet characters + if (removeNonAlphChars) { + const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g"); + input = input.replace(re, ""); + } + if (input.length === 0) return []; const matches = input.match(/<~(.+?)~>/); @@ -69,7 +81,7 @@ class FromBase85 extends Operation { .map((chr, idx) => { const digit = alphabet.indexOf(chr); if (digit < 0 || digit > 84) { - throw `Invalid character '${chr}' at index ${idx}`; + throw `Invalid character '${chr}' at index ${i + idx}`; } return digit; }); diff --git a/tests/lib/TestRegister.mjs b/tests/lib/TestRegister.mjs index 452f3f55..69e86088 100644 --- a/tests/lib/TestRegister.mjs +++ b/tests/lib/TestRegister.mjs @@ -84,7 +84,18 @@ class TestRegister { if (result.error) { if (test.expectedError) { - ret.status = "passing"; + if (result.error.displayStr === test.expectedOutput) { + ret.status = "passing"; + } else { + console.log(result); + ret.status = "failing"; + ret.output = [ + "Expected", + "\t" + test.expectedOutput.replace(/\n/g, "\n\t"), + "Received", + "\t" + result.error.displayStr.replace(/\n/g, "\n\t"), + ].join("\n"); + } } else { ret.status = "erroring"; ret.output = result.error.displayStr; diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index b6beb081..d198c408 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -24,6 +24,7 @@ import "./tests/Base45.mjs"; import "./tests/Base58.mjs"; import "./tests/Base64.mjs"; import "./tests/Base62.mjs"; +import "./tests/Base85.mjs"; import "./tests/BitwiseOp.mjs"; import "./tests/ByteRepr.mjs"; import "./tests/CartesianProduct.mjs"; diff --git a/tests/operations/tests/Base85.mjs b/tests/operations/tests/Base85.mjs new file mode 100644 index 00000000..2cf022f9 --- /dev/null +++ b/tests/operations/tests/Base85.mjs @@ -0,0 +1,48 @@ +/** + * Base85 tests + * + * @author john19696 + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +// Example from Wikipedia +const wpExample = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure." +// Escape newline, quote & backslash +const wpOutput = "9jqo^BlbD-BleB1DJ+*+F(f,q/0JhKFCj@.4Gp$d7F!,L7@<6@)/0JDEF@3BB/F*&OCAfu2/AKYi(\ +DIb:@FD,*)+C]U=@3BN#EcYf8ATD3s@q?d$AftVqCh[NqF-FD5W8ARlolDIal(\ +DIdu\ +D.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c"; + +TestRegister.addTests([ + { + name: "To Base85", + input: wpExample, + expectedOutput: wpOutput, + recipeConfig: [ + { "op": "To Base85", + "args": ["!-u"] } + ] + }, + { + name: "From Base85", + input: wpOutput + "\n", + expectedOutput: wpExample, + recipeConfig: [ + { "op": "From Base85", + "args": ["!-u", true] } + ] + }, + { + name: "From Base85", + input: wpOutput + "v", + expectedError: true, + expectedOutput: "From Base85 - Invalid character 'v' at index 337", + recipeConfig: [ + { "op": "From Base85", + "args": ["!-u", false] } + ] + }, +]); \ No newline at end of file