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.
21 public final class FieldDescriptor
22 implements Comparable
<FieldDescriptor
>, MemberDescriptor
24 /** The short type. */
26 public static final FieldDescriptor SHORT
=
27 new FieldDescriptor("S");
29 /** The integer type. */
31 public static final FieldDescriptor INTEGER
=
32 new FieldDescriptor("I");
34 /** String representation. */
35 protected final String string
;
37 /** Is this a primitive type? */
38 protected final boolean primitive
;
40 /** Array dimensions. */
41 protected final int dimensions
;
43 /** The component type. */
44 protected final FieldDescriptor component
;
46 /** The class this refers to. */
47 protected final ClassName classname
;
50 * Initializes the field descriptor.
52 * @param __n The field descriptor to decode.
53 * @throws InvalidClassFormatException If it is not a valid field descriptor.
54 * @throws NullPointerException On null arguments.
58 public FieldDescriptor(String __n
)
59 throws InvalidClassFormatException
, NullPointerException
63 throw new NullPointerException("NARG");
68 // {@squirreljme.error JC2q The field descriptor cannot be blank. (The
72 throw new InvalidClassFormatException(
73 String
.format("JC2q %s", __n
));
75 // Depends on the first character
76 char c
= __n
.charAt(0);
88 this.primitive
= true;
90 this.component
= null;
91 this.classname
= null;
96 this.primitive
= false;
97 this.classname
= null;
101 for (int i
= 0; i
< n
; i
++)
102 if (__n
.charAt(i
) != '[')
106 this.dimensions
= dims
;
109 this.component
= new FieldDescriptor(__n
.substring(1));
114 this.primitive
= false;
116 this.component
= null;
118 // {@squirreljme.error JC2r The field descriptor for a class
119 // must end with a semicolon. (The field descriptor)}
120 if (';' != __n
.charAt(n
- 1))
121 throw new InvalidClassFormatException(
122 String
.format("JC2r %s", __n
));
125 this.classname
= new ClassName(__n
.substring(1, n
- 1));
128 // {@squirreljme.error JC2s The field descriptor is not valid.
129 // (The field descriptor)}
131 throw new InvalidClassFormatException(
132 String
.format("JC2s %s", __n
));
137 * Adds dimensions to the field descriptor.
139 * @param __d The number of dimensions to add.
140 * @return The field descriptor with added dimensions.
141 * @throws IllegalArgumentException If the dimensions are negative.
145 public final FieldDescriptor
addDimensions(int __d
)
146 throws IllegalArgumentException
151 // {@squirreljme.error JC2t Cannot add negative dimensions.}
153 throw new IllegalArgumentException("JC2t");
155 // Prepend string with brackets, to declare a new array
156 StringBuilder sb
= new StringBuilder();
157 for (int i
= 0; i
< __d
; i
++)
161 sb
.append(this.toString());
162 return new FieldDescriptor(sb
.toString());
166 * Returns the name of the used class.
168 * @return The used class or {@code null} if a class is not referred to and
169 * this is a primitive type.
173 public final ClassName
className()
175 // If this is an array then the class name will be the array descriptor
176 if (this.dimensions
> 0)
177 return new ClassName(this.toString());
179 // Otherwise as normal class (or primitive representation)
181 return ClassName
.fromPrimitiveType(this.primitiveType());
182 return this.classname
;
190 public int compareTo(FieldDescriptor __o
)
192 return this.string
.compareTo(__o
.string
);
196 * Returns the component type of the array if this is one.
198 * @return The component type or {@code null} if this is not one.
202 public final FieldDescriptor
componentType()
204 return this.component
;
208 * Returns the number of dimensions in this class.
210 * @return The number of dimensions in the class.
214 public final int dimensions()
216 return this.dimensions
;
224 public boolean equals(Object __o
)
230 if (!(__o
instanceof FieldDescriptor
))
233 return this.string
.equals(((FieldDescriptor
)__o
).string
);
241 public int hashCode()
243 return this.string
.hashCode();
247 * Is this an array type?
249 * @return {@code true} if an array type.
253 public boolean isArray()
255 return this.component
!= null;
259 * Is this a primitive type?
261 * @return {@code true} if this is a primitive type.
265 public boolean isPrimitive()
267 return this.primitive
;
271 * Is this an object type?
273 * @return If this is an object type.
277 public boolean isObject()
279 return !this.isPrimitive();
283 * Returns if this is a wide field or not.
285 * @return If this is a wide field.
289 public final boolean isWide()
293 switch (this.primitiveType())
305 * Returns the primitive type for this field.
307 * @return The primitive type to use or {@code null} if there is none.
311 public PrimitiveType
primitiveType()
317 // Depends on the string
318 switch (this.toString())
320 case "B": return PrimitiveType
.BYTE
;
321 case "C": return PrimitiveType
.CHARACTER
;
322 case "D": return PrimitiveType
.DOUBLE
;
323 case "F": return PrimitiveType
.FLOAT
;
324 case "I": return PrimitiveType
.INTEGER
;
325 case "J": return PrimitiveType
.LONG
;
326 case "S": return PrimitiveType
.SHORT
;
327 case "Z": return PrimitiveType
.BOOLEAN
;
334 * Returns the simple storage type of the field.
336 * @return The simple storage type for this field.
340 public final SimpleStorageType
simpleStorageType()
344 return SimpleStorageType
.OBJECT
;
346 // Primitive types, these are promoted
347 switch (this.primitiveType())
354 return SimpleStorageType
.INTEGER
;
357 return SimpleStorageType
.LONG
;
360 return SimpleStorageType
.FLOAT
;
363 return SimpleStorageType
.DOUBLE
;
367 throw Debugging
.oops();
372 * Returns the width of this field on the stack.
374 * @return The width of the field on the stack.
378 public final int stackWidth()
380 return (this.isWide() ?
2 : 1);
388 public String
toString()