001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: IntVector.java 468655 2006-10-28 07:12:06Z minchau $
020     */
021    package org.apache.xml.utils;
022    
023    /**
024     * A very simple table that stores a list of int.
025     *
026     * This version is based on a "realloc" strategy -- a simle array is
027     * used, and when more storage is needed, a larger array is obtained
028     * and all existing data is recopied into it. As a result, read/write
029     * access to existing nodes is O(1) fast but appending may be O(N**2)
030     * slow. See also SuballocatedIntVector.
031     * @xsl.usage internal
032     */
033    public class IntVector implements Cloneable
034    {
035    
036      /** Size of blocks to allocate          */
037      protected int m_blocksize;
038    
039      /** Array of ints          */
040      protected int m_map[]; // IntStack is trying to see this directly
041    
042      /** Number of ints in array          */
043      protected int m_firstFree = 0;
044    
045      /** Size of array          */
046      protected int m_mapSize;
047    
048      /**
049       * Default constructor.  Note that the default
050       * block size is very small, for small lists.
051       */
052      public IntVector()
053      {
054    
055        m_blocksize = 32;
056        m_mapSize = m_blocksize;
057        m_map = new int[m_blocksize];
058      }
059    
060      /**
061       * Construct a IntVector, using the given block size.
062       *
063       * @param blocksize Size of block to allocate
064       */
065      public IntVector(int blocksize)
066      {
067    
068        m_blocksize = blocksize;
069        m_mapSize = blocksize;
070        m_map = new int[blocksize];
071      }
072      
073      /**
074       * Construct a IntVector, using the given block size.
075       *
076       * @param blocksize Size of block to allocate
077       */
078      public IntVector(int blocksize, int increaseSize)
079      {
080    
081        m_blocksize = increaseSize;
082        m_mapSize = blocksize;
083        m_map = new int[blocksize];
084      }
085    
086      /**
087       * Copy constructor for IntVector
088       * 
089       * @param v Existing IntVector to copy
090       */
091      public IntVector(IntVector v)
092      {
093            m_map = new int[v.m_mapSize];
094        m_mapSize = v.m_mapSize;
095        m_firstFree = v.m_firstFree;
096            m_blocksize = v.m_blocksize;
097            System.arraycopy(v.m_map, 0, m_map, 0, m_firstFree);
098      }
099    
100      /**
101       * Get the length of the list.
102       *
103       * @return length of the list
104       */
105      public final int size()
106      {
107        return m_firstFree;
108      }
109      
110      /**
111       * Get the length of the list.
112       *
113       * @return length of the list
114       */
115      public final void setSize(int sz)
116      {
117        m_firstFree = sz;
118      }
119    
120    
121      /**
122       * Append a int onto the vector.
123       *
124       * @param value Int to add to the list 
125       */
126      public final void addElement(int value)
127      {
128    
129        if ((m_firstFree + 1) >= m_mapSize)
130        {
131          m_mapSize += m_blocksize;
132    
133          int newMap[] = new int[m_mapSize];
134    
135          System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1);
136    
137          m_map = newMap;
138        }
139    
140        m_map[m_firstFree] = value;
141    
142        m_firstFree++;
143      }
144      
145      /**
146       * Append several int values onto the vector.
147       *
148       * @param value Int to add to the list 
149       */
150      public final void addElements(int value, int numberOfElements)
151      {
152    
153        if ((m_firstFree + numberOfElements) >= m_mapSize)
154        {
155          m_mapSize += (m_blocksize+numberOfElements);
156    
157          int newMap[] = new int[m_mapSize];
158    
159          System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1);
160    
161          m_map = newMap;
162        }
163    
164        for (int i = 0; i < numberOfElements; i++) 
165        {
166          m_map[m_firstFree] = value;
167          m_firstFree++;
168        }
169      }
170      
171      /**
172       * Append several slots onto the vector, but do not set the values.
173       *
174       * @param numberOfElements Int to add to the list 
175       */
176      public final void addElements(int numberOfElements)
177      {
178    
179        if ((m_firstFree + numberOfElements) >= m_mapSize)
180        {
181          m_mapSize += (m_blocksize+numberOfElements);
182    
183          int newMap[] = new int[m_mapSize];
184    
185          System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1);
186    
187          m_map = newMap;
188        }
189        
190        m_firstFree += numberOfElements;
191      }
192      
193    
194      /**
195       * Inserts the specified node in this vector at the specified index.
196       * Each component in this vector with an index greater or equal to
197       * the specified index is shifted upward to have an index one greater
198       * than the value it had previously.
199       *
200       * @param value Int to insert
201       * @param at Index of where to insert 
202       */
203      public final void insertElementAt(int value, int at)
204      {
205    
206        if ((m_firstFree + 1) >= m_mapSize)
207        {
208          m_mapSize += m_blocksize;
209    
210          int newMap[] = new int[m_mapSize];
211    
212          System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1);
213    
214          m_map = newMap;
215        }
216    
217        if (at <= (m_firstFree - 1))
218        {
219          System.arraycopy(m_map, at, m_map, at + 1, m_firstFree - at);
220        }
221    
222        m_map[at] = value;
223    
224        m_firstFree++;
225      }
226    
227      /**
228       * Inserts the specified node in this vector at the specified index.
229       * Each component in this vector with an index greater or equal to
230       * the specified index is shifted upward to have an index one greater
231       * than the value it had previously.
232       */
233      public final void removeAllElements()
234      {
235    
236        for (int i = 0; i < m_firstFree; i++)
237        {
238          m_map[i] = java.lang.Integer.MIN_VALUE;
239        }
240    
241        m_firstFree = 0;
242      }
243    
244      /**
245       * Removes the first occurrence of the argument from this vector.
246       * If the object is found in this vector, each component in the vector
247       * with an index greater or equal to the object's index is shifted
248       * downward to have an index one smaller than the value it had
249       * previously.
250       *
251       * @param s Int to remove from array
252       *
253       * @return True if the int was removed, false if it was not found
254       */
255      public final boolean removeElement(int s)
256      {
257    
258        for (int i = 0; i < m_firstFree; i++)
259        {
260          if (m_map[i] == s)
261          {
262            if ((i + 1) < m_firstFree)
263              System.arraycopy(m_map, i + 1, m_map, i - 1, m_firstFree - i);
264            else
265              m_map[i] = java.lang.Integer.MIN_VALUE;
266    
267            m_firstFree--;
268    
269            return true;
270          }
271        }
272    
273        return false;
274      }
275    
276      /**
277       * Deletes the component at the specified index. Each component in
278       * this vector with an index greater or equal to the specified
279       * index is shifted downward to have an index one smaller than
280       * the value it had previously.
281       *
282       * @param i index of where to remove and int
283       */
284      public final void removeElementAt(int i)
285      {
286    
287        if (i > m_firstFree)
288          System.arraycopy(m_map, i + 1, m_map, i, m_firstFree);
289        else
290          m_map[i] = java.lang.Integer.MIN_VALUE;
291    
292        m_firstFree--;
293      }
294    
295      /**
296       * Sets the component at the specified index of this vector to be the
297       * specified object. The previous component at that position is discarded.
298       *
299       * The index must be a value greater than or equal to 0 and less
300       * than the current size of the vector.
301       *
302       * @param value object to set
303       * @param index Index of where to set the object
304       */
305      public final void setElementAt(int value, int index)
306      {
307        m_map[index] = value;
308      }
309    
310      /**
311       * Get the nth element.
312       *
313       * @param i index of object to get
314       *
315       * @return object at given index
316       */
317      public final int elementAt(int i)
318      {
319        return m_map[i];
320      }
321    
322      /**
323       * Tell if the table contains the given node.
324       *
325       * @param s object to look for
326       *
327       * @return true if the object is in the list
328       */
329      public final boolean contains(int s)
330      {
331    
332        for (int i = 0; i < m_firstFree; i++)
333        {
334          if (m_map[i] == s)
335            return true;
336        }
337    
338        return false;
339      }
340    
341      /**
342       * Searches for the first occurence of the given argument,
343       * beginning the search at index, and testing for equality
344       * using the equals method.
345       *
346       * @param elem object to look for
347       * @param index Index of where to begin search
348       * @return the index of the first occurrence of the object
349       * argument in this vector at position index or later in the
350       * vector; returns -1 if the object is not found.
351       */
352      public final int indexOf(int elem, int index)
353      {
354    
355        for (int i = index; i < m_firstFree; i++)
356        {
357          if (m_map[i] == elem)
358            return i;
359        }
360    
361        return java.lang.Integer.MIN_VALUE;
362      }
363    
364      /**
365       * Searches for the first occurence of the given argument,
366       * beginning the search at index, and testing for equality
367       * using the equals method.
368       *
369       * @param elem object to look for
370       * @return the index of the first occurrence of the object
371       * argument in this vector at position index or later in the
372       * vector; returns -1 if the object is not found.
373       */
374      public final int indexOf(int elem)
375      {
376    
377        for (int i = 0; i < m_firstFree; i++)
378        {
379          if (m_map[i] == elem)
380            return i;
381        }
382    
383        return java.lang.Integer.MIN_VALUE;
384      }
385    
386      /**
387       * Searches for the first occurence of the given argument,
388       * beginning the search at index, and testing for equality
389       * using the equals method.
390       *
391       * @param elem Object to look for
392       * @return the index of the first occurrence of the object
393       * argument in this vector at position index or later in the
394       * vector; returns -1 if the object is not found.
395       */
396      public final int lastIndexOf(int elem)
397      {
398    
399        for (int i = (m_firstFree - 1); i >= 0; i--)
400        {
401          if (m_map[i] == elem)
402            return i;
403        }
404    
405        return java.lang.Integer.MIN_VALUE;
406      }
407      
408      /**
409       * Returns clone of current IntVector
410       * 
411       * @return clone of current IntVector
412       */
413      public Object clone()
414        throws CloneNotSupportedException
415      {
416            return new IntVector(this);
417      }
418      
419    }