package org.simantics.scl.runtime.list; import java.util.AbstractList; import java.util.Arrays; import java.util.List; public class ShareableList extends AbstractList { public static final int INITIAL_CAPACITY = 4; T[] elements; int size; boolean head; public ShareableList(T[] elements, int size, boolean head) { this.elements = elements; this.size = size; this.head = head; } @SuppressWarnings("unchecked") public ShareableList() { this.elements = (T[])new Object[INITIAL_CAPACITY]; this.size = 0; this.head = true; } @Override public T get(int index) { if(index < 0 || index >= size) throw new IndexOutOfBoundsException(); return elements[index]; } @Override public int size() { return size; } @SuppressWarnings("unchecked") public ShareableList append(T element) { T[] newElements; if(size < elements.length) { if(head) { head = false; newElements = elements; } else { newElements = (T[])new Object[elements.length]; System.arraycopy(elements, 0, newElements, 0, size); } } else { newElements = Arrays.copyOf(elements, (elements.length*3)/2 + 1); } newElements[size] = element; return new ShareableList(newElements, size+1, true); } @SuppressWarnings("unchecked") public ShareableList appendAll(List xs) { int count = xs.size(); int size = this.size; int newSize = size + count; T[] newElements; if(newSize <= elements.length) { if(head) { head = false; newElements = elements; } else { newElements = (T[])new Object[elements.length]; System.arraycopy(elements, 0, newElements, 0, size); } } else { newElements = Arrays.copyOf(elements, Math.max((elements.length*3)/2 + 1, newSize)); } for(int i=0;i(newElements, newSize, true); } @SuppressWarnings("unchecked") public static List add(List list, T element) { List result; if(list instanceof ShareableList) result = ((ShareableList)list).append(element); else { int size = list.size(); T[] newElements = (T[])new Object[(size*3)/2 + 1]; for(int i=0;i(newElements, size+1, true); } //System.out.println(list + " + " + element + " = " + result); return result; } @SuppressWarnings("unchecked") public static List concat(List a, List b) { List result; if(a instanceof ShareableList) result = ((ShareableList)a).appendAll(b); else { int aSize = a.size(); int bSize = b.size(); int size = aSize + bSize; T[] newElements = (T[])new Object[(size*3)/2 + 1]; for(int i=0;i(newElements, size, true); } //System.out.println(a + " + " + b + " = " + result); return result; } }