/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.intset;
import java.util.Set;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.debug.Assertions;
/**
* This class wraps two concrete {@link MutableIntSet}s behind the standard interface, carrying out all operations on both of them
* and performing consistency checks at every step. The purpose of this is debugging bitset implementations.
*/
class DebuggingMutableIntSet implements MutableIntSet {
final MutableIntSet primaryImpl;
final MutableIntSet secondaryImpl;
DebuggingMutableIntSet(MutableIntSet p, MutableIntSet s) {
primaryImpl = p;
secondaryImpl = s;
}
private void assertEquiv() {
assert primaryImpl.sameValue(secondaryImpl);
}
/*
* @see com.ibm.wala.util.intset.MutableIntSet#clear()
*/
@Override
public void clear() {
primaryImpl.clear();
secondaryImpl.clear();
}
/**
* @return true iff this set contains integer i
*/
@Override
public boolean contains(int i) {
assert primaryImpl.contains(i) == secondaryImpl.contains(i);
return primaryImpl.contains(i);
}
/**
*/
@Override
public boolean isEmpty() {
if (primaryImpl.isEmpty() != secondaryImpl.isEmpty()) {
System.err.println(primaryImpl + ".isEmpty() = " + primaryImpl.isEmpty() + " and " + secondaryImpl + ".isEmpty() = "
+ secondaryImpl.isEmpty());
Assertions.UNREACHABLE();
}
return primaryImpl.isEmpty();
}
/**
*/
@Override
public int size() {
if (primaryImpl.size() != secondaryImpl.size()) {
assert primaryImpl.size() == secondaryImpl.size() : "size " + primaryImpl.size() + " of " + primaryImpl
+ " differs from " + "size " + secondaryImpl.size() + " of " + secondaryImpl;
}
return primaryImpl.size();
}
@Override
public int max() {
assert primaryImpl.max() == secondaryImpl.max();
return primaryImpl.max();
}
/**
* Add an integer value to this set.
*
* @return true iff the value of this changes.
*/
@Override
public boolean add(int i) {
boolean pr = primaryImpl.add(i);
boolean sr = secondaryImpl.add(i);
if (pr != sr) {
assert pr == sr : "adding " + i + " to " + primaryImpl + " returns " + pr + ", but adding " + i + " to "
+ secondaryImpl + " returns " + sr;
}
return pr;
}
/**
* Remove an integer from this set.
*/
@Override
public boolean remove(int i) {
boolean result = primaryImpl.remove(i);
secondaryImpl.remove(i);
assertEquiv();
return result;
}
/**
* @return true iff this set contains integer i
*/
@Override
public boolean containsAny(IntSet set) {
if (set instanceof DebuggingMutableIntSet) {
DebuggingMutableIntSet db = (DebuggingMutableIntSet) set;
boolean ppr = primaryImpl.containsAny(db.primaryImpl);
boolean ssr = secondaryImpl.containsAny(db.secondaryImpl);
if (ppr != ssr) {
assert ppr == ssr : "containsAny " + this + " " + set + " " + ppr + " " + ssr;
}
return ppr;
} else {
Assertions.UNREACHABLE();
return false;
}
}
/**
* This implementation must not despoil the original value of "this"
*
* @return a new IntSet which is the intersection of this and that
*/
@Override
public IntSet intersection(IntSet that) {
if (that instanceof DebuggingMutableIntSet) {
DebuggingMutableIntSet db = (DebuggingMutableIntSet) that;
IntSet ppr = primaryImpl.intersection(db.primaryImpl);
IntSet ssr = secondaryImpl.intersection(db.secondaryImpl);
assert ppr.sameValue(ssr);
return ppr;
} else {
Assertions.UNREACHABLE();
return null;
}
}
/*
* @see com.ibm.wala.util.intset.IntSet#union(com.ibm.wala.util.intset.IntSet)
*/
@Override
public IntSet union(IntSet that) {
MutableSparseIntSet temp = new MutableSparseIntSet();
temp.addAll(this);
temp.addAll(that);
return temp;
}
/**
* @return true iff <code>this</code> has the same value as <code>that</code>.
*/
@Override
public boolean sameValue(IntSet that) {
if (that instanceof DebuggingMutableIntSet) {
DebuggingMutableIntSet db = (DebuggingMutableIntSet) that;
boolean ppr = primaryImpl.sameValue(db.primaryImpl);
boolean ssr = secondaryImpl.sameValue(db.secondaryImpl);
assert ppr == ssr;
return ppr;
} else {
Assertions.UNREACHABLE();
return false;
}
}
/**
* @return true iff <code>this</code> is a subset of <code>that</code>.
*/
@Override
public boolean isSubset(IntSet that) {
if (that instanceof DebuggingMutableIntSet) {
DebuggingMutableIntSet db = (DebuggingMutableIntSet) that;
boolean ppr = primaryImpl.isSubset(db.primaryImpl);
boolean ssr = secondaryImpl.isSubset(db.secondaryImpl);
assert ppr == ssr;
return ppr;
} else {
Assertions.UNREACHABLE();
return false;
}
}
/**
* Set the value of this to be the same as the value of set
*/
@Override
public void copySet(IntSet set) {
if (set instanceof DebuggingMutableIntSet) {
DebuggingMutableIntSet db = (DebuggingMutableIntSet) set;
primaryImpl.copySet(db.primaryImpl);
secondaryImpl.copySet(db.secondaryImpl);
assert primaryImpl.sameValue(secondaryImpl);
} else {
Assertions.UNREACHABLE();
}
}
/**
* Add all members of set to this.
*
* @return true iff the value of this changes.
*/
@Override
public boolean addAll(IntSet set) {
if (set instanceof DebuggingMutableIntSet) {
DebuggingMutableIntSet db = (DebuggingMutableIntSet) set;
int ps = primaryImpl.size();
int ss = secondaryImpl.size();
boolean ppr = primaryImpl.addAll(db.primaryImpl);
boolean ssr = secondaryImpl.addAll(db.secondaryImpl);
if (ppr != ssr) {
System.err.println("ppr was " + ppr + " (should be " + (ps != primaryImpl.size()) + ") but ssr was " + ssr + " (should be "
+ (ss != secondaryImpl.size()) + ")");
System.err.println("adding " + set + " to " + this + " failed");
Assertions.UNREACHABLE();
}
return ppr;
} else {
Assertions.UNREACHABLE();
return false;
}
}
/**
* Intersect this with another set.
*/
@Override
public void intersectWith(IntSet set) {
if (set instanceof DebuggingMutableIntSet) {
DebuggingMutableIntSet db = (DebuggingMutableIntSet) set;
primaryImpl.intersectWith(db.primaryImpl);
secondaryImpl.intersectWith(db.secondaryImpl);
if (!primaryImpl.sameValue(secondaryImpl))
assert false : this + " (" + primaryImpl.size() + ", " + secondaryImpl.size()
+ ") inconsistent after intersecting with " + set;
} else {
Assertions.UNREACHABLE();
}
}
/**
*/
@Override
public boolean addAllInIntersection(IntSet other, IntSet filter) {
if (other instanceof DebuggingMutableIntSet && filter instanceof DebuggingMutableIntSet) {
DebuggingMutableIntSet db = (DebuggingMutableIntSet) other;
DebuggingMutableIntSet df = (DebuggingMutableIntSet) filter;
boolean pr = primaryImpl.addAllInIntersection(db.primaryImpl, df.primaryImpl);
boolean sr = secondaryImpl.addAllInIntersection(db.secondaryImpl, df.secondaryImpl);
assert pr == sr;
return pr;
} else {
Assertions.UNREACHABLE();
return false;
}
}
/*
* @see com.ibm.wala.util.intset.IntSet#intIterator()
*/
@Override
public IntIterator intIterator() {
MutableSparseIntSet bits = MutableSparseIntSet.makeEmpty();
for (IntIterator pi = primaryImpl.intIterator(); pi.hasNext();) {
int x = pi.next();
assert !bits.contains(x);
bits.add(x);
}
for (IntIterator si = secondaryImpl.intIterator(); si.hasNext();) {
int x = si.next();
assert bits.contains(x);
bits.remove(x);
}
assert bits.isEmpty();
return primaryImpl.intIterator();
}
/**
* Invoke an action on each element of the Set
*/
@Override
public void foreach(IntSetAction action) {
final Set<Integer> bits = HashSetFactory.make();
primaryImpl.foreach(new IntSetAction() {
@Override
public void act(int x) {
assert !bits.contains(new Integer(x));
bits.add(new Integer(x));
}
});
secondaryImpl.foreach(new IntSetAction() {
@Override
public void act(int x) {
assert bits.contains(new Integer(x));
bits.remove(new Integer(x));
}
});
assert bits.isEmpty();
primaryImpl.foreach(action);
}
/**
* Invoke an action on each element of the Set, excluding elements of Set X
*/
@Override
public void foreachExcluding(IntSet X, IntSetAction action) {
final Set<Integer> bits = HashSetFactory.make();
primaryImpl.foreachExcluding(X, new IntSetAction() {
@Override
public void act(int x) {
assert !bits.contains(new Integer(x));
bits.add(new Integer(x));
}
});
secondaryImpl.foreachExcluding(X, new IntSetAction() {
@Override
public void act(int x) {
assert bits.contains(new Integer(x));
bits.remove(new Integer(x));
}
});
assert bits.isEmpty();
primaryImpl.foreachExcluding(X, action);
}
@Override
public String toString() {
return "[[P " + primaryImpl.toString() + ", S " + secondaryImpl.toString() + " ]]";
}
}