//===========================================================================// // File: hash.cc // // Project: MUNGA Brick: Connection Library // // Contents: Implementation details of Hash class // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 12/15/94 ECH Initial coding. // //---------------------------------------------------------------------------// // Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // // PROPRIETARY AND CONFIDENTIAL // //===========================================================================// #include "StuffHeaders.hpp" //~~~~~~~~~~~~~~~~~~~~~~~~~~~ Hash ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // //########################################################################### // Hash //########################################################################### // Hash::Hash( unsigned size, void *node, bool has_unique_entries ): SortedSocket(NULL, has_unique_entries) { // // If the size is not prime, warn and select new size // #if defined(_ARMOR) if (!CheckForPrimeSize(size)) { while (!CheckForPrimeSize(size)) size++; PAUSE(("Non-prime hash table, correct size is %d", size)); } #endif // //--------------------- // Initialize the table //--------------------- // m_hashTable.SetLength(size); for (unsigned i=0; i 0); } // //########################################################################### // DeletePlugs //########################################################################### // void Hash::DeletePlugs() { Check_Object(this); int i; for (i=0; iDeletePlugs(); delete m_hashTable[i]; m_hashTable[i] = NULL; } } } // //########################################################################### // GetNthItem //########################################################################### // void* Hash::GetNthItem(unsigned index) { STOP(("Not implemented")); return NULL; } // //########################################################################### // GetSize //########################################################################### // unsigned Hash::GetSize() { Check_Object(this); HashIterator iterator(this); unsigned i = 0; while (iterator.ReadAndNextItem() != NULL) i++; return i; } // //############################################################################# // IsEmpty //############################################################################# // bool Hash::IsEmpty() { Check_Object(this); for (int i = 0; i < m_hashTable.GetLength(); i++) { if (m_hashTable[i] != NULL) { if (!m_hashTable[i]->IsEmpty()) return false; } } return true; } // //########################################################################### // AddValueImplementation //########################################################################### // void Hash::AddValuePlug( Plug *plug, const void *value ) { Check_Object(this); Check_Object(plug); Check_Pointer(value); // //------------------------------------------------------------- // Verify that value has not been added //------------------------------------------------------------- // Verify(HasUniqueEntries() ? (FindPlug(value) == NULL) : true); // //------------------------------------------------------------- // Find hash entry //------------------------------------------------------------- // unsigned index = GetHashIndex(value); // //------------------------------------------------------------- // Get vchain for this index //------------------------------------------------------------- // SortedChain *vchain; if ((vchain = m_hashTable[index]) == NULL) { vchain = MakeSortedChain(); Check_Object(vchain); m_hashTable[index] = vchain; } // //------------------------------------------------------------- // Add to the vchain //------------------------------------------------------------- // Check_Object(vchain); vchain->AddValuePlug(plug, value); } // //########################################################################### // FindPlug //########################################################################### // Plug* Hash::FindPlug( const void *value ) { Check_Object(this); Check_Pointer(value); // //------------------------------------------------------------- // Find hash entry //------------------------------------------------------------- // unsigned index; index = GetHashIndex(value); // //------------------------------------------------------------- // Get vchain for this index //------------------------------------------------------------- // SortedChain *vchain; if ((vchain = m_hashTable[index]) == NULL) return NULL; // //------------------------------------------------------------- // Find in vchain //------------------------------------------------------------- // Check_Object(vchain); return vchain->FindPlug(value); } // //########################################################################### // CheckForPrimeSize //########################################################################### // bool Hash::CheckForPrimeSize(unsigned size) { Check_Signature(this); Verify(size > 2); unsigned upper_bound = static_cast(Sqrt(static_cast(size))); for (unsigned i = 2; i < upper_bound; i++) { if ((size % i) == 0) return false; } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~ HashIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ const unsigned HashIteratorNullPosition = -1; // //########################################################################### // HashIterator //########################################################################### // HashIterator::HashIterator(Hash *hash): SortedIterator(hash) { m_currentPosition = HashIteratorNullPosition; m_vchainIterator = NULL; First(); } Iterator* HashIterator::MakeClone() { Check_Object(this); return new(g_Heap) HashIterator(*this); } HashIterator::~HashIterator() { Check_Object(this); m_currentPosition = HashIteratorNullPosition; DeleteSortedChainIterator(); } // //########################################################################### // TestInstance //########################################################################### // void HashIterator::TestInstance() { SortedIterator::TestInstance(); if (m_vchainIterator != NULL) { Check_Object(m_vchainIterator); } } // //########################################################################### // First //########################################################################### // Iterator& HashIterator::First() { Check_Object(this); NextSortedChainIterator(0); return *this; } // //########################################################################### // Last //########################################################################### // Iterator& HashIterator::Last() { Check_Object(this); STOP(("Shouldn't reach here")); return *this; } // //########################################################################### // Next //########################################################################### // Iterator& HashIterator::Next() { Check_Object(this); if (m_vchainIterator != NULL) { Check_Object(m_vchainIterator); if (m_vchainIterator->GetCurrentPlug() != NULL) { // // Try to step to the next item in this list // m_vchainIterator->Next(); } if (m_vchainIterator->GetCurrentPlug() == NULL) { // // At end of list, step to the next list // NextSortedChainIterator(m_currentPosition+1); } } return *this; } // //########################################################################### // Previous //########################################################################### // Iterator& HashIterator::Previous() { Check_Object(this); STOP(("Not implemented")); return *this; } // //########################################################################### // ReadAndNextItem //########################################################################### // void* HashIterator::ReadAndNextItem() { Check_Object(this); void *result = NULL; if (m_vchainIterator != NULL) { Check_Object(m_vchainIterator); if (m_vchainIterator->GetCurrentPlug() != NULL) { result = m_vchainIterator->GetCurrentPlug(); m_vchainIterator->Next(); } // // List was emptied, step to next list // else { NextSortedChainIterator(m_currentPosition+1); if (m_vchainIterator != NULL) { Check_Object(m_vchainIterator); Verify(m_vchainIterator->GetCurrentPlug() != NULL); result = m_vchainIterator->GetCurrentPlug(); m_vchainIterator->Next(); } } } return result; } // //########################################################################### // Previous //########################################################################### // void* HashIterator::ReadAndPreviousItem() { Check_Object(this); void *result = GetCurrentItem(); HashIterator::Previous(); return result; } // //########################################################################### // GetCurrentImplementation //########################################################################### // void *HashIterator::GetCurrentItem() { Check_Object(this); if (m_vchainIterator != NULL) { Check_Object(m_vchainIterator); if (m_vchainIterator->GetCurrentPlug() != NULL) { return m_vchainIterator->GetCurrentPlug(); } // // List was emptied, step to next list // NextSortedChainIterator(m_currentPosition+1); if (m_vchainIterator != NULL) { Check_Object(m_vchainIterator); Verify(m_vchainIterator->GetCurrentPlug() != NULL); return m_vchainIterator->GetCurrentPlug(); } } return NULL; } // //########################################################################### // GetNthItem //########################################################################### // void* HashIterator::GetNthItem(unsigned index) { unsigned i = 0; NextSortedChainIterator(0); while (m_vchainIterator != NULL) { Check_Object(m_vchainIterator); while (m_vchainIterator->GetCurrentPlug() != NULL) { if (i == index) return m_vchainIterator->GetCurrentPlug(); m_vchainIterator->Next(); i++; } // // List was emptied, step to next list // NextSortedChainIterator(m_currentPosition+1); } return NULL; } // //########################################################################### // Remove //########################################################################### // void HashIterator::Remove() { Check_Object(this); if (m_vchainIterator != NULL) { Check_Object(m_vchainIterator); if (m_vchainIterator->GetCurrentPlug() != NULL) { m_vchainIterator->Remove(); return; } // // List was emptied, step to next list // NextSortedChainIterator(m_currentPosition+1); if (m_vchainIterator != NULL) { Check_Object(m_vchainIterator); m_vchainIterator->Remove(); return; } } } // //########################################################################### // FindPlug //########################################################################### // Plug *HashIterator::FindPlug( const void* ) { Check_Object(this); STOP(("Not implemented")); return NULL; } // //########################################################################### // GetPlugValue //########################################################################### // void* HashIterator::GetPlugValue() { Check_Object(this); STOP(("Not implemented")); return NULL; } // //########################################################################### //########################################################################### // void HashIterator::DeleteSortedChainIterator() { if (m_vchainIterator != NULL) { Check_Object(m_vchainIterator); delete m_vchainIterator; m_vchainIterator = NULL; } } // //########################################################################### //########################################################################### // void HashIterator::NextSortedChainIterator(unsigned index) { Check_Object(this); int i; DeleteSortedChainIterator(); m_currentPosition = HashIteratorNullPosition; DynamicArrayOf &hash_table = Cast_Object(Hash*, m_socket)->m_hashTable; for (i = index; i < hash_table.GetLength(); i++) { if (hash_table[i] != NULL) { // // This index contains a vchain // Check_Object(hash_table[i]); // // Create a vchain iterator // m_vchainIterator = new(g_Heap) SortedChainIterator(hash_table[i]); Check_Object(m_vchainIterator); if (m_vchainIterator->GetCurrentPlug() != NULL) { // // The vchain contains items // m_currentPosition = i; return; } // // Destroy the vchain iterator // DeleteSortedChainIterator(); } } }