• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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: InnerClassesAttribute_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  * @author Vlad Roubtsov, (C) 2003
21  */
22 public
23 final class InnerClassesAttribute_info extends Attribute_info
24 {
25     // public: ................................................................
26 
27     // ACCESSORS:
28 
makesClassNested(final int class_index, final int [] nestedAccessFlags)29     public boolean makesClassNested (final int class_index, final int [] nestedAccessFlags)
30     {
31         if (class_index > 0)
32         {
33             // TODO: avoid linear loop by keeping all class indices in a bitset
34 
35             for (int i = 0, iLimit = size (); i < iLimit; ++ i)
36             {
37                 final InnerClass_info info = get (i);
38 
39                 if (info.m_inner_class_index == class_index)
40                 {
41                     nestedAccessFlags [0] = info.m_inner_access_flags;
42                     return true;
43                 }
44             }
45         }
46 
47         return false;
48     }
49 
50     /**
51      * Returns {@link InnerClass_info} descriptor at a given offset.
52      *
53      * @param offset inner class entry offset [must be in [0, size()) range;
54      * input not checked]
55      * @return InnerClass_info descriptor [never null]
56      *
57      * @throws IndexOutOfBoundsException if 'offset' is outside of valid range
58      */
get(final int offset)59     public final InnerClass_info get (final int offset)
60     {
61         return (InnerClass_info) m_classes.get (offset);
62     }
63 
64     /**
65      * Returns the number of descriptors in this collection [can be 0].
66      */
size()67     public final int size ()
68     {
69         return m_classes.size ();
70     }
71 
length()72     public final long length ()
73     {
74         return 8 + (m_classes.size () << 3); // use size() if class becomes non-final
75     }
76 
77     // Visitor:
78 
accept(final IAttributeVisitor visitor, final Object ctx)79     public void accept (final IAttributeVisitor visitor, final Object ctx)
80     {
81         visitor.visit (this, ctx);
82     }
83 
toString()84     public String toString ()
85     {
86         final StringBuffer s = new StringBuffer ("InnerClassesAttribute_info: [attribute_name_index = " + m_name_index + ", attribute_length = " + length () + "]\n");
87 
88         for (int l = 0; l < size (); ++ l)
89         {
90             s.append ("            " + get (l));
91             s.append ("\n"); // TODO: proper EOL const
92         }
93 
94         return s.toString ();
95     }
96 
97     // Cloneable:
98 
99     /**
100      * Performs a deep copy.
101      */
clone()102     public Object clone ()
103     {
104         final InnerClassesAttribute_info _clone = (InnerClassesAttribute_info) super.clone ();
105 
106         final List/* InnerClass_info */ classes = m_classes;
107 
108         // do deep copy:
109         final int class_count = classes.size (); // use size() if class becomes non-final
110         _clone.m_classes = new ArrayList (class_count);
111         for (int e = 0; e < class_count; ++ e)
112         {
113             _clone.m_classes.add (((InnerClass_info) classes.get (e)).clone ());
114         }
115 
116         return _clone;
117     }
118 
119     // IClassFormatOutput:
120 
writeInClassFormat(final UDataOutputStream out)121     public void writeInClassFormat (final UDataOutputStream out) throws IOException
122     {
123         super.writeInClassFormat (out);
124 
125         final List/* InnerClass_info */ classes = m_classes;
126 
127         final int class_count = classes.size (); // use size() if class becomes non-final
128         out.writeU2 (class_count);
129 
130         for (int l = 0; l < class_count; ++ l)
131         {
132             ((InnerClass_info) classes.get (l)).writeInClassFormat (out);
133         }
134     }
135 
136     // protected: .............................................................
137 
138     // package: ...............................................................
139 
140 
InnerClassesAttribute_info(final int attribute_name_index, final long attribute_length, final UDataInputStream bytes)141     InnerClassesAttribute_info (final int attribute_name_index, final long attribute_length,
142                                 final UDataInputStream bytes)
143         throws IOException
144     {
145         super (attribute_name_index, attribute_length);
146 
147         final int class_count = bytes.readU2 ();
148         final List/* InnerClass_info */ classes = new ArrayList (class_count);
149 
150         for (int i = 0; i < class_count; ++ i)
151         {
152             classes.add (new InnerClass_info (bytes));
153         }
154 
155         m_classes = classes;
156     }
157 
158     // private: ...............................................................
159 
160 
161     private List/* InnerClass_info */ m_classes; // never null
162 
163 } // end of class
164 // ----------------------------------------------------------------------------