private IEnumerable <HashTableElement> GetNextAvailableSpaceForKeyEnumerable(byte[] key) { int hash = key.GetHash(); int initialIndexForKey = hash % GetTableSize(); HashTableElement element = GetElementAt(initialIndexForKey); yield return(element); while (!element.Key.EqualsBytes(NullKey) && element.Index < _simpleCollectionNextIndex.GetNextIndex()) //collision and still within the array's boundries { int nextIndex = GetNextIndexAfterCollision(element.Index); element = GetElementAt(nextIndex); if (element.Key.EqualsBytes(key)) //duplicate key { throw new InvalidKeyException("That key already exsists in the table"); } if (element.Index == initialIndexForKey) // we've looped all the way around { throw new IndexOutOfRangeException("The hash table is full"); } yield return(element); } if (element.Index >= _simpleCollectionNextIndex.GetNextIndex()) { element = new HashTableElement(key, new byte[GetValueSize()], element.Index); } yield return(element); }
private IEnumerable <HashTableElement> GetElementWithKeyEnumerable(byte[] key) { int hash = key.GetHash(); int nextAvailableArrayIndex = hash % GetTableSize(); HashTableElement element = GetElementAt(nextAvailableArrayIndex); yield return(element); while (!element.Key.EqualsBytes(key) && !element.Key.EqualsBytes(NullKey)) { int nextIndex = GetNextIndexAfterCollision(element.Index); while (nextIndex >= _simpleCollectionNextIndex.GetNextIndex()) //there's nothing past this so simulate a wrap around { nextIndex = GetNextIndexAfterCollision(element.Index); } element = GetElementAt(nextIndex); //if (element.Key.EqualsBytes(key)) // we've looped all the way around // throw new KeyNotFoundException("key not found"); yield return(element); } if (element.Key.EqualsBytes(NullKey)) // key was not located before the null key was found { throw new KeyNotFoundException("key not found"); } }
public void Remove(byte[] key) { AssertValidKey(key); //find the element while adding to moveCandidates SortedSet <HashTableElement> moveCandidates = new SortedSet <HashTableElement>(); HashTableElement removingElement = null; foreach (var hashTableElement in GetElementWithKeyEnumerable(key)) { Debug.Assert(moveCandidates.Add(hashTableElement)); removingElement = hashTableElement; } Debug.Assert(removingElement != null, "GetElementWithKeyEnumberable() should have returned at least one element or thrown an exception"); moveCandidates.Remove(removingElement); //null out the element WipeArrayAt(removingElement.Index); //rehash the elements between the hash and the removed element foreach (var moveCandidate in moveCandidates) { Debug.Assert(!moveCandidate.Key.EqualsBytes(NullKey), "GetElementWithKeyEnumerable() should not return any null elements"); WipeArrayAt(moveCandidate.Index); Put(moveCandidate.Key, moveCandidate.Value); } }
private HashTableElement GetElementAt(int index) { byte[] getResult = _simpleCollectionNextIndex.Get(index); HashTableHeader header = GetHashTableHeader(); return(HashTableElement.Deserialize(getResult, index, header.KeySize, header.ValueSize)); }
public void Put(byte[] key, byte[] value) { AssertValidKey(key); AssertValidValue(value); int putIndex = GetNextAvailableSpaceForKey(key).Index; HashTableElement element = new HashTableElement(key, value, putIndex); PutElement(element); }
//private class HashTableElementComparer : IComparer<HashTableElement> //{ // public int Compare(HashTableElement x, HashTableElement y) // { // return x.Key.GetHash() - y.Key.GetHash(); // } //} private void WipeArrayAt(int index) { HashTableElement element = new HashTableElement(NullKey, new byte[GetValueSize()], index); PutElement(element); }
private void PutElement(HashTableElement element) { _simpleCollectionNextIndex.Put(element.Index, element.Key.Append(element.Value)); }