soot.util.NumberedSet Maven / Gradle / Ivy
/* Soot - a J*va Optimization Framework
* Copyright (C) 2002 Ondrej Lhotak
*
* 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.util;
import java.util.*;
/** Holds a set of Numberable objects.
*
* @author Ondrej Lhotak
*/
public final class NumberedSet {
public NumberedSet( ArrayNumberer universe ) {
this.universe = universe;
}
public boolean add( Numberable o ) {
if( array != null ) {
int pos = findPosition( o );
if( array[pos] == o ) return false;
size++;
if( size*3 > array.length*2 ) {
doubleSize();
if( array != null ) {
pos = findPosition( o );
} else {
int number = o.getNumber();
if( number == 0 ) throw new RuntimeException( "unnumbered" );
return bits.set( number );
}
}
array[pos] = o;
return true;
} else {
int number = o.getNumber();
if( number == 0 ) throw new RuntimeException( "unnumbered" );
if( bits.set( number ) ) {
size++;
return true;
} else {
return false;
}
}
}
public boolean contains( Numberable o ) {
if( array != null ) {
return array[ findPosition(o) ] != null;
} else {
int number = o.getNumber();
if( number == 0 ) throw new RuntimeException( "unnumbered" );
return bits.get( number );
}
}
/* Private stuff. */
private final int findPosition( Numberable o ) {
int number = o.getNumber();
if( number == 0 ) throw new RuntimeException( "unnumbered" );
number = number & (array.length-1);
while(true) {
if( array[number] == o ) return number;
if( array[number] == null ) return number;
number = (number+1) & (array.length-1);
}
}
private final void doubleSize() {
int uniSize = universe.size();
if( array.length*128 > uniSize ) {
bits = new BitVector( uniSize );
Numberable[] oldArray = array;
array = null;
for (Numberable element : oldArray) {
if( element != null ) {
bits.set( element.getNumber() );
}
}
} else {
Numberable[] oldArray = array;
array = new Numberable[array.length*2];
for (Numberable element : oldArray) {
if( element != null ) {
array[findPosition(element)] = element;
}
}
}
}
public Iterator iterator() {
if( array == null ) return new BitSetIterator( this );
else return new NumberedSetIterator( this );
}
class BitSetIterator implements Iterator {
soot.util.BitSetIterator iter;
BitSetIterator( NumberedSet set ) {
iter = set.bits.iterator();
}
public final boolean hasNext() { return iter.hasNext(); }
public void remove() {
throw new RuntimeException( "Not implemented." );
}
public final Object next() {
return universe.get( iter.next() );
}
}
class NumberedSetIterator implements Iterator {
NumberedSet set;
int cur = 0;
NumberedSetIterator( NumberedSet set ) {
this.set = set;
seekNext();
}
protected final void seekNext() {
try {
while( set.array[cur] == null ) {
cur++;
}
} catch( ArrayIndexOutOfBoundsException e ) {
cur = -1;
}
}
public final boolean hasNext() { return cur != -1; }
public void remove() {
throw new RuntimeException( "Not implemented." );
}
public final Object next() {
Numberable ret = set.array[cur];
cur++;
seekNext();
return ret;
}
}
public final int size() { return size; }
private Numberable[] array = new Numberable[8];
private BitVector bits;
private int size = 0;
private ArrayNumberer universe;
}