/**
* Copyright (c) Rich Hickey. All rights reserved.
* The use and distribution terms for this software are covered by the
* Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
* which can be found in the file epl-v10.html at the root of this distribution.
* By using this software in any fashion, you are agreeing to be bound by
* the terms of this license.
* You must not remove this notice, or any other, from this software.
**/
/* rich Dec 18, 2007 */
package com.trifork.clj_ds;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.RandomAccess;
public abstract class APersistentVector<T> extends AFn implements IPersistentVector<T>, Iterable<T>,
List<T>,
RandomAccess, Comparable<T>,
Serializable {
int _hash = -1;
public String toString(){
return RT.printString(this);
}
public ISeq<T> seq(){
if(count() > 0)
return new Seq<T>(this, 0);
return null;
}
public ISeq<T> rseq(){
if(count() > 0)
return new RSeq<T>(this, count() - 1);
return null;
}
static boolean doEquals(IPersistentVector v, Object obj){
if(v == obj) return true;
if(obj instanceof List || obj instanceof IPersistentVector)
{
Collection ma = (Collection) obj;
if(ma.size() != v.count() || ma.hashCode() != v.hashCode())
return false;
for(Iterator i1 = ((List) v).iterator(), i2 = ma.iterator();
i1.hasNext();)
{
if(!Util.equals(i1.next(), i2.next()))
return false;
}
return true;
}
// if(obj instanceof IPersistentVector)
// {
// IPersistentVector ma = (IPersistentVector) obj;
// if(ma.count() != v.count() || ma.hashCode() != v.hashCode())
// return false;
// for(int i = 0; i < v.count(); i++)
// {
// if(!Util.equal(v.nth(i), ma.nth(i)))
// return false;
// }
// }
else
{
if(!(obj instanceof Sequential))
return false;
ISeq ms = RT.seq(obj);
for(int i = 0; i < v.count(); i++, ms = ms.next())
{
if(ms == null || !Util.equals(v.nth(i), ms.first()))
return false;
}
if(ms != null)
return false;
}
return true;
}
static boolean doEquiv(IPersistentVector v, Object obj){
if(obj instanceof List || obj instanceof IPersistentVector)
{
Collection ma = (Collection) obj;
if(ma.size() != v.count())
return false;
for(Iterator i1 = ((List) v).iterator(), i2 = ma.iterator();
i1.hasNext();)
{
if(!Util.equiv(i1.next(), i2.next()))
return false;
}
return true;
}
// if(obj instanceof IPersistentVector)
// {
// IPersistentVector ma = (IPersistentVector) obj;
// if(ma.count() != v.count() || ma.hashCode() != v.hashCode())
// return false;
// for(int i = 0; i < v.count(); i++)
// {
// if(!Util.equal(v.nth(i), ma.nth(i)))
// return false;
// }
// }
else
{
if(!(obj instanceof Sequential))
return false;
ISeq ms = RT.seq(obj);
for(int i = 0; i < v.count(); i++, ms = ms.next())
{
if(ms == null || !Util.equiv(v.nth(i), ms.first()))
return false;
}
if(ms != null)
return false;
}
return true;
}
public boolean equals(Object obj){
return doEquals(this, obj);
}
public boolean equiv(Object obj){
return doEquiv(this, obj);
}
public int hashCode(){
if(_hash == -1)
{
int hash = 1;
Iterator i = iterator();
while(i.hasNext())
{
Object obj = i.next();
hash = 31 * hash + (obj == null ? 0 : obj.hashCode());
}
// int hash = 0;
// for(int i = 0; i < count(); i++)
// {
// hash = Util.hashCombine(hash, Util.hash(nth(i)));
// }
this._hash = hash;
}
return _hash;
}
public T get(int index){
return nth(index);
}
public T nth(int i, T notFound){
if(i >= 0 && i < count())
return nth(i);
return notFound;
}
public T remove(int i){
throw new UnsupportedOperationException();
}
public int indexOf(Object o){
for(int i = 0; i < count(); i++)
if(Util.equiv(nth(i), o))
return i;
return -1;
}
public int lastIndexOf(Object o){
for(int i = count() - 1; i >= 0; i--)
if(Util.equiv(nth(i), o))
return i;
return -1;
}
public ListIterator<T> listIterator(){
return listIterator(0);
}
public ListIterator<T> listIterator(final int index){
return new ListIterator<T>(){
int nexti = index;
public boolean hasNext(){
return nexti < count();
}
public T next(){
return nth(nexti++);
}
public boolean hasPrevious(){
return nexti > 0;
}
public T previous(){
return nth(--nexti);
}
public int nextIndex(){
return nexti;
}
public int previousIndex(){
return nexti - 1;
}
public void remove(){
throw new UnsupportedOperationException();
}
public void set(Object o){
throw new UnsupportedOperationException();
}
public void add(Object o){
throw new UnsupportedOperationException();
}
};
}
@SuppressWarnings("unchecked")
public List<T> subList(int fromIndex, int toIndex){
return (List<T>) RT.subvec(this, fromIndex, toIndex);
}
public T set(int i, T o){
throw new UnsupportedOperationException();
}
public void add(int i, T o){
throw new UnsupportedOperationException();
}
public boolean addAll(int i, Collection c){
throw new UnsupportedOperationException();
}
public Object invoke(Object arg1) throws Exception{
if(Util.isInteger(arg1))
return nth(((Number) arg1).intValue());
throw new IllegalArgumentException("Key must be integer");
}
public Iterator<T> iterator(){
//todo - something more efficient
return new Iterator<T>(){
int i = 0;
public boolean hasNext(){
return i < count();
}
public T next(){
return nth(i++);
}
public void remove(){
throw new UnsupportedOperationException();
}
};
}
public T peek(){
if(count() > 0)
return nth(count() - 1);
return null;
}
public boolean containsKey(Object key){
if(!(Util.isInteger(key)))
return false;
int i = ((Number) key).intValue();
return i >= 0 && i < count();
}
public IMapEntry<Object, T> entryAt(Object key){
if(Util.isInteger(key))
{
int i = ((Number) key).intValue();
if(i >= 0 && i < count())
return new MapEntry<Object,T>(key, nth(i));
}
return null;
}
public IPersistentVector<T> assoc(Object key, T val){
if(Util.isInteger(key))
{
int i = ((Number) key).intValue();
return assocN(i, val);
}
throw new IllegalArgumentException("Key must be integer");
}
public T valAt(Object key, T notFound){
if(Util.isInteger(key))
{
int i = ((Number) key).intValue();
if(i >= 0 && i < count())
return nth(i);
}
return notFound;
}
public T valAt(Object key){
return valAt(key, null);
}
// java.util.Collection implementation
public Object[] toArray(){
return RT.seqToArray(seq());
}
public boolean add(T o){
throw new UnsupportedOperationException();
}
public boolean remove(Object o){
throw new UnsupportedOperationException();
}
public boolean addAll(Collection c){
throw new UnsupportedOperationException();
}
public void clear(){
throw new UnsupportedOperationException();
}
public boolean retainAll(Collection c){
throw new UnsupportedOperationException();
}
public boolean removeAll(Collection c){
throw new UnsupportedOperationException();
}
public boolean containsAll(Collection c){
for(Object o : c)
{
if(!contains(o))
return false;
}
return true;
}
public Object[] toArray(Object[] a){
if(a.length >= count())
{
ISeq s = seq();
for(int i = 0; s != null; ++i, s = s.next())
{
a[i] = s.first();
}
if(a.length > count())
a[count()] = null;
return a;
}
else
return toArray();
}
public int size(){
return count();
}
public boolean isEmpty(){
return count() == 0;
}
public boolean contains(Object o){
for(ISeq s = seq(); s != null; s = s.next())
{
if(Util.equiv(s.first(), o))
return true;
}
return false;
}
public int length(){
return count();
}
public int compareTo(Object o){
IPersistentVector v = (IPersistentVector) o;
if(count() < v.count())
return -1;
else if(count() > v.count())
return 1;
for(int i = 0; i < count(); i++)
{
int c = Util.compare(nth(i),v.nth(i));
if(c != 0)
return c;
}
return 0;
}
static class Seq<T> extends ASeq<T> implements IndexedSeq<T>, IReduce{
//todo - something more efficient
final IPersistentVector<T> v;
final int i;
public Seq(IPersistentVector<T> v, int i){
this.v = v;
this.i = i;
}
Seq(IPersistentMap meta, IPersistentVector<T> v, int i){
super(meta);
this.v = v;
this.i = i;
}
public T first(){
return v.nth(i);
}
public ISeq<T> next(){
if(i + 1 < v.count())
return new APersistentVector.Seq<T>(v, i + 1);
return null;
}
public int index(){
return i;
}
public int count(){
return v.count() - i;
}
public APersistentVector.Seq<T> withMeta(IPersistentMap meta){
return new APersistentVector.Seq<T>(meta, v, i);
}
public Object reduce(IFn f) throws Exception{
Object ret = v.nth(i);
for(int x = i + 1; x < v.count(); x++)
ret = f.invoke(ret, v.nth(x));
return ret;
}
public Object reduce(IFn f, Object start) throws Exception{
Object ret = f.invoke(start, v.nth(i));
for(int x = i + 1; x < v.count(); x++)
ret = f.invoke(ret, v.nth(x));
return ret;
}
}
public static class RSeq<T> extends ASeq<T> implements IndexedSeq<T>, Counted{
final IPersistentVector<T> v;
final int i;
public RSeq(IPersistentVector<T> vector, int i){
this.v = vector;
this.i = i;
}
RSeq(IPersistentMap meta, IPersistentVector<T> v, int i){
super(meta);
this.v = v;
this.i = i;
}
public T first(){
return v.nth(i);
}
public ISeq<T> next(){
if(i > 0)
return new APersistentVector.RSeq<T>(v, i - 1);
return null;
}
public int index(){
return i;
}
public int count(){
return i + 1;
}
public APersistentVector.RSeq<T> withMeta(IPersistentMap meta){
return new APersistentVector.RSeq<T>(meta, v, i);
}
}
static class SubVector<T> extends APersistentVector<T> implements IObj{
final IPersistentVector<T> v;
final int start;
final int end;
final IPersistentMap _meta;
@SuppressWarnings("unchecked")
public SubVector(IPersistentMap meta, IPersistentVector<T> v, int start, int end){
this._meta = meta;
if(v instanceof APersistentVector.SubVector)
{
APersistentVector.SubVector sv = (APersistentVector.SubVector) v;
start += sv.start;
end += sv.start;
v = sv.v;
}
this.v = v;
this.start = start;
this.end = end;
}
public T nth(int i){
if(start + i >= end)
throw new IndexOutOfBoundsException();
return v.nth(start + i);
}
public IPersistentVector<T> assocN(int i, T val){
if(start + i > end)
throw new IndexOutOfBoundsException();
else if(start + i == end)
return cons(val);
return new SubVector<T>(_meta, v.assocN(start + i, val), start, end);
}
public int count(){
return end - start;
}
public IPersistentVector<T> cons(T o){
return new SubVector<T>(_meta, v.assocN(end, o), start, end + 1);
}
@SuppressWarnings("unchecked")
public IPersistentCollection<T> empty(){
return PersistentVector.EMPTY.withMeta(meta());
}
@SuppressWarnings("unchecked")
public IPersistentStack<T> pop(){
if(end - 1 == start)
{
return PersistentVector.EMPTY;
}
return new SubVector<T>(_meta, v, start, end - 1);
}
public SubVector<T> withMeta(IPersistentMap meta){
if(meta == _meta)
return this;
return new SubVector<T>(meta, v, start, end);
}
public IPersistentMap meta(){
return _meta;
}
}
}