• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
CatchHandlerList(int size)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      */
get(int n)48     public Entry get(int n) {
49         return (Entry) get0(n);
50     }
51 
52     /** {@inheritDoc} */
toHuman()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      */
toHuman(String prefix, String header)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      */
catchesAll()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      */
set(int n, CstType exceptionType, int handler)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      */
set(int n, Entry entry)131     public void set(int n, Entry entry) {
132         set0(n, entry);
133     }
134 
135     /** {@inheritDoc} */
compareTo(CatchHandlerList other)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          */
Entry(CstType exceptionType, int handler)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
hashCode()195         public int hashCode() {
196             return (handler * 31) + exceptionType.hashCode();
197         }
198 
199         /** {@inheritDoc} */
200         @Override
equals(Object other)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} */
compareTo(Entry other)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          */
getExceptionType()225         public CstType getExceptionType() {
226             return exceptionType;
227         }
228 
229         /**
230          * Gets the handler address.
231          *
232          * @return {@code >= 0;} the handler address
233          */
getHandler()234         public int getHandler() {
235             return handler;
236         }
237     }
238 }
239