emul/compact/src/main/java/java/util/RegularEnumSet.java
author Jaroslav Tulach <jtulach@netbeans.org>
Sun, 22 Sep 2013 21:49:42 +0200
branchjdk7-b147
changeset 1292 9cf04876e4a5
permissions -rw-r--r--
Need EnumMap, EnumSet for the javac
     1 /*
     2  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.util;
    27 
    28 /**
    29  * Private implementation class for EnumSet, for "regular sized" enum types
    30  * (i.e., those with 64 or fewer enum constants).
    31  *
    32  * @author Josh Bloch
    33  * @since 1.5
    34  * @serial exclude
    35  */
    36 class RegularEnumSet<E extends Enum<E>> extends EnumSet<E> {
    37     private static final long serialVersionUID = 3411599620347842686L;
    38     /**
    39      * Bit vector representation of this set.  The 2^k bit indicates the
    40      * presence of universe[k] in this set.
    41      */
    42     private long elements = 0L;
    43 
    44     RegularEnumSet(Class<E>elementType, Enum[] universe) {
    45         super(elementType, universe);
    46     }
    47 
    48     void addRange(E from, E to) {
    49         elements = (-1L >>>  (from.ordinal() - to.ordinal() - 1)) << from.ordinal();
    50     }
    51 
    52     void addAll() {
    53         if (universe.length != 0)
    54             elements = -1L >>> -universe.length;
    55     }
    56 
    57     void complement() {
    58         if (universe.length != 0) {
    59             elements = ~elements;
    60             elements &= -1L >>> -universe.length;  // Mask unused bits
    61         }
    62     }
    63 
    64     /**
    65      * Returns an iterator over the elements contained in this set.  The
    66      * iterator traverses the elements in their <i>natural order</i> (which is
    67      * the order in which the enum constants are declared). The returned
    68      * Iterator is a "snapshot" iterator that will never throw {@link
    69      * ConcurrentModificationException}; the elements are traversed as they
    70      * existed when this call was invoked.
    71      *
    72      * @return an iterator over the elements contained in this set
    73      */
    74     public Iterator<E> iterator() {
    75         return new EnumSetIterator<>();
    76     }
    77 
    78     private class EnumSetIterator<E extends Enum<E>> implements Iterator<E> {
    79         /**
    80          * A bit vector representing the elements in the set not yet
    81          * returned by this iterator.
    82          */
    83         long unseen;
    84 
    85         /**
    86          * The bit representing the last element returned by this iterator
    87          * but not removed, or zero if no such element exists.
    88          */
    89         long lastReturned = 0;
    90 
    91         EnumSetIterator() {
    92             unseen = elements;
    93         }
    94 
    95         public boolean hasNext() {
    96             return unseen != 0;
    97         }
    98 
    99         public E next() {
   100             if (unseen == 0)
   101                 throw new NoSuchElementException();
   102             lastReturned = unseen & -unseen;
   103             unseen -= lastReturned;
   104             return (E) universe[Long.numberOfTrailingZeros(lastReturned)];
   105         }
   106 
   107         public void remove() {
   108             if (lastReturned == 0)
   109                 throw new IllegalStateException();
   110             elements &= ~lastReturned;
   111             lastReturned = 0;
   112         }
   113     }
   114 
   115     /**
   116      * Returns the number of elements in this set.
   117      *
   118      * @return the number of elements in this set
   119      */
   120     public int size() {
   121         return Long.bitCount(elements);
   122     }
   123 
   124     /**
   125      * Returns <tt>true</tt> if this set contains no elements.
   126      *
   127      * @return <tt>true</tt> if this set contains no elements
   128      */
   129     public boolean isEmpty() {
   130         return elements == 0;
   131     }
   132 
   133     /**
   134      * Returns <tt>true</tt> if this set contains the specified element.
   135      *
   136      * @param e element to be checked for containment in this collection
   137      * @return <tt>true</tt> if this set contains the specified element
   138      */
   139     public boolean contains(Object e) {
   140         if (e == null)
   141             return false;
   142         Class eClass = e.getClass();
   143         if (eClass != elementType && eClass.getSuperclass() != elementType)
   144             return false;
   145 
   146         return (elements & (1L << ((Enum)e).ordinal())) != 0;
   147     }
   148 
   149     // Modification Operations
   150 
   151     /**
   152      * Adds the specified element to this set if it is not already present.
   153      *
   154      * @param e element to be added to this set
   155      * @return <tt>true</tt> if the set changed as a result of the call
   156      *
   157      * @throws NullPointerException if <tt>e</tt> is null
   158      */
   159     public boolean add(E e) {
   160         typeCheck(e);
   161 
   162         long oldElements = elements;
   163         elements |= (1L << ((Enum)e).ordinal());
   164         return elements != oldElements;
   165     }
   166 
   167     /**
   168      * Removes the specified element from this set if it is present.
   169      *
   170      * @param e element to be removed from this set, if present
   171      * @return <tt>true</tt> if the set contained the specified element
   172      */
   173     public boolean remove(Object e) {
   174         if (e == null)
   175             return false;
   176         Class eClass = e.getClass();
   177         if (eClass != elementType && eClass.getSuperclass() != elementType)
   178             return false;
   179 
   180         long oldElements = elements;
   181         elements &= ~(1L << ((Enum)e).ordinal());
   182         return elements != oldElements;
   183     }
   184 
   185     // Bulk Operations
   186 
   187     /**
   188      * Returns <tt>true</tt> if this set contains all of the elements
   189      * in the specified collection.
   190      *
   191      * @param c collection to be checked for containment in this set
   192      * @return <tt>true</tt> if this set contains all of the elements
   193      *        in the specified collection
   194      * @throws NullPointerException if the specified collection is null
   195      */
   196     public boolean containsAll(Collection<?> c) {
   197         if (!(c instanceof RegularEnumSet))
   198             return super.containsAll(c);
   199 
   200         RegularEnumSet es = (RegularEnumSet)c;
   201         if (es.elementType != elementType)
   202             return es.isEmpty();
   203 
   204         return (es.elements & ~elements) == 0;
   205     }
   206 
   207     /**
   208      * Adds all of the elements in the specified collection to this set.
   209      *
   210      * @param c collection whose elements are to be added to this set
   211      * @return <tt>true</tt> if this set changed as a result of the call
   212      * @throws NullPointerException if the specified collection or any
   213      *     of its elements are null
   214      */
   215     public boolean addAll(Collection<? extends E> c) {
   216         if (!(c instanceof RegularEnumSet))
   217             return super.addAll(c);
   218 
   219         RegularEnumSet es = (RegularEnumSet)c;
   220         if (es.elementType != elementType) {
   221             if (es.isEmpty())
   222                 return false;
   223             else
   224                 throw new ClassCastException(
   225                     es.elementType + " != " + elementType);
   226         }
   227 
   228         long oldElements = elements;
   229         elements |= es.elements;
   230         return elements != oldElements;
   231     }
   232 
   233     /**
   234      * Removes from this set all of its elements that are contained in
   235      * the specified collection.
   236      *
   237      * @param c elements to be removed from this set
   238      * @return <tt>true</tt> if this set changed as a result of the call
   239      * @throws NullPointerException if the specified collection is null
   240      */
   241     public boolean removeAll(Collection<?> c) {
   242         if (!(c instanceof RegularEnumSet))
   243             return super.removeAll(c);
   244 
   245         RegularEnumSet es = (RegularEnumSet)c;
   246         if (es.elementType != elementType)
   247             return false;
   248 
   249         long oldElements = elements;
   250         elements &= ~es.elements;
   251         return elements != oldElements;
   252     }
   253 
   254     /**
   255      * Retains only the elements in this set that are contained in the
   256      * specified collection.
   257      *
   258      * @param c elements to be retained in this set
   259      * @return <tt>true</tt> if this set changed as a result of the call
   260      * @throws NullPointerException if the specified collection is null
   261      */
   262     public boolean retainAll(Collection<?> c) {
   263         if (!(c instanceof RegularEnumSet))
   264             return super.retainAll(c);
   265 
   266         RegularEnumSet<?> es = (RegularEnumSet<?>)c;
   267         if (es.elementType != elementType) {
   268             boolean changed = (elements != 0);
   269             elements = 0;
   270             return changed;
   271         }
   272 
   273         long oldElements = elements;
   274         elements &= es.elements;
   275         return elements != oldElements;
   276     }
   277 
   278     /**
   279      * Removes all of the elements from this set.
   280      */
   281     public void clear() {
   282         elements = 0;
   283     }
   284 
   285     /**
   286      * Compares the specified object with this set for equality.  Returns
   287      * <tt>true</tt> if the given object is also a set, the two sets have
   288      * the same size, and every member of the given set is contained in
   289      * this set.
   290      *
   291      * @param e object to be compared for equality with this set
   292      * @return <tt>true</tt> if the specified object is equal to this set
   293      */
   294     public boolean equals(Object o) {
   295         if (!(o instanceof RegularEnumSet))
   296             return super.equals(o);
   297 
   298         RegularEnumSet es = (RegularEnumSet)o;
   299         if (es.elementType != elementType)
   300             return elements == 0 && es.elements == 0;
   301         return es.elements == elements;
   302     }
   303 }