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 17package com.android.dx.dex.code; 18 19import com.android.dx.rop.cst.CstType; 20import com.android.dx.util.FixedSizeList; 21 22/** 23 * Table of catch entries. Each entry includes a range of code 24 * addresses for which it is valid and an associated {@link 25 * CatchHandlerList}. 26 */ 27public final class CatchTable extends FixedSizeList 28 implements Comparable<CatchTable> { 29 /** {@code non-null;} empty instance */ 30 public static final CatchTable EMPTY = new CatchTable(0); 31 32 /** 33 * Constructs an instance. All indices initially contain {@code null}. 34 * 35 * @param size {@code >= 0;} the size of the table 36 */ 37 public CatchTable(int size) { 38 super(size); 39 } 40 41 /** 42 * Gets the element at the given index. It is an error to call 43 * this with the index for an element which was never set; if you 44 * do that, this will throw {@code NullPointerException}. 45 * 46 * @param n {@code >= 0, < size();} which index 47 * @return {@code non-null;} element at that index 48 */ 49 public Entry get(int n) { 50 return (Entry) get0(n); 51 } 52 53 /** 54 * Sets the entry at the given index. 55 * 56 * @param n {@code >= 0, < size();} which index 57 * @param entry {@code non-null;} the entry to set at {@code n} 58 */ 59 public void set(int n, Entry entry) { 60 set0(n, entry); 61 } 62 63 /** {@inheritDoc} */ 64 public int compareTo(CatchTable other) { 65 if (this == other) { 66 // Easy out. 67 return 0; 68 } 69 70 int thisSize = size(); 71 int otherSize = other.size(); 72 int checkSize = Math.min(thisSize, otherSize); 73 74 for (int i = 0; i < checkSize; i++) { 75 Entry thisEntry = get(i); 76 Entry otherEntry = other.get(i); 77 int compare = thisEntry.compareTo(otherEntry); 78 if (compare != 0) { 79 return compare; 80 } 81 } 82 83 if (thisSize < otherSize) { 84 return -1; 85 } else if (thisSize > otherSize) { 86 return 1; 87 } 88 89 return 0; 90 } 91 92 /** 93 * Entry in a catch list. 94 */ 95 public static class Entry implements Comparable<Entry> { 96 /** {@code >= 0;} start address */ 97 private final int start; 98 99 /** {@code > start;} end address (exclusive) */ 100 private final int end; 101 102 /** {@code non-null;} list of catch handlers */ 103 private final CatchHandlerList handlers; 104 105 /** 106 * Constructs an instance. 107 * 108 * @param start {@code >= 0;} start address 109 * @param end {@code > start;} end address (exclusive) 110 * @param handlers {@code non-null;} list of catch handlers 111 */ 112 public Entry(int start, int end, CatchHandlerList handlers) { 113 if (start < 0) { 114 throw new IllegalArgumentException("start < 0"); 115 } 116 117 if (end <= start) { 118 throw new IllegalArgumentException("end <= start"); 119 } 120 121 if (handlers.isMutable()) { 122 throw new IllegalArgumentException("handlers.isMutable()"); 123 } 124 125 this.start = start; 126 this.end = end; 127 this.handlers = handlers; 128 } 129 130 /** {@inheritDoc} */ 131 @Override 132 public int hashCode() { 133 int hash = (start * 31) + end; 134 hash = (hash * 31) + handlers.hashCode(); 135 return hash; 136 } 137 138 /** {@inheritDoc} */ 139 @Override 140 public boolean equals(Object other) { 141 if (other instanceof Entry) { 142 return (compareTo((Entry) other) == 0); 143 } 144 145 return false; 146 } 147 148 /** {@inheritDoc} */ 149 public int compareTo(Entry other) { 150 if (start < other.start) { 151 return -1; 152 } else if (start > other.start) { 153 return 1; 154 } 155 156 if (end < other.end) { 157 return -1; 158 } else if (end > other.end) { 159 return 1; 160 } 161 162 return handlers.compareTo(other.handlers); 163 } 164 165 /** 166 * Gets the start address. 167 * 168 * @return {@code >= 0;} the start address 169 */ 170 public int getStart() { 171 return start; 172 } 173 174 /** 175 * Gets the end address (exclusive). 176 * 177 * @return {@code > start;} the end address (exclusive) 178 */ 179 public int getEnd() { 180 return end; 181 } 182 183 /** 184 * Gets the handlers. 185 * 186 * @return {@code non-null;} the handlers 187 */ 188 public CatchHandlerList getHandlers() { 189 return handlers; 190 } 191 } 192} 193