/* * FindBugs - Find Bugs in Java programs * Copyright (C) 2006, 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.npe2; import java.util.BitSet; import edu.umd.cs.findbugs.ba.vna.ValueNumber; /** * Set of values that is definitely known to be null. * * @author David Hovemeyer */ public class DefinitelyNullSet /* extends BitSet */{ private BitSet contents; private int numValueNumbers; public DefinitelyNullSet(int numValueNumbers) { this.contents = new BitSet(); this.numValueNumbers = numValueNumbers; } public NullnessValue getNulllessValue(ValueNumber valueNumber) { return getNullnessValue(valueNumber.getNumber()); } private NullnessValue getNullnessValue(int vn) { int flags = 0; int start = getStartIndex(vn); for (int i = 0; i < NullnessValue.FLAGS_MAX; i++) { if (contents.get(start + i)) { flags |= (1 << i); } } return NullnessValue.fromFlags(flags); } public void setNullnessValue(ValueNumber valueNumber, NullnessValue nullnessValue) { int flags = nullnessValue.getFlags(); int start = getStartIndex(valueNumber.getNumber()); for (int i = 0; i < NullnessValue.FLAGS_MAX; i++) { contents.set(start + i, (flags & (1 << i)) != 0); } } public void clear() { contents.clear(); } public void setTop() { contents.clear(); contents.set(lastUsedBit()); } public boolean isTop() { return contents.get(lastUsedBit()); } public void setBottom() { contents.clear(); contents.set(lastUsedBit() + 1); } public boolean isBottom() { return contents.get(lastUsedBit() + 1); } public boolean isValid() { return !(isTop() || isBottom()); } public void makeSameAs(DefinitelyNullSet other) { contents.clear(); contents.or(other.contents); } public void mergeWith(DefinitelyNullSet other) { if (this.isBottom() || other.isTop()) { return; } if (this.isTop() || other.isBottom()) { this.makeSameAs(other); return; } // Result is intersection of sets this.contents.and(other.contents); } public BitSet getAssignedNullLocationSet(ValueNumber vn) { throw new UnsupportedOperationException(); } public void addAssignedNullLocation(int valueNumber, int locationNumber) { // Base class does not maintain this information. } public void clearAssignNullLocations(int valueNumber) { // Base class does not maintain this information. } private int getStartIndex(int vn) { return vn * (1 << NullnessValue.FLAGS_MAX); } private int lastUsedBit() { return numValueNumbers * NullnessValue.FLAGS_MAX; } private int topBit() { return lastUsedBit(); } private int bottomBit() { return lastUsedBit() + 1; } /* * (non-Javadoc) * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return contents.hashCode(); } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj == null || obj.getClass() != this.getClass()) { return false; } DefinitelyNullSet other = (DefinitelyNullSet) obj; return this.contents.equals(other.contents); } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { if (isTop()) { return "[TOP]"; } else if (isBottom()) { return "[BOTTOM]"; } else { StringBuilder buf = new StringBuilder(); boolean first = true; buf.append("{"); for (int i = 0; i < numValueNumbers; i++) { NullnessValue val = getNullnessValue(i); if (val.isDefinitelyNull() || val.isDefinitelyNotNull()) { if (first) { first = false; } else { buf.append(", "); } buf.append(i); buf.append("->"); buf.append(val.toString()); } } buf.append("}"); return buf.toString(); } } }