1 /* 2 * Copyright (C) 2011 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.merge; 18 19 import com.android.dex.ClassDef; 20 import com.android.dex.Dex; 21 import java.util.Comparator; 22 23 /** 24 * Name and structure of a type. Used to order types such that each type is 25 * preceded by its supertype and implemented interfaces. 26 */ 27 final class SortableType { 28 public static final Comparator<SortableType> NULLS_LAST_ORDER = new Comparator<SortableType>() { 29 public int compare(SortableType a, SortableType b) { 30 if (a == b) { 31 return 0; 32 } 33 if (b == null) { 34 return -1; 35 } 36 if (a == null) { 37 return 1; 38 } 39 if (a.depth != b.depth) { 40 return a.depth - b.depth; 41 } 42 return a.getTypeIndex() - b.getTypeIndex(); 43 } 44 }; 45 46 private final Dex dex; 47 private ClassDef classDef; 48 private int depth = -1; 49 SortableType(Dex dex, ClassDef classDef)50 public SortableType(Dex dex, ClassDef classDef) { 51 this.dex = dex; 52 this.classDef = classDef; 53 } 54 getDex()55 public Dex getDex() { 56 return dex; 57 } 58 getClassDef()59 public ClassDef getClassDef() { 60 return classDef; 61 } 62 getTypeIndex()63 public int getTypeIndex() { 64 return classDef.getTypeIndex(); 65 } 66 67 /** 68 * Assigns this type's depth if the depths of its supertype and implemented 69 * interfaces are known. Returns false if the depth couldn't be computed 70 * yet. 71 */ tryAssignDepth(SortableType[] types)72 public boolean tryAssignDepth(SortableType[] types) { 73 int max; 74 if (classDef.getSupertypeIndex() == ClassDef.NO_INDEX) { 75 max = 0; // this is Object.class or an interface 76 } else { 77 SortableType sortableSupertype = types[classDef.getSupertypeIndex()]; 78 if (sortableSupertype == null) { 79 max = 1; // unknown, so assume it's a root. 80 } else if (sortableSupertype.depth == -1) { 81 return false; 82 } else { 83 max = sortableSupertype.depth; 84 } 85 } 86 87 for (short interfaceIndex : classDef.getInterfaces()) { 88 SortableType implemented = types[interfaceIndex]; 89 if (implemented == null) { 90 max = Math.max(max, 1); // unknown, so assume it's a root. 91 } else if (implemented.depth == -1) { 92 return false; 93 } else { 94 max = Math.max(max, implemented.depth); 95 } 96 } 97 98 depth = max + 1; 99 return true; 100 } 101 isDepthAssigned()102 public boolean isDepthAssigned() { 103 return depth != -1; 104 } 105 } 106