001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm.util;
014
015import java.util.Collection;
016import java.util.Iterator;
017import java.util.List;
018import java.util.ListIterator;
019import org.jikesrvm.VM;
020
021/**
022 * Implementation of java.util.LinkedList for use in classes that
023 * end up in the boot image.
024 */
025public final class LinkedListRVM<T> implements List<T> {
026
027  /** Element count */
028  private int count = 0;
029
030  /** pointer to first element in the list */
031  Element<T> head = null;
032
033  /** pointer to last element in the list */
034  Element<T> tail = null;
035
036  /**
037   * Insert an element at a given position in the list.
038   * <p>
039   * UNIMPLEMENTED
040   *
041   * @param pos Position in the list (0..size()-1)
042   * @param entry Element to insert
043   */
044  @Override
045  public void add(int pos, T entry) {
046    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
047  }
048
049  /**
050   * Insert at the tail of the list
051   *
052   * @param entry The entry to add.
053   * @return true (as per java collections framework standard)
054   */
055  @Override
056  public boolean add(final T entry) {
057    final Element<T> element = new Element<T>(entry);
058    element.next = null;
059    if (head == null) {
060      if (VM.VerifyAssertions) VM._assert(tail == null);
061      head = element;
062      element.prev = null;
063    } else {
064      tail.next = element;
065      element.prev = tail;
066    }
067    tail = element;
068    count++;
069    return true;
070  }
071
072  /**
073   * Insert an entry after the given element.  Used via the iterator.
074   *
075   * @param e List element
076   * @param t New list entry
077   */
078  void insertAfter(Element<T> e, T t) {
079    Element<T> newElement = new Element<T>(t);
080    if (e == null) {
081      newElement.next = head;
082      newElement.prev = null;
083      head = newElement;
084    } else {
085      newElement.next = e.next;
086      newElement.prev = e;
087      if (e.next != null) {
088        e.next.prev = newElement;
089      }
090      e.next = newElement;
091    }
092    if (tail == null || tail == e) {
093      tail = newElement;
094    }
095    count++;
096  }
097
098  /**
099   * Add all members of the given collection.
100   * <p>
101   * UNIMPLEMENTED
102   */
103  @Override
104  public boolean addAll(Collection<? extends T> arg0) {
105    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
106    return false;
107  }
108
109  /**
110   * Add all members of the given collection after the given element.
111   * <p>
112   * UNIMPLEMENTED
113   */
114  @Override
115  public boolean addAll(int arg0, Collection<? extends T> arg1) {
116    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
117    return false;
118  }
119
120  /**
121   * Discard all entries in the list
122   */
123  @Override
124  public void clear() {
125    head = tail = null;
126    count = 0;
127  }
128
129  /**
130   * Membership test
131   *
132   * @param arg0 Object to check
133   * @return true if the list contains arg0, false otherwise
134   */
135  @Override
136  public boolean contains(Object arg0) {
137    return indexOf(arg0) != -1;
138  }
139
140  /**
141   * Set inclusion test
142   *
143   * @param arg0 Objects to check
144   * @return true if the list contains all objects in arg0, false otherwise
145   */
146  @Override
147  public boolean containsAll(Collection<?> arg0) {
148    for (Object o : arg0) {
149      if (!contains(o)) {
150        return false;
151      }
152    }
153    return true;
154  }
155
156  /**
157   * @param index index of the element to return
158   * @return the nth element of the list
159   */
160  @Override
161  public T get(int index) {
162    /* Special-case getting the head of the list for speed */
163    if (index == 0 && head != null) {
164      return head.entry;
165    }
166
167    /* bounds check */
168    if (index < 0 || index >= size()) {
169      throw new IndexOutOfBoundsException();
170    }
171
172    Element<T> cursor = head;
173    for (int i = 0; i < index; i++) {
174      cursor = cursor.next;
175    }
176    return cursor.entry;
177  }
178
179  /**
180   * Return the position of the given element.
181   *
182   * @param arg0 Member to test for.
183   * @return Zero-based index of the element, or -1 if not found.
184   */
185  @Override
186  public int indexOf(Object arg0) {
187    int i = 0;
188    for (T t : this) {
189      if (t == arg0) {
190        return i;
191      }
192      i++;
193    }
194    return -1;
195  }
196
197  @Override
198  public boolean isEmpty() {
199    return count == 0;
200  }
201
202  @Override
203  public Iterator<T> iterator() {
204    return new LinkedListIteratorRVM<T>(this);
205  }
206
207  /** UNIMPLEMENTED */
208  @Override
209  public int lastIndexOf(Object arg0) {
210    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
211    return 0;
212  }
213
214  @Override
215  public ListIterator<T> listIterator() {
216    return new LinkedListIteratorRVM<T>(this);
217  }
218
219  /** UNIMPLEMENTED */
220  @Override
221  public ListIterator<T> listIterator(int arg0) {
222    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
223    return null;
224  }
225
226  /**
227   * Remove the nth element of the list.
228   *
229   * @param index n
230   * @return The nth element
231   */
232  @Override
233  public T remove(int index) {
234    /* bounds check */
235    if (index < 0 || index >= size()) {
236      throw new IndexOutOfBoundsException();
237    }
238
239    Element<T> cursor = head;
240    for (int i = 0; i < index; i++) {
241      cursor = cursor.next;
242    }
243    removeInternal(cursor);
244    return cursor.entry;
245  }
246
247  /**
248   * Remove the given element from the list
249   */
250  @Override
251  public boolean remove(Object arg0) {
252    Element<T> cursor = head;
253    while (cursor != null && !(arg0 == null ? cursor.entry == null : cursor.entry.equals(arg0))) {
254      cursor = cursor.next;
255    }
256    if (cursor == null) {
257      return false;
258    } else {
259      removeInternal(cursor);
260      return true;
261    }
262  }
263
264  void removeInternal(Element<T> e) {
265    if (e.prev == null) {
266      if (VM.VerifyAssertions) VM._assert(e == head);
267      head = e.next;
268    } else {
269      e.prev.next = e.next;
270    }
271
272    if (e.next == null) {
273      if (VM.VerifyAssertions) VM._assert(e == tail);
274      tail = e.prev;
275    } else {
276      e.next.prev = e.prev;
277    }
278
279    count--;
280  }
281
282  /** UNIMPLEMENTED */
283  @Override
284  public boolean removeAll(Collection<?> arg0) {
285    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
286    return false;
287  }
288
289  /** UNIMPLEMENTED */
290  @Override
291  public boolean retainAll(Collection<?> arg0) {
292    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
293    return false;
294  }
295
296  /** UNIMPLEMENTED */
297  @Override
298  public T set(int arg0, T arg1) {
299    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
300    return null;
301  }
302
303  @Override
304  public int size() {
305    return count;
306  }
307
308  /** UNIMPLEMENTED */
309  @Override
310  public List<T> subList(int arg0, int arg1) {
311    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
312    return null;
313  }
314
315  /** UNIMPLEMENTED */
316  @Override
317  public Object[] toArray() {
318    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
319    return null;
320  }
321
322  /** UNIMPLEMENTED */
323  @Override
324  public <U> U[] toArray(U[] arg0) {
325    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
326    return null;
327  }
328
329  /**
330   * Class for the actual elements of the list.
331   *
332   *
333   * @param <T> Type of the entry
334   */
335  static class Element<T> {
336    Element<T> next;
337    Element<T> prev;
338    T entry;
339
340    Element(T entry) {
341      this.entry = entry;
342    }
343  }
344}