1 /*
2  * reserved comment block
3  * DO NOT REMOVE OR ALTER!
4  */
5 /*
6  * Licensed to the Apache Software Foundation (ASF) under one or more
7  * contributor license agreements.  See the NOTICE file distributed with
8  * this work for additional information regarding copyright ownership.
9  * The ASF licenses this file to You under the Apache License, Version 2.0
10  * (the "License"); you may not use this file except in compliance with
11  * the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 package com.sun.org.apache.xml.internal.utils;
23 
24 import java.io.Serializable;
25 
26 import com.sun.org.apache.xml.internal.dtm.DTM;
27 
28 /**
29  * A very simple table that stores a list of Nodes.
30  * @xsl.usage internal
31  */
32 public class NodeVector implements Serializable, Cloneable
33 {
34     static final long serialVersionUID = -713473092200731870L;
35 
36   /**
37    * Size of blocks to allocate.
38    *  @serial
39    */
40   private int m_blocksize;
41 
42   /**
43    * Array of nodes this points to.
44    *  @serial
45    */
46   private int m_map[];
47 
48   /**
49    * Number of nodes in this NodeVector.
50    *  @serial
51    */
52   protected int m_firstFree = 0;
53 
54   /**
55    * Size of the array this points to.
56    *  @serial
57    */
58   private int m_mapSize;  // lazy initialization
59 
60   /**
61    * Default constructor.
62    */
NodeVector()63   public NodeVector()
64   {
65     m_blocksize = 32;
66     m_mapSize = 0;
67   }
68 
69   /**
70    * Construct a NodeVector, using the given block size.
71    *
72    * @param blocksize Size of blocks to allocate
73    */
NodeVector(int blocksize)74   public NodeVector(int blocksize)
75   {
76     m_blocksize = blocksize;
77     m_mapSize = 0;
78   }
79 
80   /**
81    * Get a cloned LocPathIterator.
82    *
83    * @return A clone of this
84    *
85    * @throws CloneNotSupportedException
86    */
clone()87   public Object clone() throws CloneNotSupportedException
88   {
89 
90     NodeVector clone = (NodeVector) super.clone();
91 
92     if ((null != this.m_map) && (this.m_map == clone.m_map))
93     {
94       clone.m_map = new int[this.m_map.length];
95 
96       System.arraycopy(this.m_map, 0, clone.m_map, 0, this.m_map.length);
97     }
98 
99     return clone;
100   }
101 
102   /**
103    * Get the length of the list.
104    *
105    * @return Number of nodes in this NodeVector
106    */
size()107   public int size()
108   {
109     return m_firstFree;
110   }
111 
112   /**
113    * Append a Node onto the vector.
114    *
115    * @param value Node to add to the vector
116    */
addElement(int value)117   public void addElement(int value)
118   {
119 
120     if ((m_firstFree + 1) >= m_mapSize)
121     {
122       if (null == m_map)
123       {
124         m_map = new int[m_blocksize];
125         m_mapSize = m_blocksize;
126       }
127       else
128       {
129         m_mapSize += m_blocksize;
130 
131         int newMap[] = new int[m_mapSize];
132 
133         System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1);
134 
135         m_map = newMap;
136       }
137     }
138 
139     m_map[m_firstFree] = value;
140 
141     m_firstFree++;
142   }
143 
144   /**
145    * Append a Node onto the vector.
146    *
147    * @param value Node to add to the vector
148    */
push(int value)149   public final void push(int value)
150   {
151 
152     int ff = m_firstFree;
153 
154     if ((ff + 1) >= m_mapSize)
155     {
156       if (null == m_map)
157       {
158         m_map = new int[m_blocksize];
159         m_mapSize = m_blocksize;
160       }
161       else
162       {
163         m_mapSize += m_blocksize;
164 
165         int newMap[] = new int[m_mapSize];
166 
167         System.arraycopy(m_map, 0, newMap, 0, ff + 1);
168 
169         m_map = newMap;
170       }
171     }
172 
173     m_map[ff] = value;
174 
175     ff++;
176 
177     m_firstFree = ff;
178   }
179 
180   /**
181    * Pop a node from the tail of the vector and return the result.
182    *
183    * @return the node at the tail of the vector
184    */
pop()185   public final int pop()
186   {
187 
188     m_firstFree--;
189 
190     int n = m_map[m_firstFree];
191 
192     m_map[m_firstFree] = DTM.NULL;
193 
194     return n;
195   }
196 
197   /**
198    * Pop a node from the tail of the vector and return the
199    * top of the stack after the pop.
200    *
201    * @return The top of the stack after it's been popped
202    */
popAndTop()203   public final int popAndTop()
204   {
205 
206     m_firstFree--;
207 
208     m_map[m_firstFree] = DTM.NULL;
209 
210     return (m_firstFree == 0) ? DTM.NULL : m_map[m_firstFree - 1];
211   }
212 
213   /**
214    * Pop a node from the tail of the vector.
215    */
popQuick()216   public final void popQuick()
217   {
218 
219     m_firstFree--;
220 
221     m_map[m_firstFree] = DTM.NULL;
222   }
223 
224   /**
225    * Return the node at the top of the stack without popping the stack.
226    * Special purpose method for TransformerImpl, pushElemTemplateElement.
227    * Performance critical.
228    *
229    * @return Node at the top of the stack or null if stack is empty.
230    */
peepOrNull()231   public final int peepOrNull()
232   {
233     return ((null != m_map) && (m_firstFree > 0))
234            ? m_map[m_firstFree - 1] : DTM.NULL;
235   }
236 
237   /**
238    * Push a pair of nodes into the stack.
239    * Special purpose method for TransformerImpl, pushElemTemplateElement.
240    * Performance critical.
241    *
242    * @param v1 First node to add to vector
243    * @param v2 Second node to add to vector
244    */
pushPair(int v1, int v2)245   public final void pushPair(int v1, int v2)
246   {
247 
248     if (null == m_map)
249     {
250       m_map = new int[m_blocksize];
251       m_mapSize = m_blocksize;
252     }
253     else
254     {
255       if ((m_firstFree + 2) >= m_mapSize)
256       {
257         m_mapSize += m_blocksize;
258 
259         int newMap[] = new int[m_mapSize];
260 
261         System.arraycopy(m_map, 0, newMap, 0, m_firstFree);
262 
263         m_map = newMap;
264       }
265     }
266 
267     m_map[m_firstFree] = v1;
268     m_map[m_firstFree + 1] = v2;
269     m_firstFree += 2;
270   }
271 
272   /**
273    * Pop a pair of nodes from the tail of the stack.
274    * Special purpose method for TransformerImpl, pushElemTemplateElement.
275    * Performance critical.
276    */
popPair()277   public final void popPair()
278   {
279 
280     m_firstFree -= 2;
281     m_map[m_firstFree] = DTM.NULL;
282     m_map[m_firstFree + 1] = DTM.NULL;
283   }
284 
285   /**
286    * Set the tail of the stack to the given node.
287    * Special purpose method for TransformerImpl, pushElemTemplateElement.
288    * Performance critical.
289    *
290    * @param n Node to set at the tail of vector
291    */
setTail(int n)292   public final void setTail(int n)
293   {
294     m_map[m_firstFree - 1] = n;
295   }
296 
297   /**
298    * Set the given node one position from the tail.
299    * Special purpose method for TransformerImpl, pushElemTemplateElement.
300    * Performance critical.
301    *
302    * @param n Node to set
303    */
setTailSub1(int n)304   public final void setTailSub1(int n)
305   {
306     m_map[m_firstFree - 2] = n;
307   }
308 
309   /**
310    * Return the node at the tail of the vector without popping
311    * Special purpose method for TransformerImpl, pushElemTemplateElement.
312    * Performance critical.
313    *
314    * @return Node at the tail of the vector
315    */
peepTail()316   public final int peepTail()
317   {
318     return m_map[m_firstFree - 1];
319   }
320 
321   /**
322    * Return the node one position from the tail without popping.
323    * Special purpose method for TransformerImpl, pushElemTemplateElement.
324    * Performance critical.
325    *
326    * @return Node one away from the tail
327    */
peepTailSub1()328   public final int peepTailSub1()
329   {
330     return m_map[m_firstFree - 2];
331   }
332 
333   /**
334    * Insert a node in order in the list.
335    *
336    * @param value Node to insert
337    */
insertInOrder(int value)338   public void insertInOrder(int value)
339   {
340 
341     for (int i = 0; i < m_firstFree; i++)
342     {
343       if (value < m_map[i])
344       {
345         insertElementAt(value, i);
346 
347         return;
348       }
349     }
350 
351     addElement(value);
352   }
353 
354   /**
355    * Inserts the specified node in this vector at the specified index.
356    * Each component in this vector with an index greater or equal to
357    * the specified index is shifted upward to have an index one greater
358    * than the value it had previously.
359    *
360    * @param value Node to insert
361    * @param at Position where to insert
362    */
insertElementAt(int value, int at)363   public void insertElementAt(int value, int at)
364   {
365 
366     if (null == m_map)
367     {
368       m_map = new int[m_blocksize];
369       m_mapSize = m_blocksize;
370     }
371     else if ((m_firstFree + 1) >= m_mapSize)
372     {
373       m_mapSize += m_blocksize;
374 
375       int newMap[] = new int[m_mapSize];
376 
377       System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1);
378 
379       m_map = newMap;
380     }
381 
382     if (at <= (m_firstFree - 1))
383     {
384       System.arraycopy(m_map, at, m_map, at + 1, m_firstFree - at);
385     }
386 
387     m_map[at] = value;
388 
389     m_firstFree++;
390   }
391 
392   /**
393    * Append the nodes to the list.
394    *
395    * @param nodes NodeVector to append to this list
396    */
appendNodes(NodeVector nodes)397   public void appendNodes(NodeVector nodes)
398   {
399 
400     int nNodes = nodes.size();
401 
402     if (null == m_map)
403     {
404       m_mapSize = nNodes + m_blocksize;
405       m_map = new int[m_mapSize];
406     }
407     else if ((m_firstFree + nNodes) >= m_mapSize)
408     {
409       m_mapSize += (nNodes + m_blocksize);
410 
411       int newMap[] = new int[m_mapSize];
412 
413       System.arraycopy(m_map, 0, newMap, 0, m_firstFree + nNodes);
414 
415       m_map = newMap;
416     }
417 
418     System.arraycopy(nodes.m_map, 0, m_map, m_firstFree, nNodes);
419 
420     m_firstFree += nNodes;
421   }
422 
423   /**
424    * Inserts the specified node in this vector at the specified index.
425    * Each component in this vector with an index greater or equal to
426    * the specified index is shifted upward to have an index one greater
427    * than the value it had previously.
428    */
removeAllElements()429   public void removeAllElements()
430   {
431 
432     if (null == m_map)
433       return;
434 
435     for (int i = 0; i < m_firstFree; i++)
436     {
437       m_map[i] = DTM.NULL;
438     }
439 
440     m_firstFree = 0;
441   }
442 
443   /**
444    * Set the length to zero, but don't clear the array.
445    */
RemoveAllNoClear()446   public void RemoveAllNoClear()
447   {
448 
449     if (null == m_map)
450       return;
451 
452     m_firstFree = 0;
453   }
454 
455   /**
456    * Removes the first occurrence of the argument from this vector.
457    * If the object is found in this vector, each component in the vector
458    * with an index greater or equal to the object's index is shifted
459    * downward to have an index one smaller than the value it had
460    * previously.
461    *
462    * @param s Node to remove from the list
463    *
464    * @return True if the node was successfully removed
465    */
removeElement(int s)466   public boolean removeElement(int s)
467   {
468 
469     if (null == m_map)
470       return false;
471 
472     for (int i = 0; i < m_firstFree; i++)
473     {
474       int node = m_map[i];
475 
476       if (node == s)
477       {
478         if (i > m_firstFree)
479           System.arraycopy(m_map, i + 1, m_map, i - 1, m_firstFree - i);
480         else
481           m_map[i] = DTM.NULL;
482 
483         m_firstFree--;
484 
485         return true;
486       }
487     }
488 
489     return false;
490   }
491 
492   /**
493    * Deletes the component at the specified index. Each component in
494    * this vector with an index greater or equal to the specified
495    * index is shifted downward to have an index one smaller than
496    * the value it had previously.
497    *
498    * @param i Index of node to remove
499    */
removeElementAt(int i)500   public void removeElementAt(int i)
501   {
502 
503     if (null == m_map)
504       return;
505 
506     if (i > m_firstFree)
507       System.arraycopy(m_map, i + 1, m_map, i - 1, m_firstFree - i);
508     else
509       m_map[i] = DTM.NULL;
510   }
511 
512   /**
513    * Sets the component at the specified index of this vector to be the
514    * specified object. The previous component at that position is discarded.
515    *
516    * The index must be a value greater than or equal to 0 and less
517    * than the current size of the vector.
518    *
519    * @param node Node to set
520    * @param index Index of where to set the node
521    */
setElementAt(int node, int index)522   public void setElementAt(int node, int index)
523   {
524 
525     if (null == m_map)
526     {
527       m_map = new int[m_blocksize];
528       m_mapSize = m_blocksize;
529     }
530 
531     if(index == -1)
532         addElement(node);
533 
534     m_map[index] = node;
535   }
536 
537   /**
538    * Get the nth element.
539    *
540    * @param i Index of node to get
541    *
542    * @return Node at specified index
543    */
elementAt(int i)544   public int elementAt(int i)
545   {
546 
547     if (null == m_map)
548       return DTM.NULL;
549 
550     return m_map[i];
551   }
552 
553   /**
554    * Tell if the table contains the given node.
555    *
556    * @param s Node to look for
557    *
558    * @return True if the given node was found.
559    */
contains(int s)560   public boolean contains(int s)
561   {
562 
563     if (null == m_map)
564       return false;
565 
566     for (int i = 0; i < m_firstFree; i++)
567     {
568       int node = m_map[i];
569 
570       if (node == s)
571         return true;
572     }
573 
574     return false;
575   }
576 
577   /**
578    * Searches for the first occurence of the given argument,
579    * beginning the search at index, and testing for equality
580    * using the equals method.
581    *
582    * @param elem Node to look for
583    * @param index Index of where to start the search
584    * @return the index of the first occurrence of the object
585    * argument in this vector at position index or later in the
586    * vector; returns -1 if the object is not found.
587    */
indexOf(int elem, int index)588   public int indexOf(int elem, int index)
589   {
590 
591     if (null == m_map)
592       return -1;
593 
594     for (int i = index; i < m_firstFree; i++)
595     {
596       int node = m_map[i];
597 
598       if (node == elem)
599         return i;
600     }
601 
602     return -1;
603   }
604 
605   /**
606    * Searches for the first occurence of the given argument,
607    * beginning the search at index, and testing for equality
608    * using the equals method.
609    *
610    * @param elem Node to look for
611    * @return the index of the first occurrence of the object
612    * argument in this vector at position index or later in the
613    * vector; returns -1 if the object is not found.
614    */
indexOf(int elem)615   public int indexOf(int elem)
616   {
617 
618     if (null == m_map)
619       return -1;
620 
621     for (int i = 0; i < m_firstFree; i++)
622     {
623       int node = m_map[i];
624 
625       if (node == elem)
626         return i;
627     }
628 
629     return -1;
630   }
631 
632   /**
633    * Sort an array using a quicksort algorithm.
634    *
635    * @param a The array to be sorted.
636    * @param lo0  The low index.
637    * @param hi0  The high index.
638    *
639    * @throws Exception
640    */
sort(int a[], int lo0, int hi0)641   public void sort(int a[], int lo0, int hi0) throws Exception
642   {
643 
644     int lo = lo0;
645     int hi = hi0;
646 
647     // pause(lo, hi);
648     if (lo >= hi)
649     {
650       return;
651     }
652     else if (lo == hi - 1)
653     {
654 
655       /*
656        *  sort a two element list by swapping if necessary
657        */
658       if (a[lo] > a[hi])
659       {
660         int T = a[lo];
661 
662         a[lo] = a[hi];
663         a[hi] = T;
664       }
665 
666       return;
667     }
668 
669     /*
670      *  Pick a pivot and move it out of the way
671      */
672     int mid = (lo + hi) >>> 1;
673     int pivot = a[mid];
674 
675     a[mid] = a[hi];
676     a[hi] = pivot;
677 
678     while (lo < hi)
679     {
680 
681       /*
682        *  Search forward from a[lo] until an element is found that
683        *  is greater than the pivot or lo >= hi
684        */
685       while (a[lo] <= pivot && lo < hi)
686       {
687         lo++;
688       }
689 
690       /*
691        *  Search backward from a[hi] until element is found that
692        *  is less than the pivot, or lo >= hi
693        */
694       while (pivot <= a[hi] && lo < hi)
695       {
696         hi--;
697       }
698 
699       /*
700        *  Swap elements a[lo] and a[hi]
701        */
702       if (lo < hi)
703       {
704         int T = a[lo];
705 
706         a[lo] = a[hi];
707         a[hi] = T;
708 
709         // pause();
710       }
711 
712       // if (stopRequested) {
713       //    return;
714       // }
715     }
716 
717     /*
718      *  Put the median in the "center" of the list
719      */
720     a[hi0] = a[hi];
721     a[hi] = pivot;
722 
723     /*
724      *  Recursive calls, elements a[lo0] to a[lo-1] are less than or
725      *  equal to pivot, elements a[hi+1] to a[hi0] are greater than
726      *  pivot.
727      */
728     sort(a, lo0, lo - 1);
729     sort(a, hi + 1, hi0);
730   }
731 
732   /**
733    * Sort an array using a quicksort algorithm.
734    *
735    * @throws Exception
736    */
sort()737   public void sort() throws Exception
738   {
739     sort(m_map, 0, m_firstFree - 1);
740   }
741 }
742