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