KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > vladium > jcd > cls > ConstantCollection


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: ConstantCollection.java,v 1.1.1.1 2004/05/09 16:57:45 vlad_r Exp $
8  */

9 package com.vladium.jcd.cls;
10
11 import java.io.IOException JavaDoc;
12 import java.util.ArrayList JavaDoc;
13 import java.util.List JavaDoc;
14
15 import com.vladium.jcd.cls.constant.*;
16 import com.vladium.jcd.lib.UDataOutputStream;
17 import com.vladium.util.ObjectIntMap;
18
19 // ----------------------------------------------------------------------------
20
/**
21  * @author (C) 2001, Vladimir Roubtsov
22  */

23 final class ConstantCollection implements IConstantCollection
24 {
25     // public: ................................................................
26

27     // IConstantCollection:
28

29     // ACCESSORS:
30

31     public CONSTANT_info get (final int index)
32     {
33         final Object JavaDoc result = m_constants.get (index - 1);
34         
35         if (result == null)
36             throw new IllegalStateException JavaDoc ("assertion failure: dereferencing an invalid constant pool slot " + index);
37         
38         return (CONSTANT_info) result;
39     }
40
41     public IConstantCollection.IConstantIterator iterator ()
42     {
43         return new ConstantIterator (m_constants);
44     }
45     
46     public int find (final int type, final IConstantComparator comparator)
47     {
48         if (comparator == null)
49             throw new IllegalArgumentException JavaDoc ("null input: comparator");
50         
51         for (int i = 0; i < m_constants.size (); ++ i)
52         {
53             final CONSTANT_info constant = (CONSTANT_info) m_constants.get (i);
54             
55             if ((constant != null) && (constant.tag () == type) && comparator.equals (constant))
56                 return i /* !!! */ + 1;
57         }
58         
59         return -1;
60     }
61     
62     public int findCONSTANT_Utf8 (final String JavaDoc value)
63     {
64         if (value == null)
65             throw new IllegalArgumentException JavaDoc ("null input: value");
66         
67         // create index lazily:
68
final ObjectIntMap index = getCONSTANT_Utf8_index ();
69         final int [] result = new int [1];
70         
71         if (index.get (value, result))
72             return result [0] /* !!! */ + 1;
73         else
74             return -1;
75     }
76     
77     public int size ()
78     {
79         return m_size;
80     }
81     
82     // Cloneable:
83

84     /**
85      * Performs a deep copy.
86      */

87     public Object JavaDoc clone ()
88     {
89         try
90         {
91             final ConstantCollection _clone = (ConstantCollection) super.clone ();
92             
93             // deep copy:
94
final int constants_count = m_constants.size ();
95             _clone.m_constants = new ArrayList JavaDoc (constants_count);
96             for (int c = 0; c < constants_count; ++ c)
97             {
98                 final CONSTANT_info constant = (CONSTANT_info) m_constants.get (c);
99                 _clone.m_constants.add (constant == null ? null : constant.clone ());
100             }
101             
102             // note: m_CONSTANT_Utf8_index is not cloned intentionally
103

104             return _clone;
105         }
106         catch (CloneNotSupportedException JavaDoc e)
107         {
108             throw new InternalError JavaDoc (e.toString ());
109         }
110     }
111
112     // IClassFormatOutput:
113

114     public void writeInClassFormat (final UDataOutputStream out) throws IOException JavaDoc
115     {
116         final int constant_pool_count = m_constants.size (); // note: this is not the same as size()
117
out.writeU2 (constant_pool_count + /* !!! */1);
118         
119         final ConstantIterator i = new ConstantIterator (m_constants);
120         for (CONSTANT_info entry; (entry = i.nextConstant ()) != null; )
121         {
122             entry.writeInClassFormat (out);
123         }
124     }
125     
126     // Visitor:
127

128     public void accept (final IClassDefVisitor visitor, final Object JavaDoc ctx)
129     {
130         visitor.visit (this, ctx);
131     }
132     
133     
134     // MUTATORS:
135

136     public CONSTANT_info set (final int index, final CONSTANT_info constant)
137     {
138         final int zindex = index - 1;
139         final CONSTANT_info result = (CONSTANT_info) m_constants.get (zindex);
140         
141         if (result == null)
142             throw new IllegalStateException JavaDoc ("assertion failure: dereferencing an invalid constant pool slot " + index);
143             
144         if (result.width () != constant.width ())
145             throw new IllegalArgumentException JavaDoc ("assertion failure: can't set entry of type [" + result.getClass ().getName () + "] to an entry of type [" + result.getClass ().getName () + "] at pool slot " + index);
146         
147         m_constants.set (zindex, constant);
148         
149         // update the string index if it is in use:
150
if (m_CONSTANT_Utf8_index != null)
151         {
152             // remove the old index value if it exists and is equal to 'index':
153
if (result instanceof CONSTANT_Utf8_info)
154             {
155                 final String JavaDoc mapKey = ((CONSTANT_Utf8_info) result).m_value;
156                 final int [] out = new int [1];
157         
158                 if (m_CONSTANT_Utf8_index.get (mapKey, out) && (out [0] == zindex))
159                     m_CONSTANT_Utf8_index.remove (mapKey);
160             }
161             
162             // add new index value if necessary:
163
if (constant instanceof CONSTANT_Utf8_info)
164                 m_CONSTANT_Utf8_index.put (((CONSTANT_Utf8_info) constant).m_value, zindex);
165         }
166         
167         return result;
168     }
169
170     public int add (final CONSTANT_info constant)
171     {
172         m_constants.add (constant);
173         ++ m_size;
174         final int result = m_constants.size ();
175         
176         for (int width = 1; width < constant.width (); ++ width)
177         {
178             ++ m_size;
179             m_constants.add (null); // insert padding empty slots
180
}
181         
182         // update the string index if it is in use:
183
if ((m_CONSTANT_Utf8_index != null) && (constant instanceof CONSTANT_Utf8_info))
184             m_CONSTANT_Utf8_index.put (((CONSTANT_Utf8_info) constant).m_value, result /* !!! */ - 1);
185         
186         return result;
187     }
188         
189     // protected: .............................................................
190

191     // package: ...............................................................
192

193
194     ConstantCollection (final int capacity)
195     {
196         m_constants = capacity < 0 ? new ArrayList JavaDoc () : new ArrayList JavaDoc (capacity);
197     }
198
199     // private: ...............................................................
200

201     
202     private static final class ConstantIterator implements IConstantCollection.IConstantIterator
203     {
204         ConstantIterator (final List JavaDoc/* CONSTANT_info */ constants)
205         {
206             m_constants = constants;
207             m_next_index = 1;
208             shift ();
209         }
210         
211         
212         public int nextIndex ()
213         {
214             final int result = m_index;
215             shift ();
216             
217             return result;
218         }
219         
220         public CONSTANT_info nextConstant ()
221         {
222             final int nextIndex = nextIndex ();
223             if (nextIndex < 0)
224                 return null;
225             else
226                 return (CONSTANT_info) m_constants.get (nextIndex - 1);
227         }
228         
229         public CONSTANT_info set (final CONSTANT_info constant)
230         {
231             final int zindex = m_prev_index - 1;
232             final CONSTANT_info result = (CONSTANT_info) m_constants.get (zindex);
233         
234             if (result == null) // this should never happen with iterators
235
throw new IllegalStateException JavaDoc ("assertion failure: dereferencing an invalid constant pool slot " + m_prev_index);
236                 
237             if (result.width () != constant.width ())
238                 throw new IllegalArgumentException JavaDoc ("assertion failure: can't set entry of type [" + result.getClass ().getName () + "] to an entry of type [" + result.getClass ().getName () + "] at pool slot " + m_prev_index);
239             
240             m_constants.set (zindex, constant);
241             
242             return result;
243         }
244         
245         
246         private void shift ()
247         {
248             m_prev_index = m_index;
249             m_index = m_next_index;
250             
251             if (m_index > 0)
252             {
253                 try
254                 {
255                     final CONSTANT_info entry = (CONSTANT_info) m_constants.get (m_index - 1);
256
257                     m_next_index += entry.width ();
258                     if (m_next_index > m_constants.size ()) m_next_index = -1;
259                 }
260                 catch (IndexOutOfBoundsException JavaDoc ioobe) // empty collection edge case
261
{
262                     m_index = m_next_index = -1;
263                 }
264             }
265         }
266         
267         
268         private int m_index, m_prev_index, m_next_index;
269         private List JavaDoc/* CONSTANT_info */ m_constants;
270         
271     } // end of nested class
272

273     
274     private ObjectIntMap getCONSTANT_Utf8_index ()
275     {
276         if (m_CONSTANT_Utf8_index == null)
277         {
278             final ObjectIntMap index = new ObjectIntMap (m_size);
279             
280             for (int i = 0; i < m_constants.size (); ++ i)
281             {
282                 final CONSTANT_info constant = (CONSTANT_info) m_constants.get (i);
283                 
284                 if ((constant != null) && (constant.tag () == CONSTANT_Utf8_info.TAG))
285                 {
286                     // it's ok to always put: the later indices will simply override the earlier ones
287
index.put (((CONSTANT_Utf8_info) constant).m_value, i); // note: unadjusted index saved here
288
}
289             }
290             
291             m_CONSTANT_Utf8_index = index;
292         }
293         
294         return m_CONSTANT_Utf8_index;
295     }
296
297
298     private List JavaDoc/* CONSTANT_info */ m_constants; // never null
299
private int m_size;
300     private transient ObjectIntMap /* String(CONSTANT_Utf value) -> int(index) */ m_CONSTANT_Utf8_index;
301     
302 } // end of class
303
// ----------------------------------------------------------------------------
304
Popular Tags