diff options
Diffstat (limited to 'third_party/protobuf/3.2.0/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java')
-rw-r--r-- | third_party/protobuf/3.2.0/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java | 673 |
1 files changed, 0 insertions, 673 deletions
diff --git a/third_party/protobuf/3.2.0/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java b/third_party/protobuf/3.2.0/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java deleted file mode 100644 index 66033f58e5..0000000000 --- a/third_party/protobuf/3.2.0/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java +++ /dev/null @@ -1,673 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf; - -import java.util.AbstractMap; -import java.util.AbstractSet; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; - -/** - * A custom map implementation from FieldDescriptor to Object optimized to - * minimize the number of memory allocations for instances with a small number - * of mappings. The implementation stores the first {@code k} mappings in an - * array for a configurable value of {@code k}, allowing direct access to the - * corresponding {@code Entry}s without the need to create an Iterator. The - * remaining entries are stored in an overflow map. Iteration over the entries - * in the map should be done as follows: - * - * <pre> {@code - * for (int i = 0; i < fieldMap.getNumArrayEntries(); i++) { - * process(fieldMap.getArrayEntryAt(i)); - * } - * for (Map.Entry<K, V> entry : fieldMap.getOverflowEntries()) { - * process(entry); - * } - * }</pre> - * - * The resulting iteration is in order of ascending field tag number. The - * object returned by {@link #entrySet()} adheres to the same contract but is - * less efficient as it necessarily involves creating an object for iteration. - * <p> - * The tradeoff for this memory efficiency is that the worst case running time - * of the {@code put()} operation is {@code O(k + lg n)}, which happens when - * entries are added in descending order. {@code k} should be chosen such that - * it covers enough common cases without adversely affecting larger maps. In - * practice, the worst case scenario does not happen for extensions because - * extension fields are serialized and deserialized in order of ascending tag - * number, but the worst case scenario can happen for DynamicMessages. - * <p> - * The running time for all other operations is similar to that of - * {@code TreeMap}. - * <p> - * Instances are not thread-safe until {@link #makeImmutable()} is called, - * after which any modifying operation will result in an - * {@link UnsupportedOperationException}. - * - * @author darick@google.com Darick Tong - */ -// This class is final for all intents and purposes because the constructor is -// private. However, the FieldDescriptor-specific logic is encapsulated in -// a subclass to aid testability of the core logic. -class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> { - - /** - * Creates a new instance for mapping FieldDescriptors to their values. - * The {@link #makeImmutable()} implementation will convert the List values - * of any repeated fields to unmodifiable lists. - * - * @param arraySize The size of the entry array containing the - * lexicographically smallest mappings. - */ - static <FieldDescriptorType extends - FieldSet.FieldDescriptorLite<FieldDescriptorType>> - SmallSortedMap<FieldDescriptorType, Object> newFieldMap(int arraySize) { - return new SmallSortedMap<FieldDescriptorType, Object>(arraySize) { - @Override - @SuppressWarnings("unchecked") - public void makeImmutable() { - if (!isImmutable()) { - for (int i = 0; i < getNumArrayEntries(); i++) { - final Map.Entry<FieldDescriptorType, Object> entry = - getArrayEntryAt(i); - if (entry.getKey().isRepeated()) { - final List value = (List) entry.getValue(); - entry.setValue(Collections.unmodifiableList(value)); - } - } - for (Map.Entry<FieldDescriptorType, Object> entry : - getOverflowEntries()) { - if (entry.getKey().isRepeated()) { - final List value = (List) entry.getValue(); - entry.setValue(Collections.unmodifiableList(value)); - } - } - } - super.makeImmutable(); - } - }; - } - - /** - * Creates a new instance for testing. - * - * @param arraySize The size of the entry array containing the - * lexicographically smallest mappings. - */ - static <K extends Comparable<K>, V> SmallSortedMap<K, V> newInstanceForTest( - int arraySize) { - return new SmallSortedMap<K, V>(arraySize); - } - - private final int maxArraySize; - // The "entry array" is actually a List because generic arrays are not - // allowed. ArrayList also nicely handles the entry shifting on inserts and - // removes. - private List<Entry> entryList; - private Map<K, V> overflowEntries; - private boolean isImmutable; - // The EntrySet is a stateless view of the Map. It's initialized the first - // time it is requested and reused henceforth. - private volatile EntrySet lazyEntrySet; - - /** - * @code arraySize Size of the array in which the lexicographically smallest - * mappings are stored. (i.e. the {@code k} referred to in the class - * documentation). - */ - private SmallSortedMap(int arraySize) { - this.maxArraySize = arraySize; - this.entryList = Collections.emptyList(); - this.overflowEntries = Collections.emptyMap(); - } - - /** Make this map immutable from this point forward. */ - public void makeImmutable() { - if (!isImmutable) { - // Note: There's no need to wrap the entryList in an unmodifiableList - // because none of the list's accessors are exposed. The iterator() of - // overflowEntries, on the other hand, is exposed so it must be made - // unmodifiable. - overflowEntries = overflowEntries.isEmpty() ? - Collections.<K, V>emptyMap() : - Collections.unmodifiableMap(overflowEntries); - isImmutable = true; - } - } - - /** @return Whether {@link #makeImmutable()} has been called. */ - public boolean isImmutable() { - return isImmutable; - } - - /** @return The number of entries in the entry array. */ - public int getNumArrayEntries() { - return entryList.size(); - } - - /** @return The array entry at the given {@code index}. */ - public Map.Entry<K, V> getArrayEntryAt(int index) { - return entryList.get(index); - } - - /** @return There number of overflow entries. */ - public int getNumOverflowEntries() { - return overflowEntries.size(); - } - - /** @return An iterable over the overflow entries. */ - public Iterable<Map.Entry<K, V>> getOverflowEntries() { - return overflowEntries.isEmpty() ? - EmptySet.<Map.Entry<K, V>>iterable() : - overflowEntries.entrySet(); - } - - - @Override - public int size() { - return entryList.size() + overflowEntries.size(); - } - - /** - * The implementation throws a {@code ClassCastException} if o is not an - * object of type {@code K}. - * - * {@inheritDoc} - */ - @Override - public boolean containsKey(Object o) { - @SuppressWarnings("unchecked") - final K key = (K) o; - return binarySearchInArray(key) >= 0 || overflowEntries.containsKey(key); - } - - /** - * The implementation throws a {@code ClassCastException} if o is not an - * object of type {@code K}. - * - * {@inheritDoc} - */ - @Override - public V get(Object o) { - @SuppressWarnings("unchecked") - final K key = (K) o; - final int index = binarySearchInArray(key); - if (index >= 0) { - return entryList.get(index).getValue(); - } - return overflowEntries.get(key); - } - - @Override - public V put(K key, V value) { - checkMutable(); - final int index = binarySearchInArray(key); - if (index >= 0) { - // Replace existing array entry. - return entryList.get(index).setValue(value); - } - ensureEntryArrayMutable(); - final int insertionPoint = -(index + 1); - if (insertionPoint >= maxArraySize) { - // Put directly in overflow. - return getOverflowEntriesMutable().put(key, value); - } - // Insert new Entry in array. - if (entryList.size() == maxArraySize) { - // Shift the last array entry into overflow. - final Entry lastEntryInArray = entryList.remove(maxArraySize - 1); - getOverflowEntriesMutable().put(lastEntryInArray.getKey(), - lastEntryInArray.getValue()); - } - entryList.add(insertionPoint, new Entry(key, value)); - return null; - } - - @Override - public void clear() { - checkMutable(); - if (!entryList.isEmpty()) { - entryList.clear(); - } - if (!overflowEntries.isEmpty()) { - overflowEntries.clear(); - } - } - - /** - * The implementation throws a {@code ClassCastException} if o is not an - * object of type {@code K}. - * - * {@inheritDoc} - */ - @Override - public V remove(Object o) { - checkMutable(); - @SuppressWarnings("unchecked") - final K key = (K) o; - final int index = binarySearchInArray(key); - if (index >= 0) { - return removeArrayEntryAt(index); - } - // overflowEntries might be Collections.unmodifiableMap(), so only - // call remove() if it is non-empty. - if (overflowEntries.isEmpty()) { - return null; - } else { - return overflowEntries.remove(key); - } - } - - private V removeArrayEntryAt(int index) { - checkMutable(); - final V removed = entryList.remove(index).getValue(); - if (!overflowEntries.isEmpty()) { - // Shift the first entry in the overflow to be the last entry in the - // array. - final Iterator<Map.Entry<K, V>> iterator = - getOverflowEntriesMutable().entrySet().iterator(); - entryList.add(new Entry(iterator.next())); - iterator.remove(); - } - return removed; - } - - /** - * @param key The key to find in the entry array. - * @return The returned integer position follows the same semantics as the - * value returned by {@link java.util.Arrays#binarySearch()}. - */ - private int binarySearchInArray(K key) { - int left = 0; - int right = entryList.size() - 1; - - // Optimization: For the common case in which entries are added in - // ascending tag order, check the largest element in the array before - // doing a full binary search. - if (right >= 0) { - int cmp = key.compareTo(entryList.get(right).getKey()); - if (cmp > 0) { - return -(right + 2); // Insert point is after "right". - } else if (cmp == 0) { - return right; - } - } - - while (left <= right) { - int mid = (left + right) / 2; - int cmp = key.compareTo(entryList.get(mid).getKey()); - if (cmp < 0) { - right = mid - 1; - } else if (cmp > 0) { - left = mid + 1; - } else { - return mid; - } - } - return -(left + 1); - } - - /** - * Similar to the AbstractMap implementation of {@code keySet()} and - * {@code values()}, the entry set is created the first time this method is - * called, and returned in response to all subsequent calls. - * - * {@inheritDoc} - */ - @Override - public Set<Map.Entry<K, V>> entrySet() { - if (lazyEntrySet == null) { - lazyEntrySet = new EntrySet(); - } - return lazyEntrySet; - } - - - /** - * @throws UnsupportedOperationException if {@link #makeImmutable()} has - * has been called. - */ - private void checkMutable() { - if (isImmutable) { - throw new UnsupportedOperationException(); - } - } - - /** - * @return a {@link SortedMap} to which overflow entries mappings can be - * added or removed. - * @throws UnsupportedOperationException if {@link #makeImmutable()} has been - * called. - */ - @SuppressWarnings("unchecked") - private SortedMap<K, V> getOverflowEntriesMutable() { - checkMutable(); - if (overflowEntries.isEmpty() && !(overflowEntries instanceof TreeMap)) { - overflowEntries = new TreeMap<K, V>(); - } - return (SortedMap<K, V>) overflowEntries; - } - - /** - * Lazily creates the entry list. Any code that adds to the list must first - * call this method. - */ - private void ensureEntryArrayMutable() { - checkMutable(); - if (entryList.isEmpty() && !(entryList instanceof ArrayList)) { - entryList = new ArrayList<Entry>(maxArraySize); - } - } - - /** - * Entry implementation that implements Comparable in order to support - * binary search within the entry array. Also checks mutability in - * {@link #setValue()}. - */ - private class Entry implements Map.Entry<K, V>, Comparable<Entry> { - - private final K key; - private V value; - - Entry(Map.Entry<K, V> copy) { - this(copy.getKey(), copy.getValue()); - } - - Entry(K key, V value) { - this.key = key; - this.value = value; - } - - @Override - public K getKey() { - return key; - } - - @Override - public V getValue() { - return value; - } - - @Override - public int compareTo(Entry other) { - return getKey().compareTo(other.getKey()); - } - - @Override - public V setValue(V newValue) { - checkMutable(); - final V oldValue = this.value; - this.value = newValue; - return oldValue; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof Map.Entry)) { - return false; - } - @SuppressWarnings("unchecked") - Map.Entry<?, ?> other = (Map.Entry<?, ?>) o; - return equals(key, other.getKey()) && equals(value, other.getValue()); - } - - @Override - public int hashCode() { - return (key == null ? 0 : key.hashCode()) ^ - (value == null ? 0 : value.hashCode()); - } - - @Override - public String toString() { - return key + "=" + value; - } - - /** equals() that handles null values. */ - private boolean equals(Object o1, Object o2) { - return o1 == null ? o2 == null : o1.equals(o2); - } - } - - /** - * Stateless view of the entries in the field map. - */ - private class EntrySet extends AbstractSet<Map.Entry<K, V>> { - - @Override - public Iterator<Map.Entry<K, V>> iterator() { - return new EntryIterator(); - } - - @Override - public int size() { - return SmallSortedMap.this.size(); - } - - /** - * Throws a {@link ClassCastException} if o is not of the expected type. - * - * {@inheritDoc} - */ - @Override - public boolean contains(Object o) { - @SuppressWarnings("unchecked") - final Map.Entry<K, V> entry = (Map.Entry<K, V>) o; - final V existing = get(entry.getKey()); - final V value = entry.getValue(); - return existing == value || - (existing != null && existing.equals(value)); - } - - @Override - public boolean add(Map.Entry<K, V> entry) { - if (!contains(entry)) { - put(entry.getKey(), entry.getValue()); - return true; - } - return false; - } - - /** - * Throws a {@link ClassCastException} if o is not of the expected type. - * - * {@inheritDoc} - */ - @Override - public boolean remove(Object o) { - @SuppressWarnings("unchecked") - final Map.Entry<K, V> entry = (Map.Entry<K, V>) o; - if (contains(entry)) { - SmallSortedMap.this.remove(entry.getKey()); - return true; - } - return false; - } - - @Override - public void clear() { - SmallSortedMap.this.clear(); - } - } - - - /** - * Iterator implementation that switches from the entry array to the overflow - * entries appropriately. - */ - private class EntryIterator implements Iterator<Map.Entry<K, V>> { - - private int pos = -1; - private boolean nextCalledBeforeRemove; - private Iterator<Map.Entry<K, V>> lazyOverflowIterator; - - @Override - public boolean hasNext() { - return (pos + 1) < entryList.size() || - getOverflowIterator().hasNext(); - } - - @Override - public Map.Entry<K, V> next() { - nextCalledBeforeRemove = true; - // Always increment pos so that we know whether the last returned value - // was from the array or from overflow. - if (++pos < entryList.size()) { - return entryList.get(pos); - } - return getOverflowIterator().next(); - } - - @Override - public void remove() { - if (!nextCalledBeforeRemove) { - throw new IllegalStateException("remove() was called before next()"); - } - nextCalledBeforeRemove = false; - checkMutable(); - - if (pos < entryList.size()) { - removeArrayEntryAt(pos--); - } else { - getOverflowIterator().remove(); - } - } - - /** - * It is important to create the overflow iterator only after the array - * entries have been iterated over because the overflow entry set changes - * when the client calls remove() on the array entries, which invalidates - * any existing iterators. - */ - private Iterator<Map.Entry<K, V>> getOverflowIterator() { - if (lazyOverflowIterator == null) { - lazyOverflowIterator = overflowEntries.entrySet().iterator(); - } - return lazyOverflowIterator; - } - } - - /** - * Helper class that holds immutable instances of an Iterable/Iterator that - * we return when the overflow entries is empty. This eliminates the creation - * of an Iterator object when there is nothing to iterate over. - */ - private static class EmptySet { - - private static final Iterator<Object> ITERATOR = - new Iterator<Object>() { - @Override - public boolean hasNext() { - return false; - } - @Override - public Object next() { - throw new NoSuchElementException(); - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - - private static final Iterable<Object> ITERABLE = - new Iterable<Object>() { - @Override - public Iterator<Object> iterator() { - return ITERATOR; - } - }; - - @SuppressWarnings("unchecked") - static <T> Iterable<T> iterable() { - return (Iterable<T>) ITERABLE; - } - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (!(o instanceof SmallSortedMap)) { - return super.equals(o); - } - - SmallSortedMap<?, ?> other = (SmallSortedMap<?, ?>) o; - final int size = size(); - if (size != other.size()) { - return false; - } - - // Best effort try to avoid allocating an entry set. - final int numArrayEntries = getNumArrayEntries(); - if (numArrayEntries != other.getNumArrayEntries()) { - return entrySet().equals(other.entrySet()); - } - - for (int i = 0; i < numArrayEntries; i++) { - if (!getArrayEntryAt(i).equals(other.getArrayEntryAt(i))) { - return false; - } - } - - if (numArrayEntries != size) { - return overflowEntries.equals(other.overflowEntries); - } - - - return true; - } - - @Override - public int hashCode() { - int h = 0; - final int listSize = getNumArrayEntries(); - for (int i = 0; i < listSize; i++) { - h += entryList.get(i).hashCode(); - } - // Avoid the iterator allocation if possible. - if (getNumOverflowEntries() > 0) { - h += overflowEntries.hashCode(); - } - return h; - } -} |