| /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under |
| * the terms of the Common Public License v1.0 which accompanies this distribution, |
| * and is available at http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * $Id: LineNumberTableAttribute_info.java,v 1.1.1.1 2004/05/09 16:57:48 vlad_r Exp $ |
| */ |
| package com.vladium.jcd.cls.attribute; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import com.vladium.jcd.lib.UDataInputStream; |
| import com.vladium.jcd.lib.UDataOutputStream; |
| |
| // ---------------------------------------------------------------------------- |
| /** |
| * The LineNumberTable attribute is an optional variable-length attribute in |
| * the attributes table of a {@link CodeAttribute_info} attribute. It may be |
| * used by debuggers to determine which part of the JVM code array corresponds |
| * to a given line number in the original source file. If LineNumberTable |
| * attributes are present in the attributes table of a given Code attribute, |
| * then they may appear in any order. Furthermore, multiple LineNumberTable |
| * attributes may together represent a given line of a source file; that is, |
| * LineNumberTable attributes need not be one-to-one with source lines.<P> |
| * |
| * The LineNumberTable attribute has the following format: |
| * <PRE> |
| * LineNumberTable_attribute { |
| * u2 attribute_name_index; |
| * u4 attribute_length; |
| * u2 line_number_table_length; |
| * { u2 start_pc; |
| * u2 line_number; |
| * } line_number_table[line_number_table_length]; |
| * } |
| * <PRE> |
| * |
| * LineNumberTable_attribute structure contains the following items: |
| * <PRE> |
| * line_number_table_length |
| * </PRE> |
| * The value of the line_number_table_length item indicates the number of |
| * entries in the line_number_table array. |
| * <PRE> |
| * line_number_table[] |
| * </PRE> |
| * Each entry in the line_number_table array indicates that the line number |
| * in the original source file changes at a given point in the code array.<P> |
| * |
| * Each line_number_table entry must contain the following two items: |
| * <PRE> |
| * start_pc |
| * </PRE> |
| * The value of the start_pc item must indicate the index into the code array |
| * at which the code for a new line in the original source file begins. The |
| * value of start_pc must be less than the value of the code_length item of |
| * the {@link CodeAttribute_info} attribute of which this LineNumberTable |
| * is an attribute.<P> |
| * <PRE> |
| * line_number |
| * </PRE> |
| * The value of the line_number item must give the corresponding line number |
| * in the original source file. |
| * |
| * @author Vlad Roubtsov, (C) 2003 |
| */ |
| public |
| final class LineNumberTableAttribute_info extends Attribute_info |
| { |
| // public: ................................................................ |
| |
| // ACCESSORS: |
| |
| /** |
| * Returns {@link LineNumber_info} descriptor at a given offset. |
| * |
| * @param offset line number entry offset [must be in [0, size()) range; |
| * input not checked] |
| * @return LineNumber_info descriptor [never null] |
| * |
| * @throws IndexOutOfBoundsException if 'offset' is outside of valid range |
| */ |
| public LineNumber_info get (final int offset) |
| { |
| return (LineNumber_info) m_lines.get (offset); |
| } |
| |
| /** |
| * Returns the number of descriptors in this collection [can be 0]. |
| */ |
| public int size () |
| { |
| return m_lines.size (); |
| } |
| |
| public long length () |
| { |
| return 8 + (m_lines.size () << 2); // use size() if class becomes non-final |
| } |
| |
| // Visitor: |
| |
| public void accept (final IAttributeVisitor visitor, final Object ctx) |
| { |
| visitor.visit (this, ctx); |
| } |
| |
| public String toString () |
| { |
| final StringBuffer s = new StringBuffer ("LineNumberTableAttribute_info: [attribute_name_index = " + m_name_index + ", attribute_length = " + length () + "]\n"); |
| |
| for (int l = 0; l < size (); ++ l) |
| { |
| s.append (" " + get (l)); |
| s.append ("\n"); // TODO: proper EOL const |
| } |
| |
| return s.toString (); |
| } |
| |
| // Cloneable: |
| |
| /** |
| * Performs a deep copy. |
| */ |
| public Object clone () |
| { |
| final LineNumberTableAttribute_info _clone = (LineNumberTableAttribute_info) super.clone (); |
| |
| // do deep copy: |
| final int lines_count = m_lines.size (); // use size() if class becomes non-final |
| _clone.m_lines = new ArrayList (lines_count); |
| for (int e = 0; e < lines_count; ++ e) |
| { |
| _clone.m_lines.add (((LineNumber_info) m_lines.get (e)).clone ()); |
| } |
| |
| return _clone; |
| } |
| |
| // IClassFormatOutput: |
| |
| public void writeInClassFormat (final UDataOutputStream out) throws IOException |
| { |
| super.writeInClassFormat (out); |
| |
| final int lines_count = m_lines.size (); // use size() if class becomes non-final |
| out.writeU2 (lines_count); |
| |
| for (int l = 0; l < lines_count; ++ l) |
| { |
| ((LineNumber_info) m_lines.get (l)).writeInClassFormat (out); |
| } |
| } |
| |
| // protected: ............................................................. |
| |
| // package: ............................................................... |
| |
| |
| LineNumberTableAttribute_info (final int attribute_name_index, final long attribute_length, |
| final UDataInputStream bytes) |
| throws IOException |
| { |
| super (attribute_name_index, attribute_length); |
| |
| final int lines_count = bytes.readU2 (); |
| m_lines = new ArrayList (lines_count); |
| |
| for (int i = 0; i < lines_count; i++) |
| { |
| m_lines.add (new LineNumber_info (bytes)); |
| } |
| } |
| |
| // private: ............................................................... |
| |
| |
| private List/* LineNumber_info */ m_lines; // never null |
| |
| } // end of class |
| // ---------------------------------------------------------------------------- |