mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			406 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			406 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Java
		
	
	
	
/* EnumMap.java - Map where keys are enum constants
 | 
						|
   Copyright (C) 2004, 2005, 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 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;
 | 
						|
 | 
						|
import java.io.Serializable;
 | 
						|
 | 
						|
/**
 | 
						|
 * @author Tom Tromey (tromey@redhat.com)
 | 
						|
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 | 
						|
 * @since 1.5
 | 
						|
 */
 | 
						|
 | 
						|
public class EnumMap<K extends Enum<K>, V>
 | 
						|
  extends AbstractMap<K, V>
 | 
						|
  implements Cloneable, Serializable
 | 
						|
{
 | 
						|
  private static final long serialVersionUID = 458661240069192865L;
 | 
						|
 | 
						|
  V[] store;
 | 
						|
  int cardinality;
 | 
						|
  Class<K> enumClass;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The cache for {@link #entrySet()}.
 | 
						|
   */
 | 
						|
  transient Set<Map.Entry<K, V>> entries;
 | 
						|
 | 
						|
  static final Object emptySlot = new Object();
 | 
						|
 | 
						|
  public EnumMap(Class<K> keyType)
 | 
						|
  {
 | 
						|
    store = (V[]) new Object[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)
 | 
						|
      {
 | 
						|
        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 = (V[]) new Object[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))
 | 
						|
      return false;
 | 
						|
    Enum<K> e = (Enum<K>) key;
 | 
						|
    if (e.getDeclaringClass() != enumClass)
 | 
						|
      return false;
 | 
						|
    return store[e.ordinal()] != emptySlot;
 | 
						|
  }
 | 
						|
 | 
						|
  public V get(Object key)
 | 
						|
  {
 | 
						|
    if (! (key instanceof Enum))
 | 
						|
      return null;
 | 
						|
    Enum<K> e = (Enum<K>) key;
 | 
						|
    if (e.getDeclaringClass() != enumClass)
 | 
						|
      return null;
 | 
						|
    V o = store[e.ordinal()];
 | 
						|
    return o == emptySlot ? null : o;
 | 
						|
  }
 | 
						|
 | 
						|
  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))
 | 
						|
      return null;
 | 
						|
    Enum<K> e = (Enum<K>) key;
 | 
						|
    if (e.getDeclaringClass() != enumClass)
 | 
						|
      return null;
 | 
						|
    V result = store[e.ordinal()];
 | 
						|
    if (result == emptySlot)
 | 
						|
      result = null;
 | 
						|
    else
 | 
						|
      --cardinality;
 | 
						|
    store[e.ordinal()] = (V) 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] = (V) 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) != null;
 | 
						|
          }
 | 
						|
        };
 | 
						|
      }
 | 
						|
    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 V next()
 | 
						|
              {
 | 
						|
                ++count;
 | 
						|
                for (++index; store[index] == emptySlot; ++index)
 | 
						|
                  ;
 | 
						|
                return store[index];
 | 
						|
              }
 | 
						|
 | 
						|
              public void remove()
 | 
						|
              {
 | 
						|
                --cardinality;
 | 
						|
                store[index] = (V) 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 Map.Entry<K,V> 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.SimpleEntry<K, V>(enumClass.getEnumConstants()[index],
 | 
						|
                                                           store[index])
 | 
						|
                {
 | 
						|
                  public V setValue(V newVal)
 | 
						|
                  {
 | 
						|
                    value = newVal;
 | 
						|
                    return put(key, newVal);
 | 
						|
                  }
 | 
						|
                };
 | 
						|
              }
 | 
						|
 | 
						|
              public void remove()
 | 
						|
              {
 | 
						|
                --cardinality;
 | 
						|
                store[index] = (V) emptySlot;
 | 
						|
              }
 | 
						|
            };
 | 
						|
          }
 | 
						|
 | 
						|
          public void clear()
 | 
						|
          {
 | 
						|
            EnumMap.this.clear();
 | 
						|
          }
 | 
						|
 | 
						|
          public boolean contains(Object o)
 | 
						|
          {
 | 
						|
            if (! (o instanceof Map.Entry))
 | 
						|
              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))
 | 
						|
              return false;
 | 
						|
            Map.Entry<K, V> other = (Map.Entry<K, V>) o;
 | 
						|
            return EnumMap.this.remove(other.getKey()) != null;
 | 
						|
          }
 | 
						|
        };
 | 
						|
      }
 | 
						|
    return entries;
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean equals(Object o)
 | 
						|
  {
 | 
						|
    if (! (o instanceof EnumMap))
 | 
						|
      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> result;
 | 
						|
    try
 | 
						|
      {
 | 
						|
        result = (EnumMap<K, V>) super.clone();
 | 
						|
      }
 | 
						|
    catch (CloneNotSupportedException ignore)
 | 
						|
      {
 | 
						|
        // Can't happen.
 | 
						|
        result = null;
 | 
						|
      }
 | 
						|
    result.store = (V[]) store.clone();
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
}
 |