/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.api.impl;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
public final class ReadOnlyArrayList<T> implements List<T> {
private final T[] arr;
private final int first;
private final int last;
private ReadOnlyArrayList(T[] arr, int first, int last) {
this.arr = arr;
this.first = first;
this.last = last;
if (first > last) {
throw new IllegalArgumentException();
}
}
public static <T> List<T> asList(T[] arr, int first, int last) {
return new ReadOnlyArrayList<>(arr, first, last);
}
@Override
public int size() {
return last - first;
}
@Override
public boolean isEmpty() {
return first == last;
}
@Override
public boolean contains(Object o) {
for (int i = first; i < last; i++) {
if (o == arr[i] || (o != null && o.equals(arr[i]))) {
return true;
}
}
return false;
}
@Override
public Iterator<T> iterator() {
return new LI(first);
}
@Override
public Object[] toArray() {
return toArray(new Object[size()]);
}
@Override
@SuppressWarnings("unchecked")
public <A> A[] toArray(A[] b) {
A[] a;
if (b.length < size()) {
a = (A[]) Array.newInstance(b.getClass().getComponentType(), size());
} else {
a = b;
}
for (int i = 0, at = first; at < last; i++, at++) {
a[i] = (A) arr[at];
}
return a;
}
@Override
public boolean add(Object e) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
@Override
public boolean containsAll(Collection<?> c) {
for (Object obj : c) {
if (!contains(obj)) {
return false;
}
}
return true;
}
@Override
public boolean addAll(Collection<? extends T> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(int index, Collection<? extends T> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public T get(int index) {
int at = first + index;
T ret = arr[at];
if (at >= last) {
throw new ArrayIndexOutOfBoundsException();
}
return ret;
}
@Override
public T set(int index, Object element) {
throw new UnsupportedOperationException();
}
@Override
public void add(int index, Object element) {
throw new UnsupportedOperationException();
}
@Override
public T remove(int index) {
throw new UnsupportedOperationException();
}
@Override
public int indexOf(Object o) {
for (int i = first; i < last; i++) {
if (arr[i] == null) {
if (o == null) {
return i - first;
}
} else {
if (arr[i].equals(o)) {
return i - first;
}
}
}
return -1;
}
@Override
public int lastIndexOf(Object o) {
for (int i = last - 1; i >= first; i--) {
if (arr[i] == null) {
if (o == null) {
return i - first;
}
} else {
if (arr[i].equals(o)) {
return i - first;
}
}
}
return -1;
}
@Override
public ListIterator<T> listIterator() {
return new LI(first);
}
@Override
public ListIterator<T> listIterator(int index) {
return new LI(first + index);
}
@Override
public List<T> subList(int fromIndex, int toIndex) {
return new ReadOnlyArrayList<>(arr, first + fromIndex, first + toIndex);
}
@TruffleBoundary
@Override
public String toString() {
Iterator<T> it = iterator();
if (!it.hasNext()) {
return "[]";
}
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
T e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (!it.hasNext()) {
return sb.append(']').toString();
}
sb.append(',').append(' ');
}
}
private final class LI implements ListIterator<T>, Iterator<T> {
private int index;
LI(int index) {
this.index = index;
}
@Override
public boolean hasNext() {
return index < last;
}
@Override
public T next() {
if (index >= last) {
throw new NoSuchElementException();
}
return arr[index++];
}
@Override
public boolean hasPrevious() {
return index > first;
}
@Override
public T previous() {
if (first == index) {
throw new NoSuchElementException();
}
return arr[--index];
}
@Override
public int nextIndex() {
return index - first;
}
@Override
public int previousIndex() {
return index - 1 - first;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public void set(Object e) {
throw new UnsupportedOperationException();
}
@Override
public void add(Object e) {
throw new UnsupportedOperationException();
}
}
}