summaryrefslogtreecommitdiff
path: root/dx/src/com/android/dx/rop/cst/StdConstantPool.java
diff options
context:
space:
mode:
Diffstat (limited to 'dx/src/com/android/dx/rop/cst/StdConstantPool.java')
-rw-r--r--dx/src/com/android/dx/rop/cst/StdConstantPool.java139
1 files changed, 139 insertions, 0 deletions
diff --git a/dx/src/com/android/dx/rop/cst/StdConstantPool.java b/dx/src/com/android/dx/rop/cst/StdConstantPool.java
new file mode 100644
index 0000000..244395d
--- /dev/null
+++ b/dx/src/com/android/dx/rop/cst/StdConstantPool.java
@@ -0,0 +1,139 @@
+/*
+ * 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.rop.cst;
+
+import com.android.dx.util.ExceptionWithContext;
+import com.android.dx.util.Hex;
+import com.android.dx.util.MutabilityControl;
+
+/**
+ * Standard implementation of {@link ConstantPool}, which directly stores
+ * an array of {@link Constant} objects and can be made immutable.
+ */
+public final class StdConstantPool
+ extends MutabilityControl implements ConstantPool {
+ /** {@code non-null;} array of entries */
+ private final Constant[] entries;
+
+ /**
+ * Constructs an instance. All indices initially contain {@code null}.
+ *
+ * @param size the size of the pool; this corresponds to the
+ * class file field {@code constant_pool_count}, and is in fact
+ * always at least one more than the actual size of the constant pool,
+ * as element {@code 0} is always invalid.
+ */
+ public StdConstantPool(int size) {
+ super(size > 1);
+
+ if (size < 1) {
+ throw new IllegalArgumentException("size < 1");
+ }
+
+ entries = new Constant[size];
+ }
+
+ /** {@inheritDoc} */
+ public int size() {
+ return entries.length;
+ }
+
+ /** {@inheritDoc} */
+ public Constant getOrNull(int n) {
+ try {
+ return entries[n];
+ } catch (IndexOutOfBoundsException ex) {
+ // Translate the exception.
+ return throwInvalid(n);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public Constant get0Ok(int n) {
+ if (n == 0) {
+ return null;
+ }
+
+ return get(n);
+ }
+
+ /** {@inheritDoc} */
+ public Constant get(int n) {
+ try {
+ Constant result = entries[n];
+
+ if (result == null) {
+ throwInvalid(n);
+ }
+
+ return result;
+ } catch (IndexOutOfBoundsException ex) {
+ // Translate the exception.
+ return throwInvalid(n);
+ }
+ }
+
+ /**
+ * Sets the entry at the given index.
+ *
+ * @param n {@code >= 1, < size();} which entry
+ * @param cst {@code null-ok;} the constant to store
+ */
+ public void set(int n, Constant cst) {
+ throwIfImmutable();
+
+ boolean cat2 = (cst != null) && cst.isCategory2();
+
+ if (n < 1) {
+ throw new IllegalArgumentException("n < 1");
+ }
+
+ if (cat2) {
+ // Storing a category-2 entry nulls out the next index.
+ if (n == (entries.length - 1)) {
+ throw new IllegalArgumentException("(n == size - 1) && " +
+ "cst.isCategory2()");
+ }
+ entries[n + 1] = null;
+ }
+
+ if ((cst != null) && (entries[n] == null)) {
+ /*
+ * Overwriting the second half of a category-2 entry nulls out
+ * the first half.
+ */
+ Constant prev = entries[n - 1];
+ if ((prev != null) && prev.isCategory2()) {
+ entries[n - 1] = null;
+ }
+ }
+
+ entries[n] = cst;
+ }
+
+ /**
+ * Throws the right exception for an invalid cpi.
+ *
+ * @param idx the bad cpi
+ * @return never
+ * @throws ExceptionWithContext always thrown
+ */
+ private static Constant throwInvalid(int idx) {
+ throw new ExceptionWithContext("invalid constant pool index " +
+ Hex.u2(idx));
+ }
+}