[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[cp-patches] [generics] Patch: FYI: EnumSet and EnumMap
From: |
Tom Tromey |
Subject: |
[cp-patches] [generics] Patch: FYI: EnumSet and EnumMap |
Date: |
03 Sep 2004 14:40:14 -0600 |
I'm checking this in on the generics branch.
This is an implementation of EnumSet and EnumMap.
Not compiled or tested or documented, that stuff comes later.
Tom
Index: ChangeLog
from Tom Tromey <address@hidden>
* java/util/EnumMap.java: New file.
* java/util/EnumSet.java: New file.
* java/util/BitSet.java (containsAll): New method.
Index: java/util/BitSet.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/util/BitSet.java,v
retrieving revision 1.13
diff -u -r1.13 BitSet.java
--- java/util/BitSet.java 30 Apr 2002 14:03:11 -0000 1.13
+++ java/util/BitSet.java 3 Sep 2004 20:53:32 -0000
@@ -1,5 +1,5 @@
/* BitSet.java -- A vector of bits.
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -735,4 +735,15 @@
bits = nd;
}
}
+
+ // This is used by EnumSet for efficiency.
+ final boolean containsAll(BitSet other)
+ {
+ for (int i = bs.bits.length - 1; i >= 0; i--)
+ {
+ if ((bits[i] & bs.bits[i]) != bs.bits[i])
+ return false;
+ }
+ return true;
+ }
}
Index: java/util/EnumMap.java
===================================================================
RCS file: java/util/EnumMap.java
diff -N java/util/EnumMap.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ java/util/EnumMap.java 3 Sep 2004 20:53:33 -0000
@@ -0,0 +1,385 @@
+/* EnumMap.java - Map where keys are enum constants
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** @since 1.5 */
+public class EnumMap<K extends Enum<K>, V>
+ extends AbstractMap<K, V>
+ implements Cloneable, Serializable
+{
+ V[] store;
+ int cardinality;
+ Class<K> enumClass;
+
+ /**
+ * The cache for address@hidden #entrySet()}.
+ */
+ transient Set<Map.Entry<K, V>> entries;
+
+ static final Object emptySlot = new Object();
+
+ public EnumMap(Class<K> keyType)
+ {
+ store = new V[keyType.getEnumConstants().length];
+ Arrays.fill(store, emptySlot);
+ cardinality = 0;
+ enumClass = keyType;
+ }
+
+ public EnumMap(EnumMap<K, ? extends V> map)
+ {
+ store = (V[]) map.store.clone();
+ cardinality = map.cardinality;
+ enumClass = map.enumClass;
+ }
+
+ public EnumMap(Map<K, ? extends V> map)
+ {
+ if (map instanceof EnumMap<K, ? extends V>)
+ {
+ EnumMap<K, ? extends V> other = (EnumMap<K, ? extends V>) map;
+ store = (V[]) other.store.clone();
+ cardinality = other.cardinality;
+ enumClass = other.enumClass;
+ }
+ else
+ {
+ for (K key : map.keySet())
+ {
+ V value = map.get(key);
+ if (store == null)
+ {
+ enumClass = key.getDeclaringClass();
+ store = new V[enumClass.getEnumConstants().length];
+ }
+ int o = key.ordinal();
+ if (store[o] == emptySlot)
+ ++cardinality;
+ store[o] = value;
+ }
+ // There must be a single element.
+ if (store == null)
+ throw new IllegalArgumentException("no elements in map");
+ }
+ }
+
+ public int size()
+ {
+ return cardinality;
+ }
+
+ public boolean containsValue(Object value)
+ {
+ for (V i : store)
+ {
+ if (i != emptySlot && AbstractCollection.equals(i , value))
+ return true;
+ }
+ return false;
+ }
+
+ public boolean containsKey(Object key)
+ {
+ if (! (key instanceof Enum<K>))
+ return false;
+ Enum<K> e = (Enum<K>) key;
+ if (e.enumClass != enumClass)
+ return false;
+ return store[e.ordinal()] != emptySlot;
+ }
+
+ public V get(Object key)
+ {
+ if (! (key instanceof Enum<K>))
+ return null;
+ Enum<K> e = (Enum<K>) key;
+ if (e.enumClass != enumClass)
+ return null;
+ return store[e.ordinal()];
+ }
+
+ public V put(K key, V value)
+ {
+ int o = key.ordinal();
+ V result;
+ if (store[o] == emptySlot)
+ {
+ result = null;
+ ++cardinality;
+ }
+ else
+ result = store[o];
+ store[o] = value;
+ return result;
+ }
+
+ public V remove(Object key)
+ {
+ if (! (key instanceof Enum<K>))
+ return null;
+ Enum<K> e = (Enum<K>) key;
+ if (e.enumClass != enumClass)
+ return null;
+ V result = store[e.ordinal()];
+ if (result == emptySlot)
+ result = null;
+ else
+ --cardinality;
+ store[e.ordinal()] = emptySlot;
+ return result;
+ }
+
+ public void putAll(Map<? extends K, ? extends V> map)
+ {
+ for (K key : map.keySet())
+ {
+ V value = map.get(key);
+
+ int o = key.ordinal();
+ if (store[o] == emptySlot)
+ ++cardinality;
+ store[o] = value;
+ }
+ }
+
+ public void clear()
+ {
+ Arrays.fill(store, emptySlot);
+ cardinality = 0;
+ }
+
+ public Set<K> keySet()
+ {
+ if (keys == null)
+ {
+ keys = new AbstractSet<K>()
+ {
+ public int size()
+ {
+ return cardinality;
+ }
+
+ public Iterator<K> iterator()
+ {
+ return new Iterator<K>()
+ {
+ int count = 0;
+ int index = -1;
+
+ public boolean hasNext()
+ {
+ return count < cardinality;
+ }
+
+ public K next()
+ {
+ ++count;
+ for (++index; store[index] == emptySlot; ++index)
+ ;
+ return enumClass.getEnumConstants()[index];
+ }
+
+ public void remove()
+ {
+ --cardinality;
+ store[index] = emptySlot;
+ }
+ };
+ }
+
+ public void clear()
+ {
+ EnumMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ return contains(o);
+ }
+
+ public boolean remove(Object o)
+ {
+ return EnumMap.this.remove(o);
+ }
+ };
+ }
+ return keys;
+ }
+
+ public Collection<V> values()
+ {
+ if (values == null)
+ {
+ values = new AbstractCollection<V>()
+ {
+ public int size()
+ {
+ return cardinality;
+ }
+
+ public Iterator<V> iterator()
+ {
+ return new Iterator<V>()
+ {
+ int count = 0;
+ int index = -1;
+
+ public boolean hasNext()
+ {
+ return count < cardinality;
+ }
+
+ public K next()
+ {
+ ++count;
+ for (++index; store[index] == emptySlot; ++index)
+ ;
+ return store[index];
+ }
+
+ public void remove()
+ {
+ --cardinality;
+ store[index] = emptySlot;
+ }
+ };
+ }
+
+ public void clear()
+ {
+ EnumMap.this.clear();
+ }
+ };
+ }
+ return values;
+ }
+
+ public Set<Map.Entry<K, V>> entrySet()
+ {
+ if (entries == null)
+ {
+ entries = new AbstractSet<Map.Entry<K, V>>()
+ {
+ public int size()
+ {
+ return cardinality;
+ }
+
+ public Iterator<Map.Entry<K, V>> iterator()
+ {
+ return new Iterator<Map.Entry<K, V>>()
+ {
+ int count = 0;
+ int index = -1;
+
+ public boolean hasNext()
+ {
+ return count < cardinality;
+ }
+
+ public K next()
+ {
+ ++count;
+ for (++index; store[index] == emptySlot; ++index)
+ ;
+ // FIXME: we could just return something that
+ // only knows the index. That would be cleaner.
+ return new AbstractMap.BasicMapEntry<K,
V>(enumClass.getEnumConstants()[index],
+ store[index])
+ {
+ public V setValue(K newVal)
+ {
+ value = newVal;
+ return put(key, newVal);
+ }
+ };
+ }
+
+ public void remove()
+ {
+ --cardinality;
+ store[index] = emptySlot;
+ }
+ };
+ }
+
+ public void clear()
+ {
+ EnumMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ if (! (o instanceof Map.Entry<K, V>))
+ return false;
+ Map.Entry<K, V> other = (Map.Entry<K, V>) o;
+ return (containsKey(other.getKey())
+ && AbstractCollection.equals(get(other.getKey()),
+ other.getValue()));
+ }
+
+ public boolean remove(Object o)
+ {
+ if (! (o instanceof Map.Entry<K, V>))
+ return false;
+ Map.Entry<K, V> other = (Map.Entry<K, V>) o;
+ return EnumMap.this.remove(other.getKey());
+ }
+ };
+ }
+ return entries;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof EnumMap<K, V>))
+ return false;
+ EnumMap<K, V> other = (EnumMap<K, V>) o;
+ if (other.enumClass != enumClass || other.cardinality != cardinality)
+ return false;
+ return Arrays.equals(store, other.store);
+ }
+
+ public EnumMap<K, V> clone()
+ {
+ EnumMap<K, V> r = (EnumMap<K, V>) super.clone();
+ r.store = (V[]) store.clone();
+ return r;
+ }
+}
Index: java/util/EnumSet.java
===================================================================
RCS file: java/util/EnumSet.java
diff -N java/util/EnumSet.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ java/util/EnumSet.java 3 Sep 2004 20:53:33 -0000
@@ -0,0 +1,346 @@
+/* EnumSet.java - Set of enum objects
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** @since 1.5 */
+// FIXME: serialization is special.
+public class EnumSet<T extends Enum<T>>
+ extends AbstractSet<T>
+ implements Cloneable, Serializable
+{
+ BitSet store;
+ int cardinality;
+ Class<T> enumClass;
+
+ EnumSet()
+ {
+ }
+
+ public EnumSet<T> clone()
+ {
+ EnumSet<T> r = super.clone();
+ r.store = store.clone();
+ return r;
+ }
+
+ public int size()
+ {
+ return cardinality;
+ }
+
+ public Iterator<T> iterator()
+ {
+ return new Iterator<T>()
+ {
+ int next = -1;
+ int count = 0;
+
+ public boolean hasNext()
+ {
+ return count < cardinality;
+ }
+
+ public T next()
+ {
+ next = store.nextSetBit(next + 1);
+ ++count;
+ return enumClass.getEnumConstants()[next];
+ }
+
+ public void remove()
+ {
+ if (! store.get(next))
+ {
+ store.clear(next);
+ --cardinality;
+ }
+ }
+ };
+ }
+
+ public boolean add(T val)
+ {
+ if (store.get(val.ordinal()))
+ return false;
+ store.set(val.ordinal());
+ ++cardinality;
+ return true;
+ }
+
+ public boolean addAll(Collection<? extends T> c)
+ {
+ boolean result = false;
+ if (c instanceof EnumSet<T>)
+ {
+ EnumSet<T> other = (EnumSet<T>) c;
+ if (enumClass == other.enumClass)
+ {
+ store.or(other.store);
+ int save = cardinality;
+ cardinality = store.cardinality();
+ result = save != cardinality;
+ }
+ }
+ else
+ {
+ for (T val : c)
+ {
+ if (add (val))
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ public void clear()
+ {
+ store.clear();
+ cardinality = 0;
+ }
+
+ public boolean contains(Object o)
+ {
+ if (! (o instanceof Enum<T>))
+ return false;
+ Enum<T> e = (Enum<T>) o;
+ if (e.getDeclaringClass() != enumClass)
+ return false;
+ return store.get(e.ordinal());
+ }
+
+ public boolean containsAll(Collection<?> c)
+ {
+ if (c instanceof EnumSet<T>)
+ {
+ EnumSet<T> other = (EnumSet<T>) c;
+ if (enumClass == other.enumClass)
+ return store.containsAll(other.store);
+ return false;
+ }
+ return super.containsAll(c);
+ }
+
+ public boolean remove(Object o)
+ {
+ if (! (o instanceof Enum<T>))
+ return false;
+ Enum<T> e = (Enum<T>) o;
+ if (e.getDeclaringClass() != enumClass)
+ return false;
+ store.clear(e.ordinal());
+ --cardinality;
+ return true;
+ }
+
+ public boolean removeAll(Collection<?> c)
+ {
+ if (c instanceof EnumSet<T>)
+ {
+ EnumSet<T> other = (EnumSet<T>) 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<T>)
+ {
+ EnumSet<T> other = (EnumSet<T>) 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 static <T extends Enum<T>> EnumSet<T> allOf(Class<T> eltType)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ 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 static <T extends Enum<T>> EnumSet<T> noneOf(Class<T> eltType)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ r.store = new BitSet(eltType.getEnumConstants().length);
+ r.enumClass = eltType;
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> copyOf(EnumSet<T> other)
+ {
+ // We can't just use `other.clone' since we don't want to make a
+ // subclass.
+ EnumSet<T> r = new EnumSet<T>();
+ r.store = other.store.clone();
+ r.cardinality = other.cardinality;
+ r.enumClass = other.enumClass;
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> copyOf(Collection<T> other)
+ {
+ if (other instanceof EnumSet<T>)
+ return copyOf((EnumSet<T>) other);
+ EnumSet<T> r = new EnumSet<T>();
+ for (T val : other)
+ {
+ if (r.store == null)
+ {
+ r.enumClass = val.getDeclaringClass();
+ r.store = new BitSet(r.enumClass.getEnumConstants().length);
+ }
+ 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 <T extends Enum<T>> EnumSet<T> complementOf(EnumSet<T> other)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ r.store = other.store.clone();
+ r.store.flip(0, r.store.size());
+ r.cardinality = r.store.size() - other.cardinality;
+ r.enumClass = other.enumClass;
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> of(T first)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ r.enumClass = first.getDeclaringClass();
+ r.store = new BitSet(r.enumClass.getEnumConstants().length);
+ r.store.set(first.ordinal());
+ r.cardinality = 1;
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> of(T first, T second)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ 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();
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> of(T first, T second, T third)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ 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();
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> of(T first, T second, T third,
+ T fourth)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ 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();
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> of(T first, T second, T third,
+ T fourth, T fifth)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ 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();
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> of(T first, T... rest)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ r.enumClass = first.getDeclaringClass();
+ r.store = new BitSet(r.enumClass.getEnumConstants().length);
+ r.store.set(first.ordinal());
+ for (T val : rest)
+ r.store.set(val.ordinal());
+ r.cardinality = r.store.cardinality();
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> range(T from, T to)
+ {
+ if (from.compareTo(to) > 0)
+ throw new IllegalArgumentException();
+ EnumSet<T> r = new EnumSet<T>();
+ 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;
+ return r;
+ }
+}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [cp-patches] [generics] Patch: FYI: EnumSet and EnumMap,
Tom Tromey <=