/*
 * 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 org.apache.felix.resolver.util;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.AbstractCollection;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;

/**
 * Based on fastutil Object2ObjectLinkedOpenHashMap
 */
public class OpenHashMap<K, V> implements Serializable, Cloneable, SortedMap<K, V> {

    private static final long serialVersionUID = 0L;
    protected transient Object[] key;
    protected transient Object[] value;
    protected transient int mask;
    protected transient boolean containsNullKey;
    protected transient int first;
    protected transient int last;
    protected transient long[] link;
    protected transient int n;
    protected transient int maxFill;
    protected int size;
    protected final float f;
    protected V defRetValue;

    protected transient Iterable<Map.Entry<K, V>> fast;
    protected transient SortedSet<Map.Entry<K, V>> entries;
    protected transient SortedSet<K> keys;
    protected transient Collection<V> values;

    public OpenHashMap(int expected, float f) {
        this.first = -1;
        this.last = -1;
        if (f > 0.0F && f <= 1.0F) {
            if (expected < 0) {
                throw new IllegalArgumentException("The expected number of elements must be nonnegative");
            } else {
                this.f = f;
                this.n = arraySize(expected, f);
                this.mask = this.n - 1;
                this.maxFill = maxFill(this.n, f);
                this.key = new Object[this.n + 1];
                this.value = new Object[this.n + 1];
                this.link = new long[this.n + 1];
            }
        } else {
            throw new IllegalArgumentException("Load factor must be greater than 0 and smaller than or equal to 1");
        }
    }

    public OpenHashMap(int expected) {
        this(expected, 0.75F);
    }

    public OpenHashMap() {
        this(16, 0.75F);
    }

    public OpenHashMap(Map<? extends K, ? extends V> m, float f) {
        this(m.size(), f);
        this.putAll(m);
    }

    public OpenHashMap(Map<? extends K, ? extends V> m) {
        this(m, 0.75F);
    }

    public OpenHashMap(K[] k, V[] v, float f) {
        this(k.length, f);
        if (k.length != v.length) {
            throw new IllegalArgumentException("The key array and the value array have different lengths (" + k.length + " and " + v.length + ")");
        } else {
            for (int i = 0; i < k.length; ++i) {
                this.put(k[i], v[i]);
            }

        }
    }

    public OpenHashMap(K[] k, V[] v) {
        this(k, v, 0.75F);
    }

    public void defaultReturnValue(V rv) {
        this.defRetValue = rv;
    }

    public V defaultReturnValue() {
        return this.defRetValue;
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Map)) {
            return false;
        } else {
            Map<?, ?> m = (Map<?, ?>) o;
            int n = m.size();
            if (this.size() != n) {
                return false;
            }
            Iterator<? extends Entry<?, ?>> i = this.fast().iterator();
            while (n-- > 0) {
                Entry<?, ?> e = i.next();
                Object k = e.getKey();
                Object v = e.getValue();
                Object v2 = m.get(k);
                if (v == null) {
                    if (v2 != null) {
                        return false;
                    }
                } else if (!v.equals(v2)) {
                    return false;
                }
            }
            return true;
        }
    }

    public String toString() {
        StringBuilder s = new StringBuilder();
        Iterator<Map.Entry<K, V>> i = this.fast().iterator();
        int n = this.size();
        boolean first = true;
        s.append("{");

        while (n-- != 0) {
            if (first) {
                first = false;
            } else {
                s.append(", ");
            }

            Map.Entry<K, V> e = i.next();
            if (this == e.getKey()) {
                s.append("(this map)");
            } else {
                s.append(String.valueOf(e.getKey()));
            }

            s.append("=>");
            if (this == e.getValue()) {
                s.append("(this map)");
            } else {
                s.append(String.valueOf(e.getValue()));
            }
        }

        s.append("}");
        return s.toString();
    }

    private int realSize() {
        return this.containsNullKey ? this.size - 1 : this.size;
    }

    private void ensureCapacity(int capacity) {
        int needed = arraySize(capacity, this.f);
        if (needed > this.n) {
            this.rehash(needed);
        }

    }

    private void tryCapacity(long capacity) {
        int needed = (int) Math.min(1073741824L, Math.max(2L, nextPowerOfTwo((long) Math.ceil((double) ((float) capacity / this.f)))));
        if (needed > this.n) {
            this.rehash(needed);
        }

    }

    @SuppressWarnings("unchecked")
    private V removeEntry(int pos) {
        Object oldValue = this.value[pos];
        this.value[pos] = null;
        --this.size;
        this.fixPointers(pos);
        this.shiftKeys(pos);
        if (this.size < this.maxFill / 4 && this.n > 16) {
            this.rehash(this.n / 2);
        }

        return (V) oldValue;
    }

    @SuppressWarnings("unchecked")
    private V removeNullEntry() {
        this.containsNullKey = false;
        Object oldValue = this.value[this.n];
        this.value[this.n] = null;
        --this.size;
        this.fixPointers(this.n);
        if (this.size < this.maxFill / 4 && this.n > 16) {
            this.rehash(this.n / 2);
        }

        return (V) oldValue;
    }

    public void putAll(Map<? extends K, ? extends V> m) {
        if ((double) this.f <= 0.5D) {
            this.ensureCapacity(m.size());
        } else {
            this.tryCapacity((long) (this.size() + m.size()));
        }

        int n = m.size();
        if (m instanceof OpenHashMap) {
            Iterator<? extends Map.Entry<? extends K, ? extends V>> i = ((OpenHashMap<? extends K, ? extends V>) m).fast().iterator();
            while (n-- != 0) {
                Map.Entry<? extends K, ? extends V> e = i.next();
                this.put(e.getKey(), e.getValue());
            }
        } else {
            Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator();
            while (n-- != 0) {
                Map.Entry<? extends K, ? extends V> e = i.next();
                this.put(e.getKey(), e.getValue());
            }
        }
    }

    private int insert(K k, V v) {
        int pos;
        if (k == null) {
            if (this.containsNullKey) {
                return this.n;
            }

            this.containsNullKey = true;
            pos = this.n;
        } else {
            Object[] key = this.key;
            Object curr;
            if ((curr = key[pos = mix(k.hashCode()) & this.mask]) != null) {
                if (curr.equals(k)) {
                    return pos;
                }

                while ((curr = key[pos = pos + 1 & this.mask]) != null) {
                    if (curr.equals(k)) {
                        return pos;
                    }
                }
            }

            key[pos] = k;
        }

        this.value[pos] = v;
        if (this.size == 0) {
            this.first = this.last = pos;
            this.link[pos] = -1L;
        } else {
            this.link[this.last] ^= (this.link[this.last] ^ (long) pos & 0xFFFFFFFFL) & 0xFFFFFFFFL;
            this.link[pos] = ((long) this.last & 0xFFFFFFFFL) << 32 | 0xFFFFFFFFL;
            this.last = pos;
        }

        if (this.size++ >= this.maxFill) {
            this.rehash(arraySize(this.size + 1, this.f));
        }

        return -1;
    }

    @SuppressWarnings("unchecked")
    public V put(K k, V v) {
        int pos = this.insert(k, v);
        if (pos < 0) {
            return this.defRetValue;
        } else {
            Object oldValue = this.value[pos];
            this.value[pos] = v;
            return (V) oldValue;
        }
    }

    @SuppressWarnings("unchecked")
    public V getOrCompute(K k) {
        int pos;
        if (k == null) {
            if (this.containsNullKey) {
                return (V) this.value[this.n];
            }

            this.containsNullKey = true;
            pos = this.n;
        } else {
            Object[] key = this.key;
            Object curr;
            if ((curr = key[pos = mix(k.hashCode()) & this.mask]) != null) {
                if (curr.equals(k)) {
                    return (V) this.value[pos];
                }

                while ((curr = key[pos = pos + 1 & this.mask]) != null) {
                    if (curr.equals(k)) {
                        return (V) this.value[pos];
                    }
                }
            }

            key[pos] = k;
        }

        Object v;
        this.value[pos] = (v = compute(k));
        if (this.size == 0) {
            this.first = this.last = pos;
            this.link[pos] = -1L;
        } else {
            this.link[this.last] ^= (this.link[this.last] ^ (long) pos & 0xFFFFFFFFL) & 0xFFFFFFFFL;
            this.link[pos] = ((long) this.last & 0xFFFFFFFFL) << 32 | 0xFFFFFFFFL;
            this.last = pos;
        }

        if (this.size++ >= this.maxFill) {
            this.rehash(arraySize(this.size + 1, this.f));
        }

        return (V) v;
    }

    protected V compute(K k) {
        throw new UnsupportedOperationException();
    }

    protected final void shiftKeys(int pos) {
        Object[] key = this.key;

        label32:
        while (true) {
            int last = pos;

            Object curr;
            for (pos = pos + 1 & this.mask; (curr = key[pos]) != null; pos = pos + 1 & this.mask) {
                int slot = mix(curr.hashCode()) & this.mask;
                if (last <= pos) {
                    if (last < slot && slot <= pos) {
                        continue;
                    }
                } else if (last < slot || slot <= pos) {
                    continue;
                }

                key[last] = curr;
                this.value[last] = this.value[pos];
                this.fixPointers(pos, last);
                continue label32;
            }

            key[last] = null;
            this.value[last] = null;
            return;
        }
    }

    public V remove(Object k) {
        if (k == null) {
            return this.containsNullKey ? this.removeNullEntry() : this.defRetValue;
        } else {
            Object[] key = this.key;
            Object curr;
            int pos;
            if ((curr = key[pos = mix(k.hashCode()) & this.mask]) == null) {
                return this.defRetValue;
            } else if (k.equals(curr)) {
                return this.removeEntry(pos);
            } else {
                while ((curr = key[pos = pos + 1 & this.mask]) != null) {
                    if (k.equals(curr)) {
                        return this.removeEntry(pos);
                    }
                }

                return this.defRetValue;
            }
        }
    }

    @SuppressWarnings("unchecked")
    public V removeFirst() {
        if (this.size == 0) {
            throw new NoSuchElementException();
        } else {
            int pos = this.first;
            this.first = (int) this.link[pos];
            if (0 <= this.first) {
                this.link[this.first] |= 0xFFFFFFFF00000000L;
            }

            --this.size;
            Object v = this.value[pos];
            if (pos == this.n) {
                this.containsNullKey = false;
                this.value[this.n] = null;
            } else {
                this.shiftKeys(pos);
            }

            if (this.size < this.maxFill / 4 && this.n > 16) {
                this.rehash(this.n / 2);
            }

            return (V) v;
        }
    }

    @SuppressWarnings("unchecked")
    public V removeLast() {
        if (this.size == 0) {
            throw new NoSuchElementException();
        } else {
            int pos = this.last;
            this.last = (int) (this.link[pos] >>> 32);
            if (0 <= this.last) {
                this.link[this.last] |= 0xFFFFFFFFL;
            }

            --this.size;
            Object v = this.value[pos];
            if (pos == this.n) {
                this.containsNullKey = false;
                this.value[this.n] = null;
            } else {
                this.shiftKeys(pos);
            }

            if (this.size < this.maxFill / 4 && this.n > 16) {
                this.rehash(this.n / 2);
            }

            return (V) v;
        }
    }

    @SuppressWarnings("unchecked")
    public V get(Object k) {
        if (k == null) {
            return containsNullKey ? (V) value[n] : defRetValue;
        }

        final Object[] key = this.key;
        Object curr;
        int pos;

        // The starting point
        if ((curr = key[pos = mix(k.hashCode()) & mask]) == null) {
            return defRetValue;
        }
        if (k.equals(curr)) {
            return (V) value[pos];
        }

        // There's always an usused entry
        while (true) {
            if ((curr = key[pos = (pos + 1) & mask]) == null) {
                return defRetValue;
            }
            if (k.equals(curr)) {
                return (V) value[pos];
            }
        }
    }

    public boolean containsKey(Object k) {
        if (k == null) {
            return this.containsNullKey;
        } else {
            Object[] key = this.key;
            Object curr;
            int pos;
            if ((curr = key[pos = mix(k.hashCode()) & this.mask]) == null) {
                return false;
            } else if (k.equals(curr)) {
                return true;
            } else {
                while ((curr = key[pos = pos + 1 & this.mask]) != null) {
                    if (k.equals(curr)) {
                        return true;
                    }
                }

                return false;
            }
        }
    }

    public boolean containsValue(Object v) {
        Object[] value = this.value;
        Object[] key = this.key;
        if (containsNullKey && (value[n] == null && v == null) || value[n].equals(v)) {
            return true;
        }
        for (int i = n; i-- != 0;) {
            if (!(key[i] == null) && (value[i] == null && v == null) || value[i].equals(v)) {
                return true;
            }
        }
        return false;
    }

    public void clear() {
        if (size != 0) {
            size = 0;
            containsNullKey = false;
            Arrays.fill(key, (Object) null);
            Arrays.fill(value, (Object) null);
            first = last = -1;
        }
    }

    public int size() {
        return this.size;
    }

    public boolean isEmpty() {
        return this.size == 0;
    }

    protected void fixPointers(int i) {
        if (size == 0) {
            first = last = -1;
        } else if (first == i) {
            first = (int) link[i];
            if (0 <= first) {
                link[first] |= 0xFFFFFFFF00000000L;
            }
        } else if (last == i) {
            last = (int) (link[i] >>> 32);
            if (0 <= last) {
                link[last] |= 0xFFFFFFFFL;
            }
        } else {
            long linki = link[i];
            int prev = (int) (linki >>> 32);
            int next = (int) linki;
            link[prev] ^= (link[prev] ^ linki & 0xFFFFFFFFL) & 0xFFFFFFFFL;
            link[next] ^= (link[next] ^ linki & 0xFFFFFFFF00000000L) & 0xFFFFFFFF00000000L;
        }
    }

    protected void fixPointers(int s, int d) {
        if (size == 1) {
            first = last = d;
            link[d] = -1L;
        } else if (first == s) {
            first = d;
            link[(int) link[s]] ^= (link[(int) link[s]] ^ ((long) d & 0xFFFFFFFFL) << 32) & 0xFFFFFFFF00000000L;
            link[d] = link[s];
        } else if (last == s) {
            last = d;
            link[(int) (link[s] >>> 32)] ^= (link[(int) (link[s] >>> 32)] ^ (long) d & 0xFFFFFFFFL) & 0xFFFFFFFFL;
            link[d] = link[s];
        } else {
            long links = link[s];
            int prev = (int) (links >>> 32);
            int next = (int) links;
            link[prev] ^= (link[prev] ^ (long) d & 0xFFFFFFFFL) & 0xFFFFFFFFL;
            link[next] ^= (link[next] ^ ((long) d & 0xFFFFFFFFL) << 32) & 0xFFFFFFFF00000000L;
            link[d] = links;
        }
    }

    @SuppressWarnings("unchecked")
    public K firstKey() {
        if (size == 0) {
            throw new NoSuchElementException();
        } else {
            return (K) key[first];
        }
    }

    @SuppressWarnings("unchecked")
    public K lastKey() {
        if (size == 0) {
            throw new NoSuchElementException();
        } else {
            return (K) key[last];
        }
    }

    public Comparator<? super K> comparator() {
        return null;
    }

    public SortedMap<K, V> tailMap(K from) {
        throw new UnsupportedOperationException();
    }

    public SortedMap<K, V> headMap(K to) {
        throw new UnsupportedOperationException();
    }

    public SortedMap<K, V> subMap(K from, K to) {
        throw new UnsupportedOperationException();
    }

    public Iterable<Map.Entry<K, V>> fast() {
        if (fast == null) {
            fast = new Iterable<Entry<K, V>>() {
                public Iterator<Entry<K, V>> iterator() {
                    return new FastEntryIterator();
                }
            };
        }

        return fast;
    }

    public SortedSet<Map.Entry<K, V>> entrySet() {
        if (entries == null) {
            entries = new MapEntrySet();
        }

        return this.entries;
    }

    public SortedSet<K> keySet() {
        if (keys == null) {
            keys = new KeySet();
        }

        return keys;
    }

    public Collection<V> values() {
        if (values == null) {
            values = new AbstractObjectCollection<V>() {
                public Iterator<V> iterator() {
                    return new ValueIterator();
                }

                public int size() {
                    return size;
                }

                public boolean contains(Object v) {
                    return containsValue(v);
                }

                public void clear() {
                    OpenHashMap.this.clear();
                }
            };
        }

        return values;
    }

    /** Rehashes the map, making the table as small as possible.
     *
     * <P>This method rehashes the table to the smallest size satisfying the
     * load factor. It can be used when the set will not be changed anymore, so
     * to optimize access speed and size.
     *
     * <P>If the table size is already the minimum possible, this method
     * does nothing.
     *
     * @return true if there was enough memory to trim the map.
     * @see #trim(int)
     */
    public boolean trim() {
        int l = arraySize(size, f);
        if (l >= n) {
            return true;
        } else {
            try {
                rehash(l);
                return true;
            } catch (OutOfMemoryError cantDoIt) {
                return false;
            }
        }
    }

    /** Rehashes this map if the table is too large.
     *
     * <P>Let <var>N</var> be the smallest table size that can hold
     * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
     * table size is smaller than or equal to <var>N</var>, this method does
     * nothing. Otherwise, it rehashes this map in a table of size
     * <var>N</var>.
     *
     * <P>This method is useful when reusing maps.  {@linkplain #clear() Clearing a
     * map} leaves the table size untouched. If you are reusing a map
     * many times, you can call this method with a typical
     * size to avoid keeping around a very large table just
     * because of a few large transient maps.
     *
     * @param n the threshold for the trimming.
     * @return true if there was enough memory to trim the map.
     * @see #trim()
     */
    public boolean trim(int n) {
        int l = nextPowerOfTwo((int) Math.ceil((double) ((float) n / f)));
        if (n <= l) {
            return true;
        } else {
            try {
                rehash(l);
                return true;
            } catch (OutOfMemoryError cantDoIt) {
                return false;
            }
        }
    }

    /** Rehashes the map.
     *
     * <P>This method implements the basic rehashing strategy, and may be
     * overriden by subclasses implementing different rehashing strategies (e.g.,
     * disk-based rehashing). However, you should not override this method
     * unless you understand the internal workings of this class.
     *
     * @param newN the new size
     */
    protected void rehash(int newN) {
        Object[] key = this.key;
        Object[] value = this.value;

        int mask = newN - 1;
        Object[] newKey = new Object[newN + 1];
        Object[] newValue = new Object[newN + 1];

        int i = first, prev = -1, newPrev = -1, t, pos;
        final long[] link = this.link;
        final long[] newLink = new long[newN + 1];
        first = -1;

        for (int j = size; j-- != 0;) {
            if (key[i] == null) {
                pos = newN;
            } else {
                pos = mix(key[i].hashCode()) & mask;
                while (newKey[pos] != null) {
                    pos = ( pos + 1 ) & mask;
                }
                newKey[pos] = key[i];
            }

            newValue[pos] = value[i];

            if (prev != -1) {
                newLink[newPrev] ^= (newLink[newPrev] ^ (long) pos & 0xFFFFFFFFL) & 0xFFFFFFFFL;
                newLink[pos] ^= (newLink[pos] ^ ((long) newPrev & 0xFFFFFFFFL) << 32) & 0xFFFFFFFF00000000L;
                newPrev = pos;
            } else {
                newPrev = first = pos;
                newLink[pos] = -1L;
            }

            t = i;
            i = (int) link[i];
            prev = t;
        }

        this.link = newLink;
        this.last = newPrev;
        if (newPrev != -1) {
            newLink[newPrev] |= -1 & 0xFFFFFFFFL;
        }

        n = newN;
        this.mask = mask;
        maxFill = maxFill(n, f);
        this.key = newKey;
        this.value = newValue;
    }

    @SuppressWarnings("unchecked")
    public OpenHashMap<K, V> clone() {
        OpenHashMap<K, V> c;
        try {
            c = (OpenHashMap<K, V>) super.clone();
        } catch (CloneNotSupportedException cantHappen) {
            throw new InternalError();
        }

        c.fast = null;
        c.keys = null;
        c.values = null;
        c.entries = null;
        c.containsNullKey = containsNullKey;
        c.key = key.clone();
        c.value = value.clone();
        c.link = link.clone();
        return c;
    }

    public int hashCode() {
        int h = 0;
        for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
            while (key[i] == null) {
                ++i;
            }

            if (this != key[i]) {
                t = key[i].hashCode();
            }

            if (this != value[i]) {
                t ^= value[i] == null ? 0 : value[i].hashCode();
            }

            h += t;
            i++;
        }

        if (containsNullKey) {
            h += value[n] == null ? 0 : value[n].hashCode();
        }

        return h;
    }

    private void writeObject(ObjectOutputStream s) throws IOException {
        Object[] key = this.key;
        Object[] value = this.value;
        OpenHashMap<K, V>.MapIterator i = new MapIterator();
        s.defaultWriteObject();
        int j = this.size;

        while (j-- != 0) {
            int e = i.nextEntry();
            s.writeObject(key[e]);
            s.writeObject(value[e]);
        }

    }

    private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
        s.defaultReadObject();
        this.n = arraySize(this.size, this.f);
        this.maxFill = maxFill(this.n, this.f);
        this.mask = this.n - 1;
        Object[] key = this.key = new Object[this.n + 1];
        Object[] value = this.value = new Object[this.n + 1];
        long[] link = this.link = new long[this.n + 1];
        int prev = -1;
        this.first = this.last = -1;
        int i = this.size;

        while (i-- != 0) {
            Object k = s.readObject();
            Object v = s.readObject();
            int pos;
            if (k == null) {
                pos = this.n;
                this.containsNullKey = true;
            } else {
                for (pos = mix(k.hashCode()) & this.mask; key[pos] != null; pos = pos + 1 & this.mask) {
                    ;
                }

                key[pos] = k;
            }

            value[pos] = v;
            if (this.first != -1) {
                link[prev] ^= (link[prev] ^ (long) pos & 0xFFFFFFFFL) & 0xFFFFFFFFL;
                link[pos] ^= (link[pos] ^ ((long) prev & 0xFFFFFFFFL) << 32) & 0xFFFFFFFF00000000L;
                prev = pos;
            } else {
                prev = this.first = pos;
                link[pos] |= 0xFFFFFFFF00000000L;
            }
        }

        this.last = prev;
        if (prev != -1) {
            link[prev] |= 0xFFFFFFFFL;
        }

    }

    private final class ValueIterator extends MapIterator implements Iterator<V> {
        public ValueIterator() {
            super();
        }

        @SuppressWarnings("unchecked")
        public V next() {
            return (V) value[this.nextEntry()];
        }
    }

    private final class KeySet extends AbstractObjectSet<K> implements SortedSet<K> {
        private KeySet() {
        }

        public Iterator<K> iterator() {
            return new KeyIterator();
        }

        public int size() {
            return size;
        }

        public boolean contains(Object k) {
            return containsKey(k);
        }

        public boolean remove(Object k) {
            int oldSize = size;
            OpenHashMap.this.remove(k);
            return size != oldSize;
        }

        public void clear() {
            OpenHashMap.this.clear();
        }

        @SuppressWarnings("unchecked")
        public K first() {
            if (size == 0) {
                throw new NoSuchElementException();
            } else {
                return (K) key[first];
            }
        }

        @SuppressWarnings("unchecked")
        public K last() {
            if (size == 0) {
                throw new NoSuchElementException();
            } else {
                return (K) key[last];
            }
        }

        public Comparator<? super K> comparator() {
            return null;
        }

        public final SortedSet<K> tailSet(K from) {
            throw new UnsupportedOperationException();
        }

        public final SortedSet<K> headSet(K to) {
            throw new UnsupportedOperationException();
        }

        public final SortedSet<K> subSet(K from, K to) {
            throw new UnsupportedOperationException();
        }
    }

    private final class KeyIterator extends MapIterator implements Iterator<K> {
        public KeyIterator() {
            super();
        }

        @SuppressWarnings("unchecked")
        public K next() {
            return (K) key[this.nextEntry()];
        }
    }

    private final class MapEntrySet extends AbstractObjectSet<Entry<K, V>> implements SortedSet<Entry<K, V>> {
        private MapEntrySet() {
        }

        public EntryIterator iterator() {
            return new EntryIterator();
        }

        public Comparator<? super Entry<K, V>> comparator() {
            return null;
        }

        public SortedSet<Entry<K, V>> subSet(Entry<K, V> fromElement, Entry<K, V> toElement) {
            throw new UnsupportedOperationException();
        }

        public SortedSet<Entry<K, V>> headSet(Entry<K, V> toElement) {
            throw new UnsupportedOperationException();
        }

        public SortedSet<Entry<K, V>> tailSet(Entry<K, V> fromElement) {
            throw new UnsupportedOperationException();
        }

        public Entry<K, V> first() {
            if (size == 0) {
                throw new NoSuchElementException();
            } else {
                return new MapEntry(first);
            }
        }

        public Entry<K, V> last() {
            if (size == 0) {
                throw new NoSuchElementException();
            } else {
                return new MapEntry(last);
            }
        }

        public boolean contains(Object o) {
            if (!(o instanceof java.util.Map.Entry)) {
                return false;
            } else {
                Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
                Object k = e.getKey();
                if (k == null) {
                    if (containsNullKey) {
                        if (value[n] == null) {
                            if (e.getValue() != null) {
                                return false;
                            }
                        } else if (!value[n].equals(e.getValue())) {
                            return false;
                        }

                        return true;
                    }

                    return false;
                } else {
                    Object[] key = OpenHashMap.this.key;
                    Object curr;
                    int pos;
                    if ((curr = key[pos = mix(k.hashCode()) & mask]) == null) {
                        return false;
                    } else if (k.equals(curr)) {
                        return value[pos] == null ? e.getValue() == null : value[pos].equals(e.getValue());
                    } else {
                        while ((curr = key[pos = pos + 1 & mask]) != null) {
                            if (k.equals(curr)) {
                                return value[pos] == null ? e.getValue() == null : value[pos].equals(e.getValue());
                            }
                        }

                        return false;
                    }
                }
            }
        }

        public boolean remove(Object o) {
            if (!(o instanceof java.util.Map.Entry)) {
                return false;
            } else {
                Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
                Object k = e.getKey();
                Object v = e.getValue();
                if (k == null) {
                    if (containsNullKey) {
                        if (value[n] == null) {
                            if (v != null) {
                                return false;
                            }
                        } else if (!value[n].equals(v)) {
                            return false;
                        }

                        removeNullEntry();
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    Object[] key = OpenHashMap.this.key;
                    Object curr;
                    int pos;
                    if ((curr = key[pos = mix(k.hashCode()) & mask]) == null) {
                        return false;
                    } else if (curr.equals(k)) {
                        if (value[pos] == null) {
                            if (v != null) {
                                return false;
                            }
                        } else if (!value[pos].equals(v)) {
                            return false;
                        }

                        removeEntry(pos);
                        return true;
                    } else {
                        while (true) {
                            do {
                                if ((curr = key[pos = pos + 1 & mask]) == null) {
                                    return false;
                                }
                            } while (!curr.equals(k));

                            if (value[pos] == null) {
                                if (v == null) {
                                    break;
                                }
                            } else if (value[pos].equals(v)) {
                                break;
                            }
                        }

                        removeEntry(pos);
                        return true;
                    }
                }
            }
        }

        public int size() {
            return size;
        }

        public void clear() {
            OpenHashMap.this.clear();
        }
    }

    private class FastEntryIterator extends MapIterator implements Iterator<Entry<K, V>> {
        final MapEntry entry;

        public FastEntryIterator() {
            super();
            this.entry = new MapEntry();
        }

        public MapEntry next() {
            this.entry.index = this.nextEntry();
            return this.entry;
        }
    }

    private class EntryIterator extends MapIterator implements Iterator<Entry<K, V>> {
        private MapEntry entry;

        public EntryIterator() {
            super();
        }

        public MapEntry next() {
            return this.entry = new MapEntry(this.nextEntry());
        }

        public void remove() {
            super.remove();
            this.entry.index = -1;
        }
    }

    public static abstract class AbstractObjectSet<K> extends AbstractObjectCollection<K> implements Cloneable {
        public boolean equals(Object o) {
            if (o == this) {
                return true;
            } else if (!(o instanceof Set)) {
                return false;
            } else {
                Set<?> s = (Set<?>) o;
                return s.size() == this.size() && this.containsAll(s);
            }
        }

        public int hashCode() {
            int h = 0;
            int n = this.size();

            Object k;
            for (Iterator<K> i = this.iterator(); n-- != 0; h += k == null ? 0 : k.hashCode()) {
                k = i.next();
            }

            return h;
        }
    }

    private class MapIterator {
        /**
         * The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists).
         */
        int prev = -1;
        /**
         * The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists).
         */
        int next = -1;
        /**
         * The last entry that was returned (or -1 if we did not iterate or used {@link java.util.Iterator#remove()}).
         */
        int curr = -1;
        /**
         * The current index (in the sense of a {@link java.util.ListIterator}). Note that this value is not meaningful when this iterator has been created using the nonempty constructor.
         */
        int index = -1;

        private MapIterator() {
            this.next = first;
            this.index = 0;
        }

        public boolean hasNext() {
            return this.next != -1;
        }

        private void ensureIndexKnown() {
            if (index < 0) {
                if (prev == -1) {
                    index = 0;
                } else if (next == -1) {
                    index = size;
                } else {
                    int pos = first;
                    for (index = 1; pos != prev; ++index) {
                        pos = (int) link[pos];
                    }
                }
            }
        }

        public int nextEntry() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            } else {
                curr = next;
                next = (int) link[curr];
                prev = curr;
                if (index >= 0) {
                    ++index;
                }
                return curr;
            }
        }

        public void remove() {
            this.ensureIndexKnown();
            if (curr == -1) throw new IllegalStateException();

            if (curr == prev) {
                    /* If the last operation was a next(), we are removing an entry that preceeds
                     * the current index, and thus we must decrement it. */
                index--;
                prev = (int) (link[curr] >>> 32);
            } else {
                next = (int) link[curr];
            }

            size--;
            /* Now we manually fix the pointers. Because of our knowledge of next
             * and prev, this is going to be faster than calling fixPointers(). */
            if (prev == -1) {
                first = next;
            } else {
                link[prev] ^= (link[prev] ^ (long) next & 0xFFFFFFFFL) & 0xFFFFFFFFL;
            }
            if (next == -1) {
                last = prev;
            } else {
                link[next] ^= (link[next] ^ ((long) prev & 0xFFFFFFFFL) << 32) & 0xFFFFFFFF00000000L;
            }

            int last, slot, pos = curr;
            curr = -1;

            if (pos == n) {
                containsNullKey = false;
                value[n] = null;
            } else {
                Object curr;
                Object[] key = OpenHashMap.this.key;
                // We have to horribly duplicate the shiftKeys() code because we need to update next/prev.
                for (; ; ) {
                    pos = ((last = pos) + 1) & mask;
                    for (; ; ) {
                        if ((curr = key[pos]) == null) {
                            key[last] = null;
                            value[last] = null;
                            return;
                        }
                        slot = mix(curr.hashCode()) & mask;
                        if (last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos) break;
                        pos = (pos + 1) & mask;
                    }
                    key[last] = curr;
                    value[last] = value[pos];
                    if (next == pos) next = last;
                    if (prev == pos) prev = last;
                    fixPointers(pos, last);
                }
            }
        }
    }

    final class MapEntry implements Entry<K, V> {
        int index;

        MapEntry(int index) {
            this.index = index;
        }

        MapEntry() {
        }

        @SuppressWarnings("unchecked")
        public K getKey() {
            return (K) key[this.index];
        }

        @SuppressWarnings("unchecked")
        public V getValue() {
            return (V) value[this.index];
        }

        @SuppressWarnings("unchecked")
        public V setValue(V v) {
            Object oldValue = value[this.index];
            value[this.index] = v;
            return (V) oldValue;
        }

        public boolean equals(Object o) {
            if (!(o instanceof Entry)) {
                return false;
            } else {
                Entry<?, ?> e = (Entry<?, ?>) o;
                if (key[this.index] == null) {
                    if (e.getKey() != null) {
                        return false;
                    }
                } else if (!key[this.index].equals(e.getKey())) {
                    return false;
                }

                if (value[this.index] == null) {
                    if (e.getValue() != null) {
                        return false;
                    }
                } else if (!value[this.index].equals(e.getValue())) {
                    return false;
                }

                return true;
            }
        }

        public int hashCode() {
            return (key[this.index] == null ? 0 :
                    key[this.index].hashCode()) ^ (value[this.index] == null ? 0 :
                    value[this.index].hashCode());
        }

        public String toString() {
            return key[this.index] + "=>" + value[this.index];
        }
    }


    public static abstract class AbstractObjectCollection<K> extends AbstractCollection<K> {
        protected AbstractObjectCollection() {
        }

        public Object[] toArray() {
            Object[] a = new Object[this.size()];
            unwrap(this.iterator(), a);
            return a;
        }

        @SuppressWarnings("unchecked")
        public <T> T[] toArray(T[] a) {
            if (a.length < this.size()) {
                a = (T[]) Array.newInstance(a.getClass().getComponentType(), this.size());
            }
            unwrap(this.iterator(), a);
            return a;
        }

        public boolean addAll(Collection<? extends K> c) {
            boolean retVal = false;
            Iterator<? extends K> i = c.iterator();
            int n = c.size();

            while (n-- != 0) {
                if (this.add(i.next())) {
                    retVal = true;
                }
            }

            return retVal;
        }

        public boolean add(K k) {
            throw new UnsupportedOperationException();
        }

        public boolean containsAll(Collection<?> c) {
            int n = c.size();
            Iterator<?> i = c.iterator();

            do {
                if (n-- == 0) {
                    return true;
                }
            } while (this.contains(i.next()));

            return false;
        }

        public boolean retainAll(Collection<?> c) {
            boolean retVal = false;
            int n = this.size();
            Iterator<K> i = this.iterator();

            while (n-- != 0) {
                if (!c.contains(i.next())) {
                    i.remove();
                    retVal = true;
                }
            }

            return retVal;
        }

        public boolean removeAll(Collection<?> c) {
            boolean retVal = false;
            int n = c.size();
            Iterator<?> i = c.iterator();

            while (n-- != 0) {
                if (this.remove(i.next())) {
                    retVal = true;
                }
            }

            return retVal;
        }

        public boolean isEmpty() {
            return this.size() == 0;
        }

        public String toString() {
            StringBuilder s = new StringBuilder();
            Iterator<K> i = this.iterator();
            int n = this.size();
            boolean first = true;
            s.append("{");

            while (n-- != 0) {
                if (first) {
                    first = false;
                } else {
                    s.append(", ");
                }

                Object k = i.next();
                if (this == k) {
                    s.append("(this collection)");
                } else {
                    s.append(String.valueOf(k));
                }
            }

            s.append("}");
            return s.toString();
        }
    }

    private static int arraySize(int expected, float f) {
        long s = Math.max(2L, nextPowerOfTwo((long) Math.ceil((double) ((float) expected / f))));
        if (s > 0x40000000L) {
            throw new IllegalArgumentException("Too large (" + expected + " expected elements with load factor " + f + ")");
        } else {
            return (int) s;
        }
    }

    private static int maxFill(int n, float f) {
        return Math.min((int) Math.ceil((double) ((float) n * f)), n - 1);
    }

    private static int nextPowerOfTwo(int x) {
        if (x == 0) {
            return 1;
        } else {
            --x;
            x |= x >> 1;
            x |= x >> 2;
            x |= x >> 4;
            x |= x >> 8;
            return (x | x >> 16) + 1;
        }
    }

    private static long nextPowerOfTwo(long x) {
        if (x == 0L) {
            return 1L;
        } else {
            --x;
            x |= x >> 1;
            x |= x >> 2;
            x |= x >> 4;
            x |= x >> 8;
            x |= x >> 16;
            return (x | x >> 32) + 1L;
        }
    }

    private static int mix(int x) {
        int h = x * -1640531527;
        return h ^ h >>> 16;
    }

    private static <K> int unwrap(Iterator<? extends K> i, K[] array, int offset, int max) {
        if (max < 0) {
            throw new IllegalArgumentException("The maximum number of elements (" + max + ") is negative");
        } else if (offset >= 0 && offset + max <= array.length) {
            int j;
            for (j = max; j-- != 0 && i.hasNext(); array[offset++] = i.next()) {
                ;
            }

            return max - j - 1;
        } else {
            throw new IllegalArgumentException();
        }
    }

    private static <K> int unwrap(Iterator<? extends K> i, K[] array) {
        return unwrap(i, array, 0, array.length);
    }
}
