Home | History | Annotate | Download | only in attribute
      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  */
      9 package com.vladium.jcd.cls.attribute;
     10 
     11 import java.io.IOException;
     12 import java.util.ArrayList;
     13 import java.util.List;
     14 
     15 import com.vladium.jcd.lib.UDataInputStream;
     16 import 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  */
     70 public
     71 final 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 // ----------------------------------------------------------------------------