soot.jimple.spark.sets.SortedArraySet Maven / Gradle / Ivy
package soot.jimple.spark.sets;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 2002 Ondrej Lhotak
* %%
* 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 2.1 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
* .
* #L%
*/
import soot.Type;
import soot.jimple.spark.pag.Node;
import soot.jimple.spark.pag.PAG;
import soot.util.BitVector;
/**
* Implementation of points-to set using a sorted array.
*
* @author Ondrej Lhotak
*/
public final class SortedArraySet extends PointsToSetInternal {
public SortedArraySet(Type type, PAG pag) {
super(type);
this.pag = pag;
}
/** Returns true if this set contains no run-time objects. */
public final boolean isEmpty() {
return size == 0;
}
/**
* Adds contents of other into this set, returns true if this set changed.
*/
public final boolean addAll(final PointsToSetInternal other, final PointsToSetInternal exclude) {
boolean ret = false;
BitVector typeMask = (pag.getTypeManager()).get(type);
if (other instanceof SortedArraySet) {
SortedArraySet o = (SortedArraySet) other;
Node[] mya = nodes;
Node[] oa = o.nodes;
int osize = o.size;
Node[] newa = new Node[size + osize];
int myi = 0;
int oi = 0;
int newi = 0;
for (;;) {
if (myi < size) {
if (oi < osize) {
int myhc = mya[myi].getNumber();
int ohc = oa[oi].getNumber();
if (myhc < ohc) {
newa[newi++] = mya[myi++];
} else if (myhc > ohc) {
if ((type == null || typeMask == null || typeMask.get(ohc))
&& (exclude == null || !exclude.contains(oa[oi]))) {
newa[newi++] = oa[oi];
ret = true;
}
oi++;
} else {
newa[newi++] = mya[myi++];
oi++;
}
} else { // oi >= osize
newa[newi++] = mya[myi++];
}
} else { // myi >= size
if (oi < osize) {
int ohc = oa[oi].getNumber();
if ((type == null || typeMask == null || typeMask.get(ohc)) && (exclude == null || !exclude.contains(oa[oi]))) {
newa[newi++] = oa[oi];
ret = true;
}
oi++;
} else {
break;
}
}
}
nodes = newa;
size = newi;
return ret;
}
return super.addAll(other, exclude);
}
/** Calls v's visit method on all nodes in this set. */
public final boolean forall(P2SetVisitor v) {
for (int i = 0; i < size; i++) {
v.visit(nodes[i]);
}
return v.getReturnValue();
}
/** Adds n to this set, returns true if n was not already in this set. */
public final boolean add(Node n) {
if (pag.getTypeManager().castNeverFails(n.getType(), type)) {
if (contains(n)) {
return false;
}
int left = 0;
int right = size;
int mid;
int hc = n.getNumber();
while (left < right) {
mid = (left + right) / 2;
int midhc = nodes[mid].getNumber();
if (midhc < hc) {
left = mid + 1;
} else if (midhc > hc) {
right = mid;
} else {
break;
}
}
if (nodes == null) {
nodes = new Node[size + 4];
} else if (size == nodes.length) {
Node[] newNodes = new Node[size + 4];
System.arraycopy(nodes, 0, newNodes, 0, nodes.length);
nodes = newNodes;
}
System.arraycopy(nodes, left, nodes, left + 1, size - left);
nodes[left] = n;
size++;
return true;
}
return false;
}
/** Returns true iff the set contains n. */
public final boolean contains(Node n) {
int left = 0;
int right = size;
int hc = n.getNumber();
while (left < right) {
int mid = (left + right) / 2;
int midhc = nodes[mid].getNumber();
if (midhc < hc) {
left = mid + 1;
} else if (midhc > hc) {
right = mid;
} else {
return true;
}
}
return false;
}
public final static P2SetFactory getFactory() {
return new P2SetFactory() {
public final PointsToSetInternal newSet(Type type, PAG pag) {
return new SortedArraySet(type, pag);
}
};
}
/* End of public methods. */
/* End of package methods. */
private Node[] nodes = null;
private int size = 0;
private PAG pag = null;
}