package com.google.gson.internal;
import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Set;
public final class StringMap<V> extends AbstractMap<String, V>
{
private LinkedEntry<V> header;
private static final Map.Entry[] EMPTY_TABLE = new LinkedEntry[2];
private LinkedEntry<V>[] table;
private int size;
private int threshold;
private Set<String> keySet;
private Set<Map.Entry<String, V>> entrySet;
private Collection<V> values;
private static final int seed = new Random().nextInt();
public StringMap()
{
this.table = ((LinkedEntry[])EMPTY_TABLE);
this.threshold = -1;
this.header = new LinkedEntry();
}
public int size() {
return this.size;
}
public boolean containsKey(Object key) {
return ((key instanceof String)) && (getEntry((String)key) != null);
}
public V get(Object key) {
if ((key instanceof String)) {
LinkedEntry entry = getEntry((String)key);
return entry != null ? entry.value : null;
}
return null;
}
private LinkedEntry<V> getEntry(String key)
{
if (key == null) {
return null;
}
int hash = hash(key);
LinkedEntry[] tab = this.table;
for (LinkedEntry e = tab[(hash & tab.length - 1)]; e != null; e = e.next) {
String eKey = e.key;
if ((eKey == key) || ((e.hash == hash) && (key.equals(eKey)))) {
return e;
}
}
return null;
}
public V put(String key, V value) {
if (key == null) {
throw new NullPointerException("key == null");
}
int hash = hash(key);
LinkedEntry[] tab = this.table;
int index = hash & tab.length - 1;
for (LinkedEntry e = tab[index]; e != null; e = e.next) {
if ((e.hash == hash) && (key.equals(e.key))) {
Object oldValue = e.value;
e.value = value;
return oldValue;
}
}
if (this.size++ > this.threshold) {
tab = doubleCapacity();
index = hash & tab.length - 1;
}
addNewEntry(key, value, hash, index);
return null;
}
private void addNewEntry(String key, V value, int hash, int index) {
LinkedEntry header = this.header;
LinkedEntry oldTail = header.prv;
LinkedEntry newTail = new LinkedEntry(key, value, hash, this.table[index], header, oldTail);
LinkedEntry tmp52_49 = (header.prv = newTail); oldTail.nxt = tmp52_49; this.table[index] = tmp52_49;
}
private LinkedEntry<V>[] makeTable(int newCapacity)
{
LinkedEntry[] newTable = (LinkedEntry[])new LinkedEntry[newCapacity];
this.table = newTable;
this.threshold = ((newCapacity >> 1) + (newCapacity >> 2));
return newTable;
}
private LinkedEntry<V>[] doubleCapacity()
{
LinkedEntry[] oldTable = this.table;
int oldCapacity = oldTable.length;
if (oldCapacity == 1073741824) {
return oldTable;
}
int newCapacity = oldCapacity * 2;
LinkedEntry[] newTable = makeTable(newCapacity);
if (this.size == 0) {
return newTable;
}
for (int j = 0; j < oldCapacity; j++)
{
LinkedEntry e = oldTable[j];
if (e != null)
{
int highBit = e.hash & oldCapacity;
LinkedEntry broken = null;
newTable[(j | highBit)] = e;
for (LinkedEntry n = e.next; n != null; n = n.next) {
int nextHighBit = n.hash & oldCapacity;
if (nextHighBit != highBit) {
if (broken == null)
newTable[(j | nextHighBit)] = n;
else {
broken.next = n;
}
broken = e;
highBit = nextHighBit;
}
e = n;
}
if (broken != null)
broken.next = null;
}
}
return newTable;
}
public V remove(Object key) {
if ((key == null) || (!(key instanceof String))) {
return null;
}
int hash = hash((String)key);
LinkedEntry[] tab = this.table;
int index = hash & tab.length - 1;
LinkedEntry e = tab[index]; LinkedEntry prev = null;
for (; e != null; e = e.next) {
if ((e.hash == hash) && (key.equals(e.key))) {
if (prev == null)
tab[index] = e.next;
else {
prev.next = e.next;
}
this.size -= 1;
unlink(e);
return e.value;
}
prev = e;
}
return null;
}
private void unlink(LinkedEntry<V> e) {
e.prv.nxt = e.nxt;
e.nxt.prv = e.prv;
e.nxt = (e.prv = null);
}
public void clear() {
if (this.size != 0) {
Arrays.fill(this.table, null);
this.size = 0;
}
LinkedEntry header = this.header;
for (LinkedEntry e = header.nxt; e != header; ) {
LinkedEntry nxt = e.nxt;
e.nxt = (e.prv = null);
e = nxt;
}
header.nxt = (header.prv = header);
}
public Set<String> keySet() {
Set ks = this.keySet;
return this.keySet = new KeySet(null);
}
public Collection<V> values() {
Collection vs = this.values;
return this.values = new Values(null);
}
public Set<Map.Entry<String, V>> entrySet() {
Set es = this.entrySet;
return this.entrySet = new EntrySet(null);
}
private boolean removeMapping(Object key, Object value)
{
if ((key == null) || (!(key instanceof String))) {
return false;
}
int hash = hash((String)key);
LinkedEntry[] tab = this.table;
int index = hash & tab.length - 1;
LinkedEntry e = tab[index]; for (LinkedEntry prev = null; e != null; e = e.next) {
if ((e.hash == hash) && (key.equals(e.key))) {
if (value == null ? e.value != null : !value.equals(e.value)) {
return false;
}
if (prev == null)
tab[index] = e.next;
else {
prev.next = e.next;
}
this.size -= 1;
unlink(e);
return true;
}
prev = e;
}
return false;
}
private static int hash(String key)
{
int h = seed;
for (int i = 0; i < key.length(); i++) {
int h2 = h + key.charAt(i);
int h3 = h2 + h2 << 10;
h = h3 ^ h3 >>> 6;
}
h ^= h >>> 20 ^ h >>> 12;
return h ^ h >>> 7 ^ h >>> 4;
}
private final class EntrySet extends AbstractSet<Map.Entry<String, V>>
{
private EntrySet()
{
}
public Iterator<Map.Entry<String, V>> iterator()
{
// Byte code:
// 0: new 34 com/google/gson/internal/StringMap$EntrySet$1
// 3: dup
// 4: aload_0
// 5: invokespecial 74 com/google/gson/internal/StringMap$EntrySet$1:<init> (Lcom/google/gson/internal/StringMap$EntrySet;)V
// 8: areturn
}
public boolean contains(Object o)
{
if (!(o instanceof Map.Entry)) {
return false;
}
Map.Entry e = (Map.Entry)o;
Object mappedValue = StringMap.this.get(e.getKey());
return (mappedValue != null) && (mappedValue.equals(e.getValue()));
}
public boolean remove(Object o) {
if (!(o instanceof Map.Entry)) {
return false;
}
Map.Entry e = (Map.Entry)o;
return StringMap.this.removeMapping(e.getKey(), e.getValue());
}
public int size() {
return StringMap.this.size;
}
public void clear() {
StringMap.this.clear();
}
}
private final class KeySet extends AbstractSet<String>
{
private KeySet()
{
}
public Iterator<String> iterator()
{
// Byte code:
// 0: new 26 com/google/gson/internal/StringMap$KeySet$1
// 3: dup
// 4: aload_0
// 5: invokespecial 56 com/google/gson/internal/StringMap$KeySet$1:<init> (Lcom/google/gson/internal/StringMap$KeySet;)V
// 8: areturn
}
public int size()
{
return StringMap.this.size;
}
public boolean contains(Object o) {
return StringMap.this.containsKey(o);
}
public boolean remove(Object o) {
int oldSize = StringMap.this.size;
StringMap.this.remove(o);
return StringMap.this.size != oldSize;
}
public void clear() {
StringMap.this.clear();
}
}
static class LinkedEntry<V>
implements Map.Entry<String, V>
{
final String key;
V value;
final int hash;
LinkedEntry<V> next;
LinkedEntry<V> nxt;
LinkedEntry<V> prv;
LinkedEntry()
{
this(null, null, 0, null, null, null);
this.prv = this; this.nxt = this;
}
LinkedEntry(String key, V value, int hash, LinkedEntry<V> next, LinkedEntry<V> nxt, LinkedEntry<V> prv)
{
this.key = key;
this.value = value;
this.hash = hash;
this.next = next;
this.nxt = nxt;
this.prv = prv;
}
public final String getKey() {
return this.key;
}
public final V getValue() {
return this.value;
}
public final V setValue(V value) {
Object oldValue = this.value;
this.value = value;
return oldValue;
}
public final boolean equals(Object o) {
if (!(o instanceof Map.Entry)) {
return false;
}
Map.Entry e = (Map.Entry)o;
Object eValue = e.getValue();
return (this.key.equals(e.getKey())) && (this.value == null ? eValue == null : this.value.equals(eValue));
}
public final int hashCode()
{
return (this.key == null ? 0 : this.key.hashCode()) ^ (this.value == null ? 0 : this.value.hashCode());
}
public final String toString() {
return this.key + "=" + this.value;
}
}
private abstract class LinkedHashIterator<T>
implements Iterator<T>
{
StringMap.LinkedEntry<V> next = StringMap.this.header.nxt;
StringMap.LinkedEntry<V> lastReturned = null;
private LinkedHashIterator() { }
public final boolean hasNext() { return this.next != StringMap.this.header; }
final StringMap.LinkedEntry<V> nextEntry()
{
StringMap.LinkedEntry e = this.next;
if (e == StringMap.this.header) {
throw new NoSuchElementException();
}
this.next = e.nxt;
return this.lastReturned = e;
}
public final void remove() {
if (this.lastReturned == null) {
throw new IllegalStateException();
}
StringMap.this.remove(this.lastReturned.key);
this.lastReturned = null;
}
}
private final class Values extends AbstractCollection<V>
{
private Values()
{
}
public Iterator<V> iterator()
{
// Byte code:
// 0: new 23 com/google/gson/internal/StringMap$Values$1
// 3: dup
// 4: aload_0
// 5: invokespecial 50 com/google/gson/internal/StringMap$Values$1:<init> (Lcom/google/gson/internal/StringMap$Values;)V
// 8: areturn
}
public int size()
{
return StringMap.this.size;
}
public boolean contains(Object o) {
return StringMap.this.containsValue(o);
}
public void clear() {
StringMap.this.clear();
}
}
}