qilin.core.sets.DoublePointsToSet Maven / Gradle / Ivy
/* Qilin - a Java Pointer Analysis Framework
* Copyright (C) 2021-2030 Qilin developers
*
* This program 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 3.0 of the
* License, or (at your option) any later version.
*
* This program 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
*/
package qilin.core.sets;
import java.util.Iterator;
/**
* Implementation of points-to set that holds two sets: one for new elements that have not yet been
* propagated, and the other for elements that have already been propagated.
*
* @author Ondrej Lhotak
*/
public class DoublePointsToSet extends PointsToSetInternal {
protected HybridPointsToSet newSet;
protected HybridPointsToSet oldSet;
public DoublePointsToSet() {
newSet = new HybridPointsToSet();
oldSet = new HybridPointsToSet();
}
/** Returns true if this set contains no run-time objects. */
@Override
public boolean isEmpty() {
return oldSet.isEmpty() && newSet.isEmpty();
}
/** Returns true if this set shares some objects with other. */
public boolean hasNonEmptyIntersection(PointsToSetInternal other) {
return oldSet.hasNonEmptyIntersection(other) || newSet.hasNonEmptyIntersection(other);
}
@Override
public int size() {
return oldSet.size() + newSet.size();
}
private class DoublePTSIterator implements Iterator {
private final Iterator oldIt = oldSet.iterator();
private final Iterator newIt = newSet.iterator();
@Override
public boolean hasNext() {
return oldIt.hasNext() || newIt.hasNext();
}
@Override
public Integer next() {
if (oldIt.hasNext()) {
return oldIt.next();
} else {
return newIt.next();
}
}
}
public Iterator iterator() {
return new DoublePTSIterator();
}
/*
* Empty this set.
* */
@Override
public void clear() {
oldSet.clear();
newSet.clear();
}
/** Adds contents of other into this set, returns true if this set changed. */
public boolean addAll(PointsToSetInternal other, PointsToSetInternal exclude) {
if (exclude != null) {
throw new RuntimeException("exclude set must be null.");
}
return newSet.addAll(other, oldSet);
}
/** Calls v's visit method on all nodes in this set. */
@Override
public boolean forall(P2SetVisitor v) {
oldSet.forall(v);
newSet.forall(v);
return v.getReturnValue();
}
/** Adds n to this set, returns true if idx was not already in this set. */
public boolean add(int idx) {
if (oldSet.contains(idx)) {
return false;
}
return newSet.add(idx);
}
/** Returns set of nodes already present before last call to flushNew. */
public HybridPointsToSet getOldSet() {
return oldSet;
}
/** Returns set of newly-added nodes since last call to flushNew. */
public HybridPointsToSet getNewSet() {
return newSet;
}
public HybridPointsToSet getNewSetCopy() {
HybridPointsToSet newCopy = new HybridPointsToSet();
newCopy.addAll(newSet, null);
return newCopy;
}
/** Sets all newly-added nodes to old nodes. */
public void flushNew() {
oldSet.addAll(newSet, null);
newSet = new HybridPointsToSet();
}
/** Returns true iff the set contains idx. */
@Override
public boolean contains(int idx) {
return oldSet.contains(idx) || newSet.contains(idx);
}
}