1 package mockit.asm.types;
2
3 import static mockit.asm.jvmConstants.Opcodes.ACONST_NULL;
4 import static mockit.asm.jvmConstants.Opcodes.ALOAD;
5
6 import edu.umd.cs.findbugs.annotations.NonNull;
7
8 import org.checkerframework.checker.index.qual.NonNegative;
9
10 public abstract class ReferenceType extends JavaType {
11
12
13
14 @NonNull
15 final char[] typeDescChars;
16
17
18
19
20 @NonNegative
21 final int off;
22
23 ReferenceType(@NonNull char[] typeDesc) {
24 super(typeDesc.length);
25 typeDescChars = typeDesc;
26 off = 0;
27 }
28
29 ReferenceType(@NonNull char[] typeDesc, @NonNegative int off, @NonNegative int len) {
30 super(len);
31 typeDescChars = typeDesc;
32 this.off = off;
33 }
34
35
36
37
38
39
40
41 @NonNull
42 public static ReferenceType createFromTypeDescriptor(@NonNull String typeDesc) {
43 return getReferenceType(typeDesc.toCharArray(), 0);
44 }
45
46
47
48
49
50
51
52
53
54
55 @NonNull
56 static ReferenceType getReferenceType(@NonNull char[] buf, @NonNegative int off) {
57 switch (buf[off]) {
58 case '[':
59 return ArrayType.create(buf, off);
60 case 'L':
61 return ObjectType.create(buf, off);
62 case '(':
63 return new MethodType(buf, off, buf.length - off);
64 default:
65 throw new IllegalArgumentException("Invalid type descriptor: " + new String(buf));
66 }
67 }
68
69
70
71
72 @NonNull
73 public static ReferenceType createFromInternalName(@NonNull String internalName) {
74 char[] buf = internalName.toCharArray();
75 return buf[0] == '[' ? new ArrayType(buf) : new ObjectType(buf);
76 }
77
78 static int findTypeNameLength(@NonNull char[] buf, @NonNegative int off, @NonNegative int len) {
79 len++;
80
81 while (buf[off + len] != ';') {
82 len++;
83 }
84
85 return len;
86 }
87
88 static void getDescriptor(@NonNull StringBuilder buf, @NonNull Class<?> aClass) {
89 buf.append('L');
90
91 String name = aClass.getName();
92 int len = name.length();
93
94 for (int i = 0; i < len; i++) {
95 char c = name.charAt(i);
96 buf.append(c == '.' ? '/' : c);
97 }
98
99 buf.append(';');
100 }
101
102 @Override
103 void getDescriptor(@NonNull StringBuilder typeDesc) {
104 typeDesc.append(typeDescChars, off, len);
105 }
106
107
108
109
110
111
112
113
114 @NonNull
115 public final String getInternalName() {
116 return new String(typeDescChars, off, len);
117 }
118
119 @Override
120 public int getSize() {
121 return 1;
122 }
123
124 @Override
125 public int getOpcode(int opcode) {
126 return opcode + 4;
127 }
128
129 @Override
130 public final int getLoadOpcode() {
131 return ALOAD;
132 }
133
134 @Override
135 public final int getConstOpcode() {
136 return ACONST_NULL;
137 }
138
139 @Override
140 public final boolean equals(Object o) {
141 if (this == o) {
142 return true;
143 }
144
145 if (!(o instanceof ReferenceType)) {
146 return false;
147 }
148
149 ReferenceType t = (ReferenceType) o;
150
151 if (getClass() != t.getClass() || len != t.len) {
152 return false;
153 }
154
155 for (int i = off, j = t.off, end = i + len; i < end; i++, j++) {
156 if (typeDescChars[i] != t.typeDescChars[j]) {
157 return false;
158 }
159 }
160
161 return true;
162 }
163
164 @Override
165 public final int hashCode() {
166 int hc = 13;
167
168 for (int i = off, end = i + len; i < end; i++) {
169
170 hc = 17 * (hc + typeDescChars[i]);
171 }
172
173 return hc;
174 }
175 }