Home | History | Annotate | Download | only in code
      1 /*
      2  * Copyright (C) 2008 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.dex.code;
     18 
     19 import com.android.dx.rop.cst.CstType;
     20 import com.android.dx.util.FixedSizeList;
     21 import com.android.dx.util.Hex;
     22 
     23 /**
     24  * Ordered list of (exception type, handler address) entries.
     25  */
     26 public final class CatchHandlerList extends FixedSizeList
     27         implements Comparable<CatchHandlerList> {
     28     /** {@code non-null;} empty instance */
     29     public static final CatchHandlerList EMPTY = new CatchHandlerList(0);
     30 
     31     /**
     32      * Constructs an instance. All indices initially contain {@code null}.
     33      *
     34      * @param size {@code >= 0;} the size of the list
     35      */
     36     public CatchHandlerList(int size) {
     37         super(size);
     38     }
     39 
     40     /**
     41      * Gets the element at the given index. It is an error to call
     42      * this with the index for an element which was never set; if you
     43      * do that, this will throw {@code NullPointerException}.
     44      *
     45      * @param n {@code >= 0, < size();} which index
     46      * @return {@code non-null;} element at that index
     47      */
     48     public Entry get(int n) {
     49         return (Entry) get0(n);
     50     }
     51 
     52     /** {@inheritDoc} */
     53     public String toHuman() {
     54         return toHuman("", "");
     55     }
     56 
     57     /**
     58      * Get the human form of this instance, prefixed on each line
     59      * with the string.
     60      *
     61      * @param prefix {@code non-null;} the prefix for every line
     62      * @param header {@code non-null;} the header for the first line (after the
     63      * first prefix)
     64      * @return {@code non-null;} the human form
     65      */
     66     public String toHuman(String prefix, String header) {
     67         StringBuilder sb = new StringBuilder(100);
     68         int size = size();
     69 
     70         sb.append(prefix);
     71         sb.append(header);
     72         sb.append("catch ");
     73 
     74         for (int i = 0; i < size; i++) {
     75             Entry entry = get(i);
     76 
     77             if (i != 0) {
     78                 sb.append(",\n");
     79                 sb.append(prefix);
     80                 sb.append("  ");
     81             }
     82 
     83             if ((i == (size - 1)) && catchesAll()) {
     84                 sb.append("<any>");
     85             } else {
     86                 sb.append(entry.getExceptionType().toHuman());
     87             }
     88 
     89             sb.append(" -> ");
     90             sb.append(Hex.u2or4(entry.getHandler()));
     91         }
     92 
     93         return sb.toString();
     94     }
     95 
     96     /**
     97      * Returns whether or not this instance ends with a "catch-all"
     98      * handler.
     99      *
    100      * @return {@code true} if this instance ends with a "catch-all"
    101      * handler or {@code false} if not
    102      */
    103     public boolean catchesAll() {
    104         int size = size();
    105 
    106         if (size == 0) {
    107             return false;
    108         }
    109 
    110         Entry last = get(size - 1);
    111         return last.getExceptionType().equals(CstType.OBJECT);
    112     }
    113 
    114     /**
    115      * Sets the entry at the given index.
    116      *
    117      * @param n {@code >= 0, < size();} which index
    118      * @param exceptionType {@code non-null;} type of exception handled
    119      * @param handler {@code >= 0;} exception handler address
    120      */
    121     public void set(int n, CstType exceptionType, int handler) {
    122         set0(n, new Entry(exceptionType, handler));
    123     }
    124 
    125     /**
    126      * Sets the entry at the given index.
    127      *
    128      * @param n {@code >= 0, < size();} which index
    129      * @param entry {@code non-null;} the entry to set at {@code n}
    130      */
    131     public void set(int n, Entry entry) {
    132         set0(n, entry);
    133     }
    134 
    135     /** {@inheritDoc} */
    136     public int compareTo(CatchHandlerList other) {
    137         if (this == other) {
    138             // Easy out.
    139             return 0;
    140         }
    141 
    142         int thisSize = size();
    143         int otherSize = other.size();
    144         int checkSize = Math.min(thisSize, otherSize);
    145 
    146         for (int i = 0; i < checkSize; i++) {
    147             Entry thisEntry = get(i);
    148             Entry otherEntry = other.get(i);
    149             int compare = thisEntry.compareTo(otherEntry);
    150             if (compare != 0) {
    151                 return compare;
    152             }
    153         }
    154 
    155         if (thisSize < otherSize) {
    156             return -1;
    157         } else if (thisSize > otherSize) {
    158             return 1;
    159         }
    160 
    161         return 0;
    162     }
    163 
    164     /**
    165      * Entry in the list.
    166      */
    167     public static class Entry implements Comparable<Entry> {
    168         /** {@code non-null;} type of exception handled */
    169         private final CstType exceptionType;
    170 
    171         /** {@code >= 0;} exception handler address */
    172         private final int handler;
    173 
    174         /**
    175          * Constructs an instance.
    176          *
    177          * @param exceptionType {@code non-null;} type of exception handled
    178          * @param handler {@code >= 0;} exception handler address
    179          */
    180         public Entry(CstType exceptionType, int handler) {
    181             if (handler < 0) {
    182                 throw new IllegalArgumentException("handler < 0");
    183             }
    184 
    185             if (exceptionType == null) {
    186                 throw new NullPointerException("exceptionType == null");
    187             }
    188 
    189             this.handler = handler;
    190             this.exceptionType = exceptionType;
    191         }
    192 
    193         /** {@inheritDoc} */
    194         @Override
    195         public int hashCode() {
    196             return (handler * 31) + exceptionType.hashCode();
    197         }
    198 
    199         /** {@inheritDoc} */
    200         @Override
    201         public boolean equals(Object other) {
    202             if (other instanceof Entry) {
    203                 return (compareTo((Entry) other) == 0);
    204             }
    205 
    206             return false;
    207         }
    208 
    209         /** {@inheritDoc} */
    210         public int compareTo(Entry other) {
    211             if (handler < other.handler) {
    212                 return -1;
    213             } else if (handler > other.handler) {
    214                 return 1;
    215             }
    216 
    217             return exceptionType.compareTo(other.exceptionType);
    218         }
    219 
    220         /**
    221          * Gets the exception type handled.
    222          *
    223          * @return {@code non-null;} the exception type
    224          */
    225         public CstType getExceptionType() {
    226             return exceptionType;
    227         }
    228 
    229         /**
    230          * Gets the handler address.
    231          *
    232          * @return {@code >= 0;} the handler address
    233          */
    234         public int getHandler() {
    235             return handler;
    236         }
    237     }
    238 }
    239