summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author zaaarf <zaaarf@proton.me>2023-02-07 15:03:00 +0100
committer zaaarf <zaaarf@proton.me>2023-02-07 15:03:00 +0100
commitaf259809cab916fa7b4151765e875a660a37178d (patch)
tree2d3e3149cac18c1a55e23244b9b672ac5af85326
parent53c8d23cd28f35e82b44e8da865c83343f5187e2 (diff)
feat: added some more utils to InsnSequence
-rw-r--r--src/main/java/ftbsc/lll/tools/InsnSequence.java70
1 files changed, 69 insertions, 1 deletions
diff --git a/src/main/java/ftbsc/lll/tools/InsnSequence.java b/src/main/java/ftbsc/lll/tools/InsnSequence.java
index fbd5f5c..c23e5e1 100644
--- a/src/main/java/ftbsc/lll/tools/InsnSequence.java
+++ b/src/main/java/ftbsc/lll/tools/InsnSequence.java
@@ -27,5 +27,73 @@ public class InsnSequence extends InsnList implements Opcodes {
throw new InstructionMismatchException("Nodes" + getFirst() + " and " + getLast() + " are not connected.");
}
- //TODO replace
+ /**
+ * Extends the existing get function from InsnList to allow for negative indexes.
+ * @param index the index of the instruction that must be returned
+ * @return the instruction whose index is given
+ */
+ @Override
+ public AbstractInsnNode get(int index) {
+ if(index >= 0)
+ return super.get(index);
+ index = Math.abs(index);
+ if(index > size())
+ throw new IndexOutOfBoundsException();
+ return this.toArray()[size() - index];
+ }
+
+ /**
+ * Replaces a node with another one. Mostly used internally.
+ * @param oldNode node to replace
+ * @param newNode new node
+ */
+ public void replaceNode(AbstractInsnNode oldNode, AbstractInsnNode newNode) {
+ super.insert(oldNode, newNode);
+ super.remove(oldNode);
+ }
+
+ /**
+ * Replaces n occurrences of said opcode with the given node.
+ * @param opcode the opcode to replace
+ * @param newNode the replacement node
+ * @param amount how many occurrences to replace, set to 0 to replace all
+ * @return true if anything was changed, false otherwise
+ */
+ public boolean replace(int opcode, AbstractInsnNode newNode, int amount) {
+ return replace(opcode, newNode, amount, false);
+ }
+
+ /**
+ * Replaces n occurrences of said opcode with the given node.
+ * @param opcode the opcode to replace
+ * @param newNode the replacement node
+ * @param reverse whether the search should be done from the end
+ * @param amount how many occurrences to replace, set to 0 to replace all
+ * @return true if anything was changed, false otherwise
+ */
+ public boolean replace(int opcode, AbstractInsnNode newNode, int amount, boolean reverse) {
+ boolean changed = false;
+ for(AbstractInsnNode cur = this.getFirst();
+ cur != null && cur.getPrevious() != this.getLast() && cur.getNext() != this.getFirst();
+ cur = reverse ? cur.getPrevious() : cur.getNext()) {
+ if(cur.getOpcode() == opcode) {
+ this.replaceNode(cur, newNode);
+ changed = true;
+ amount--; // will go to negative if it was already 0, causing it to go on until for loop finishes
+ if(amount == 0)
+ return changed;
+ }
+ }
+ return changed;
+ }
+
+ /**
+ * Cut a number of nodes from the list.
+ * @param amount how many nodes to cut
+ * @param reverse true if should cut from the end, false otherwise
+ */
+ public void cut(int amount, boolean reverse) {
+ for(int i = 0; i < amount; i++)
+ this.remove(reverse ? getLast() : getFirst());
+ }
}