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