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