From 473210a961853103e0155332b2df87559cc63f08 Mon Sep 17 00:00:00 2001 From: Dalibor Topic Date: Wed, 8 Aug 2007 08:00:32 +0000 Subject: re PR classpath/32844 (EnumSet causes code to be miscompiled) 2007-07-31 Dalibor Topic PR 32844 * java/util/EnumSet.java: Made class abstract per API spec. (size, iterator, add, addAll, clear, contains, containsAll, remove, removeAll, retainAll) Moved into an anonymous inner class in of(T). (allOf, noneOf, copyOf, of, range) Made more implementation independent. (of(T)) return an instance of an anonymous class implementing EmptySet. From-SVN: r127291 --- libjava/classpath/java/util/EnumSet.java | 389 +++++++++++++++---------------- 1 file changed, 188 insertions(+), 201 deletions(-) (limited to 'libjava/classpath/java/util') diff --git a/libjava/classpath/java/util/EnumSet.java b/libjava/classpath/java/util/EnumSet.java index 44ae370..543df0c 100644 --- a/libjava/classpath/java/util/EnumSet.java +++ b/libjava/classpath/java/util/EnumSet.java @@ -43,16 +43,20 @@ import java.io.Serializable; /** * @author Tom Tromey (tromey@redhat.com) * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @author Dalibor Topic (robilad@kaffe.org) * @since 1.5 */ -// FIXME: serialization is special. -public class EnumSet> +// FIXME: serialization is special, uses SerializationProxy. +// of(E e) is the 'bottom' method that creates a real EnumSet. +public abstract class EnumSet> extends AbstractSet implements Cloneable, Serializable { private static final long serialVersionUID = 4782406773684236311L; + // These fields could go into the anonymous inner class in of(E), + // complementOf would need to be refactored then, though. BitSet store; int cardinality; Class enumClass; @@ -78,276 +82,246 @@ public class EnumSet> return r; } - public int size() + public static > EnumSet allOf(Class eltType) { - return cardinality; + // create an EnumSet from the list of values of the type + return copyOf(Arrays.asList(eltType.getEnumConstants())); } - public Iterator iterator() + public static > EnumSet noneOf(Class eltType) { - return new Iterator() - { - int next = -1; - int count = 0; + return complementOf(allOf(eltType)); + } - public boolean hasNext() - { - return count < cardinality; - } + public static > EnumSet copyOf(EnumSet other) + { + return other.clone(); + } - public T next() - { - next = store.nextSetBit(next + 1); - ++count; - return enumClass.getEnumConstants()[next]; - } + public static > EnumSet copyOf(Collection other) + { + if (other instanceof EnumSet) + return copyOf((EnumSet) other); + if (other.isEmpty()) + throw new IllegalArgumentException("Collection is empty"); - public void remove() + EnumSet r = null; + + for (T val : other) { - if (! store.get(next)) - { - store.clear(next); - --cardinality; - } + if (r == null) + r = of(val); + else + r.add(val); } - }; + + return r; } - public boolean add(T val) + public static > EnumSet complementOf(EnumSet other) { - if (store.get(val.ordinal())) - return false; - store.set(val.ordinal()); - ++cardinality; - return true; + EnumSet r = other.clone(); + r.store.flip(0, r.store.size()); + r.cardinality = r.store.size() - other.cardinality; + return r; } - public boolean addAll(Collection c) + public static > EnumSet of(T first) { - boolean result = false; - if (c instanceof EnumSet) + EnumSet r = new EnumSet() + { + public boolean add(T val) + { + if (store.get(val.ordinal())) + return false; + + store.set(val.ordinal()); + ++cardinality; + return true; + } + + public boolean addAll(Collection c) { - EnumSet other = (EnumSet) c; - if (enumClass == other.enumClass) + boolean result = false; + if (c instanceof EnumSet) + { + EnumSet other = (EnumSet) c; + if (enumClass == other.enumClass) { store.or(other.store); int save = cardinality; cardinality = store.cardinality(); result = save != cardinality; } - } - else - { - for (T val : c) + } + else + { + for (T val : c) { if (add (val)) - result = true; + result = true; } + } + return result; } - return result; - } - public void clear() - { - store.clear(); - cardinality = 0; - } - - public boolean contains(Object o) - { - if (! (o instanceof Enum)) - return false; - Enum e = (Enum) o; - if (e.getDeclaringClass() != enumClass) - return false; - return store.get(e.ordinal()); - } - - public boolean containsAll(Collection c) - { - if (c instanceof EnumSet) + public void clear() { - EnumSet other = (EnumSet) c; - if (enumClass == other.enumClass) - return store.containsAll(other.store); - return false; + store.clear(); + cardinality = 0; } - return super.containsAll(c); - } - - public boolean remove(Object o) - { - if (! (o instanceof Enum)) - return false; - Enum e = (Enum) o; - if (e.getDeclaringClass() != enumClass) - return false; - store.clear(e.ordinal()); - --cardinality; - return true; - } - public boolean removeAll(Collection c) - { - if (c instanceof EnumSet) + public boolean contains(Object o) { - EnumSet other = (EnumSet) c; - if (enumClass != other.enumClass) + if (! (o instanceof Enum)) + return false; + + Enum e = (Enum) o; + if (e.getDeclaringClass() != enumClass) return false; - store.andNot(other.store); - int save = cardinality; - cardinality = store.cardinality(); - return save != cardinality; + + return store.get(e.ordinal()); } - return super.removeAll(c); - } - public boolean retainAll(Collection c) - { - if (c instanceof EnumSet) + public boolean containsAll(Collection c) { - EnumSet other = (EnumSet) c; - if (enumClass != other.enumClass) + if (c instanceof EnumSet) + { + EnumSet other = (EnumSet) c; + if (enumClass == other.enumClass) + return store.containsAll(other.store); + return false; - store.and(other.store); - int save = cardinality; - cardinality = store.cardinality(); - return save != cardinality; + } + return super.containsAll(c); } - return super.retainAll(c); - } - public static > EnumSet allOf(Class eltType) - { - EnumSet r = new EnumSet(); - r.store = new BitSet(eltType.getEnumConstants().length); - r.store.set(0, r.store.size()); - r.cardinality = r.store.size(); - r.enumClass = eltType; - return r; - } + public Iterator iterator() + { + return new Iterator() + { + int next = -1; + int count = 0; - public static > EnumSet noneOf(Class eltType) - { - EnumSet r = new EnumSet(); - r.store = new BitSet(eltType.getEnumConstants().length); - r.enumClass = eltType; - return r; - } + public boolean hasNext() + { + return count < cardinality; + } - public static > EnumSet copyOf(EnumSet other) - { - // We can't just use `other.clone' since we don't want to make a - // subclass. - EnumSet r = new EnumSet(); - r.store = (BitSet) other.store.clone(); - r.cardinality = other.cardinality; - r.enumClass = other.enumClass; - return r; - } + public T next() + { + next = store.nextSetBit(next + 1); + ++count; + return enumClass.getEnumConstants()[next]; + } - public static > EnumSet copyOf(Collection other) - { - if (other instanceof EnumSet) - return copyOf((EnumSet) other); - EnumSet r = new EnumSet(); - for (T val : other) - { - if (r.store == null) + public void remove() { - r.enumClass = val.getDeclaringClass(); - r.store = new BitSet(r.enumClass.getEnumConstants().length); + if (! store.get(next)) + { + store.clear(next); + --cardinality; + } } - r.store.set(val.ordinal()); + }; } - // The collection must contain at least one element. - if (r.store == null) - throw new IllegalArgumentException(); - r.cardinality = r.store.cardinality(); - return r; - } - public static > EnumSet complementOf(EnumSet other) - { - EnumSet r = new EnumSet(); - r.store = (BitSet) other.store.clone(); - r.store.flip(0, r.store.size()); - r.cardinality = r.store.size() - other.cardinality; - r.enumClass = other.enumClass; - return r; - } + public boolean remove(Object o) + { + if (! (o instanceof Enum)) + return false; - public static > EnumSet of(T first) - { - EnumSet r = new EnumSet(); + Enum e = (Enum) o; + if (e.getDeclaringClass() != enumClass) + return false; + + store.clear(e.ordinal()); + --cardinality; + return true; + } + + public boolean removeAll(Collection c) + { + if (c instanceof EnumSet) + { + EnumSet other = (EnumSet) c; + if (enumClass != other.enumClass) + return false; + + store.andNot(other.store); + int save = cardinality; + cardinality = store.cardinality(); + return save != cardinality; + } + return super.removeAll(c); + } + + public boolean retainAll(Collection c) + { + if (c instanceof EnumSet) + { + EnumSet other = (EnumSet) c; + if (enumClass != other.enumClass) + return false; + + store.and(other.store); + int save = cardinality; + cardinality = store.cardinality(); + return save != cardinality; + } + return super.retainAll(c); + } + + public int size() + { + return cardinality; + } + }; + + // initialize the class r.enumClass = first.getDeclaringClass(); r.store = new BitSet(r.enumClass.getEnumConstants().length); - r.store.set(first.ordinal()); - r.cardinality = 1; + + r.add(first); return r; } public static > EnumSet of(T first, T second) { - EnumSet r = new EnumSet(); - r.enumClass = first.getDeclaringClass(); - r.store = new BitSet(r.enumClass.getEnumConstants().length); - r.store.set(first.ordinal()); - r.store.set(second.ordinal()); - r.cardinality = r.store.cardinality(); + EnumSet r = of(first); + r.add(second); return r; } public static > EnumSet of(T first, T second, T third) { - EnumSet r = new EnumSet(); - r.enumClass = first.getDeclaringClass(); - r.store = new BitSet(r.enumClass.getEnumConstants().length); - r.store.set(first.ordinal()); - r.store.set(second.ordinal()); - r.store.set(third.ordinal()); - r.cardinality = r.store.cardinality(); + EnumSet r = of(first, second); + r.add(third); return r; } public static > EnumSet of(T first, T second, T third, T fourth) { - EnumSet r = new EnumSet(); - r.enumClass = first.getDeclaringClass(); - r.store = new BitSet(r.enumClass.getEnumConstants().length); - r.store.set(first.ordinal()); - r.store.set(second.ordinal()); - r.store.set(third.ordinal()); - r.store.set(fourth.ordinal()); - r.cardinality = r.store.cardinality(); + EnumSet r = of(first, second, third); + r.add(fourth); return r; } public static > EnumSet of(T first, T second, T third, T fourth, T fifth) { - EnumSet r = new EnumSet(); - r.enumClass = first.getDeclaringClass(); - r.store = new BitSet(r.enumClass.getEnumConstants().length); - r.store.set(first.ordinal()); - r.store.set(second.ordinal()); - r.store.set(third.ordinal()); - r.store.set(fourth.ordinal()); - r.store.set(fifth.ordinal()); - r.cardinality = r.store.cardinality(); + EnumSet r = of(first, second, third, fourth); + r.add(fifth); return r; } public static > EnumSet of(T first, T... rest) { - EnumSet r = new EnumSet(); - r.enumClass = first.getDeclaringClass(); - r.store = new BitSet(r.enumClass.getEnumConstants().length); - r.store.set(first.ordinal()); + EnumSet r = noneOf(first.getDeclaringClass()); + r.add(first); for (T val : rest) - r.store.set(val.ordinal()); - r.cardinality = r.store.cardinality(); + r.add(val); return r; } @@ -355,11 +329,24 @@ public class EnumSet> { if (from.compareTo(to) > 0) throw new IllegalArgumentException(); - EnumSet r = new EnumSet(); - r.store = new BitSet(from.getDeclaringClass().getEnumConstants().length); - r.store.set(from.ordinal(), to.ordinal() + 1); - r.enumClass = from.getDeclaringClass(); - r.cardinality = to.ordinal() - from.ordinal() + 1; + Class type = from.getDeclaringClass(); + EnumSet r = noneOf(type); + + T[] values = type.getEnumConstants(); + // skip over values until start of range is found + int i = 0; + while (from != values[i]) + i++; + + // add values until end of range is found + while (to != values[i]) { + r.add(values[i]); + i++; + } + + // add end of range + r.add(to); + return r; } } -- cgit v1.1