diff options
author | Roel Spilker <r.spilker@gmail.com> | 2010-08-07 22:27:32 +0200 |
---|---|---|
committer | Roel Spilker <r.spilker@gmail.com> | 2010-08-07 22:27:32 +0200 |
commit | 2683c24ee96fd7228198512f5cfcb2fd0b0cfabd (patch) | |
tree | ce72e5c7dfd719139ba165658733aac7f665953f /src | |
parent | b14eef7eed8703824773467606f3be0c03a04b33 (diff) | |
download | lombok-2683c24ee96fd7228198512f5cfcb2fd0b0cfabd.tar.gz lombok-2683c24ee96fd7228198512f5cfcb2fd0b0cfabd.tar.bz2 lombok-2683c24ee96fd7228198512f5cfcb2fd0b0cfabd.zip |
Fixed some bugs in reading the constant pool and added tests
Diffstat (limited to 'src')
-rw-r--r-- | src/core/lombok/bytecode/ClassFileMetaData.java | 122 |
1 files changed, 120 insertions, 2 deletions
diff --git a/src/core/lombok/bytecode/ClassFileMetaData.java b/src/core/lombok/bytecode/ClassFileMetaData.java index df50969a..693a9ad5 100644 --- a/src/core/lombok/bytecode/ClassFileMetaData.java +++ b/src/core/lombok/bytecode/ClassFileMetaData.java @@ -40,6 +40,7 @@ public class ClassFileMetaData { private static final byte NAME_TYPE = 12; private static final int NOT_FOUND = -1; + private static final int START_OF_CONSTANT_POOL = 8; private final byte[] byteCode; @@ -52,12 +53,12 @@ public class ClassFileMetaData { public ClassFileMetaData(byte[] byteCode) { this.byteCode = byteCode; - maxPoolSize = readValue(8) + 1; + maxPoolSize = readValue(START_OF_CONSTANT_POOL); offsets = new int[maxPoolSize]; types = new byte[maxPoolSize]; utf8s = new String[maxPoolSize]; int position = 10; - for (int i = 1; i < maxPoolSize - 1; i++) { + for (int i = 1; i < maxPoolSize; i++) { byte type = byteCode[position]; types[i] = type; position++; @@ -84,6 +85,7 @@ public class ClassFileMetaData { case LONG: case DOUBLE: position += 8; + i++; break; case 0: break; @@ -178,6 +180,65 @@ public class ClassFileMetaData { return false; } + public boolean containsLong(long value) { + for (int i = 1; i < maxPoolSize; i++) { + if (types[i] == LONG && readLong(i) == value) return true; + } + return false; + } + + public boolean containsDouble(double value) { + boolean isNan = Double.isNaN(value); + for (int i = 1; i < maxPoolSize; i++) { + if (types[i] == DOUBLE) { + double d = readDouble(i); + if (d == value || (isNan && Double.isNaN(d))) return true; + } + } + return false; + } + + public boolean containsInteger(int value) { + for (int i = 1; i < maxPoolSize; i++) { + if (types[i] == INTEGER && readInteger(i) == value) return true; + } + return false; + } + + public boolean containsFloat(float value) { + boolean isNan = Float.isNaN(value); + for (int i = 1; i < maxPoolSize; i++) { + if (types[i] == FLOAT) { + float f = readFloat(i); + if (f == value || (isNan && Float.isNaN(f))) return true; + } + } + return false; + } + + private long readLong(int index) { + int pos = offsets[index]; + return ((long)read32(pos)) << 32 | read32(pos + 4); + } + + private double readDouble(int index) { + int pos = offsets[index]; + long bits = ((long)read32(pos)) << 32 | (read32(pos + 4) & 0x00000000FFFFFFFF); + return Double.longBitsToDouble(bits); + } + + private long readInteger(int index) { + return read32(offsets[index]); + } + + private float readFloat(int index) { + return Float.intBitsToFloat(read32(offsets[index])); + } + + private int read32(int pos) { + return (byteCode[pos] & 0xFF) << 24 | (byteCode[pos + 1] & 0xFF) << 16 | (byteCode[pos + 2] & 0xFF) << 8 | (byteCode[pos + 3] &0xFF); + } + public String getClassName() { return getClassName(readValue(endOfPool + 2)); } @@ -197,6 +258,63 @@ public class ClassFileMetaData { return result; } + public String poolContent() { + StringBuilder result = new StringBuilder(); + for (int i = 1; i < maxPoolSize; i++) { + result.append(String.format("#%02d: ", i)); + int pos = offsets[i]; + switch(types[i]) { + case UTF8: + result.append("Utf8 ").append(utf8s[i]); + break; + case CLASS: + result.append("Class ").append(getClassName(i)); + break; + case STRING: + result.append("String \"").append(utf8s[readValue(pos)]).append("\""); + break; + case INTEGER: + result.append("int ").append(readInteger(i)); + break; + case FLOAT: + result.append("float ").append(readFloat(i)); + break; + case FIELD: + appendAccess(result.append("Field "), i); + break; + case METHOD: + case IMETHOD: + appendAccess(result.append("Method "), i); + break; + case NAME_TYPE: + appendNameAndType(result.append("Name&Type "), i); + break; + case LONG: + result.append("long ").append(readLong(i)); + break; + case DOUBLE: + result.append("double ").append(readDouble(i)); + break; + case 0: + result.append("(cont.)"); + break; + } + result.append("\n"); + } + return result.toString(); + } + + private void appendAccess(StringBuilder result, int index) { + int pos = offsets[index]; + result.append(getClassName(readValue(pos))).append("."); + appendNameAndType(result, readValue(pos + 2)); + } + + private void appendNameAndType(StringBuilder result, int index) { + int pos = offsets[index]; + result.append(utf8s[readValue(pos)]).append(":").append(utf8s[readValue(pos + 2)]); + } + private String getClassName(int classIndex) { if (classIndex < 1) return null; return utf8s[readValue(offsets[classIndex])]; |