removed Makefile; lifted repo/org.ibex.tool/src/ to src/
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / classfmt / FieldInfo.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.classfmt;
12
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
15 import org.eclipse.jdt.internal.compiler.env.IBinaryField;
16 import org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
17 import org.eclipse.jdt.internal.compiler.impl.ByteConstant;
18 import org.eclipse.jdt.internal.compiler.impl.CharConstant;
19 import org.eclipse.jdt.internal.compiler.impl.Constant;
20 import org.eclipse.jdt.internal.compiler.impl.DoubleConstant;
21 import org.eclipse.jdt.internal.compiler.impl.FloatConstant;
22 import org.eclipse.jdt.internal.compiler.impl.IntConstant;
23 import org.eclipse.jdt.internal.compiler.impl.LongConstant;
24 import org.eclipse.jdt.internal.compiler.impl.ShortConstant;
25 import org.eclipse.jdt.internal.compiler.impl.StringConstant;
26 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
27 import org.eclipse.jdt.internal.compiler.util.Util;
28
29 public class FieldInfo extends ClassFileStruct implements AttributeNamesConstants, IBinaryField, Comparable, TypeIds {
30         private Constant constant;
31         private boolean isDeprecated;
32         private boolean isSynthetic;
33         private int[] constantPoolOffsets;
34         private int accessFlags;
35         private char[] name;
36         private char[] signature;
37         private int attributeBytes;
38         private Object wrappedConstantValue;
39 /**
40  * @param classFileBytes byte[]
41  * @param offsets int[]
42  * @param offset int
43  */
44 public FieldInfo (byte classFileBytes[], int offsets[], int offset) {
45         super(classFileBytes, offset);
46         constantPoolOffsets = offsets;
47         accessFlags = -1;
48         int attributesCount = u2At(6);
49         int readOffset = 8;
50         for (int i = 0; i < attributesCount; i++) {
51                 readOffset += (6 + u4At(readOffset + 2));
52         }
53         attributeBytes = readOffset;
54 }
55 /**
56  * Return the constant of the field.
57  * Return org.eclipse.jdt.internal.compiler.impl.Constant.NotAConstant if there is none.
58  * @return org.eclipse.jdt.internal.compiler.impl.Constant
59  */
60 public Constant getConstant() {
61         if (constant == null) {
62                 // read constant
63                 readConstantAttribute();
64         }
65         return constant;
66 }
67 /**
68  * Answer an int whose bits are set according the access constants
69  * defined by the VM spec.
70  * Set the AccDeprecated and AccSynthetic bits if necessary
71  * @return int
72  */
73 public int getModifiers() {
74         if (accessFlags == -1) {
75                 // compute the accessflag. Don't forget the deprecated attribute
76                 accessFlags = u2At(0);
77                 readDeprecatedAndSyntheticAttributes();
78                 if (isDeprecated) {
79                         accessFlags |= AccDeprecated;
80                 }
81                 if (isSynthetic) {
82                         accessFlags |= AccSynthetic;
83                 }
84         }
85         return accessFlags;
86 }
87 /**
88  * Answer the name of the field.
89  * @return char[]
90  */
91 public char[] getName() {
92         if (name == null) {
93                 // read the name
94                 int utf8Offset = constantPoolOffsets[u2At(2)] - structOffset;
95                 name = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
96         }
97         return name;
98 }
99 /**
100  * Answer the resolved name of the receiver's type in the
101  * class file format as specified in section 4.3.2 of the Java 2 VM spec.
102  *
103  * For example:
104  *   - java.lang.String is Ljava/lang/String;
105  *   - an int is I
106  *   - a 2 dimensional array of strings is [[Ljava/lang/String;
107  *   - an array of floats is [F
108  * @return char[]
109  */
110 public char[] getTypeName() {
111         if (signature == null) {
112                 // read the signature
113                 int utf8Offset = constantPoolOffsets[u2At(4)] - structOffset;
114                 signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
115         }
116         return signature;
117 }
118 /**
119  * Return a wrapper that contains the constant of the field.
120  * @return java.lang.Object
121  */
122 public Object getWrappedConstantValue() {
123
124         if (this.wrappedConstantValue == null) {
125                 if (hasConstant()) {
126                         Constant fieldConstant = getConstant();
127                         switch (fieldConstant.typeID()) {
128                                 case T_int :
129                                         this.wrappedConstantValue = new Integer(fieldConstant.intValue());
130                                         break;
131                                 case T_byte :
132                                         this.wrappedConstantValue = new Byte(fieldConstant.byteValue());
133                                         break;
134                                 case T_short :
135                                         this.wrappedConstantValue = new Short(fieldConstant.shortValue());
136                                         break;
137                                 case T_char :
138                                         this.wrappedConstantValue = new Character(fieldConstant.charValue());
139                                         break;
140                                 case T_float :
141                                         this.wrappedConstantValue = new Float(fieldConstant.floatValue());
142                                         break;
143                                 case T_double :
144                                         this.wrappedConstantValue = new Double(fieldConstant.doubleValue());
145                                         break;
146                                 case T_boolean :
147                                         this.wrappedConstantValue = Util.toBoolean(fieldConstant.booleanValue());
148                                         break;
149                                 case T_long :
150                                         this.wrappedConstantValue = new Long(fieldConstant.longValue());
151                                         break;
152                                 case T_String :
153                                         this.wrappedConstantValue = fieldConstant.stringValue();
154                         }
155                 }
156         }
157         return this.wrappedConstantValue;
158 }
159 /**
160  * Return true if the field has a constant value attribute, false otherwise.
161  * @return boolean
162  */
163 public boolean hasConstant() {
164         return getConstant() != Constant.NotAConstant;
165 }
166 /**
167  * Return true if the field is a synthetic field, false otherwise.
168  * @return boolean
169  */
170 public boolean isSynthetic() {
171         return (getModifiers() & AccSynthetic) != 0;
172 }
173
174 private void readConstantAttribute() {
175         int attributesCount = u2At(6);
176         int readOffset = 8;
177         boolean isConstant = false;
178         for (int i = 0; i < attributesCount; i++) {
179                 int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
180                 char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
181                 if (CharOperation
182                         .equals(attributeName, ConstantValueName)) {
183                         isConstant = true;
184                         // read the right constant
185                         int relativeOffset = constantPoolOffsets[u2At(readOffset + 6)] - structOffset;
186                         switch (u1At(relativeOffset)) {
187                                 case IntegerTag :
188                                         char[] sign = getTypeName();
189                                         if (sign.length == 1) {
190                                                 switch (sign[0]) {
191                                                         case 'Z' : // boolean constant
192                                                                 constant = new BooleanConstant(i4At(relativeOffset + 1) == 1);
193                                                                 break;
194                                                         case 'I' : // integer constant
195                                                                 constant = new IntConstant(i4At(relativeOffset + 1));
196                                                                 break;
197                                                         case 'C' : // char constant
198                                                                 constant = new CharConstant((char) i4At(relativeOffset + 1));
199                                                                 break;
200                                                         case 'B' : // byte constant
201                                                                 constant = new ByteConstant((byte) i4At(relativeOffset + 1));
202                                                                 break;
203                                                         case 'S' : // short constant
204                                                                 constant = new ShortConstant((short) i4At(relativeOffset + 1));
205                                                                 break;
206                                                         default:
207                                                                 constant = Constant.NotAConstant;                   
208                                                 }
209                                         } else {
210                                                 constant = Constant.NotAConstant;
211                                         }
212                                         break;
213                                 case FloatTag :
214                                         constant = new FloatConstant(floatAt(relativeOffset + 1));
215                                         break;
216                                 case DoubleTag :
217                                         constant = new DoubleConstant(doubleAt(relativeOffset + 1));
218                                         break;
219                                 case LongTag :
220                                         constant = new LongConstant(i8At(relativeOffset + 1));
221                                         break;
222                                 case StringTag :
223                                         utf8Offset = constantPoolOffsets[u2At(relativeOffset + 1)] - structOffset;
224                                         constant = 
225                                                 new StringConstant(
226                                                         String.valueOf(utf8At(utf8Offset + 3, u2At(utf8Offset + 1)))); 
227                                         break;
228                         }
229                 }
230                 readOffset += (6 + u4At(readOffset + 2));
231         }
232         if (!isConstant) {
233                 constant = Constant.NotAConstant;
234         }
235 }
236 private void readDeprecatedAndSyntheticAttributes() {
237         int attributesCount = u2At(6);
238         int readOffset = 8;
239         for (int i = 0; i < attributesCount; i++) {
240                 int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
241                 char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
242                 if (CharOperation.equals(attributeName, DeprecatedName)) {
243                         isDeprecated = true;
244                 } else if (CharOperation.equals(attributeName, SyntheticName)) {
245                         isSynthetic = true;
246                 }
247                 readOffset += (6 + u4At(readOffset + 2));
248         }
249 }
250 /**
251  * Answer the size of the receiver in bytes.
252  * 
253  * @return int
254  */
255 public int sizeInBytes() {
256         return attributeBytes;
257 }
258 public void throwFormatException() throws ClassFormatException {
259         throw new ClassFormatException(ClassFormatException.ErrBadFieldInfo);
260 }
261 public String toString() {
262         StringBuffer buffer = new StringBuffer(this.getClass().getName());
263         int modifiers = getModifiers();
264         return buffer
265                 .append("{") //$NON-NLS-1$
266                 .append(
267                         ((modifiers & AccDeprecated) != 0 ? "deprecated " : "") //$NON-NLS-1$ //$NON-NLS-2$
268                                 + ((modifiers & 0x0001) == 1 ? "public " : "") //$NON-NLS-1$ //$NON-NLS-2$
269                                 + ((modifiers & 0x0002) == 0x0002 ? "private " : "") //$NON-NLS-1$ //$NON-NLS-2$
270                                 + ((modifiers & 0x0004) == 0x0004 ? "protected " : "") //$NON-NLS-1$ //$NON-NLS-2$
271                                 + ((modifiers & 0x0008) == 0x000008 ? "static " : "") //$NON-NLS-1$ //$NON-NLS-2$
272                                 + ((modifiers & 0x0010) == 0x0010 ? "final " : "") //$NON-NLS-1$ //$NON-NLS-2$
273                                 + ((modifiers & 0x0040) == 0x0040 ? "volatile " : "") //$NON-NLS-1$ //$NON-NLS-2$
274                                 + ((modifiers & 0x0080) == 0x0080 ? "transient " : "")) //$NON-NLS-1$ //$NON-NLS-2$
275                 .append(getTypeName())
276                 .append(" ") //$NON-NLS-1$
277                 .append(getName())
278                 .append(" ") //$NON-NLS-1$
279                 .append(getConstant())
280                 .append("}") //$NON-NLS-1$
281                 .toString(); 
282 }
283
284 public int compareTo(Object o) {
285         if (!(o instanceof FieldInfo)) {
286                 throw new ClassCastException();
287         }
288         return new String(this.getName()).compareTo(new String(((FieldInfo) o).getName()));
289 }
290 /**
291  * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
292  * will be therefore fully initialized and we can get rid of the bytes.
293  */
294 void initialize() {
295         getModifiers();
296         getName();
297         getConstant();
298         getTypeName();
299         reset();
300 }
301 protected void reset() {
302         this.constantPoolOffsets = null;
303         super.reset();
304 }
305
306 }