/* Soot - a J*va Optimization Framework * Copyright (C) 2007 Manu Sridharan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package soot.jimple.spark.ondemand.genericutil; import java.util.Arrays; public class ImmutableStack<T> { private static final ImmutableStack<Object> EMPTY = new ImmutableStack<Object>( new Object[0]); private static final int MAX_SIZE = Integer.MAX_VALUE; public static int getMaxSize() { return MAX_SIZE; } @SuppressWarnings("unchecked") public static final <T> ImmutableStack<T> emptyStack() { return (ImmutableStack<T>) EMPTY; } final private T[] entries; private ImmutableStack(T[] entries) { this.entries = entries; } public boolean equals(Object o) { if (this == o) return true; if (o != null && o instanceof ImmutableStack) { ImmutableStack other = (ImmutableStack) o; return Arrays.equals(entries, other.entries); } return false; } public int hashCode() { return Util.hashArray(this.entries); } @SuppressWarnings("unchecked") public ImmutableStack<T> push(T entry) { assert entry != null; if (MAX_SIZE == 0) { return emptyStack(); } int size = entries.length + 1; T[] tmpEntries = null; if (size <= MAX_SIZE) { tmpEntries = (T[]) new Object[size]; System.arraycopy(entries, 0, tmpEntries, 0, entries.length); tmpEntries[size - 1] = entry; } else { tmpEntries = (T[]) new Object[MAX_SIZE]; System.arraycopy(entries, 1, tmpEntries, 0, entries.length - 1); tmpEntries[MAX_SIZE - 1] = entry; } return new ImmutableStack<T>(tmpEntries); } public T peek() { assert entries.length != 0; return entries[entries.length - 1]; } @SuppressWarnings("unchecked") public ImmutableStack<T> pop() { assert entries.length != 0; int size = entries.length - 1; T[] tmpEntries = (T[]) new Object[size]; System.arraycopy(entries, 0, tmpEntries, 0, size); return new ImmutableStack<T>(tmpEntries); } public boolean isEmpty() { return entries.length == 0; } public int size() { return entries.length; } public T get(int i) { return entries[i]; } public String toString() { String objArrayToString = Util.objArrayToString(entries); assert entries.length <= MAX_SIZE : objArrayToString; return objArrayToString; } public boolean contains(T entry) { return Util.arrayContains(entries, entry, entries.length); } public boolean topMatches(ImmutableStack<T> other) { if (other.size() > size()) return false; for (int i = other.size() - 1, j = this.size() - 1; i >= 0; i--, j--) { if (!other.get(i).equals(get(j))) return false; } return true; } @SuppressWarnings("unchecked") public ImmutableStack<T> reverse() { T[] tmpEntries = (T[]) new Object[entries.length]; for (int i = entries.length - 1, j = 0; i >= 0; i--, j++) { tmpEntries[j] = entries[i]; } return new ImmutableStack<T>(tmpEntries); } @SuppressWarnings("unchecked") public ImmutableStack<T> popAll(ImmutableStack<T> other) { // TODO Auto-generated method stub assert topMatches(other); int size = entries.length - other.entries.length; T[] tmpEntries = (T[]) new Object[size]; System.arraycopy(entries, 0, tmpEntries, 0, size); return new ImmutableStack<T>(tmpEntries); } @SuppressWarnings("unchecked") public ImmutableStack<T> pushAll(ImmutableStack<T> other) { // TODO Auto-generated method stub int size = entries.length + other.entries.length; T[] tmpEntries = null; if (size <= MAX_SIZE) { tmpEntries = (T[]) new Object[size]; System.arraycopy(entries, 0, tmpEntries, 0, entries.length); System.arraycopy(other.entries, 0, tmpEntries, entries.length, other.entries.length); } else { tmpEntries = (T[]) new Object[MAX_SIZE]; // other has size at most MAX_SIZE // must keep all in other // top MAX_SIZE - other.size from this int numFromThis = MAX_SIZE - other.entries.length; System.arraycopy(entries, entries.length - numFromThis, tmpEntries, 0, numFromThis); System.arraycopy(other.entries, 0, tmpEntries, numFromThis, other.entries.length); } return new ImmutableStack<T>(tmpEntries); } }