1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* Licensed to the Apache Software Foundation (ASF) under one or more
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements.  See the NOTICE file distributed with
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership.
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License.  You may obtain a copy of the License at
7f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
9f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License.
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.util;
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
2155392539fea537abfb6581b474918f9d611fba27Jesse Wilson * A concrete EnumSet for enums with more than 64 elements.
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project@SuppressWarnings("serial")
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectfinal class HugeEnumSet<E extends Enum<E>> extends EnumSet<E> {
25f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
2655392539fea537abfb6581b474918f9d611fba27Jesse Wilson    private static final int BIT_IN_LONG = 64;
2755392539fea537abfb6581b474918f9d611fba27Jesse Wilson
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    final private E[] enums;
29f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private long[] bits;
31f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int size;
33f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs an instance.
36f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param elementType non-null; type of the elements
38fb0ec0e650bf8be35acb0d47da0311a7c446aa33Elliott Hughes     * @param enums non-null; pre-populated array of constants in ordinal
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * order
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    HugeEnumSet(Class<E> elementType, E[] enums) {
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(elementType);
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.enums = enums;
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        bits = new long[(enums.length + BIT_IN_LONG - 1) / BIT_IN_LONG];
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
46f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private class HugeEnumSetIterator implements Iterator<E> {
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
4955392539fea537abfb6581b474918f9d611fba27Jesse Wilson        /**
5055392539fea537abfb6581b474918f9d611fba27Jesse Wilson         * The bits yet to be returned for the long in bits[index]. As values from the current index
5155392539fea537abfb6581b474918f9d611fba27Jesse Wilson         * are returned, their bits are zeroed out. When this reaches zero, the index must be
5255392539fea537abfb6581b474918f9d611fba27Jesse Wilson         * incremented.
5355392539fea537abfb6581b474918f9d611fba27Jesse Wilson         */
5455392539fea537abfb6581b474918f9d611fba27Jesse Wilson        private long currentBits = bits[0];
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
5655392539fea537abfb6581b474918f9d611fba27Jesse Wilson        /**
5755392539fea537abfb6581b474918f9d611fba27Jesse Wilson         * The index into HugeEnumSet.bits of the next value to return.
5855392539fea537abfb6581b474918f9d611fba27Jesse Wilson         */
5955392539fea537abfb6581b474918f9d611fba27Jesse Wilson        private int index;
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
6155392539fea537abfb6581b474918f9d611fba27Jesse Wilson        /**
6255392539fea537abfb6581b474918f9d611fba27Jesse Wilson         * The single bit of the next value to return.
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
6455392539fea537abfb6581b474918f9d611fba27Jesse Wilson        private long mask;
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
6655392539fea537abfb6581b474918f9d611fba27Jesse Wilson        /**
6755392539fea537abfb6581b474918f9d611fba27Jesse Wilson         * The candidate for removal. If null, no value may be removed.
6855392539fea537abfb6581b474918f9d611fba27Jesse Wilson         */
6955392539fea537abfb6581b474918f9d611fba27Jesse Wilson        private E last;
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private HugeEnumSetIterator() {
7255392539fea537abfb6581b474918f9d611fba27Jesse Wilson            computeNextElement();
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
7555392539fea537abfb6581b474918f9d611fba27Jesse Wilson        /**
7655392539fea537abfb6581b474918f9d611fba27Jesse Wilson         * Assigns mask and index to the next available value, cycling currentBits as necessary.
7755392539fea537abfb6581b474918f9d611fba27Jesse Wilson         */
7855392539fea537abfb6581b474918f9d611fba27Jesse Wilson        void computeNextElement() {
7955392539fea537abfb6581b474918f9d611fba27Jesse Wilson            while (true) {
8055392539fea537abfb6581b474918f9d611fba27Jesse Wilson                if (currentBits != 0) {
8155392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    mask = currentBits & -currentBits; // the lowest 1 bit in currentBits
8255392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    return;
8355392539fea537abfb6581b474918f9d611fba27Jesse Wilson                } else if (++index < bits.length) {
8455392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    currentBits = bits[index];
8555392539fea537abfb6581b474918f9d611fba27Jesse Wilson                } else {
8655392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    mask = 0;
8755392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    return;
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public boolean hasNext() {
9355392539fea537abfb6581b474918f9d611fba27Jesse Wilson            return mask != 0;
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public E next() {
9755392539fea537abfb6581b474918f9d611fba27Jesse Wilson            if (mask == 0) {
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new NoSuchElementException();
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
10055392539fea537abfb6581b474918f9d611fba27Jesse Wilson
10155392539fea537abfb6581b474918f9d611fba27Jesse Wilson            int ordinal = Long.numberOfTrailingZeros(mask) + index * BIT_IN_LONG;
10255392539fea537abfb6581b474918f9d611fba27Jesse Wilson            last = enums[ordinal];
10355392539fea537abfb6581b474918f9d611fba27Jesse Wilson
10455392539fea537abfb6581b474918f9d611fba27Jesse Wilson            currentBits &= ~mask;
10555392539fea537abfb6581b474918f9d611fba27Jesse Wilson            computeNextElement();
10655392539fea537abfb6581b474918f9d611fba27Jesse Wilson
10755392539fea537abfb6581b474918f9d611fba27Jesse Wilson            return last;
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void remove() {
11155392539fea537abfb6581b474918f9d611fba27Jesse Wilson            if (last == null) {
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalStateException();
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
11455392539fea537abfb6581b474918f9d611fba27Jesse Wilson
11555392539fea537abfb6581b474918f9d611fba27Jesse Wilson            HugeEnumSet.this.remove(last);
11655392539fea537abfb6581b474918f9d611fba27Jesse Wilson            last = null;
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
119f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean add(E element) {
122415c7497ec02890a73eb293f98f69c1f6983389bElliott Hughes        elementClass.cast(element); // Called to throw ClassCastException.
12355392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int ordinal = element.ordinal();
12455392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int index = ordinal / BIT_IN_LONG;
12555392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int inBits = ordinal % BIT_IN_LONG;
12655392539fea537abfb6581b474918f9d611fba27Jesse Wilson        long oldBits = bits[index];
12755392539fea537abfb6581b474918f9d611fba27Jesse Wilson        long newBits = oldBits | (1L << inBits);
12855392539fea537abfb6581b474918f9d611fba27Jesse Wilson        if (oldBits != newBits) {
12955392539fea537abfb6581b474918f9d611fba27Jesse Wilson            bits[index] = newBits;
13055392539fea537abfb6581b474918f9d611fba27Jesse Wilson            size++;
13155392539fea537abfb6581b474918f9d611fba27Jesse Wilson            return true;
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
13355392539fea537abfb6581b474918f9d611fba27Jesse Wilson        return false;
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
135f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean addAll(Collection<? extends E> collection) {
13855392539fea537abfb6581b474918f9d611fba27Jesse Wilson        if (collection.isEmpty() || collection == this) {
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
14155392539fea537abfb6581b474918f9d611fba27Jesse Wilson
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (collection instanceof EnumSet) {
14355392539fea537abfb6581b474918f9d611fba27Jesse Wilson            EnumSet<?> set = (EnumSet) collection; // raw type due to javac bug 6548436
144415c7497ec02890a73eb293f98f69c1f6983389bElliott Hughes            set.elementClass.asSubclass(elementClass); // Called to throw ClassCastException.
14555392539fea537abfb6581b474918f9d611fba27Jesse Wilson
14655392539fea537abfb6581b474918f9d611fba27Jesse Wilson            HugeEnumSet<E> hugeSet = (HugeEnumSet<E>) set;
14755392539fea537abfb6581b474918f9d611fba27Jesse Wilson            boolean changed = false;
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < bits.length; i++) {
14955392539fea537abfb6581b474918f9d611fba27Jesse Wilson                long oldBits = bits[i];
15055392539fea537abfb6581b474918f9d611fba27Jesse Wilson                long newBits = oldBits | hugeSet.bits[i];
15155392539fea537abfb6581b474918f9d611fba27Jesse Wilson                if (oldBits != newBits) {
15255392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    bits[i] = newBits;
15355392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    size += Long.bitCount(newBits) - Long.bitCount(oldBits);
15455392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    changed = true;
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
15755392539fea537abfb6581b474918f9d611fba27Jesse Wilson            return changed;
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return super.addAll(collection);
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
161f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int size() {
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return size;
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
166f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void clear() {
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Arrays.fill(bits, 0);
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        size = 0;
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
172f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void complement() {
17555392539fea537abfb6581b474918f9d611fba27Jesse Wilson        size = 0;
17655392539fea537abfb6581b474918f9d611fba27Jesse Wilson        for (int i = 0, length = bits.length; i < length; i++) {
17755392539fea537abfb6581b474918f9d611fba27Jesse Wilson            long b = ~bits[i];
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
17955392539fea537abfb6581b474918f9d611fba27Jesse Wilson            // zero out unused bits on the last element
18055392539fea537abfb6581b474918f9d611fba27Jesse Wilson            if (i == length - 1) {
18155392539fea537abfb6581b474918f9d611fba27Jesse Wilson                b &= -1L >>> (BIT_IN_LONG - (enums.length % BIT_IN_LONG));
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
18355392539fea537abfb6581b474918f9d611fba27Jesse Wilson
18455392539fea537abfb6581b474918f9d611fba27Jesse Wilson            size += Long.bitCount(b);
18555392539fea537abfb6581b474918f9d611fba27Jesse Wilson            bits[i] = b;
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
188f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean contains(Object object) {
19155392539fea537abfb6581b474918f9d611fba27Jesse Wilson        if (object == null || !isValidType(object.getClass())) {
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
19455392539fea537abfb6581b474918f9d611fba27Jesse Wilson
19555392539fea537abfb6581b474918f9d611fba27Jesse Wilson        @SuppressWarnings("unchecked") // guarded by isValidType()
19655392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int ordinal = ((E) object).ordinal();
19755392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int index = ordinal / BIT_IN_LONG;
19855392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int inBits = ordinal % BIT_IN_LONG;
19955392539fea537abfb6581b474918f9d611fba27Jesse Wilson        return (bits[index] & (1L << inBits)) != 0;
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
201f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public HugeEnumSet<E> clone() {
20455392539fea537abfb6581b474918f9d611fba27Jesse Wilson        HugeEnumSet<E> set = (HugeEnumSet<E>) super.clone();
20555392539fea537abfb6581b474918f9d611fba27Jesse Wilson        set.bits = bits.clone();
20655392539fea537abfb6581b474918f9d611fba27Jesse Wilson        return set;
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
208f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean containsAll(Collection<?> collection) {
21155392539fea537abfb6581b474918f9d611fba27Jesse Wilson        if (collection.isEmpty()) {
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (collection instanceof HugeEnumSet) {
21555392539fea537abfb6581b474918f9d611fba27Jesse Wilson            HugeEnumSet<?> set = (HugeEnumSet<?>) collection;
21655392539fea537abfb6581b474918f9d611fba27Jesse Wilson            if (isValidType(set.elementClass)) {
21755392539fea537abfb6581b474918f9d611fba27Jesse Wilson                for (int i = 0; i < bits.length; i++) {
21855392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    long setBits = set.bits[i];
21955392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    if ((bits[i] & setBits) != setBits) {
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return false;
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return true;
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return !(collection instanceof EnumSet) && super.containsAll(collection);
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
228f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean equals(Object object) {
23155392539fea537abfb6581b474918f9d611fba27Jesse Wilson        if (object == null) {
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isValidType(object.getClass())) {
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return super.equals(object);
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
23755392539fea537abfb6581b474918f9d611fba27Jesse Wilson        return Arrays.equals(bits, ((HugeEnumSet<?>) object).bits);
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
239f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Iterator<E> iterator() {
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return new HugeEnumSetIterator();
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
244f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean remove(Object object) {
24755392539fea537abfb6581b474918f9d611fba27Jesse Wilson        if (object == null || !isValidType(object.getClass())) {
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
25055392539fea537abfb6581b474918f9d611fba27Jesse Wilson
25155392539fea537abfb6581b474918f9d611fba27Jesse Wilson        @SuppressWarnings("unchecked") // guarded by isValidType()
25255392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int ordinal = ((E) object).ordinal();
25355392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int index = ordinal / BIT_IN_LONG;
25455392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int inBits = ordinal % BIT_IN_LONG;
25555392539fea537abfb6581b474918f9d611fba27Jesse Wilson        long oldBits = bits[index];
25655392539fea537abfb6581b474918f9d611fba27Jesse Wilson        long newBits = oldBits & ~(1L << inBits);
25755392539fea537abfb6581b474918f9d611fba27Jesse Wilson        if (oldBits != newBits) {
25855392539fea537abfb6581b474918f9d611fba27Jesse Wilson            bits[index] = newBits;
25955392539fea537abfb6581b474918f9d611fba27Jesse Wilson            size--;
26055392539fea537abfb6581b474918f9d611fba27Jesse Wilson            return true;
26155392539fea537abfb6581b474918f9d611fba27Jesse Wilson        }
26255392539fea537abfb6581b474918f9d611fba27Jesse Wilson        return false;
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
264f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean removeAll(Collection<?> collection) {
26755392539fea537abfb6581b474918f9d611fba27Jesse Wilson        if (collection.isEmpty()) {
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
270f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (collection instanceof EnumSet) {
27255392539fea537abfb6581b474918f9d611fba27Jesse Wilson            EnumSet<?> set = (EnumSet<?>) collection;
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!isValidType(set.elementClass)) {
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return false;
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
27655392539fea537abfb6581b474918f9d611fba27Jesse Wilson
27755392539fea537abfb6581b474918f9d611fba27Jesse Wilson            HugeEnumSet<E> hugeSet = (HugeEnumSet<E>) set;
27855392539fea537abfb6581b474918f9d611fba27Jesse Wilson            boolean changed = false;
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < bits.length; i++) {
28055392539fea537abfb6581b474918f9d611fba27Jesse Wilson                long oldBits = bits[i];
28155392539fea537abfb6581b474918f9d611fba27Jesse Wilson                long newBits = oldBits & ~hugeSet.bits[i];
28255392539fea537abfb6581b474918f9d611fba27Jesse Wilson                if (oldBits != newBits) {
28355392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    bits[i] = newBits;
28455392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    size += Long.bitCount(newBits) - Long.bitCount(oldBits);
28555392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    changed = true;
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
28855392539fea537abfb6581b474918f9d611fba27Jesse Wilson            return changed;
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return super.removeAll(collection);
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
292f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean retainAll(Collection<?> collection) {
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (collection instanceof EnumSet) {
29655392539fea537abfb6581b474918f9d611fba27Jesse Wilson            EnumSet<?> set = (EnumSet<?>) collection;
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!isValidType(set.elementClass)) {
29855392539fea537abfb6581b474918f9d611fba27Jesse Wilson                if (size > 0) {
29955392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    clear();
30055392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    return true;
30155392539fea537abfb6581b474918f9d611fba27Jesse Wilson                } else {
30255392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    return false;
30355392539fea537abfb6581b474918f9d611fba27Jesse Wilson                }
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
30655392539fea537abfb6581b474918f9d611fba27Jesse Wilson            HugeEnumSet<E> hugeSet = (HugeEnumSet<E>) set;
30755392539fea537abfb6581b474918f9d611fba27Jesse Wilson            boolean changed = false;
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < bits.length; i++) {
30955392539fea537abfb6581b474918f9d611fba27Jesse Wilson                long oldBits = bits[i];
31055392539fea537abfb6581b474918f9d611fba27Jesse Wilson                long newBits = oldBits & hugeSet.bits[i];
31155392539fea537abfb6581b474918f9d611fba27Jesse Wilson                if (oldBits != newBits) {
31255392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    bits[i] = newBits;
31355392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    size += Long.bitCount(newBits) - Long.bitCount(oldBits);
31455392539fea537abfb6581b474918f9d611fba27Jesse Wilson                    changed = true;
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
31755392539fea537abfb6581b474918f9d611fba27Jesse Wilson            return changed;
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return super.retainAll(collection);
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
321f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void setRange(E start, E end) {
32455392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int startOrdinal = start.ordinal();
32555392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int startIndex = startOrdinal / BIT_IN_LONG;
32655392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int startInBits = startOrdinal % BIT_IN_LONG;
32755392539fea537abfb6581b474918f9d611fba27Jesse Wilson
32855392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int endOrdinal = end.ordinal();
32955392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int endIndex = endOrdinal / BIT_IN_LONG;
33055392539fea537abfb6581b474918f9d611fba27Jesse Wilson        int endInBits = endOrdinal % BIT_IN_LONG;
33155392539fea537abfb6581b474918f9d611fba27Jesse Wilson
33255392539fea537abfb6581b474918f9d611fba27Jesse Wilson        if (startIndex == endIndex) {
33355392539fea537abfb6581b474918f9d611fba27Jesse Wilson            long range = (-1L >>> (BIT_IN_LONG -(endInBits - startInBits + 1))) << startInBits;
33455392539fea537abfb6581b474918f9d611fba27Jesse Wilson            size -= Long.bitCount(bits[startIndex]);
33555392539fea537abfb6581b474918f9d611fba27Jesse Wilson            bits[startIndex] |= range;
33655392539fea537abfb6581b474918f9d611fba27Jesse Wilson            size += Long.bitCount(bits[startIndex]);
33755392539fea537abfb6581b474918f9d611fba27Jesse Wilson
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
33955392539fea537abfb6581b474918f9d611fba27Jesse Wilson            long range = (-1L >>> startInBits) << startInBits;
34055392539fea537abfb6581b474918f9d611fba27Jesse Wilson            size -= Long.bitCount(bits[startIndex]);
34155392539fea537abfb6581b474918f9d611fba27Jesse Wilson            bits[startIndex] |= range;
34255392539fea537abfb6581b474918f9d611fba27Jesse Wilson            size += Long.bitCount(bits[startIndex]);
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
34455392539fea537abfb6581b474918f9d611fba27Jesse Wilson            // endInBits + 1 is the number of consecutive ones.
34555392539fea537abfb6581b474918f9d611fba27Jesse Wilson            // 63 - endInBits is the following zeros of the right most one.
34655392539fea537abfb6581b474918f9d611fba27Jesse Wilson            range = -1L >>> (BIT_IN_LONG - (endInBits + 1));
34755392539fea537abfb6581b474918f9d611fba27Jesse Wilson            size -= Long.bitCount(bits[endIndex]);
34855392539fea537abfb6581b474918f9d611fba27Jesse Wilson            bits[endIndex] |= range;
34955392539fea537abfb6581b474918f9d611fba27Jesse Wilson            size += Long.bitCount(bits[endIndex]);
35055392539fea537abfb6581b474918f9d611fba27Jesse Wilson            for (int i = (startIndex + 1); i <= (endIndex - 1); i++) {
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                size -= Long.bitCount(bits[i]);
35255392539fea537abfb6581b474918f9d611fba27Jesse Wilson                bits[i] = -1L;
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                size += Long.bitCount(bits[i]);
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
358