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
17package com.android.dx.rop.code;
18
19import com.android.dx.util.Hex;
20
21/**
22 * Constants used as "access flags" in various places in classes, and
23 * related utilities. Although, at the rop layer, flags are generally
24 * ignored, this is the layer of communication, and as such, this
25 * package is where these definitions belong. The flag definitions are
26 * identical to Java access flags, but {@code ACC_SUPER} isn't
27 * used at all in translated code, and {@code ACC_SYNCHRONIZED}
28 * is only used in a very limited way.
29 */
30public final class AccessFlags {
31    /** public member / class */
32    public static final int ACC_PUBLIC = 0x0001;
33
34    /** private member */
35    public static final int ACC_PRIVATE = 0x0002;
36
37    /** protected member */
38    public static final int ACC_PROTECTED = 0x0004;
39
40    /** static member */
41    public static final int ACC_STATIC = 0x0008;
42
43    /** final member / class */
44    public static final int ACC_FINAL = 0x0010;
45
46    /**
47     * synchronized method; only valid in dex files for {@code native}
48     * methods
49     */
50    public static final int ACC_SYNCHRONIZED = 0x0020;
51
52    /**
53     * class with new-style {@code invokespecial} for superclass
54     * method access
55     */
56    public static final int ACC_SUPER = 0x0020;
57
58    /** volatile field */
59    public static final int ACC_VOLATILE = 0x0040;
60
61    /** bridge method (generated) */
62    public static final int ACC_BRIDGE = 0x0040;
63
64    /** transient field */
65    public static final int ACC_TRANSIENT = 0x0080;
66
67    /** varargs method */
68    public static final int ACC_VARARGS = 0x0080;
69
70    /** native method */
71    public static final int ACC_NATIVE = 0x0100;
72
73    /** "class" is in fact an public static final interface */
74    public static final int ACC_INTERFACE = 0x0200;
75
76    /** abstract method / class */
77    public static final int ACC_ABSTRACT = 0x0400;
78
79    /**
80     * method with strict floating point ({@code strictfp})
81     * behavior
82     */
83    public static final int ACC_STRICT = 0x0800;
84
85    /** synthetic member */
86    public static final int ACC_SYNTHETIC = 0x1000;
87
88    /** class is an annotation type */
89    public static final int ACC_ANNOTATION = 0x2000;
90
91    /**
92     * class is an enumerated type; field is an element of an enumerated
93     * type
94     */
95    public static final int ACC_ENUM = 0x4000;
96
97    /** method is a constructor */
98    public static final int ACC_CONSTRUCTOR = 0x10000;
99
100    /**
101     * method was declared {@code synchronized}; has no effect on
102     * execution (other than inspecting this flag, per se)
103     */
104    public static final int ACC_DECLARED_SYNCHRONIZED = 0x20000;
105
106    /** flags defined on classes */
107    public static final int CLASS_FLAGS =
108        ACC_PUBLIC | ACC_FINAL | ACC_SUPER | ACC_INTERFACE | ACC_ABSTRACT |
109        ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM;
110
111    /** flags defined on inner classes */
112    public static final int INNER_CLASS_FLAGS =
113        ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL |
114        ACC_INTERFACE | ACC_ABSTRACT | ACC_SYNTHETIC | ACC_ANNOTATION |
115        ACC_ENUM;
116
117    /** flags defined on fields */
118    public static final int FIELD_FLAGS =
119        ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL |
120        ACC_VOLATILE | ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM;
121
122    /** flags defined on methods */
123    public static final int METHOD_FLAGS =
124        ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL |
125        ACC_SYNCHRONIZED | ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE |
126        ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC | ACC_CONSTRUCTOR |
127        ACC_DECLARED_SYNCHRONIZED;
128
129    /** indicates conversion of class flags */
130    private static final int CONV_CLASS = 1;
131
132    /** indicates conversion of field flags */
133    private static final int CONV_FIELD = 2;
134
135    /** indicates conversion of method flags */
136    private static final int CONV_METHOD = 3;
137
138    /**
139     * This class is uninstantiable.
140     */
141    private AccessFlags() {
142        // This space intentionally left blank.
143    }
144
145    /**
146     * Returns a human-oriented string representing the given access flags,
147     * as defined on classes (not fields or methods).
148     *
149     * @param flags the flags
150     * @return {@code non-null;} human-oriented string
151     */
152    public static String classString(int flags) {
153        return humanHelper(flags, CLASS_FLAGS, CONV_CLASS);
154    }
155
156    /**
157     * Returns a human-oriented string representing the given access flags,
158     * as defined on inner classes.
159     *
160     * @param flags the flags
161     * @return {@code non-null;} human-oriented string
162     */
163    public static String innerClassString(int flags) {
164        return humanHelper(flags, INNER_CLASS_FLAGS, CONV_CLASS);
165    }
166
167    /**
168     * Returns a human-oriented string representing the given access flags,
169     * as defined on fields (not classes or methods).
170     *
171     * @param flags the flags
172     * @return {@code non-null;} human-oriented string
173     */
174    public static String fieldString(int flags) {
175        return humanHelper(flags, FIELD_FLAGS, CONV_FIELD);
176    }
177
178    /**
179     * Returns a human-oriented string representing the given access flags,
180     * as defined on methods (not classes or fields).
181     *
182     * @param flags the flags
183     * @return {@code non-null;} human-oriented string
184     */
185    public static String methodString(int flags) {
186        return humanHelper(flags, METHOD_FLAGS, CONV_METHOD);
187    }
188
189    /**
190     * Returns whether the flag {@code ACC_PUBLIC} is on in the given
191     * flags.
192     *
193     * @param flags the flags to check
194     * @return the value of the {@code ACC_PUBLIC} flag
195     */
196    public static boolean isPublic(int flags) {
197        return (flags & ACC_PUBLIC) != 0;
198    }
199
200    /**
201     * Returns whether the flag {@code ACC_PROTECTED} is on in the given
202     * flags.
203     *
204     * @param flags the flags to check
205     * @return the value of the {@code ACC_PROTECTED} flag
206     */
207    public static boolean isProtected(int flags) {
208        return (flags & ACC_PROTECTED) != 0;
209    }
210
211    /**
212     * Returns whether the flag {@code ACC_PRIVATE} is on in the given
213     * flags.
214     *
215     * @param flags the flags to check
216     * @return the value of the {@code ACC_PRIVATE} flag
217     */
218    public static boolean isPrivate(int flags) {
219        return (flags & ACC_PRIVATE) != 0;
220    }
221
222    /**
223     * Returns whether the flag {@code ACC_STATIC} is on in the given
224     * flags.
225     *
226     * @param flags the flags to check
227     * @return the value of the {@code ACC_STATIC} flag
228     */
229    public static boolean isStatic(int flags) {
230        return (flags & ACC_STATIC) != 0;
231    }
232
233    /**
234     * Returns whether the flag {@code ACC_SYNCHRONIZED} is on in
235     * the given flags.
236     *
237     * @param flags the flags to check
238     * @return the value of the {@code ACC_SYNCHRONIZED} flag
239     */
240    public static boolean isSynchronized(int flags) {
241        return (flags & ACC_SYNCHRONIZED) != 0;
242    }
243
244    /**
245     * Returns whether the flag {@code ACC_ABSTRACT} is on in the given
246     * flags.
247     *
248     * @param flags the flags to check
249     * @return the value of the {@code ACC_ABSTRACT} flag
250     */
251    public static boolean isAbstract(int flags) {
252        return (flags & ACC_ABSTRACT) != 0;
253    }
254
255    /**
256     * Returns whether the flag {@code ACC_NATIVE} is on in the given
257     * flags.
258     *
259     * @param flags the flags to check
260     * @return the value of the {@code ACC_NATIVE} flag
261     */
262    public static boolean isNative(int flags) {
263        return (flags & ACC_NATIVE) != 0;
264    }
265
266    /**
267     * Returns whether the flag {@code ACC_ANNOTATION} is on in the given
268     * flags.
269     *
270     * @param flags the flags to check
271     * @return the value of the {@code ACC_ANNOTATION} flag
272     */
273    public static boolean isAnnotation(int flags) {
274        return (flags & ACC_ANNOTATION) != 0;
275    }
276
277    /**
278     * Returns whether the flag {@code ACC_DECLARED_SYNCHRONIZED} is
279     * on in the given flags.
280     *
281     * @param flags the flags to check
282     * @return the value of the {@code ACC_DECLARED_SYNCHRONIZED} flag
283     */
284    public static boolean isDeclaredSynchronized(int flags) {
285        return (flags & ACC_DECLARED_SYNCHRONIZED) != 0;
286    }
287
288    /**
289     * Helper to return a human-oriented string representing the given
290     * access flags.
291     *
292     * @param flags the defined flags
293     * @param mask mask for the "defined" bits
294     * @param what what the flags represent (one of {@code CONV_*})
295     * @return {@code non-null;} human-oriented string
296     */
297    private static String humanHelper(int flags, int mask, int what) {
298        StringBuffer sb = new StringBuffer(80);
299        int extra = flags & ~mask;
300
301        flags &= mask;
302
303        if ((flags & ACC_PUBLIC) != 0) {
304            sb.append("|public");
305        }
306        if ((flags & ACC_PRIVATE) != 0) {
307            sb.append("|private");
308        }
309        if ((flags & ACC_PROTECTED) != 0) {
310            sb.append("|protected");
311        }
312        if ((flags & ACC_STATIC) != 0) {
313            sb.append("|static");
314        }
315        if ((flags & ACC_FINAL) != 0) {
316            sb.append("|final");
317        }
318        if ((flags & ACC_SYNCHRONIZED) != 0) {
319            if (what == CONV_CLASS) {
320                sb.append("|super");
321            } else {
322                sb.append("|synchronized");
323            }
324        }
325        if ((flags & ACC_VOLATILE) != 0) {
326            if (what == CONV_METHOD) {
327                sb.append("|bridge");
328            } else {
329                sb.append("|volatile");
330            }
331        }
332        if ((flags & ACC_TRANSIENT) != 0) {
333            if (what == CONV_METHOD) {
334                sb.append("|varargs");
335            } else {
336                sb.append("|transient");
337            }
338        }
339        if ((flags & ACC_NATIVE) != 0) {
340            sb.append("|native");
341        }
342        if ((flags & ACC_INTERFACE) != 0) {
343            sb.append("|interface");
344        }
345        if ((flags & ACC_ABSTRACT) != 0) {
346            sb.append("|abstract");
347        }
348        if ((flags & ACC_STRICT) != 0) {
349            sb.append("|strictfp");
350        }
351        if ((flags & ACC_SYNTHETIC) != 0) {
352            sb.append("|synthetic");
353        }
354        if ((flags & ACC_ANNOTATION) != 0) {
355            sb.append("|annotation");
356        }
357        if ((flags & ACC_ENUM) != 0) {
358            sb.append("|enum");
359        }
360        if ((flags & ACC_CONSTRUCTOR) != 0) {
361            sb.append("|constructor");
362        }
363        if ((flags & ACC_DECLARED_SYNCHRONIZED) != 0) {
364            sb.append("|declared_synchronized");
365        }
366
367        if ((extra != 0) || (sb.length() == 0)) {
368            sb.append('|');
369            sb.append(Hex.u2(extra));
370        }
371
372        return sb.substring(1);
373    }
374}
375