PageRenderTime 54ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/src/share/classes/com/sun/tools/javac/util/List.java

http://github.com/kmizu/JavaCo
Java | 484 lines | 317 code | 52 blank | 115 comment | 89 complexity | bb59dbda11ad9b01d8129adc36630ee7 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
  3. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4. *
  5. * This code is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 only, as
  7. * published by the Free Software Foundation. Oracle designates this
  8. * particular file as subject to the "Classpath" exception as provided
  9. * by Oracle in the LICENSE file that accompanied this code.
  10. *
  11. * This code is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14. * version 2 for more details (a copy is included in the LICENSE file that
  15. * accompanied this code).
  16. *
  17. * You should have received a copy of the GNU General Public License version
  18. * 2 along with this work; if not, write to the Free Software Foundation,
  19. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20. *
  21. * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22. * or visit www.oracle.com if you need additional information or have any
  23. * questions.
  24. */
  25. package com.sun.tools.javac.util;
  26. import java.lang.reflect.Array;
  27. import java.util.ArrayList;
  28. import java.util.Collection;
  29. import java.util.Collections;
  30. import java.util.Iterator;
  31. import java.util.AbstractCollection;
  32. import java.util.ListIterator;
  33. import java.util.NoSuchElementException;
  34. /** A class for generic linked lists. Links are supposed to be
  35. * immutable, the only exception being the incremental construction of
  36. * lists via ListBuffers. List is the main container class in
  37. * GJC. Most data structures and algorthms in GJC use lists rather
  38. * than arrays.
  39. *
  40. * <p>Lists are always trailed by a sentinel element, whose head and tail
  41. * are both null.
  42. *
  43. * <p><b>This is NOT part of any supported API.
  44. * If you write code that depends on this, you do so at your own risk.
  45. * This code and its internal interfaces are subject to change or
  46. * deletion without notice.</b>
  47. */
  48. public class List<A> extends AbstractCollection<A> implements java.util.List<A> {
  49. /** The first element of the list, supposed to be immutable.
  50. */
  51. public A head;
  52. /** The remainder of the list except for its first element, supposed
  53. * to be immutable.
  54. */
  55. //@Deprecated
  56. public List<A> tail;
  57. /** Construct a list given its head and tail.
  58. */
  59. List(A head, List<A> tail) {
  60. this.tail = tail;
  61. this.head = head;
  62. }
  63. /** Construct an empty list.
  64. */
  65. @SuppressWarnings("unchecked")
  66. public static <A> List<A> nil() {
  67. return EMPTY_LIST;
  68. }
  69. private static List EMPTY_LIST = new List<Object>(null,null) {
  70. public List<Object> setTail(List<Object> tail) {
  71. throw new UnsupportedOperationException();
  72. }
  73. public boolean isEmpty() {
  74. return true;
  75. }
  76. };
  77. /** Construct a list consisting of given element.
  78. */
  79. public static <A> List<A> of(A x1) {
  80. return new List<A>(x1, List.<A>nil());
  81. }
  82. /** Construct a list consisting of given elements.
  83. */
  84. public static <A> List<A> of(A x1, A x2) {
  85. return new List<A>(x1, of(x2));
  86. }
  87. /** Construct a list consisting of given elements.
  88. */
  89. public static <A> List<A> of(A x1, A x2, A x3) {
  90. return new List<A>(x1, of(x2, x3));
  91. }
  92. /** Construct a list consisting of given elements.
  93. */
  94. public static <A> List<A> of(A x1, A x2, A x3, A... rest) {
  95. return new List<A>(x1, new List<A>(x2, new List<A>(x3, from(rest))));
  96. }
  97. /**
  98. * Construct a list consisting all elements of given array.
  99. * @param array an array; if {@code null} return an empty list
  100. */
  101. public static <A> List<A> from(A[] array) {
  102. List<A> xs = nil();
  103. if (array != null)
  104. for (int i = array.length - 1; i >= 0; i--)
  105. xs = new List<A>(array[i], xs);
  106. return xs;
  107. }
  108. /** Construct a list consisting of a given number of identical elements.
  109. * @param len The number of elements in the list.
  110. * @param init The value of each element.
  111. */
  112. @Deprecated
  113. public static <A> List<A> fill(int len, A init) {
  114. List<A> l = nil();
  115. for (int i = 0; i < len; i++) l = new List<A>(init, l);
  116. return l;
  117. }
  118. /** Does list have no elements?
  119. */
  120. @Override
  121. public boolean isEmpty() {
  122. return tail == null;
  123. }
  124. /** Does list have elements?
  125. */
  126. //@Deprecated
  127. public boolean nonEmpty() {
  128. return tail != null;
  129. }
  130. /** Return the number of elements in this list.
  131. */
  132. //@Deprecated
  133. public int length() {
  134. List<A> l = this;
  135. int len = 0;
  136. while (l.tail != null) {
  137. l = l.tail;
  138. len++;
  139. }
  140. return len;
  141. }
  142. @Override
  143. public int size() {
  144. return length();
  145. }
  146. public List<A> setTail(List<A> tail) {
  147. this.tail = tail;
  148. return tail;
  149. }
  150. /** Prepend given element to front of list, forming and returning
  151. * a new list.
  152. */
  153. public List<A> prepend(A x) {
  154. return new List<A>(x, this);
  155. }
  156. /** Prepend given list of elements to front of list, forming and returning
  157. * a new list.
  158. */
  159. public List<A> prependList(List<A> xs) {
  160. if (this.isEmpty()) return xs;
  161. if (xs.isEmpty()) return this;
  162. if (xs.tail.isEmpty()) return prepend(xs.head);
  163. // return this.prependList(xs.tail).prepend(xs.head);
  164. List<A> result = this;
  165. List<A> rev = xs.reverse();
  166. assert rev != xs;
  167. // since xs.reverse() returned a new list, we can reuse the
  168. // individual List objects, instead of allocating new ones.
  169. while (rev.nonEmpty()) {
  170. List<A> h = rev;
  171. rev = rev.tail;
  172. h.setTail(result);
  173. result = h;
  174. }
  175. return result;
  176. }
  177. /** Reverse list.
  178. * If the list is empty or a singleton, then the same list is returned.
  179. * Otherwise a new list is formed.
  180. */
  181. public List<A> reverse() {
  182. // if it is empty or a singleton, return itself
  183. if (isEmpty() || tail.isEmpty())
  184. return this;
  185. List<A> rev = nil();
  186. for (List<A> l = this; l.nonEmpty(); l = l.tail)
  187. rev = new List<A>(l.head, rev);
  188. return rev;
  189. }
  190. /** Append given element at length, forming and returning
  191. * a new list.
  192. */
  193. public List<A> append(A x) {
  194. return of(x).prependList(this);
  195. }
  196. /** Append given list at length, forming and returning
  197. * a new list.
  198. */
  199. public List<A> appendList(List<A> x) {
  200. return x.prependList(this);
  201. }
  202. /**
  203. * Append given list buffer at length, forming and returning a new
  204. * list.
  205. */
  206. public List<A> appendList(ListBuffer<A> x) {
  207. return appendList(x.toList());
  208. }
  209. /** Copy successive elements of this list into given vector until
  210. * list is exhausted or end of vector is reached.
  211. */
  212. @Override @SuppressWarnings("unchecked")
  213. public <T> T[] toArray(T[] vec) {
  214. int i = 0;
  215. List<A> l = this;
  216. Object[] dest = vec;
  217. while (l.nonEmpty() && i < vec.length) {
  218. dest[i] = l.head;
  219. l = l.tail;
  220. i++;
  221. }
  222. if (l.isEmpty()) {
  223. if (i < vec.length)
  224. vec[i] = null;
  225. return vec;
  226. }
  227. vec = (T[])Array.newInstance(vec.getClass().getComponentType(), size());
  228. return toArray(vec);
  229. }
  230. public Object[] toArray() {
  231. return toArray(new Object[size()]);
  232. }
  233. /** Form a string listing all elements with given separator character.
  234. */
  235. public String toString(String sep) {
  236. if (isEmpty()) {
  237. return "";
  238. } else {
  239. StringBuffer buf = new StringBuffer();
  240. buf.append(head);
  241. for (List<A> l = tail; l.nonEmpty(); l = l.tail) {
  242. buf.append(sep);
  243. buf.append(l.head);
  244. }
  245. return buf.toString();
  246. }
  247. }
  248. /** Form a string listing all elements with comma as the separator character.
  249. */
  250. @Override
  251. public String toString() {
  252. return toString(",");
  253. }
  254. /** Compute a hash code, overrides Object
  255. * @see java.util.List#hashCode
  256. */
  257. @Override
  258. public int hashCode() {
  259. List<A> l = this;
  260. int h = 1;
  261. while (l.tail != null) {
  262. h = h * 31 + (l.head == null ? 0 : l.head.hashCode());
  263. l = l.tail;
  264. }
  265. return h;
  266. }
  267. /** Is this list the same as other list?
  268. * @see java.util.List#equals
  269. */
  270. @Override
  271. public boolean equals(Object other) {
  272. if (other instanceof List<?>)
  273. return equals(this, (List<?>)other);
  274. if (other instanceof java.util.List<?>) {
  275. List<A> t = this;
  276. Iterator<?> oIter = ((java.util.List<?>) other).iterator();
  277. while (t.tail != null && oIter.hasNext()) {
  278. Object o = oIter.next();
  279. if ( !(t.head == null ? o == null : t.head.equals(o)))
  280. return false;
  281. t = t.tail;
  282. }
  283. return (t.isEmpty() && !oIter.hasNext());
  284. }
  285. return false;
  286. }
  287. /** Are the two lists the same?
  288. */
  289. public static boolean equals(List xs, List ys) {
  290. while (xs.tail != null && ys.tail != null) {
  291. if (xs.head == null) {
  292. if (ys.head != null) return false;
  293. } else {
  294. if (!xs.head.equals(ys.head)) return false;
  295. }
  296. xs = xs.tail;
  297. ys = ys.tail;
  298. }
  299. return xs.tail == null && ys.tail == null;
  300. }
  301. /** Does the list contain the specified element?
  302. */
  303. @Override
  304. public boolean contains(Object x) {
  305. List<A> l = this;
  306. while (l.tail != null) {
  307. if (x == null) {
  308. if (l.head == null) return true;
  309. } else {
  310. if (l.head.equals(x)) return true;
  311. }
  312. l = l.tail;
  313. }
  314. return false;
  315. }
  316. /** The last element in the list, if any, or null.
  317. */
  318. public A last() {
  319. A last = null;
  320. List<A> t = this;
  321. while (t.tail != null) {
  322. last = t.head;
  323. t = t.tail;
  324. }
  325. return last;
  326. }
  327. @SuppressWarnings("unchecked")
  328. public static <T> List<T> convert(Class<T> klass, List<?> list) {
  329. if (list == null)
  330. return null;
  331. for (Object o : list)
  332. klass.cast(o);
  333. return (List<T>)list;
  334. }
  335. private static Iterator EMPTYITERATOR = new Iterator() {
  336. public boolean hasNext() {
  337. return false;
  338. }
  339. public Object next() {
  340. throw new java.util.NoSuchElementException();
  341. }
  342. public void remove() {
  343. throw new UnsupportedOperationException();
  344. }
  345. };
  346. @SuppressWarnings("unchecked")
  347. private static <A> Iterator<A> emptyIterator() {
  348. return EMPTYITERATOR;
  349. }
  350. @Override
  351. public Iterator<A> iterator() {
  352. if (tail == null)
  353. return emptyIterator();
  354. return new Iterator<A>() {
  355. List<A> elems = List.this;
  356. public boolean hasNext() {
  357. return elems.tail != null;
  358. }
  359. public A next() {
  360. if (elems.tail == null)
  361. throw new NoSuchElementException();
  362. A result = elems.head;
  363. elems = elems.tail;
  364. return result;
  365. }
  366. public void remove() {
  367. throw new UnsupportedOperationException();
  368. }
  369. };
  370. }
  371. public A get(int index) {
  372. if (index < 0)
  373. throw new IndexOutOfBoundsException(String.valueOf(index));
  374. List<A> l = this;
  375. for (int i = index; i-- > 0 && !l.isEmpty(); l = l.tail)
  376. ;
  377. if (l.isEmpty())
  378. throw new IndexOutOfBoundsException("Index: " + index + ", " +
  379. "Size: " + size());
  380. return l.head;
  381. }
  382. public boolean addAll(int index, Collection<? extends A> c) {
  383. if (c.isEmpty())
  384. return false;
  385. throw new UnsupportedOperationException();
  386. }
  387. public A set(int index, A element) {
  388. throw new UnsupportedOperationException();
  389. }
  390. public void add(int index, A element) {
  391. throw new UnsupportedOperationException();
  392. }
  393. public A remove(int index) {
  394. throw new UnsupportedOperationException();
  395. }
  396. public int indexOf(Object o) {
  397. int i = 0;
  398. for (List<A> l = this; l.tail != null; l = l.tail, i++) {
  399. if (l.head == null ? o == null : l.head.equals(o))
  400. return i;
  401. }
  402. return -1;
  403. }
  404. public int lastIndexOf(Object o) {
  405. int last = -1;
  406. int i = 0;
  407. for (List<A> l = this; l.tail != null; l = l.tail, i++) {
  408. if (l.head == null ? o == null : l.head.equals(o))
  409. last = i;
  410. }
  411. return last;
  412. }
  413. public ListIterator<A> listIterator() {
  414. return Collections.unmodifiableList(new ArrayList<A>(this)).listIterator();
  415. }
  416. public ListIterator<A> listIterator(int index) {
  417. return Collections.unmodifiableList(new ArrayList<A>(this)).listIterator(index);
  418. }
  419. public java.util.List<A> subList(int fromIndex, int toIndex) {
  420. if (fromIndex < 0 || toIndex > size() || fromIndex > toIndex)
  421. throw new IllegalArgumentException();
  422. ArrayList<A> a = new ArrayList<A>(toIndex - fromIndex);
  423. int i = 0;
  424. for (List<A> l = this; l.tail != null; l = l.tail, i++) {
  425. if (i == toIndex)
  426. break;
  427. if (i >= fromIndex)
  428. a.add(l.head);
  429. }
  430. return Collections.unmodifiableList(a);
  431. }
  432. }