1 16 17 package org.cojen.classfile.attribute; 18 19 import java.util.ArrayList ; 20 import java.util.Collections ; 21 import java.util.List ; 22 import java.util.Set ; 23 import java.util.TreeSet ; 24 import java.io.DataInput ; 25 import java.io.DataOutput ; 26 import java.io.IOException ; 27 import org.cojen.classfile.Attribute; 28 import org.cojen.classfile.ConstantPool; 29 import org.cojen.classfile.FixedLocation; 30 import org.cojen.classfile.Location; 31 32 38 public class LineNumberTableAttr extends Attribute { 39 40 private List mEntries = new ArrayList (); 41 private boolean mClean = false; 42 43 public LineNumberTableAttr(ConstantPool cp) { 44 super(cp, LINE_NUMBER_TABLE); 45 } 46 47 public LineNumberTableAttr(ConstantPool cp, String name) { 48 super(cp, name); 49 } 50 51 public LineNumberTableAttr(ConstantPool cp, String name, int length, DataInput din) 52 throws IOException 53 { 54 super(cp, name); 55 56 int size = din.readUnsignedShort(); 57 for (int i=0; i<size; i++) { 58 int start_pc = din.readUnsignedShort(); 59 int line_number = din.readUnsignedShort(); 60 61 try { 62 addEntry(new FixedLocation(start_pc), line_number); 63 } catch (IllegalArgumentException e) { 64 } 65 } 66 } 67 68 public int getLineNumber(Location start) { 69 clean(); 70 int index = Collections.binarySearch(mEntries, new Entry(start, 0)); 71 if (index < 0) { 72 if ((index = -index - 2) < 0) { 73 return -1; 74 } 75 } 76 return ((Entry)mEntries.get(index)).mLineNumber; 77 } 78 79 public void addEntry(Location start, int line_number) throws IllegalArgumentException { 80 if (line_number < 0 || line_number > 65535) { 81 throw new IllegalArgumentException ("Value for line number out of " + 82 "valid range: " + line_number); 83 } 84 mEntries.add(new Entry(start, line_number)); 85 mClean = false; 86 } 87 88 public int getLength() { 89 clean(); 90 return 2 + 4 * mEntries.size(); 91 } 92 93 public void writeDataTo(DataOutput dout) throws IOException { 94 int size = mEntries.size(); 95 dout.writeShort(size); 96 for (int i=0; i<size; i++) { 97 Entry entry = (Entry)mEntries.get(i); 98 99 int start_pc = entry.mStart.getLocation(); 100 101 if (start_pc < 0 || start_pc > 65535) { 102 throw new IllegalStateException 103 ("Value for line number table entry start PC out of " + 104 "valid range: " + start_pc); 105 } 106 107 dout.writeShort(start_pc); 108 dout.writeShort(entry.mLineNumber); 109 } 110 } 111 112 private void clean() { 113 if (!mClean) { 114 mClean = true; 115 116 122 Set reduced = new TreeSet (); 123 for (int i = mEntries.size(); --i >= 0; ) { 124 reduced.add(mEntries.get(i)); 125 } 126 127 mEntries = new ArrayList (reduced); 128 } 129 } 130 131 private static class Entry implements Comparable { 132 public final Location mStart; 133 public final int mLineNumber; 134 135 public Entry(Location start, int line_number) { 136 mStart = start; 137 mLineNumber = line_number; 138 } 139 140 public int compareTo(Object other) { 141 int thisLoc = mStart.getLocation(); 142 int thatLoc = ((Entry)other).mStart.getLocation(); 143 144 if (thisLoc < thatLoc) { 145 return -1; 146 } else if (thisLoc > thatLoc) { 147 return 1; 148 } else { 149 return 0; 150 } 151 } 152 153 public boolean equals(Object other) { 154 if (other instanceof Entry) { 155 return mStart.getLocation() == 156 ((Entry)other).mStart.getLocation(); 157 } 158 return false; 159 } 160 161 public String toString() { 162 return "start_pc=" + mStart.getLocation() + " => " + 163 "line_number=" + mLineNumber; 164 } 165 } 166 } 167 | Popular Tags |