/* * SetOfVariables.java - This file is part of the Jakstab project. * Copyright 2007-2015 Johannes Kinder <jk@jakstab.org> * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code 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 Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, see <http://www.gnu.org/licenses/>. */ package org.jakstab.rtl.expressions; import java.io.Serializable; import java.util.*; import org.jakstab.util.Logger; /** * A specialized set for variables, uses bitvectors to speed up set operations. * * @author Johannes Kinder */ public class SetOfVariables extends AbstractSet<RTLVariable> implements Set<RTLVariable>, Serializable { public static final SetOfVariables EMPTY_SET = new SetOfVariables(); @SuppressWarnings("unused") private final static Logger logger = Logger.getLogger(SetOfVariables.class); private static final long serialVersionUID = -5505393011046912608L; private final BitSet bitSet; public SetOfVariables() { bitSet = new BitSet(ExpressionFactory.DEFAULT_VARIABLE_COUNT); } public SetOfVariables(Collection<RTLVariable> collection) { this(); addAll(collection); } public SetOfVariables(SetOfVariables proto) { this.bitSet = (BitSet)proto.bitSet.clone(); } @Override public final boolean add(RTLVariable e) { if (bitSet.get(e.getIndex())) return false; bitSet.set(e.getIndex()); return true; } @Override public final boolean addAll(Collection<? extends RTLVariable> c) { boolean changed = false; for(RTLVariable element : c) { changed |= add(element); } return changed; } /** * Adds all elements of an array to this Set. * * @param array the array to take the elements from * @return true if this set was changed, false otherwise */ public final boolean addAll(RTLVariable[] array) { if (array == null) return false; boolean changed = false; for (int i=0; i<array.length; i++) changed |= this.add(array[i]); return changed; } public final void addAll(SetOfVariables vset) { bitSet.or(vset.bitSet); } @Override public final void clear() { bitSet.clear(); } @Override public final boolean contains(Object o) { if (o instanceof RTLVariable) { return bitSet.get(((RTLVariable)o).getIndex()); } else return false; } /* * @see java.util.AbstractCollection#containsAll(java.util.Collection) */ @Override public final boolean containsAll(Collection<?> c) { if (c instanceof SetOfVariables) { SetOfVariables vset = (SetOfVariables)c; BitSet bitSetCopy = (BitSet)bitSet.clone(); bitSetCopy.and(vset.bitSet); return bitSetCopy.equals(bitSet); } else { return super.containsAll(c); } } @Override public boolean equals(Object o) { if (o instanceof SetOfVariables) return equals((SetOfVariables)o); else return super.equals(o); } public boolean equals(SetOfVariables vset) { return vset != null && bitSet.equals(vset.bitSet); } @Override public int hashCode() { return bitSet.hashCode(); } @Override public final boolean isEmpty() { return bitSet.isEmpty(); } @Override public final Iterator<RTLVariable> iterator() { return new Iterator<RTLVariable>() { private int index = 0; @Override public boolean hasNext() { return (bitSet.nextSetBit(index) >= 0); } @Override public RTLVariable next() { int nextSet = bitSet.nextSetBit(index); index = nextSet + 1; return ExpressionFactory.getVariable(nextSet); } @Override public void remove() { bitSet.clear(index - 1); } }; } @Override public final boolean remove(Object o) { if (o instanceof RTLVariable) { RTLVariable var = (RTLVariable)o; if (!bitSet.get(var.getIndex())) return false; else { bitSet.clear(var.getIndex()); return true; } } else return false; } @Override public final boolean removeAll(Collection<?> c) { if (c instanceof SetOfVariables) { SetOfVariables vset = (SetOfVariables)c; if (bitSet.intersects(vset.bitSet)) { bitSet.andNot(vset.bitSet); return true; } else return false; } else { return super.removeAll(c); } } public final void removeAll(SetOfVariables vset) { bitSet.andNot(vset.bitSet); } /* * @see java.util.AbstractCollection#retainAll(java.util.Collection) */ @Override public final boolean retainAll(Collection<?> c) { if (c instanceof SetOfVariables) { SetOfVariables vset = (SetOfVariables)c; if (!bitSet.equals(vset.bitSet)) { bitSet.and(vset.bitSet); return true; } else return false; } else { return super.retainAll(c); } } public final void retainAll(SetOfVariables vset) { bitSet.and(vset.bitSet); } @Override public final int size() { return bitSet.cardinality(); } }