1 // -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the GNU General Public License v3+, or later.
7 // See license.mkd for licensing and copyright information.
8 // ---------------------------------------------------------------------------
10 package net
.multiphasicapps
.classfile
;
12 import cc
.squirreljme
.runtime
.cldc
.annotation
.Exported
;
13 import cc
.squirreljme
.runtime
.cldc
.debug
.Debugging
;
16 * This represents the type descriptor of a field.
20 public final class FieldDescriptor
21 implements Comparable
<FieldDescriptor
>, MemberDescriptor
23 /** The short type. */
24 public static final FieldDescriptor SHORT
=
25 new FieldDescriptor("S");
27 /** The integer type. */
28 public static final FieldDescriptor INTEGER
=
29 new FieldDescriptor("I");
31 /** String representation. */
32 protected final String string
;
34 /** Is this a primitive type? */
35 protected final boolean primitive
;
37 /** Array dimensions. */
38 protected final int dimensions
;
40 /** The component type. */
41 protected final FieldDescriptor component
;
43 /** The class this refers to. */
44 protected final ClassName classname
;
47 * Initializes the field descriptor.
49 * @param __n The field descriptor to decode.
50 * @throws InvalidClassFormatException If it is not a valid field descriptor.
51 * @throws NullPointerException On null arguments.
54 public FieldDescriptor(String __n
)
55 throws InvalidClassFormatException
, NullPointerException
59 throw new NullPointerException("NARG");
64 // {@squirreljme.error JC2q The field descriptor cannot be blank. (The
68 throw new InvalidClassFormatException(
69 String
.format("JC2q %s", __n
));
71 // Depends on the first character
72 char c
= __n
.charAt(0);
84 this.primitive
= true;
86 this.component
= null;
87 this.classname
= null;
92 this.primitive
= false;
93 this.classname
= null;
97 for (int i
= 0; i
< n
; i
++)
98 if (__n
.charAt(i
) != '[')
102 this.dimensions
= dims
;
105 this.component
= new FieldDescriptor(__n
.substring(1));
110 this.primitive
= false;
112 this.component
= null;
114 // {@squirreljme.error JC2r The field descriptor for a class
115 // must end with a semicolon. (The field descriptor)}
116 if (';' != __n
.charAt(n
- 1))
117 throw new InvalidClassFormatException(
118 String
.format("JC2r %s", __n
));
121 this.classname
= new ClassName(__n
.substring(1, n
- 1));
124 // {@squirreljme.error JC2s The field descriptor is not valid.
125 // (The field descriptor)}
127 throw new InvalidClassFormatException(
128 String
.format("JC2s %s", __n
));
133 * Adds dimensions to the field descriptor.
135 * @param __d The number of dimensions to add.
136 * @return The field descriptor with added dimensions.
137 * @throws IllegalArgumentException If the dimensions are negative.
140 public final FieldDescriptor
addDimensions(int __d
)
141 throws IllegalArgumentException
146 // {@squirreljme.error JC2t Cannot add negative dimensions.}
148 throw new IllegalArgumentException("JC2t");
150 // Prepend string with brackets, to declare a new array
151 StringBuilder sb
= new StringBuilder();
152 for (int i
= 0; i
< __d
; i
++)
156 sb
.append(this.toString());
157 return new FieldDescriptor(sb
.toString());
161 * Returns the name of the used class.
163 * @return The used class or {@code null} if a class is not referred to and
164 * this is a primitive type.
167 public final ClassName
className()
169 // If this is an array then the class name will be the array descriptor
170 if (this.dimensions
> 0)
171 return new ClassName(this.toString());
173 // Otherwise as normal class (or primitive representation)
175 return ClassName
.fromPrimitiveType(this.primitiveType());
176 return this.classname
;
184 public int compareTo(FieldDescriptor __o
)
186 return this.string
.compareTo(__o
.string
);
190 * Returns the component type of the array if this is one.
192 * @return The component type or {@code null} if this is not one.
195 public final FieldDescriptor
componentType()
197 return this.component
;
201 * Returns the number of dimensions in this class.
203 * @return The number of dimensions in the class.
206 public final int dimensions()
208 return this.dimensions
;
216 public boolean equals(Object __o
)
222 if (!(__o
instanceof FieldDescriptor
))
225 return this.string
.equals(((FieldDescriptor
)__o
).string
);
233 public int hashCode()
235 return this.string
.hashCode();
239 * Is this an array type?
241 * @return {@code true} if an array type.
244 public boolean isArray()
246 return this.component
!= null;
250 * Is this a primitive type?
252 * @return {@code true} if this is a primitive type.
255 public boolean isPrimitive()
257 return this.primitive
;
261 * Is this an object type?
263 * @return If this is an object type.
266 public boolean isObject()
268 return !this.isPrimitive();
272 * Returns if this is a wide field or not.
274 * @return If this is a wide field.
277 public final boolean isWide()
281 switch (this.primitiveType())
293 * Returns the primitive type for this field.
295 * @return The primitive type to use or {@code null} if there is none.
298 public PrimitiveType
primitiveType()
304 // Depends on the string
305 switch (this.toString())
307 case "B": return PrimitiveType
.BYTE
;
308 case "C": return PrimitiveType
.CHARACTER
;
309 case "D": return PrimitiveType
.DOUBLE
;
310 case "F": return PrimitiveType
.FLOAT
;
311 case "I": return PrimitiveType
.INTEGER
;
312 case "J": return PrimitiveType
.LONG
;
313 case "S": return PrimitiveType
.SHORT
;
314 case "Z": return PrimitiveType
.BOOLEAN
;
321 * Returns the simple storage type of the field.
323 * @return The simple storage type for this field.
326 public final SimpleStorageType
simpleStorageType()
330 return SimpleStorageType
.OBJECT
;
332 // Primitive types, these are promoted
333 switch (this.primitiveType())
340 return SimpleStorageType
.INTEGER
;
343 return SimpleStorageType
.LONG
;
346 return SimpleStorageType
.FLOAT
;
349 return SimpleStorageType
.DOUBLE
;
353 throw Debugging
.oops();
358 * Returns the width of this field on the stack.
360 * @return The width of the field on the stack.
363 public final int stackWidth()
365 return (this.isWide() ?
2 : 1);
373 public String
toString()