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 final IndexMap indexMap; 48 private ClassDef classDef; 49 private int depth = -1; 50 SortableType(Dex dex, IndexMap indexMap, ClassDef classDef)51 public SortableType(Dex dex, IndexMap indexMap, ClassDef classDef) { 52 this.dex = dex; 53 this.indexMap = indexMap; 54 this.classDef = classDef; 55 } 56 getDex()57 public Dex getDex() { 58 return dex; 59 } 60 getIndexMap()61 public IndexMap getIndexMap() { 62 return indexMap; 63 } 64 getClassDef()65 public ClassDef getClassDef() { 66 return classDef; 67 } 68 getTypeIndex()69 public int getTypeIndex() { 70 return classDef.getTypeIndex(); 71 } 72 73 /** 74 * Assigns this type's depth if the depths of its supertype and implemented 75 * interfaces are known. Returns false if the depth couldn't be computed 76 * yet. 77 */ tryAssignDepth(SortableType[] types)78 public boolean tryAssignDepth(SortableType[] types) { 79 int max; 80 if (classDef.getSupertypeIndex() == ClassDef.NO_INDEX) { 81 max = 0; // this is Object.class or an interface 82 } else { 83 SortableType sortableSupertype = types[classDef.getSupertypeIndex()]; 84 if (sortableSupertype == null) { 85 max = 1; // unknown, so assume it's a root. 86 } else if (sortableSupertype.depth == -1) { 87 return false; 88 } else { 89 max = sortableSupertype.depth; 90 } 91 } 92 93 for (short interfaceIndex : classDef.getInterfaces()) { 94 SortableType implemented = types[interfaceIndex]; 95 if (implemented == null) { 96 max = Math.max(max, 1); // unknown, so assume it's a root. 97 } else if (implemented.depth == -1) { 98 return false; 99 } else { 100 max = Math.max(max, implemented.depth); 101 } 102 } 103 104 depth = max + 1; 105 return true; 106 } 107 isDepthAssigned()108 public boolean isDepthAssigned() { 109 return depth != -1; 110 } 111 } 112