1/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved. 2 * 3 * This program and the accompanying materials are made available under 4 * the terms of the Common Public License v1.0 which accompanies this distribution, 5 * and is available at http://www.eclipse.org/legal/cpl-v10.html 6 * 7 * $Id: LineNumberTableAttribute_info.java,v 1.1.1.1 2004/05/09 16:57:48 vlad_r Exp $ 8 */ 9package com.vladium.jcd.cls.attribute; 10 11import java.io.IOException; 12import java.util.ArrayList; 13import java.util.List; 14 15import com.vladium.jcd.lib.UDataInputStream; 16import com.vladium.jcd.lib.UDataOutputStream; 17 18// ---------------------------------------------------------------------------- 19/** 20 * The LineNumberTable attribute is an optional variable-length attribute in 21 * the attributes table of a {@link CodeAttribute_info} attribute. It may be 22 * used by debuggers to determine which part of the JVM code array corresponds 23 * to a given line number in the original source file. If LineNumberTable 24 * attributes are present in the attributes table of a given Code attribute, 25 * then they may appear in any order. Furthermore, multiple LineNumberTable 26 * attributes may together represent a given line of a source file; that is, 27 * LineNumberTable attributes need not be one-to-one with source lines.<P> 28 * 29 * The LineNumberTable attribute has the following format: 30 * <PRE> 31 * LineNumberTable_attribute { 32 * u2 attribute_name_index; 33 * u4 attribute_length; 34 * u2 line_number_table_length; 35 * { u2 start_pc; 36 * u2 line_number; 37 * } line_number_table[line_number_table_length]; 38 * } 39 * <PRE> 40 * 41 * LineNumberTable_attribute structure contains the following items: 42 * <PRE> 43 * line_number_table_length 44 * </PRE> 45 * The value of the line_number_table_length item indicates the number of 46 * entries in the line_number_table array. 47 * <PRE> 48 * line_number_table[] 49 * </PRE> 50 * Each entry in the line_number_table array indicates that the line number 51 * in the original source file changes at a given point in the code array.<P> 52 * 53 * Each line_number_table entry must contain the following two items: 54 * <PRE> 55 * start_pc 56 * </PRE> 57 * The value of the start_pc item must indicate the index into the code array 58 * at which the code for a new line in the original source file begins. The 59 * value of start_pc must be less than the value of the code_length item of 60 * the {@link CodeAttribute_info} attribute of which this LineNumberTable 61 * is an attribute.<P> 62 * <PRE> 63 * line_number 64 * </PRE> 65 * The value of the line_number item must give the corresponding line number 66 * in the original source file. 67 * 68 * @author Vlad Roubtsov, (C) 2003 69 */ 70public 71final class LineNumberTableAttribute_info extends Attribute_info 72{ 73 // public: ................................................................ 74 75 // ACCESSORS: 76 77 /** 78 * Returns {@link LineNumber_info} descriptor at a given offset. 79 * 80 * @param offset line number entry offset [must be in [0, size()) range; 81 * input not checked] 82 * @return LineNumber_info descriptor [never null] 83 * 84 * @throws IndexOutOfBoundsException if 'offset' is outside of valid range 85 */ 86 public LineNumber_info get (final int offset) 87 { 88 return (LineNumber_info) m_lines.get (offset); 89 } 90 91 /** 92 * Returns the number of descriptors in this collection [can be 0]. 93 */ 94 public int size () 95 { 96 return m_lines.size (); 97 } 98 99 public long length () 100 { 101 return 8 + (m_lines.size () << 2); // use size() if class becomes non-final 102 } 103 104 // Visitor: 105 106 public void accept (final IAttributeVisitor visitor, final Object ctx) 107 { 108 visitor.visit (this, ctx); 109 } 110 111 public String toString () 112 { 113 final StringBuffer s = new StringBuffer ("LineNumberTableAttribute_info: [attribute_name_index = " + m_name_index + ", attribute_length = " + length () + "]\n"); 114 115 for (int l = 0; l < size (); ++ l) 116 { 117 s.append (" " + get (l)); 118 s.append ("\n"); // TODO: proper EOL const 119 } 120 121 return s.toString (); 122 } 123 124 // Cloneable: 125 126 /** 127 * Performs a deep copy. 128 */ 129 public Object clone () 130 { 131 final LineNumberTableAttribute_info _clone = (LineNumberTableAttribute_info) super.clone (); 132 133 // do deep copy: 134 final int lines_count = m_lines.size (); // use size() if class becomes non-final 135 _clone.m_lines = new ArrayList (lines_count); 136 for (int e = 0; e < lines_count; ++ e) 137 { 138 _clone.m_lines.add (((LineNumber_info) m_lines.get (e)).clone ()); 139 } 140 141 return _clone; 142 } 143 144 // IClassFormatOutput: 145 146 public void writeInClassFormat (final UDataOutputStream out) throws IOException 147 { 148 super.writeInClassFormat (out); 149 150 final int lines_count = m_lines.size (); // use size() if class becomes non-final 151 out.writeU2 (lines_count); 152 153 for (int l = 0; l < lines_count; ++ l) 154 { 155 ((LineNumber_info) m_lines.get (l)).writeInClassFormat (out); 156 } 157 } 158 159 // protected: ............................................................. 160 161 // package: ............................................................... 162 163 164 LineNumberTableAttribute_info (final int attribute_name_index, final long attribute_length, 165 final UDataInputStream bytes) 166 throws IOException 167 { 168 super (attribute_name_index, attribute_length); 169 170 final int lines_count = bytes.readU2 (); 171 m_lines = new ArrayList (lines_count); 172 173 for (int i = 0; i < lines_count; i++) 174 { 175 m_lines.add (new LineNumber_info (bytes)); 176 } 177 } 178 179 // private: ............................................................... 180 181 182 private List/* LineNumber_info */ m_lines; // never null 183 184} // end of class 185// ----------------------------------------------------------------------------