1 /*
2  * Copyright (C) 2007 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.rop.type;
18 
19 import com.android.dx.util.FixedSizeList;
20 
21 /**
22  * Standard implementation of {@link TypeList}.
23  */
24 public final class StdTypeList
25         extends FixedSizeList implements TypeList {
26     /** {@code non-null;} no-element instance */
27     public static final StdTypeList EMPTY = new StdTypeList(0);
28 
29     /** {@code non-null;} the list {@code [int]} */
30     public static final StdTypeList INT = StdTypeList.make(Type.INT);
31 
32     /** {@code non-null;} the list {@code [long]} */
33     public static final StdTypeList LONG = StdTypeList.make(Type.LONG);
34 
35     /** {@code non-null;} the list {@code [float]} */
36     public static final StdTypeList FLOAT = StdTypeList.make(Type.FLOAT);
37 
38     /** {@code non-null;} the list {@code [double]} */
39     public static final StdTypeList DOUBLE = StdTypeList.make(Type.DOUBLE);
40 
41     /** {@code non-null;} the list {@code [Object]} */
42     public static final StdTypeList OBJECT = StdTypeList.make(Type.OBJECT);
43 
44     /** {@code non-null;} the list {@code [ReturnAddress]} */
45     public static final StdTypeList RETURN_ADDRESS
46             = StdTypeList.make(Type.RETURN_ADDRESS);
47 
48     /** {@code non-null;} the list {@code [Throwable]} */
49     public static final StdTypeList THROWABLE =
50         StdTypeList.make(Type.THROWABLE);
51 
52     /** {@code non-null;} the list {@code [int, int]} */
53     public static final StdTypeList INT_INT =
54         StdTypeList.make(Type.INT, Type.INT);
55 
56     /** {@code non-null;} the list {@code [long, long]} */
57     public static final StdTypeList LONG_LONG =
58         StdTypeList.make(Type.LONG, Type.LONG);
59 
60     /** {@code non-null;} the list {@code [float, float]} */
61     public static final StdTypeList FLOAT_FLOAT =
62         StdTypeList.make(Type.FLOAT, Type.FLOAT);
63 
64     /** {@code non-null;} the list {@code [double, double]} */
65     public static final StdTypeList DOUBLE_DOUBLE =
66         StdTypeList.make(Type.DOUBLE, Type.DOUBLE);
67 
68     /** {@code non-null;} the list {@code [Object, Object]} */
69     public static final StdTypeList OBJECT_OBJECT =
70         StdTypeList.make(Type.OBJECT, Type.OBJECT);
71 
72     /** {@code non-null;} the list {@code [int, Object]} */
73     public static final StdTypeList INT_OBJECT =
74         StdTypeList.make(Type.INT, Type.OBJECT);
75 
76     /** {@code non-null;} the list {@code [long, Object]} */
77     public static final StdTypeList LONG_OBJECT =
78         StdTypeList.make(Type.LONG, Type.OBJECT);
79 
80     /** {@code non-null;} the list {@code [float, Object]} */
81     public static final StdTypeList FLOAT_OBJECT =
82         StdTypeList.make(Type.FLOAT, Type.OBJECT);
83 
84     /** {@code non-null;} the list {@code [double, Object]} */
85     public static final StdTypeList DOUBLE_OBJECT =
86         StdTypeList.make(Type.DOUBLE, Type.OBJECT);
87 
88     /** {@code non-null;} the list {@code [long, int]} */
89     public static final StdTypeList LONG_INT =
90         StdTypeList.make(Type.LONG, Type.INT);
91 
92     /** {@code non-null;} the list {@code [int[], int]} */
93     public static final StdTypeList INTARR_INT =
94         StdTypeList.make(Type.INT_ARRAY, Type.INT);
95 
96     /** {@code non-null;} the list {@code [long[], int]} */
97     public static final StdTypeList LONGARR_INT =
98         StdTypeList.make(Type.LONG_ARRAY, Type.INT);
99 
100     /** {@code non-null;} the list {@code [float[], int]} */
101     public static final StdTypeList FLOATARR_INT =
102         StdTypeList.make(Type.FLOAT_ARRAY, Type.INT);
103 
104     /** {@code non-null;} the list {@code [double[], int]} */
105     public static final StdTypeList DOUBLEARR_INT =
106         StdTypeList.make(Type.DOUBLE_ARRAY, Type.INT);
107 
108     /** {@code non-null;} the list {@code [Object[], int]} */
109     public static final StdTypeList OBJECTARR_INT =
110         StdTypeList.make(Type.OBJECT_ARRAY, Type.INT);
111 
112     /** {@code non-null;} the list {@code [boolean[], int]} */
113     public static final StdTypeList BOOLEANARR_INT =
114         StdTypeList.make(Type.BOOLEAN_ARRAY, Type.INT);
115 
116     /** {@code non-null;} the list {@code [byte[], int]} */
117     public static final StdTypeList BYTEARR_INT =
118         StdTypeList.make(Type.BYTE_ARRAY, Type.INT);
119 
120     /** {@code non-null;} the list {@code [char[], int]} */
121     public static final StdTypeList CHARARR_INT =
122         StdTypeList.make(Type.CHAR_ARRAY, Type.INT);
123 
124     /** {@code non-null;} the list {@code [short[], int]} */
125     public static final StdTypeList SHORTARR_INT =
126         StdTypeList.make(Type.SHORT_ARRAY, Type.INT);
127 
128     /** {@code non-null;} the list {@code [int, int[], int]} */
129     public static final StdTypeList INT_INTARR_INT =
130         StdTypeList.make(Type.INT, Type.INT_ARRAY, Type.INT);
131 
132     /** {@code non-null;} the list {@code [long, long[], int]} */
133     public static final StdTypeList LONG_LONGARR_INT =
134         StdTypeList.make(Type.LONG, Type.LONG_ARRAY, Type.INT);
135 
136     /** {@code non-null;} the list {@code [float, float[], int]} */
137     public static final StdTypeList FLOAT_FLOATARR_INT =
138         StdTypeList.make(Type.FLOAT, Type.FLOAT_ARRAY, Type.INT);
139 
140     /** {@code non-null;} the list {@code [double, double[], int]} */
141     public static final StdTypeList DOUBLE_DOUBLEARR_INT =
142         StdTypeList.make(Type.DOUBLE, Type.DOUBLE_ARRAY, Type.INT);
143 
144     /** {@code non-null;} the list {@code [Object, Object[], int]} */
145     public static final StdTypeList OBJECT_OBJECTARR_INT =
146         StdTypeList.make(Type.OBJECT, Type.OBJECT_ARRAY, Type.INT);
147 
148     /** {@code non-null;} the list {@code [int, boolean[], int]} */
149     public static final StdTypeList INT_BOOLEANARR_INT =
150         StdTypeList.make(Type.INT, Type.BOOLEAN_ARRAY, Type.INT);
151 
152     /** {@code non-null;} the list {@code [int, byte[], int]} */
153     public static final StdTypeList INT_BYTEARR_INT =
154         StdTypeList.make(Type.INT, Type.BYTE_ARRAY, Type.INT);
155 
156     /** {@code non-null;} the list {@code [int, char[], int]} */
157     public static final StdTypeList INT_CHARARR_INT =
158         StdTypeList.make(Type.INT, Type.CHAR_ARRAY, Type.INT);
159 
160     /** {@code non-null;} the list {@code [int, short[], int]} */
161     public static final StdTypeList INT_SHORTARR_INT =
162         StdTypeList.make(Type.INT, Type.SHORT_ARRAY, Type.INT);
163 
164     /**
165      * Makes a single-element instance.
166      *
167      * @param type {@code non-null;} the element
168      * @return {@code non-null;} an appropriately-constructed instance
169      */
make(Type type)170     public static StdTypeList make(Type type) {
171         StdTypeList result = new StdTypeList(1);
172         result.set(0, type);
173         return result;
174     }
175 
176     /**
177      * Makes a two-element instance.
178      *
179      * @param type0 {@code non-null;} the first element
180      * @param type1 {@code non-null;} the second element
181      * @return {@code non-null;} an appropriately-constructed instance
182      */
make(Type type0, Type type1)183     public static StdTypeList make(Type type0, Type type1) {
184         StdTypeList result = new StdTypeList(2);
185         result.set(0, type0);
186         result.set(1, type1);
187         return result;
188     }
189 
190     /**
191      * Makes a three-element instance.
192      *
193      * @param type0 {@code non-null;} the first element
194      * @param type1 {@code non-null;} the second element
195      * @param type2 {@code non-null;} the third element
196      * @return {@code non-null;} an appropriately-constructed instance
197      */
make(Type type0, Type type1, Type type2)198     public static StdTypeList make(Type type0, Type type1, Type type2) {
199         StdTypeList result = new StdTypeList(3);
200         result.set(0, type0);
201         result.set(1, type1);
202         result.set(2, type2);
203         return result;
204     }
205 
206     /**
207      * Makes a four-element instance.
208      *
209      * @param type0 {@code non-null;} the first element
210      * @param type1 {@code non-null;} the second element
211      * @param type2 {@code non-null;} the third element
212      * @param type3 {@code non-null;} the fourth element
213      * @return {@code non-null;} an appropriately-constructed instance
214      */
make(Type type0, Type type1, Type type2, Type type3)215     public static StdTypeList make(Type type0, Type type1, Type type2,
216                                    Type type3) {
217         StdTypeList result = new StdTypeList(4);
218         result.set(0, type0);
219         result.set(1, type1);
220         result.set(2, type2);
221         result.set(3, type3);
222         return result;
223     }
224 
225     /**
226      * Returns the given list as a comma-separated list of human forms. This
227      * is a static method so as to work on arbitrary {@link TypeList}
228      * instances.
229      *
230      * @param list {@code non-null;} the list to convert
231      * @return {@code non-null;} the human form
232      */
toHuman(TypeList list)233     public static String toHuman(TypeList list) {
234         int size = list.size();
235 
236         if (size == 0) {
237             return "<empty>";
238         }
239 
240         StringBuffer sb = new StringBuffer(100);
241 
242         for (int i = 0; i < size; i++) {
243             if (i != 0) {
244                 sb.append(", ");
245             }
246             sb.append(list.getType(i).toHuman());
247         }
248 
249         return sb.toString();
250     }
251 
252     /**
253      * Returns a hashcode of the contents of the given list. This
254      * is a static method so as to work on arbitrary {@link TypeList}
255      * instances.
256      *
257      * @param list {@code non-null;} the list to inspect
258      * @return {@code non-null;} the hash code
259      */
hashContents(TypeList list)260     public static int hashContents(TypeList list) {
261         int size = list.size();
262         int hash = 0;
263 
264         for (int i = 0; i < size; i++) {
265             hash = (hash * 31) + list.getType(i).hashCode();
266         }
267 
268         return hash;
269     }
270 
271     /**
272      * Compares the contents of the given two instances for equality. This
273      * is a static method so as to work on arbitrary {@link TypeList}
274      * instances.
275      *
276      * @param list1 {@code non-null;} one list to compare
277      * @param list2 {@code non-null;} another list to compare
278      * @return whether the two lists contain corresponding equal elements
279      */
equalContents(TypeList list1, TypeList list2)280     public static boolean equalContents(TypeList list1, TypeList list2) {
281         int size = list1.size();
282 
283         if (list2.size() != size) {
284             return false;
285         }
286 
287         for (int i = 0; i < size; i++) {
288             if (! list1.getType(i).equals(list2.getType(i))) {
289                 return false;
290             }
291         }
292 
293         return true;
294     }
295 
296     /**
297      * Compares the contents of the given two instances for ordering. This
298      * is a static method so as to work on arbitrary {@link TypeList}
299      * instances.
300      *
301      * @param list1 {@code non-null;} one list to compare
302      * @param list2 {@code non-null;} another list to compare
303      * @return the order of the two lists
304      */
compareContents(TypeList list1, TypeList list2)305     public static int compareContents(TypeList list1, TypeList list2) {
306         int size1 = list1.size();
307         int size2 = list2.size();
308         int size = Math.min(size1, size2);
309 
310         for (int i = 0; i < size; i++) {
311             int comparison = list1.getType(i).compareTo(list2.getType(i));
312             if (comparison != 0) {
313                 return comparison;
314             }
315         }
316 
317         if (size1 == size2) {
318             return 0;
319         } else if (size1 < size2) {
320             return -1;
321         } else {
322             return 1;
323         }
324     }
325 
326     /**
327      * Constructs an instance. All indices initially contain {@code null}.
328      *
329      * @param size the size of the list
330      */
StdTypeList(int size)331     public StdTypeList(int size) {
332         super(size);
333     }
334 
335     /** {@inheritDoc} */
getType(int n)336     public Type getType(int n) {
337         return get(n);
338     }
339 
340     /** {@inheritDoc} */
getWordCount()341     public int getWordCount() {
342         int sz = size();
343         int result = 0;
344 
345         for (int i = 0; i < sz; i++) {
346             result += get(i).getCategory();
347         }
348 
349         return result;
350     }
351 
352     /** {@inheritDoc} */
withAddedType(Type type)353     public TypeList withAddedType(Type type) {
354         int sz = size();
355         StdTypeList result = new StdTypeList(sz + 1);
356 
357         for (int i = 0; i < sz; i++) {
358             result.set0(i, get0(i));
359         }
360 
361         result.set(sz, type);
362         result.setImmutable();
363         return result;
364     }
365 
366     /**
367      * Gets the indicated element. It is an error to call this with the
368      * index for an element which was never set; if you do that, this
369      * will throw {@code NullPointerException}.
370      *
371      * @param n {@code >= 0, < size();} which element
372      * @return {@code non-null;} the indicated element
373      */
get(int n)374     public Type get(int n) {
375         return (Type) get0(n);
376     }
377 
378     /**
379      * Sets the type at the given index.
380      *
381      * @param n {@code >= 0, < size();} which element
382      * @param type {@code non-null;} the type to store
383      */
set(int n, Type type)384     public void set(int n, Type type) {
385         set0(n, type);
386     }
387 
388     /**
389      * Returns a new instance, which is the same as this instance,
390      * except that it has an additional type prepended to the
391      * original.
392      *
393      * @param type {@code non-null;} the new first element
394      * @return {@code non-null;} an appropriately-constructed instance
395      */
withFirst(Type type)396     public StdTypeList withFirst(Type type) {
397         int sz = size();
398         StdTypeList result = new StdTypeList(sz + 1);
399 
400         result.set0(0, type);
401         for (int i = 0; i < sz; i++) {
402             result.set0(i + 1, getOrNull0(i));
403         }
404 
405         return result;
406     }
407 }
408