Home | History | Annotate | Download | only in cst
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.dx.rop.cst;
     18 
     19 import com.android.dex.util.ExceptionWithContext;
     20 import com.android.dx.util.Hex;
     21 import com.android.dx.util.MutabilityControl;
     22 
     23 /**
     24  * Standard implementation of {@link ConstantPool}, which directly stores
     25  * an array of {@link Constant} objects and can be made immutable.
     26  */
     27 public final class StdConstantPool
     28         extends MutabilityControl implements ConstantPool {
     29     /** {@code non-null;} array of entries */
     30     private final Constant[] entries;
     31 
     32     /**
     33      * Constructs an instance. All indices initially contain {@code null}.
     34      *
     35      * @param size the size of the pool; this corresponds to the
     36      * class file field {@code constant_pool_count}, and is in fact
     37      * always at least one more than the actual size of the constant pool,
     38      * as element {@code 0} is always invalid.
     39      */
     40     public StdConstantPool(int size) {
     41         super(size > 1);
     42 
     43         if (size < 1) {
     44             throw new IllegalArgumentException("size < 1");
     45         }
     46 
     47         entries = new Constant[size];
     48     }
     49 
     50     /** {@inheritDoc} */
     51     @Override
     52     public int size() {
     53         return entries.length;
     54     }
     55 
     56     /** {@inheritDoc} */
     57     @Override
     58     public Constant getOrNull(int n) {
     59         try {
     60             return entries[n];
     61         } catch (IndexOutOfBoundsException ex) {
     62             // Translate the exception.
     63             return throwInvalid(n);
     64         }
     65     }
     66 
     67     /** {@inheritDoc} */
     68     @Override
     69     public Constant get0Ok(int n) {
     70         if (n == 0) {
     71             return null;
     72         }
     73 
     74         return get(n);
     75     }
     76 
     77     /** {@inheritDoc} */
     78     @Override
     79     public Constant get(int n) {
     80         try {
     81             Constant result = entries[n];
     82 
     83             if (result == null) {
     84                 throwInvalid(n);
     85             }
     86 
     87             return result;
     88         } catch (IndexOutOfBoundsException ex) {
     89             // Translate the exception.
     90             return throwInvalid(n);
     91         }
     92     }
     93 
     94     /**
     95      * Get all entries in this constant pool.
     96      *
     97      * @return the returned array may contain null entries.
     98      */
     99     @Override
    100     public Constant[] getEntries() {
    101         return entries;
    102     }
    103 
    104     /**
    105      * Sets the entry at the given index.
    106      *
    107      * @param n {@code >= 1, < size();} which entry
    108      * @param cst {@code null-ok;} the constant to store
    109      */
    110     public void set(int n, Constant cst) {
    111         throwIfImmutable();
    112 
    113         boolean cat2 = (cst != null) && cst.isCategory2();
    114 
    115         if (n < 1) {
    116             throw new IllegalArgumentException("n < 1");
    117         }
    118 
    119         if (cat2) {
    120             // Storing a category-2 entry nulls out the next index.
    121             if (n == (entries.length - 1)) {
    122                 throw new IllegalArgumentException("(n == size - 1) && " +
    123                                                    "cst.isCategory2()");
    124             }
    125             entries[n + 1] = null;
    126         }
    127 
    128         if ((cst != null) && (entries[n] == null)) {
    129             /*
    130              * Overwriting the second half of a category-2 entry nulls out
    131              * the first half.
    132              */
    133             Constant prev = entries[n - 1];
    134             if ((prev != null) && prev.isCategory2()) {
    135                 entries[n - 1] = null;
    136             }
    137         }
    138 
    139         entries[n] = cst;
    140     }
    141 
    142     /**
    143      * Throws the right exception for an invalid cpi.
    144      *
    145      * @param idx the bad cpi
    146      * @return never
    147      * @throws ExceptionWithContext always thrown
    148      */
    149     private static Constant throwInvalid(int idx) {
    150         throw new ExceptionWithContext("invalid constant pool index " +
    151                                        Hex.u2(idx));
    152     }
    153 }
    154