| /* Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package java.util; |
| |
| |
| /** |
| * This is a concrete subclass of EnumSet designed specifically for enum type |
| * with less than or equal to 64 elements. |
| * |
| */ |
| @SuppressWarnings("serial") |
| final class MiniEnumSet<E extends Enum<E>> extends EnumSet<E> { |
| private static final int MAX_ELEMENTS = 64; |
| |
| private int size; |
| |
| private final E[] enums; |
| |
| private long bits; |
| |
| // BEGIN android-changed |
| /** |
| * Constructs an instance. |
| * |
| * @param elementType non-null; type of the elements |
| * @param enums non-null; prepopulated array of constants in ordinal |
| * order |
| */ |
| MiniEnumSet(Class<E> elementType, E[] enums) { |
| super(elementType); |
| this.enums = enums; |
| } |
| // END android-changed |
| |
| private class MiniEnumSetIterator implements Iterator<E> { |
| |
| private long unProcessedBits; |
| |
| /* |
| * Mask for current element. |
| */ |
| private long currentElementMask; |
| |
| private boolean canProcess = true; |
| |
| private MiniEnumSetIterator() { |
| unProcessedBits = bits; |
| if (0 == unProcessedBits) { |
| canProcess = false; |
| } |
| } |
| |
| public boolean hasNext() { |
| return canProcess; |
| } |
| |
| public E next() { |
| if (!canProcess) { |
| throw new NoSuchElementException(); |
| } |
| currentElementMask = unProcessedBits & (-unProcessedBits); |
| unProcessedBits -= currentElementMask; |
| if (0 == unProcessedBits) { |
| canProcess = false; |
| } |
| return enums[Long.numberOfTrailingZeros(currentElementMask)]; |
| } |
| |
| public void remove() { |
| if ( currentElementMask == 0 ) { |
| throw new IllegalStateException(); |
| } |
| bits &= ~currentElementMask; |
| size = Long.bitCount(bits); |
| currentElementMask = 0; |
| } |
| } |
| |
| @Override |
| public Iterator<E> iterator() { |
| return new MiniEnumSetIterator(); |
| } |
| |
| @Override |
| public int size() { |
| return size; |
| } |
| |
| @Override |
| public void clear() { |
| bits = 0; |
| size = 0; |
| } |
| |
| @Override |
| public boolean add(E element) { |
| if (!isValidType(element.getDeclaringClass())) { |
| throw new ClassCastException(); |
| } |
| long mask = 1l << element.ordinal(); |
| if ((bits & mask) == mask) { |
| return false; |
| } |
| bits |= mask; |
| |
| size++; |
| return true; |
| } |
| |
| @Override |
| public boolean addAll(Collection<? extends E> collection) { |
| if (0 == collection.size()) { |
| return false; |
| } |
| if (collection instanceof EnumSet) { |
| EnumSet<?> set = (EnumSet)collection; |
| if (!isValidType(set.elementClass)) { |
| throw new ClassCastException(); |
| } |
| MiniEnumSet<?> miniSet = (MiniEnumSet<?>) set; |
| long oldBits = bits; |
| bits |= miniSet.bits; |
| size = Long.bitCount(bits); |
| return (oldBits != bits); |
| } |
| return super.addAll(collection); |
| } |
| |
| @Override |
| public boolean contains(Object object) { |
| if (null == object) { |
| return false; |
| } |
| if (!isValidType(object.getClass())) { |
| return false; |
| } |
| Enum<?> element = (Enum<?>) object; |
| int ordinal = element.ordinal(); |
| return (bits & (1l << ordinal)) != 0; |
| } |
| |
| @Override |
| public boolean containsAll(Collection<?> collection) { |
| if (collection.size() == 0) { |
| return true; |
| } |
| if (collection instanceof MiniEnumSet) { |
| MiniEnumSet<?> set = (MiniEnumSet<?>) collection; |
| return isValidType(set.elementClass ) && ((bits & set.bits) == set.bits); |
| } |
| return !(collection instanceof EnumSet) && super.containsAll(collection); |
| } |
| |
| @Override |
| public boolean removeAll(Collection<?> collection) { |
| if (0 == collection.size()) { |
| return false; |
| } |
| if (collection instanceof EnumSet) { |
| EnumSet<E> set = (EnumSet<E>) collection; |
| boolean removeSuccessful = false; |
| if (isValidType(set.elementClass)) { |
| long mask = bits & ((MiniEnumSet<E>) set).bits; |
| if (mask != 0) { |
| bits -= mask; |
| size = Long.bitCount(bits); |
| removeSuccessful = true; |
| } |
| } |
| return removeSuccessful; |
| } |
| return super.removeAll(collection); |
| } |
| |
| @Override |
| public boolean retainAll(Collection<?> collection) { |
| if (collection instanceof EnumSet) { |
| EnumSet<E> set = (EnumSet<E>) collection; |
| if (!isValidType(set.elementClass)) { |
| clear(); |
| return true; |
| } |
| boolean retainSuccessful = false; |
| long oldBits = bits; |
| bits &= ((MiniEnumSet<E>)set).bits; |
| if (oldBits != bits) { |
| size = Long.bitCount(bits); |
| retainSuccessful = true; |
| } |
| return retainSuccessful; |
| } |
| return super.retainAll(collection); |
| } |
| |
| @Override |
| public boolean remove(Object object) { |
| if (!contains(object)) { |
| return false; |
| } |
| Enum<?> element = (Enum<?>) object; |
| int ordinal = element.ordinal(); |
| bits -= (1l << ordinal); |
| size--; |
| return true; |
| } |
| |
| @Override |
| public boolean equals(Object object) { |
| if (!(object instanceof EnumSet)) { |
| return super.equals(object); |
| } |
| EnumSet<?> set =(EnumSet<?>)object; |
| if( !isValidType(set.elementClass) ) { |
| return size == 0 && set.size() == 0; |
| } |
| return bits == ((MiniEnumSet<?>)set).bits; |
| } |
| |
| @Override |
| void complement() { |
| if (0 != enums.length) { |
| bits = ~bits; |
| bits &= (-1l >>> (MAX_ELEMENTS - enums.length)); |
| size = enums.length - size; |
| } |
| } |
| |
| @Override |
| void setRange(E start, E end) { |
| int length = end.ordinal() - start.ordinal() + 1; |
| long range = (-1l >>> (MAX_ELEMENTS - length)) << start.ordinal(); |
| bits |= range; |
| size = Long.bitCount(bits); |
| } |
| } |