/*
* Bytecode Analysis Framework
* Copyright (C) 2005, University of Maryland
*
* 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 edu.umd.cs.findbugs.ba.interproc;
import java.util.BitSet;
import java.util.Iterator;
/**
* Method property recording which parameters are have some property
* (originally, which were required to be nonnull, now made more generic)
*
* @author David Hovemeyer
*/
public class ParameterProperty {
/**
* Maximum number of parameters that can be represented by a
* ParameterProperty.
*/
public static final int MAX_PARAMS = 32;
private int bits;
/**
* Constructor. Parameters are all assumed not to be non-null.
*/
public ParameterProperty() {
this.bits = 0;
}
/**
* Constructor. Parameters are all assumed not to be non-null.
*/
public ParameterProperty(int bits) {
this.bits = bits;
}
/**
* Get the non-null param bitset.
*
* @return the non-null param bitset
*/
public int getParamsWithProperty() {
return bits;
}
public Iterable<Integer> iterable() {
return new Iterable<Integer>() {
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
int nextInt = 0;
{
advanceNextInt();
}
private void advanceNextInt() {
while (!hasProperty(nextInt) && nextInt < 32)
nextInt++;
if (nextInt >= 32)
nextInt = -1;
}
public boolean hasNext() {
return nextInt >= 0;
}
public Integer next() {
int result = nextInt;
nextInt++;
advanceNextInt();
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}
/**
* Set the non-null param bitset.
*
* @param nonNullParamSet
* the non-null param bitset
*/
public void setParamsWithProperty(int nonNullParamSet) {
this.bits = nonNullParamSet;
}
/**
* Set the non-null param set from given BitSet.
*
* @param nonNullSet
* BitSet indicating which parameters are non-null
*/
public void setParamsWithProperty(BitSet nonNullSet) {
for (int i = 0; i < 32; ++i) {
setParamWithProperty(i, nonNullSet.get(i));
}
}
/**
* Set whether or not a parameter might be non-null.
*
* @param param
* the parameter index
* @param hasProperty
* true if the parameter might be non-null, false otherwise
*/
public void setParamWithProperty(int param, boolean hasProperty) {
if (param < 0 || param > 31)
return;
if (hasProperty) {
bits |= (1 << param);
} else {
bits &= ~(1 << param);
}
}
/**
* Return whether or not a parameter might be non-null.
*
* @param param
* the parameter index
* @return true if the parameter might be non-null, false otherwise
*/
public boolean hasProperty(int param) {
if (param < 0 || param > 31)
return false;
else
return (bits & (1 << param)) != 0;
}
/**
* Given a bitset of null arguments passed to the method represented by this
* property, return a bitset indicating which null arguments correspond to
* an non-null param.
*
* @param nullArgSet
* bitset of null arguments
* @return bitset intersecting null arguments and non-null params
*/
public BitSet getMatchingParameters(BitSet nullArgSet) {
BitSet result = new BitSet();
for (int i = 0; i < 32; ++i) {
result.set(i, nullArgSet.get(i) && hasProperty(i));
}
return result;
}
public BitSet getAsBitSet() {
BitSet result = new BitSet();
if (isEmpty())
return result;
for (int i = 0; i < 32; ++i) {
result.set(i, hasProperty(i));
}
return result;
}
/**
* Return whether or not the set of non-null parameters is empty.
*
* @return true if the set is empty, false if it contains at least one
* parameter
*/
public boolean isEmpty() {
return bits == 0;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append('{');
for (int i = 0; i < 32; ++i) {
if (hasProperty(i)) {
if (buf.length() > 1)
buf.append(',');
buf.append(i);
}
}
buf.append('}');
return buf.toString();
}
/**
* Intersect this set with the given set. Useful for summarizing the
* properties of multiple methods.
*
* @param targetDerefParamSet
* another set
*/
public void intersectWith(ParameterProperty targetDerefParamSet) {
bits &= targetDerefParamSet.bits;
}
/**
* Make this object the same as the given one.
*
* @param other
* another ParameterNullnessProperty
*/
public void copyFrom(ParameterProperty other) {
this.bits = other.bits;
}
}