//
// Copyright (C) 2012 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.util;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* simple identity set for objects
* we don't sort&bisect, assuming the number of entries will be small
* be aware this doesn't scale to large sets
*/
@SuppressWarnings("unchecked")
public class IdentityArrayObjectSet<E> implements IdentityObjectSet<E> {
static final int DEFAULT_CAPACITY = 4;
private class StoreOrderIterator implements Iterator<E> {
int next = 0;
@Override
public void remove() {
int idx = next-1;
if (idx >=0){
if (idx < size-1){
System.arraycopy(elements, next, elements, idx, size-idx);
}
size--;
next = idx;
}
}
@Override
public boolean hasNext() {
return (next < size);
}
@Override
public E next() {
if (next < size){
return (E) elements[next++];
} else {
throw new NoSuchElementException();
}
}
}
protected int size;
protected Object[] elements;
public IdentityArrayObjectSet(){
// nothing, elements allocated on demand
}
public IdentityArrayObjectSet (int initialCapacity){
elements = new Object[initialCapacity];
}
public IdentityArrayObjectSet (E initialElement){
elements = new Object[DEFAULT_CAPACITY];
elements[0] = initialElement;
size = 1;
}
public int size(){
return size;
}
public boolean isEmpty(){
return (size == 0);
}
public boolean add (E obj){
for (int i=0; i<size; i++){
if (elements[i] == obj){
return false;
}
}
if (size == 0){
elements = new Object[DEFAULT_CAPACITY];
} else if (size == elements.length){
Object[] newElements = new Object[elements.length * 3 / 2];
System.arraycopy(elements, 0, newElements, 0, size);
elements = newElements;
}
elements[size] = obj;
size++;
return true;
}
public boolean contains (E obj){
for (int i=0; i<size; i++){
if (elements[i] == obj){
return true;
}
}
return false;
}
public boolean remove (E obj){
int len = size;
for (int i=0; i<len; i++){
if (elements[i] == obj){
len--;
if (len == 0){
size = 0;
elements = null;
} else if (i < len){
System.arraycopy(elements, i+1, elements, i, len-i);
} else {
elements[len] = null; // avoid memory leak
}
size = len;
return true;
}
}
return false;
}
public ObjectSet<E> clone(){
try {
return (ObjectSet<E>)super.clone();
} catch (CloneNotSupportedException x){
// can't happen
return null;
}
}
@Override
public Iterator<E> iterator(){
return new StoreOrderIterator();
}
@Override
public String toString(){
StringBuilder sb = new StringBuilder(/*getClass().getName()*/);
sb.append('{');
for (int i=0; i<size; i++){
if (i>0){
sb.append(',');
}
sb.append(elements[i]);
}
sb.append('}');
return sb.toString();
}
}