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 */ 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 * @author Vlad Roubtsov, (C) 2003 21 */ 22public 23final class InnerClassesAttribute_info extends Attribute_info 24{ 25 // public: ................................................................ 26 27 // ACCESSORS: 28 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 */ 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 */ 67 public final int size () 68 { 69 return m_classes.size (); 70 } 71 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 79 public void accept (final IAttributeVisitor visitor, final Object ctx) 80 { 81 visitor.visit (this, ctx); 82 } 83 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 */ 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 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 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// ----------------------------------------------------------------------------