com.android.dx.cf.code.ByteCatchList Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of builder Show documentation
Show all versions of builder Show documentation
Library to build Android applications.
/*
* 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.cf.code;
import com.android.dx.rop.cst.CstType;
import com.android.dx.rop.type.StdTypeList;
import com.android.dx.rop.type.TypeList;
import com.android.dx.util.FixedSizeList;
import com.android.dx.util.IntList;
/**
* List of catch entries, that is, the elements of an "exception table,"
* which is part of a standard {@code Code} attribute.
*/
public final class ByteCatchList extends FixedSizeList {
/** {@code non-null;} convenient zero-entry instance */
public static final ByteCatchList EMPTY = new ByteCatchList(0);
/**
* Constructs an instance.
*
* @param count the number of elements to be in the table
*/
public ByteCatchList(int count) {
super(count);
}
/**
* Gets the total length of this structure in bytes, when included in
* a {@code Code} attribute. The returned value includes the
* two bytes for {@code exception_table_length}.
*
* @return {@code >= 2;} the total length, in bytes
*/
public int byteLength() {
return 2 + size() * 8;
}
/**
* Gets the indicated item.
*
* @param n {@code >= 0;} which item
* @return {@code null-ok;} the indicated item
*/
public Item get(int n) {
return (Item) get0(n);
}
/**
* Sets the item at the given index.
*
* @param n {@code >= 0, < size();} which entry to set
* @param item {@code non-null;} the item
*/
public void set(int n, Item item) {
if (item == null) {
throw new NullPointerException("item == null");
}
set0(n, item);
}
/**
* Sets the item at the given index.
*
* @param n {@code >= 0, < size();} which entry to set
* @param startPc {@code >= 0;} the start pc (inclusive) of the handler's range
* @param endPc {@code >= startPc;} the end pc (exclusive) of the
* handler's range
* @param handlerPc {@code >= 0;} the pc of the exception handler
* @param exceptionClass {@code null-ok;} the exception class or
* {@code null} to catch all exceptions with this handler
*/
public void set(int n, int startPc, int endPc, int handlerPc,
CstType exceptionClass) {
set0(n, new Item(startPc, endPc, handlerPc, exceptionClass));
}
/**
* Gets the list of items active at the given address. The result is
* automatically made immutable.
*
* @param pc which address
* @return {@code non-null;} list of exception handlers active at
* {@code pc}
*/
public ByteCatchList listFor(int pc) {
int sz = size();
Item[] resultArr = new Item[sz];
int resultSz = 0;
for (int i = 0; i < sz; i++) {
Item one = get(i);
if (one.covers(pc) && typeNotFound(one, resultArr, resultSz)) {
resultArr[resultSz] = one;
resultSz++;
}
}
if (resultSz == 0) {
return EMPTY;
}
ByteCatchList result = new ByteCatchList(resultSz);
for (int i = 0; i < resultSz; i++) {
result.set(i, resultArr[i]);
}
result.setImmutable();
return result;
}
/**
* Helper method for {@link #listFor}, which tells whether a match
* is not found for the exception type of the given item in
* the given array. A match is considered to be either an exact type
* match or the class {@code Object} which represents a catch-all.
*
* @param item {@code non-null;} item with the exception type to look for
* @param arr {@code non-null;} array to search in
* @param count {@code non-null;} maximum number of elements in the array to check
* @return {@code true} iff the exception type is not found
*/
private static boolean typeNotFound(Item item, Item[] arr, int count) {
CstType type = item.getExceptionClass();
for (int i = 0; i < count; i++) {
CstType one = arr[i].getExceptionClass();
if ((one == type) || (one == CstType.OBJECT)) {
return false;
}
}
return true;
}
/**
* Returns a target list corresponding to this instance. The result
* is a list of all the exception handler addresses, with the given
* {@code noException} address appended if appropriate. The
* result is automatically made immutable.
*
* @param noException {@code >= -1;} the no-exception address to append, or
* {@code -1} not to append anything
* @return {@code non-null;} list of exception targets, with
* {@code noException} appended if necessary
*/
public IntList toTargetList(int noException) {
if (noException < -1) {
throw new IllegalArgumentException("noException < -1");
}
boolean hasDefault = (noException >= 0);
int sz = size();
if (sz == 0) {
if (hasDefault) {
/*
* The list is empty, but there is a no-exception
* address; so, the result is just that address.
*/
return IntList.makeImmutable(noException);
}
/*
* The list is empty and there isn't even a no-exception
* address.
*/
return IntList.EMPTY;
}
IntList result = new IntList(sz + (hasDefault ? 1 : 0));
for (int i = 0; i < sz; i++) {
result.add(get(i).getHandlerPc());
}
if (hasDefault) {
result.add(noException);
}
result.setImmutable();
return result;
}
/**
* Returns a rop-style catches list equivalent to this one.
*
* @return {@code non-null;} the converted instance
*/
public TypeList toRopCatchList() {
int sz = size();
if (sz == 0) {
return StdTypeList.EMPTY;
}
StdTypeList result = new StdTypeList(sz);
for (int i = 0; i < sz; i++) {
result.set(i, get(i).getExceptionClass().getClassType());
}
result.setImmutable();
return result;
}
/**
* Item in an exception handler list.
*/
public static class Item {
/** {@code >= 0;} the start pc (inclusive) of the handler's range */
private final int startPc;
/** {@code >= startPc;} the end pc (exclusive) of the handler's range */
private final int endPc;
/** {@code >= 0;} the pc of the exception handler */
private final int handlerPc;
/** {@code null-ok;} the exception class or {@code null} to catch all
* exceptions with this handler */
private final CstType exceptionClass;
/**
* Constructs an instance.
*
* @param startPc {@code >= 0;} the start pc (inclusive) of the
* handler's range
* @param endPc {@code >= startPc;} the end pc (exclusive) of the
* handler's range
* @param handlerPc {@code >= 0;} the pc of the exception handler
* @param exceptionClass {@code null-ok;} the exception class or
* {@code null} to catch all exceptions with this handler
*/
public Item(int startPc, int endPc, int handlerPc,
CstType exceptionClass) {
if (startPc < 0) {
throw new IllegalArgumentException("startPc < 0");
}
if (endPc < startPc) {
throw new IllegalArgumentException("endPc < startPc");
}
if (handlerPc < 0) {
throw new IllegalArgumentException("handlerPc < 0");
}
this.startPc = startPc;
this.endPc = endPc;
this.handlerPc = handlerPc;
this.exceptionClass = exceptionClass;
}
/**
* Gets the start pc (inclusive) of the handler's range.
*
* @return {@code >= 0;} the start pc (inclusive) of the handler's range.
*/
public int getStartPc() {
return startPc;
}
/**
* Gets the end pc (exclusive) of the handler's range.
*
* @return {@code >= startPc;} the end pc (exclusive) of the
* handler's range.
*/
public int getEndPc() {
return endPc;
}
/**
* Gets the pc of the exception handler.
*
* @return {@code >= 0;} the pc of the exception handler
*/
public int getHandlerPc() {
return handlerPc;
}
/**
* Gets the class of exception handled.
*
* @return {@code non-null;} the exception class; {@link CstType#OBJECT}
* if this entry handles all possible exceptions
*/
public CstType getExceptionClass() {
return (exceptionClass != null) ?
exceptionClass : CstType.OBJECT;
}
/**
* Returns whether the given address is in the range of this item.
*
* @param pc the address
* @return {@code true} iff this item covers {@code pc}
*/
public boolean covers(int pc) {
return (pc >= startPc) && (pc < endPc);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy