1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xalan" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, Lotus
  53. * Development Corporation., http://www.lotus.com. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package org.apache.xml.utils;
  58. import java.io.Serializable;
  59. import org.apache.xml.dtm.DTM;
  60. /**
  61. * <meta name="usage" content="internal"/>
  62. * A very simple table that stores a list of Nodes.
  63. */
  64. public class NodeVector implements Serializable, Cloneable
  65. {
  66. /**
  67. * Size of blocks to allocate.
  68. * @serial
  69. */
  70. private int m_blocksize;
  71. /**
  72. * Array of nodes this points to.
  73. * @serial
  74. */
  75. private int m_map[];
  76. /**
  77. * Number of nodes in this NodeVector.
  78. * @serial
  79. */
  80. protected int m_firstFree = 0;
  81. /**
  82. * Size of the array this points to.
  83. * @serial
  84. */
  85. private int m_mapSize; // lazy initialization
  86. /**
  87. * Default constructor.
  88. */
  89. public NodeVector()
  90. {
  91. m_blocksize = 32;
  92. m_mapSize = 0;
  93. }
  94. /**
  95. * Construct a NodeVector, using the given block size.
  96. *
  97. * @param blocksize Size of blocks to allocate
  98. */
  99. public NodeVector(int blocksize)
  100. {
  101. m_blocksize = blocksize;
  102. m_mapSize = 0;
  103. }
  104. /**
  105. * Get a cloned LocPathIterator.
  106. *
  107. * @return A clone of this
  108. *
  109. * @throws CloneNotSupportedException
  110. */
  111. public Object clone() throws CloneNotSupportedException
  112. {
  113. NodeVector clone = (NodeVector) super.clone();
  114. if ((null != this.m_map) && (this.m_map == clone.m_map))
  115. {
  116. clone.m_map = new int[this.m_map.length];
  117. System.arraycopy(this.m_map, 0, clone.m_map, 0, this.m_map.length);
  118. }
  119. return clone;
  120. }
  121. /**
  122. * Get the length of the list.
  123. *
  124. * @return Number of nodes in this NodeVector
  125. */
  126. public int size()
  127. {
  128. return m_firstFree;
  129. }
  130. /**
  131. * Append a Node onto the vector.
  132. *
  133. * @param value Node to add to the vector
  134. */
  135. public void addElement(int value)
  136. {
  137. if ((m_firstFree + 1) >= m_mapSize)
  138. {
  139. if (null == m_map)
  140. {
  141. m_map = new int[m_blocksize];
  142. m_mapSize = m_blocksize;
  143. }
  144. else
  145. {
  146. m_mapSize += m_blocksize;
  147. int newMap[] = new int[m_mapSize];
  148. System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1);
  149. m_map = newMap;
  150. }
  151. }
  152. m_map[m_firstFree] = value;
  153. m_firstFree++;
  154. }
  155. /**
  156. * Append a Node onto the vector.
  157. *
  158. * @param value Node to add to the vector
  159. */
  160. public final void push(int value)
  161. {
  162. int ff = m_firstFree;
  163. if ((ff + 1) >= m_mapSize)
  164. {
  165. if (null == m_map)
  166. {
  167. m_map = new int[m_blocksize];
  168. m_mapSize = m_blocksize;
  169. }
  170. else
  171. {
  172. m_mapSize += m_blocksize;
  173. int newMap[] = new int[m_mapSize];
  174. System.arraycopy(m_map, 0, newMap, 0, ff + 1);
  175. m_map = newMap;
  176. }
  177. }
  178. m_map[ff] = value;
  179. ff++;
  180. m_firstFree = ff;
  181. }
  182. /**
  183. * Pop a node from the tail of the vector and return the result.
  184. *
  185. * @return the node at the tail of the vector
  186. */
  187. public final int pop()
  188. {
  189. m_firstFree--;
  190. int n = m_map[m_firstFree];
  191. m_map[m_firstFree] = DTM.NULL;
  192. return n;
  193. }
  194. /**
  195. * Pop a node from the tail of the vector and return the
  196. * top of the stack after the pop.
  197. *
  198. * @return The top of the stack after it's been popped
  199. */
  200. public final int popAndTop()
  201. {
  202. m_firstFree--;
  203. m_map[m_firstFree] = DTM.NULL;
  204. return (m_firstFree == 0) ? DTM.NULL : m_map[m_firstFree - 1];
  205. }
  206. /**
  207. * Pop a node from the tail of the vector.
  208. */
  209. public final void popQuick()
  210. {
  211. m_firstFree--;
  212. m_map[m_firstFree] = DTM.NULL;
  213. }
  214. /**
  215. * Return the node at the top of the stack without popping the stack.
  216. * Special purpose method for TransformerImpl, pushElemTemplateElement.
  217. * Performance critical.
  218. *
  219. * @return Node at the top of the stack or null if stack is empty.
  220. */
  221. public final int peepOrNull()
  222. {
  223. return ((null != m_map) && (m_firstFree > 0))
  224. ? m_map[m_firstFree - 1] : DTM.NULL;
  225. }
  226. /**
  227. * Push a pair of nodes into the stack.
  228. * Special purpose method for TransformerImpl, pushElemTemplateElement.
  229. * Performance critical.
  230. *
  231. * @param v1 First node to add to vector
  232. * @param v2 Second node to add to vector
  233. */
  234. public final void pushPair(int v1, int v2)
  235. {
  236. if (null == m_map)
  237. {
  238. m_map = new int[m_blocksize];
  239. m_mapSize = m_blocksize;
  240. }
  241. else
  242. {
  243. if ((m_firstFree + 2) >= m_mapSize)
  244. {
  245. m_mapSize += m_blocksize;
  246. int newMap[] = new int[m_mapSize];
  247. System.arraycopy(m_map, 0, newMap, 0, m_firstFree);
  248. m_map = newMap;
  249. }
  250. }
  251. m_map[m_firstFree] = v1;
  252. m_map[m_firstFree + 1] = v2;
  253. m_firstFree += 2;
  254. }
  255. /**
  256. * Pop a pair of nodes from the tail of the stack.
  257. * Special purpose method for TransformerImpl, pushElemTemplateElement.
  258. * Performance critical.
  259. */
  260. public final void popPair()
  261. {
  262. m_firstFree -= 2;
  263. m_map[m_firstFree] = DTM.NULL;
  264. m_map[m_firstFree + 1] = DTM.NULL;
  265. }
  266. /**
  267. * Set the tail of the stack to the given node.
  268. * Special purpose method for TransformerImpl, pushElemTemplateElement.
  269. * Performance critical.
  270. *
  271. * @param n Node to set at the tail of vector
  272. */
  273. public final void setTail(int n)
  274. {
  275. m_map[m_firstFree - 1] = n;
  276. }
  277. /**
  278. * Set the given node one position from the tail.
  279. * Special purpose method for TransformerImpl, pushElemTemplateElement.
  280. * Performance critical.
  281. *
  282. * @param n Node to set
  283. */
  284. public final void setTailSub1(int n)
  285. {
  286. m_map[m_firstFree - 2] = n;
  287. }
  288. /**
  289. * Return the node at the tail of the vector without popping
  290. * Special purpose method for TransformerImpl, pushElemTemplateElement.
  291. * Performance critical.
  292. *
  293. * @return Node at the tail of the vector
  294. */
  295. public final int peepTail()
  296. {
  297. return m_map[m_firstFree - 1];
  298. }
  299. /**
  300. * Return the node one position from the tail without popping.
  301. * Special purpose method for TransformerImpl, pushElemTemplateElement.
  302. * Performance critical.
  303. *
  304. * @return Node one away from the tail
  305. */
  306. public final int peepTailSub1()
  307. {
  308. return m_map[m_firstFree - 2];
  309. }
  310. /**
  311. * Insert a node in order in the list.
  312. *
  313. * @param value Node to insert
  314. */
  315. public void insertInOrder(int value)
  316. {
  317. for (int i = 0; i < m_firstFree; i++)
  318. {
  319. if (value < m_map[i])
  320. {
  321. insertElementAt(value, i);
  322. return;
  323. }
  324. }
  325. addElement(value);
  326. }
  327. /**
  328. * Inserts the specified node in this vector at the specified index.
  329. * Each component in this vector with an index greater or equal to
  330. * the specified index is shifted upward to have an index one greater
  331. * than the value it had previously.
  332. *
  333. * @param value Node to insert
  334. * @param at Position where to insert
  335. */
  336. public void insertElementAt(int value, int at)
  337. {
  338. if (null == m_map)
  339. {
  340. m_map = new int[m_blocksize];
  341. m_mapSize = m_blocksize;
  342. }
  343. else if ((m_firstFree + 1) >= m_mapSize)
  344. {
  345. m_mapSize += m_blocksize;
  346. int newMap[] = new int[m_mapSize];
  347. System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1);
  348. m_map = newMap;
  349. }
  350. if (at <= (m_firstFree - 1))
  351. {
  352. System.arraycopy(m_map, at, m_map, at + 1, m_firstFree - at);
  353. }
  354. m_map[at] = value;
  355. m_firstFree++;
  356. }
  357. /**
  358. * Append the nodes to the list.
  359. *
  360. * @param nodes NodeVector to append to this list
  361. */
  362. public void appendNodes(NodeVector nodes)
  363. {
  364. int nNodes = nodes.size();
  365. if (null == m_map)
  366. {
  367. m_mapSize = nNodes + m_blocksize;
  368. m_map = new int[m_mapSize];
  369. }
  370. else if ((m_firstFree + nNodes) >= m_mapSize)
  371. {
  372. m_mapSize += (nNodes + m_blocksize);
  373. int newMap[] = new int[m_mapSize];
  374. System.arraycopy(m_map, 0, newMap, 0, m_firstFree + nNodes);
  375. m_map = newMap;
  376. }
  377. System.arraycopy(nodes.m_map, 0, m_map, m_firstFree, nNodes);
  378. m_firstFree += nNodes;
  379. }
  380. /**
  381. * Inserts the specified node in this vector at the specified index.
  382. * Each component in this vector with an index greater or equal to
  383. * the specified index is shifted upward to have an index one greater
  384. * than the value it had previously.
  385. */
  386. public void removeAllElements()
  387. {
  388. if (null == m_map)
  389. return;
  390. for (int i = 0; i < m_firstFree; i++)
  391. {
  392. m_map[i] = DTM.NULL;
  393. }
  394. m_firstFree = 0;
  395. }
  396. /**
  397. * Set the length to zero, but don't clear the array.
  398. */
  399. public void RemoveAllNoClear()
  400. {
  401. if (null == m_map)
  402. return;
  403. m_firstFree = 0;
  404. }
  405. /**
  406. * Removes the first occurrence of the argument from this vector.
  407. * If the object is found in this vector, each component in the vector
  408. * with an index greater or equal to the object's index is shifted
  409. * downward to have an index one smaller than the value it had
  410. * previously.
  411. *
  412. * @param s Node to remove from the list
  413. *
  414. * @return True if the node was successfully removed
  415. */
  416. public boolean removeElement(int s)
  417. {
  418. if (null == m_map)
  419. return false;
  420. for (int i = 0; i < m_firstFree; i++)
  421. {
  422. int node = m_map[i];
  423. if (node == s)
  424. {
  425. if (i > m_firstFree)
  426. System.arraycopy(m_map, i + 1, m_map, i - 1, m_firstFree - i);
  427. else
  428. m_map[i] = DTM.NULL;
  429. m_firstFree--;
  430. return true;
  431. }
  432. }
  433. return false;
  434. }
  435. /**
  436. * Deletes the component at the specified index. Each component in
  437. * this vector with an index greater or equal to the specified
  438. * index is shifted downward to have an index one smaller than
  439. * the value it had previously.
  440. *
  441. * @param i Index of node to remove
  442. */
  443. public void removeElementAt(int i)
  444. {
  445. if (null == m_map)
  446. return;
  447. if (i > m_firstFree)
  448. System.arraycopy(m_map, i + 1, m_map, i - 1, m_firstFree - i);
  449. else
  450. m_map[i] = DTM.NULL;
  451. }
  452. /**
  453. * Sets the component at the specified index of this vector to be the
  454. * specified object. The previous component at that position is discarded.
  455. *
  456. * The index must be a value greater than or equal to 0 and less
  457. * than the current size of the vector.
  458. *
  459. * @param node Node to set
  460. * @param index Index of where to set the node
  461. */
  462. public void setElementAt(int node, int index)
  463. {
  464. if (null == m_map)
  465. {
  466. m_map = new int[m_blocksize];
  467. m_mapSize = m_blocksize;
  468. }
  469. if(index == -1)
  470. addElement(node);
  471. m_map[index] = node;
  472. }
  473. /**
  474. * Get the nth element.
  475. *
  476. * @param i Index of node to get
  477. *
  478. * @return Node at specified index
  479. */
  480. public int elementAt(int i)
  481. {
  482. if (null == m_map)
  483. return DTM.NULL;
  484. return m_map[i];
  485. }
  486. /**
  487. * Tell if the table contains the given node.
  488. *
  489. * @param s Node to look for
  490. *
  491. * @return True if the given node was found.
  492. */
  493. public boolean contains(int s)
  494. {
  495. if (null == m_map)
  496. return false;
  497. for (int i = 0; i < m_firstFree; i++)
  498. {
  499. int node = m_map[i];
  500. if (node == s)
  501. return true;
  502. }
  503. return false;
  504. }
  505. /**
  506. * Searches for the first occurence of the given argument,
  507. * beginning the search at index, and testing for equality
  508. * using the equals method.
  509. *
  510. * @param elem Node to look for
  511. * @param index Index of where to start the search
  512. * @return the index of the first occurrence of the object
  513. * argument in this vector at position index or later in the
  514. * vector; returns -1 if the object is not found.
  515. */
  516. public int indexOf(int elem, int index)
  517. {
  518. if (null == m_map)
  519. return -1;
  520. for (int i = index; i < m_firstFree; i++)
  521. {
  522. int node = m_map[i];
  523. if (node == elem)
  524. return i;
  525. }
  526. return -1;
  527. }
  528. /**
  529. * Searches for the first occurence of the given argument,
  530. * beginning the search at index, and testing for equality
  531. * using the equals method.
  532. *
  533. * @param elem Node to look for
  534. * @return the index of the first occurrence of the object
  535. * argument in this vector at position index or later in the
  536. * vector; returns -1 if the object is not found.
  537. */
  538. public int indexOf(int elem)
  539. {
  540. if (null == m_map)
  541. return -1;
  542. for (int i = 0; i < m_firstFree; i++)
  543. {
  544. int node = m_map[i];
  545. if (node == elem)
  546. return i;
  547. }
  548. return -1;
  549. }
  550. /**
  551. * Sort an array using a quicksort algorithm.
  552. *
  553. * @param a The array to be sorted.
  554. * @param lo0 The low index.
  555. * @param hi0 The high index.
  556. *
  557. * @throws Exception
  558. */
  559. public void sort(int a[], int lo0, int hi0) throws Exception
  560. {
  561. int lo = lo0;
  562. int hi = hi0;
  563. // pause(lo, hi);
  564. if (lo >= hi)
  565. {
  566. return;
  567. }
  568. else if (lo == hi - 1)
  569. {
  570. /*
  571. * sort a two element list by swapping if necessary
  572. */
  573. if (a[lo] > a[hi])
  574. {
  575. int T = a[lo];
  576. a[lo] = a[hi];
  577. a[hi] = T;
  578. }
  579. return;
  580. }
  581. /*
  582. * Pick a pivot and move it out of the way
  583. */
  584. int pivot = a[(lo + hi) / 2];
  585. a[(lo + hi) / 2] = a[hi];
  586. a[hi] = pivot;
  587. while (lo < hi)
  588. {
  589. /*
  590. * Search forward from a[lo] until an element is found that
  591. * is greater than the pivot or lo >= hi
  592. */
  593. while (a[lo] <= pivot && lo < hi)
  594. {
  595. lo++;
  596. }
  597. /*
  598. * Search backward from a[hi] until element is found that
  599. * is less than the pivot, or lo >= hi
  600. */
  601. while (pivot <= a[hi] && lo < hi)
  602. {
  603. hi--;
  604. }
  605. /*
  606. * Swap elements a[lo] and a[hi]
  607. */
  608. if (lo < hi)
  609. {
  610. int T = a[lo];
  611. a[lo] = a[hi];
  612. a[hi] = T;
  613. // pause();
  614. }
  615. // if (stopRequested) {
  616. // return;
  617. // }
  618. }
  619. /*
  620. * Put the median in the "center" of the list
  621. */
  622. a[hi0] = a[hi];
  623. a[hi] = pivot;
  624. /*
  625. * Recursive calls, elements a[lo0] to a[lo-1] are less than or
  626. * equal to pivot, elements a[hi+1] to a[hi0] are greater than
  627. * pivot.
  628. */
  629. sort(a, lo0, lo - 1);
  630. sort(a, hi + 1, hi0);
  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. */
  641. public void sort() throws Exception
  642. {
  643. sort(m_map, 0, m_firstFree - 1);
  644. }
  645. }