1616package com .reandroid .dex .common ;
1717
1818import com .reandroid .dex .smali .SmaliReader ;
19+ import com .reandroid .utils .StringsUtil ;
1920import com .reandroid .utils .collection .ArrayCollection ;
2021import com .reandroid .utils .collection .ArrayIterator ;
22+ import com .reandroid .utils .collection .EmptyIterator ;
2123
24+ import java .io .IOException ;
2225import java .lang .annotation .ElementType ;
2326import java .util .HashMap ;
2427import java .util .Iterator ;
2528import java .util .List ;
29+ import java .util .NoSuchElementException ;
2630import java .util .function .Predicate ;
2731
2832public class AccessFlag extends Modifier {
@@ -44,66 +48,63 @@ public class AccessFlag extends Modifier {
4448 public static final AccessFlag SYNTHETIC ;
4549 public static final AccessFlag ANNOTATION ;
4650 public static final AccessFlag ENUM ;
51+
4752 // for flags of dalvik.annotation.MethodParameters
4853 public static final AccessFlag MANDATED ;
54+
4955 public static final AccessFlag CONSTRUCTOR ;
5056 public static final AccessFlag DECLARED_SYNCHRONIZED ;
5157
5258 private static final AccessFlag [] VALUES ;
59+ private static final AccessFlag [] METHOD_VALUES ;
60+ private static final int MASK ;
5361
5462 private static final HashMap <String , AccessFlag > accessFlagsByName ;
5563
5664 static {
5765
58- PUBLIC = new AccessFlag (0x1 , "public" , true , true , true );
59- PRIVATE = new AccessFlag (0x2 , "private" , true , true , true );
60- PROTECTED = new AccessFlag (0x4 , "protected" , true , true , true );
61- STATIC = new AccessFlag (0x8 , "static" , true , true , true );
62- FINAL = new AccessFlag (0x10 , "final" , true , true , true );
63- SYNCHRONIZED = new AccessFlag (0x20 , "synchronized" , false , true , false );
64- VOLATILE = new AccessFlag (0x40 , "volatile" , false , false , true );
65- BRIDGE = new AccessFlag (0x40 , "bridge" , false , true , false );
66- TRANSIENT = new AccessFlag (0x80 , "transient" , false , false , true );
67- VARARGS = new AccessFlag (0x80 , "varargs" , false , true , false );
68- NATIVE = new AccessFlag (0x100 , "native" , false , true , false );
69- INTERFACE = new AccessFlag (0x200 , "interface" , true , false , false );
70- ABSTRACT = new AccessFlag (0x400 , "abstract" , true , true , false );
71- STRICTFP = new AccessFlag (0x800 , "strictfp" , false , true , false );
72- SYNTHETIC = new AccessFlag (0x1000 , "synthetic" , true , true , true );
73- ANNOTATION = new AccessFlag (0x2000 , "annotation" , true , false , false );
74- ENUM = new AccessFlag (0x4000 , "enum" , true , false , true );
75- MANDATED = new AccessFlag (0x8000 , "mandated" , false , false , false );
76- CONSTRUCTOR = new AccessFlag (0x10000 , "constructor" , false , true , false );
77- DECLARED_SYNCHRONIZED = new AccessFlag (0x20000 , "declared-synchronized" , false , true , false );
78-
79- VALUES = new AccessFlag []{
80- PUBLIC ,
81- PRIVATE ,
82- PROTECTED ,
83- STATIC ,
84- FINAL ,
85- SYNCHRONIZED ,
86- VOLATILE ,
87- BRIDGE ,
88- TRANSIENT ,
89- VARARGS ,
90- NATIVE ,
91- INTERFACE ,
92- ABSTRACT ,
93- STRICTFP ,
94- SYNTHETIC ,
95- ANNOTATION ,
96- ENUM ,
97- MANDATED ,
98- CONSTRUCTOR ,
99- DECLARED_SYNCHRONIZED
100- };
101-
102- accessFlagsByName = new HashMap <>();
103- for (AccessFlag accessFlag : VALUES ) {
104- accessFlagsByName .put (accessFlag .getName (), accessFlag );
105- }
66+ AccessFlag [] values = new AccessFlag [18 ];
67+ VALUES = values ;
68+
69+ PUBLIC = values [0 ] = new AccessFlag (0x1 , "public" , true , true , true );
70+ PRIVATE = values [1 ] = new AccessFlag (0x1 << 1 , "private" , true , true , true );
71+ PROTECTED = values [2 ] = new AccessFlag (0x1 << 2 , "protected" , true , true , true );
72+ STATIC = values [3 ] = new AccessFlag (0x1 << 3 , "static" , true , true , true );
73+ FINAL = values [4 ] = new AccessFlag (0x1 << 4 , "final" , true , true , true );
74+ SYNCHRONIZED = values [5 ] = new AccessFlag (0x1 << 5 , "synchronized" , false , true , false );
75+
76+ VOLATILE = values [6 ] = new AccessFlag (0x1 << 6 , "volatile" , false , false , true );
77+ BRIDGE = new AccessFlag (0x1 << 6 , "bridge" , false , true , false );
78+
79+ TRANSIENT = values [7 ] = new AccessFlag (0x1 << 7 , "transient" , false , false , true );
80+ VARARGS = new AccessFlag (0x1 << 7 , "varargs" , false , true , false );
10681
82+ NATIVE = values [8 ] = new AccessFlag (0x1 << 8 , "native" , false , true , false );
83+ INTERFACE = values [9 ] = new AccessFlag (0x1 << 9 , "interface" , true , false , false );
84+ ABSTRACT = values [10 ] = new AccessFlag (0x1 << 10 , "abstract" , true , true , false );
85+ STRICTFP = values [11 ] = new AccessFlag (0x1 << 11 , "strictfp" , false , true , false );
86+ SYNTHETIC = values [12 ] = new AccessFlag (0x1 << 12 , "synthetic" , true , true , true );
87+ ANNOTATION = values [13 ] = new AccessFlag (0x1 << 13 , "annotation" , true , false , false );
88+ ENUM = values [14 ] = new AccessFlag (0x1 << 14 , "enum" , true , false , true );
89+ MANDATED = values [15 ] = new AccessFlag (0x1 << 15 , "mandated" , false , false , false );
90+ CONSTRUCTOR = values [16 ] = new AccessFlag (0x1 << 16 , "constructor" , false , true , false );
91+ DECLARED_SYNCHRONIZED = values [17 ] = new AccessFlag (0x1 << 17 , "declared-synchronized" , false , true , false );
92+
93+ MASK = (0x1 << values .length ) - 1 ;
94+
95+ AccessFlag [] methodValues = values .clone ();
96+ methodValues [6 ] = BRIDGE ;
97+ methodValues [7 ] = VARARGS ;
98+ METHOD_VALUES = methodValues ;
99+
100+ HashMap <String , AccessFlag > map = new HashMap <>(20 );
101+ accessFlagsByName = map ;
102+
103+ for (AccessFlag accessFlag : values ) {
104+ map .put (accessFlag .getName (), accessFlag );
105+ }
106+ map .put (BRIDGE .getName (), BRIDGE );
107+ map .put (VARARGS .getName (), VARARGS );
107108 }
108109
109110 private final boolean validForClass ;
@@ -118,65 +119,94 @@ private AccessFlag(int value, String name, boolean validForClass, boolean validF
118119 this .validForField = validForField ;
119120 }
120121
121- @ Override
122- public boolean isSet (int accessFlags ) {
123- return (getValue () & accessFlags ) != 0 ;
124- }
125- public boolean isSet (ElementType elementType , int accessFlags ) {
126- if (elementType == ElementType .TYPE ) {
127- return isSetForClass (accessFlags );
128- }
129- if (elementType == ElementType .FIELD ) {
130- return isSetForField (accessFlags );
131- }
132- if (elementType == ElementType .METHOD ) {
133- return isSetForMethod (accessFlags );
134- }
135- return false ;
122+ public boolean isValidForClass () {
123+ return validForClass ;
136124 }
137- private boolean isSetForField ( int value ) {
138- return validForField && ( getValue () & value ) != 0 ;
125+ public boolean isValidForField ( ) {
126+ return validForField ;
139127 }
140- private boolean isSetForMethod ( int value ) {
141- return validForMethod && ( getValue () & value ) != 0 ;
128+ public boolean isValidForMethod ( ) {
129+ return validForMethod ;
142130 }
143- private boolean isSetForClass (int value ) {
144- return validForClass && (getValue () & value ) != 0 ;
131+
132+ @ Override
133+ public boolean isSet (int accessFlags ) {
134+ return (getValue () & accessFlags ) != 0 ;
145135 }
146136
147137 public static Iterator <AccessFlag > valuesOf (ElementType elementType , int value ) {
148- if (elementType == ElementType .TYPE ) {
149- return valuesOfClass (value );
138+ return valuesOf (elementType == ElementType .METHOD , value );
139+ }
140+ public static Iterator <AccessFlag > valuesOf (int value ) {
141+ value = value & MASK ;
142+ if (value == 0 ) {
143+ return EmptyIterator .of ();
150144 }
151- if (elementType == ElementType .FIELD ) {
152- return valuesOfField (value );
145+ return new FlagsIterator (VALUES , value );
146+ }
147+ public static Iterator <AccessFlag > valuesOf (boolean method , int value ) {
148+ value = value & MASK ;
149+ if (value == 0 ) {
150+ return EmptyIterator .of ();
153151 }
154- if (elementType == ElementType .METHOD ) {
155- return valuesOfMethod (value );
152+ AccessFlag [] values ;
153+ if (method ) {
154+ values = METHOD_VALUES ;
155+ } else {
156+ values = VALUES ;
156157 }
157- return valuesOf (value );
158- }
159- public static Iterator <AccessFlag > valuesOfClass (int value ) {
160- return getValues (accessFlag -> accessFlag .isSetForClass (value ));
161- }
162- public static Iterator <AccessFlag > valuesOfMethod (int value ) {
163- return getValues (accessFlag -> accessFlag .isSetForMethod (value ));
164- }
165- public static Iterator <AccessFlag > valuesOfField (int value ) {
166- return getValues (accessFlag -> accessFlag .isSetForField (value ));
167- }
168- public static Iterator <AccessFlag > valuesOf (int value ) {
169- return getValues (accessFlag -> accessFlag .isSet (value ));
158+ return new FlagsIterator (values , value );
170159 }
171160 public static AccessFlag valueOf (String name ) {
172161 return accessFlagsByName .get (name );
173162 }
174163 public static Iterator <AccessFlag > getValues () {
175- return getValues ( null );
164+ return new ArrayIterator <>( VALUES );
176165 }
177166 public static Iterator <AccessFlag > getValues (Predicate <AccessFlag > filter ) {
178167 return new ArrayIterator <>(VALUES , filter );
179168 }
169+ public static String toString (int flags ) {
170+ return toString (false , flags );
171+ }
172+ public static String toString (boolean method , int flags ) {
173+ flags = flags & MASK ;
174+ if (flags == 0 ) {
175+ return StringsUtil .EMPTY ;
176+ }
177+ StringBuilder builder = new StringBuilder ();
178+ try {
179+ append (method , flags , builder );
180+ } catch (IOException e ) {
181+ builder .append (" # Unexpected AccessFlags.append: " );
182+ builder .append (e .getMessage ());
183+ }
184+ return builder .toString ();
185+ }
186+ public static void append (int flags , Appendable appendable ) throws IOException {
187+ append (false , flags , appendable );
188+ }
189+ public static void append (boolean method , int flags , Appendable appendable ) throws IOException {
190+ flags = flags & MASK ;
191+ if (flags == 0 ) {
192+ return ;
193+ }
194+ AccessFlag [] values ;
195+ if (method ) {
196+ values = METHOD_VALUES ;
197+ } else {
198+ values = VALUES ;
199+ }
200+ int i = 0 ;
201+ while (flags != 0 ) {
202+ if ((flags & 0x1 ) != 0 ) {
203+ appendable .append (values [i ].getName ());
204+ appendable .append (' ' );
205+ }
206+ flags = flags >>> 1 ;
207+ i ++;
208+ }
209+ }
180210 public static AccessFlag [] parse (SmaliReader reader ) {
181211 List <AccessFlag > accessFlags = null ;
182212 AccessFlag flag ;
@@ -220,4 +250,35 @@ public static int combineAccessFlags(Iterator<? extends Modifier> iterator) {
220250 }
221251 return result ;
222252 }
253+ static class FlagsIterator implements Iterator <AccessFlag > {
254+
255+ private final AccessFlag [] values ;
256+ private int flags ;
257+ private int index ;
258+
259+ public FlagsIterator (AccessFlag [] values , int flags ) {
260+ this .values = values ;
261+ this .flags = flags ;
262+ }
263+ @ Override
264+ public boolean hasNext () {
265+ return flags != 0 ;
266+ }
267+ @ Override
268+ public AccessFlag next () {
269+ int flags = this .flags ;
270+ if (flags == 0 ) {
271+ throw new NoSuchElementException ();
272+ }
273+ int index = this .index ;
274+ while ((flags & 0x1 ) == 0 ) {
275+ flags = flags >>> 1 ;
276+ index ++;
277+ }
278+ AccessFlag accessFlag = values [index ];
279+ this .flags = flags >>> 1 ;
280+ this .index = index + 1 ;
281+ return accessFlag ;
282+ }
283+ }
223284}
0 commit comments