summaryrefslogtreecommitdiff
path: root/dx/src/com/android/dx/cf/code/SwitchList.java
diff options
context:
space:
mode:
Diffstat (limited to 'dx/src/com/android/dx/cf/code/SwitchList.java')
-rw-r--r--dx/src/com/android/dx/cf/code/SwitchList.java193
1 files changed, 193 insertions, 0 deletions
diff --git a/dx/src/com/android/dx/cf/code/SwitchList.java b/dx/src/com/android/dx/cf/code/SwitchList.java
new file mode 100644
index 0000000..621d728
--- /dev/null
+++ b/dx/src/com/android/dx/cf/code/SwitchList.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dx.cf.code;
+
+import com.android.dx.util.IntList;
+import com.android.dx.util.MutabilityControl;
+
+/**
+ * List of (value, target) mappings representing the choices of a
+ * {@code tableswitch} or {@code lookupswitch} instruction. It
+ * also holds the default target for the switch.
+ */
+public final class SwitchList extends MutabilityControl {
+ /** {@code non-null;} list of test values */
+ private final IntList values;
+
+ /**
+ * {@code non-null;} list of targets corresponding to the test values; there
+ * is always one extra element in the target list, to hold the
+ * default target
+ */
+ private final IntList targets;
+
+ /** ultimate size of the list */
+ private int size;
+
+ /**
+ * Constructs an instance.
+ *
+ * @param size {@code >= 0;} the number of elements to be in the table
+ */
+ public SwitchList(int size) {
+ super(true);
+ this.values = new IntList(size);
+ this.targets = new IntList(size + 1);
+ this.size = size;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setImmutable() {
+ values.setImmutable();
+ targets.setImmutable();
+ super.setImmutable();
+ }
+
+ /**
+ * Gets the size of the list.
+ *
+ * @return {@code >= 0;} the list size
+ */
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Gets the indicated test value.
+ *
+ * @param n {@code >= 0;}, < size(); which index
+ * @return the test value
+ */
+ public int getValue(int n) {
+ return values.get(n);
+ }
+
+ /**
+ * Gets the indicated target. Asking for the target at {@code size()}
+ * returns the default target.
+ *
+ * @param n {@code >= 0, <= size();} which index
+ * @return {@code >= 0;} the target
+ */
+ public int getTarget(int n) {
+ return targets.get(n);
+ }
+
+ /**
+ * Gets the default target. This is just a shorthand for
+ * {@code getTarget(size())}.
+ *
+ * @return {@code >= 0;} the default target
+ */
+ public int getDefaultTarget() {
+ return targets.get(size);
+ }
+
+ /**
+ * Gets the list of all targets. This includes one extra element at the
+ * end of the list, which holds the default target.
+ *
+ * @return {@code non-null;} the target list
+ */
+ public IntList getTargets() {
+ return targets;
+ }
+
+ /**
+ * Gets the list of all case values.
+ *
+ * @return {@code non-null;} the case value list
+ */
+ public IntList getValues() {
+ return values;
+ }
+
+ /**
+ * Sets the default target. It is only valid to call this method
+ * when all the non-default elements have been set.
+ *
+ * @param target {@code >= 0;} the absolute (not relative) default target
+ * address
+ */
+ public void setDefaultTarget(int target) {
+ throwIfImmutable();
+
+ if (target < 0) {
+ throw new IllegalArgumentException("target < 0");
+ }
+
+ if (targets.size() != size) {
+ throw new RuntimeException("non-default elements not all set");
+ }
+
+ targets.add(target);
+ }
+
+ /**
+ * Adds the given item.
+ *
+ * @param value the test value
+ * @param target {@code >= 0;} the absolute (not relative) target address
+ */
+ public void add(int value, int target) {
+ throwIfImmutable();
+
+ if (target < 0) {
+ throw new IllegalArgumentException("target < 0");
+ }
+
+ values.add(value);
+ targets.add(target);
+ }
+
+ /**
+ * Shrinks this instance if possible, removing test elements that
+ * refer to the default target. This is only valid after the instance
+ * is fully populated, including the default target (naturally).
+ */
+ public void removeSuperfluousDefaults() {
+ throwIfImmutable();
+
+ int sz = size;
+
+ if (sz != (targets.size() - 1)) {
+ throw new IllegalArgumentException("incomplete instance");
+ }
+
+ int defaultTarget = targets.get(sz);
+ int at = 0;
+
+ for (int i = 0; i < sz; i++) {
+ int target = targets.get(i);
+ if (target != defaultTarget) {
+ if (i != at) {
+ targets.set(at, target);
+ values.set(at, values.get(i));
+ }
+ at++;
+ }
+ }
+
+ if (at != sz) {
+ values.shrink(at);
+ targets.set(at, defaultTarget);
+ targets.shrink(at + 1);
+ size = at;
+ }
+ }
+}