diff --git a/jode/jode/bytecode/BinaryInfo.java b/jode/jode/bytecode/BinaryInfo.java index d3bdb8a..622f023 100644 --- a/jode/jode/bytecode/BinaryInfo.java +++ b/jode/jode/bytecode/BinaryInfo.java @@ -19,6 +19,8 @@ package jode.bytecode; import java.io.*; +import java.util.Enumeration; +import jode.util.SimpleDictionary; /** * @@ -34,18 +36,7 @@ public class BinaryInfo { private int status = 0; - protected AttributeInfo[] attributes; - - public AttributeInfo findAttribute(String name) { - for (int i=0; i< attributes.length; i++) - if (attributes[i].getName().equals(name)) - return attributes[i]; - return null; - } - - public AttributeInfo[] getAttributes() { - return attributes; - } + protected SimpleDictionary unknownAttributes; protected void skipAttributes(DataInputStream input) throws IOException { int count = input.readUnsignedShort(); @@ -61,17 +52,144 @@ public class BinaryInfo { } } + protected int getKnownAttributeCount() { + return 0; + } + + protected void readAttribute(String name, int length, + ConstantPool constantPool, + DataInputStream input, + int howMuch) throws IOException { + byte[] data = new byte[length]; + input.readFully(data); + unknownAttributes.put(name, data); + } + + class ConstrainedInputStream extends FilterInputStream { + int length; + + public ConstrainedInputStream(int attrLength, InputStream input) { + super(input); + length = attrLength; + } + + public int read() throws IOException { + if (length > 0) { + int data = super.read(); + length--; + return data; + } + throw new EOFException(); + } + + public int read(byte[] b, int off, int len) throws IOException { + if (length < len) { + len = length; + } + if (len == 0) + return -1; + int count = super.read(b, off, len); + length -= count; + return count; + } + + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + public long skip(long count) throws IOException { + if (length < count) { + count = length; + } + count = super.skip(count); + length -= (int) count; + return count; + } + + public void skipRemaining() throws IOException { + while (length > 0) { + int skipped = (int) skip(length); + if (skipped == 0) + throw new EOFException(); + length -= skipped; + } + } + } + protected void readAttributes(ConstantPool constantPool, DataInputStream input, int howMuch) throws IOException { if ((howMuch & ALL_ATTRIBUTES) != 0) { int count = input.readUnsignedShort(); - attributes = new AttributeInfo[count]; + unknownAttributes = new SimpleDictionary(); for (int i=0; i< count; i++) { - attributes[i] = new AttributeInfo(); - attributes[i].read(constantPool, input, howMuch); + String attrName = + constantPool.getUTF8(input.readUnsignedShort()); + final int attrLength = input.readInt(); + ConstrainedInputStream constrInput = + new ConstrainedInputStream(attrLength, input); + readAttribute(attrName, attrLength, + constantPool, new DataInputStream(constrInput), + howMuch); + constrInput.skipRemaining(); } } else skipAttributes(input); } + + protected void prepareAttributes(GrowableConstantPool gcp) { + Enumeration enum = unknownAttributes.keys(); + while (enum.hasMoreElements()) + gcp.putUTF8((String) enum.nextElement()); + } + + protected void writeKnownAttributes + (GrowableConstantPool constantPool, + DataOutputStream output) throws IOException { + } + + protected void writeAttributes + (GrowableConstantPool constantPool, + DataOutputStream output) throws IOException { + int count = unknownAttributes.size() + getKnownAttributeCount(); + output.writeShort(count); + writeKnownAttributes(constantPool, output); + Enumeration keys = unknownAttributes.keys(); + Enumeration elts = unknownAttributes.elements(); + while (keys.hasMoreElements()) { + String name = (String) keys.nextElement(); + byte[] data = (byte[]) elts.nextElement(); + output.writeShort(constantPool.putUTF8(name)); + output.writeInt(data.length); + output.write(data); + } + } + + public int getAttributeSize() { + int size = 2; /* attribute count */ + Enumeration enum = unknownAttributes.elements(); + while (enum.hasMoreElements()) + size += 2 + 4 + ((byte[]) enum.nextElement()).length; + return size; + } + + public byte[] findAttribute(String name) { + return (byte[]) unknownAttributes.get(name); + } + + public Enumeration getAttributes() { + return unknownAttributes.elements(); + } + + public void setAttribute(String name, byte[] content) { + unknownAttributes.put(name, content); + } + + public byte[] removeAttribute(String name) { + return (byte[]) unknownAttributes.remove(name); + } + + public void removeAllAttributes() { + unknownAttributes = new SimpleDictionary(); + } }