From 383fe50fc999880754f74c832b1e4bfd16457621 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Thu, 23 Aug 2018 23:23:00 +0100 Subject: [PATCH] Support for negative values in 'Drop bytes' and 'Take bytes'. Closes #266 --- src/core/operations/DropBytes.mjs | 48 ++++++++++++++++++++++++------- src/core/operations/TakeBytes.mjs | 46 +++++++++++++++++++++++------ 2 files changed, 75 insertions(+), 19 deletions(-) diff --git a/src/core/operations/DropBytes.mjs b/src/core/operations/DropBytes.mjs index e697f4e9..80492c34 100644 --- a/src/core/operations/DropBytes.mjs +++ b/src/core/operations/DropBytes.mjs @@ -5,7 +5,6 @@ */ import Operation from "../Operation"; -import OperationError from "../errors/OperationError"; /** * Drop bytes operation @@ -20,7 +19,7 @@ class DropBytes extends Operation { this.name = "Drop bytes"; this.module = "Default"; - this.description = "Cuts a slice of the specified number of bytes out of the data."; + this.description = "Cuts a slice of the specified number of bytes out of the data. Negative values are allowed."; this.inputType = "ArrayBuffer"; this.outputType = "ArrayBuffer"; this.args = [ @@ -50,14 +49,25 @@ class DropBytes extends Operation { * @throws {OperationError} if invalid input */ run(input, args) { - const start = args[0], - length = args[1], - applyToEachLine = args[2]; - - if (start < 0 || length < 0) - throw new OperationError("Error: Invalid value"); + let start = args[0], + length = args[1]; + const applyToEachLine = args[2]; if (!applyToEachLine) { + if (start < 0) { // Take from the end + start = input.byteLength + start; + } + + if (length < 0) { // Flip start point + start = start + length; + if (start < 0) { + start = input.byteLength + start; + length = start - length; + } else { + length = -length; + } + } + const left = input.slice(0, start), right = input.slice(start + length, input.byteLength); const result = new Uint8Array(left.byteLength + right.byteLength); @@ -82,10 +92,28 @@ class DropBytes extends Operation { } lines.push(line); - let output = []; + let output = [], + s = start, + l = length; for (i = 0; i < lines.length; i++) { - output = output.concat(lines[i].slice(0, start).concat(lines[i].slice(start+length, lines[i].length))); + if (s < 0) { // Take from the end + s = lines[i].length + s; + } + + if (l < 0) { // Flip start point + s = s + l; + if (s < 0) { + s = lines[i].length + s; + l = s - l; + } else { + l = -l; + } + } + + output = output.concat(lines[i].slice(0, s).concat(lines[i].slice(s+l, lines[i].length))); output.push(0x0a); + s = start; + l = length; } return new Uint8Array(output.slice(0, output.length-1)).buffer; } diff --git a/src/core/operations/TakeBytes.mjs b/src/core/operations/TakeBytes.mjs index 5806ee87..4bf6d951 100644 --- a/src/core/operations/TakeBytes.mjs +++ b/src/core/operations/TakeBytes.mjs @@ -5,7 +5,6 @@ */ import Operation from "../Operation"; -import OperationError from "../errors/OperationError"; /** * Take bytes operation @@ -20,7 +19,7 @@ class TakeBytes extends Operation { this.name = "Take bytes"; this.module = "Default"; - this.description = "Takes a slice of the specified number of bytes from the data."; + this.description = "Takes a slice of the specified number of bytes from the data. Negative values are allowed."; this.inputType = "ArrayBuffer"; this.outputType = "ArrayBuffer"; this.args = [ @@ -50,15 +49,27 @@ class TakeBytes extends Operation { * @throws {OperationError} if invalid value */ run(input, args) { - const start = args[0], - length = args[1], - applyToEachLine = args[2]; + let start = args[0], + length = args[1]; + const applyToEachLine = args[2]; - if (start < 0 || length < 0) - throw new OperationError("Error: Invalid value"); + if (!applyToEachLine) { + if (start < 0) { // Take from the end + start = input.byteLength + start; + } + + if (length < 0) { // Flip start point + start = start + length; + if (start < 0) { + start = input.byteLength + start; + length = start - length; + } else { + length = -length; + } + } - if (!applyToEachLine) return input.slice(start, start+length); + } // Split input into lines const data = new Uint8Array(input); @@ -77,9 +88,26 @@ class TakeBytes extends Operation { lines.push(line); let output = []; + let s = start, + l = length; for (i = 0; i < lines.length; i++) { - output = output.concat(lines[i].slice(start, start+length)); + if (s < 0) { // Take from the end + s = lines[i].length + s; + } + + if (l < 0) { // Flip start point + s = s + l; + if (s < 0) { + s = lines[i].length + s; + l = s - l; + } else { + l = -l; + } + } + output = output.concat(lines[i].slice(s, s+l)); output.push(0x0a); + s = start; + l = length; } return new Uint8Array(output.slice(0, output.length-1)).buffer; }