package net.minecraft.util;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.util.HashSet;
import java.util.Set;
public class IntHashMap
{
/** An array of HashEntries representing the heads of hash slot lists */
private transient IntHashMapEntry[] slots = new IntHashMapEntry[16];
/** The number of items stored in this map */
private transient int count;
/** The grow threshold */
private int threshold = 12;
/** The scale factor used to determine when to grow the table */
private final float growFactor = 0.75F;
/** A serial stamp used to mark changes */
private transient volatile int versionStamp;
/** The set of all the keys stored in this MCHash object */
private Set keySet = new HashSet();
/**
* Makes the passed in integer suitable for hashing by a number of shifts
*/
private static int computeHash(int par0)
{
par0 ^= par0 >>> 20 ^ par0 >>> 12;
return par0 ^ par0 >>> 7 ^ par0 >>> 4;
}
/**
* Computes the index of the slot for the hash and slot count passed in.
*/
private static int getSlotIndex(int par0, int par1)
{
return par0 & par1 - 1;
}
/**
* Returns the object associated to a key
*/
public Object lookup(int par1)
{
int j = computeHash(par1);
for (IntHashMapEntry inthashmapentry = this.slots[getSlotIndex(j, this.slots.length)]; inthashmapentry != null; inthashmapentry = inthashmapentry.nextEntry)
{
if (inthashmapentry.hashEntry == par1)
{
return inthashmapentry.valueEntry;
}
}
return null;
}
/**
* Return true if an object is associated with the given key
*/
public boolean containsItem(int par1)
{
return this.lookupEntry(par1) != null;
}
/**
* Returns the key/object mapping for a given key as a MCHashEntry
*/
final IntHashMapEntry lookupEntry(int par1)
{
int j = computeHash(par1);
for (IntHashMapEntry inthashmapentry = this.slots[getSlotIndex(j, this.slots.length)]; inthashmapentry != null; inthashmapentry = inthashmapentry.nextEntry)
{
if (inthashmapentry.hashEntry == par1)
{
return inthashmapentry;
}
}
return null;
}
/**
* Adds a key and associated value to this map
*/
public void addKey(int par1, Object par2Obj)
{
this.keySet.add(Integer.valueOf(par1));
int j = computeHash(par1);
int k = getSlotIndex(j, this.slots.length);
for (IntHashMapEntry inthashmapentry = this.slots[k]; inthashmapentry != null; inthashmapentry = inthashmapentry.nextEntry)
{
if (inthashmapentry.hashEntry == par1)
{
inthashmapentry.valueEntry = par2Obj;
return;
}
}
++this.versionStamp;
this.insert(j, par1, par2Obj, k);
}
/**
* Increases the number of hash slots
*/
private void grow(int par1)
{
IntHashMapEntry[] ainthashmapentry = this.slots;
int j = ainthashmapentry.length;
if (j == 1073741824)
{
this.threshold = Integer.MAX_VALUE;
}
else
{
IntHashMapEntry[] ainthashmapentry1 = new IntHashMapEntry[par1];
this.copyTo(ainthashmapentry1);
this.slots = ainthashmapentry1;
this.threshold = (int)((float)par1 * this.growFactor);
}
}
/**
* Copies the hash slots to a new array
*/
private void copyTo(IntHashMapEntry[] par1ArrayOfIntHashMapEntry)
{
IntHashMapEntry[] ainthashmapentry1 = this.slots;
int i = par1ArrayOfIntHashMapEntry.length;
for (int j = 0; j < ainthashmapentry1.length; ++j)
{
IntHashMapEntry inthashmapentry = ainthashmapentry1[j];
if (inthashmapentry != null)
{
ainthashmapentry1[j] = null;
IntHashMapEntry inthashmapentry1;
do
{
inthashmapentry1 = inthashmapentry.nextEntry;
int k = getSlotIndex(inthashmapentry.slotHash, i);
inthashmapentry.nextEntry = par1ArrayOfIntHashMapEntry[k];
par1ArrayOfIntHashMapEntry[k] = inthashmapentry;
inthashmapentry = inthashmapentry1;
}
while (inthashmapentry1 != null);
}
}
}
/**
* Removes the specified object from the map and returns it
*/
public Object removeObject(int par1)
{
this.keySet.remove(Integer.valueOf(par1));
IntHashMapEntry inthashmapentry = this.removeEntry(par1);
return inthashmapentry == null ? null : inthashmapentry.valueEntry;
}
/**
* Removes the specified entry from the map and returns it
*/
final IntHashMapEntry removeEntry(int par1)
{
int j = computeHash(par1);
int k = getSlotIndex(j, this.slots.length);
IntHashMapEntry inthashmapentry = this.slots[k];
IntHashMapEntry inthashmapentry1;
IntHashMapEntry inthashmapentry2;
for (inthashmapentry1 = inthashmapentry; inthashmapentry1 != null; inthashmapentry1 = inthashmapentry2)
{
inthashmapentry2 = inthashmapentry1.nextEntry;
if (inthashmapentry1.hashEntry == par1)
{
++this.versionStamp;
--this.count;
if (inthashmapentry == inthashmapentry1)
{
this.slots[k] = inthashmapentry2;
}
else
{
inthashmapentry.nextEntry = inthashmapentry2;
}
return inthashmapentry1;
}
inthashmapentry = inthashmapentry1;
}
return inthashmapentry1;
}
/**
* Removes all entries from the map
*/
public void clearMap()
{
++this.versionStamp;
IntHashMapEntry[] ainthashmapentry = this.slots;
for (int i = 0; i < ainthashmapentry.length; ++i)
{
ainthashmapentry[i] = null;
}
this.count = 0;
}
/**
* Adds an object to a slot
*/
private void insert(int par1, int par2, Object par3Obj, int par4)
{
IntHashMapEntry inthashmapentry = this.slots[par4];
this.slots[par4] = new IntHashMapEntry(par1, par2, par3Obj, inthashmapentry);
if (this.count++ >= this.threshold)
{
this.grow(2 * this.slots.length);
}
}
@SideOnly(Side.CLIENT)
/**
* Return the Set of all keys stored in this MCHash object
*/
public Set getKeySet()
{
return this.keySet;
}
/**
* Returns the hash code for a key
*/
static int getHash(int par0)
{
return computeHash(par0);
}
}