//===========================================================================// // File: table.cc // // Project: MUNGA Brick: Connection Library // // Contents: Implementation details of Table class // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 09/30/94 ECH Initial coding. // // 11/02/94 JMA Made compatible with SGI CC, merged with iterator // // 11/03/94 ECH Made compatible with BC4.0 // // 11/05/94 JMA Made compatible with GNU C++ // // 12/12/94 ECH Changed release handling // //---------------------------------------------------------------------------// // Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // // PROPRIETARY AND CONFIDENTIAL // //===========================================================================// #include "StuffHeaders.hpp" // //########################################################################### // TABLEENTRY //########################################################################### // TableEntry::~TableEntry() { Check_Object(this); Table *table = Cast_Object(Table*, m_socket); unsigned index; // //-------------------------------------- // Find the link in the table and remove //-------------------------------------- // index = table->SearchForTableEntry(this); table->RemoveNthTableEntry(index); // //-------------------------------------------- // Notify iterators that link is being deleted //-------------------------------------------- // table->SendIteratorMemo(PlugRemoved, &index); // //------------------------------------------ // Remove this link from any m_plug references //------------------------------------------ // ReleaseFromPlug(); } // //########################################################################### // TABLE //########################################################################### // // //########################################################################### // Table //########################################################################### // Table::Table( void *, bool has_unique_entries ): SortedSocket(NULL, has_unique_entries) { m_numItems = 0; } // //########################################################################### // ~Table //########################################################################### // Table::~Table() { Check_Object(this); int i = m_numItems; while (i > 0) { --i; Check_Object(m_array[i]); delete m_array[i]; } } // //########################################################################### // TestInstance //########################################################################### // void Table::TestInstance() { SortedSocket::TestInstance(); if (m_numItems > 0 || m_array.GetLength() > 0) { Verify(m_numItems > 0); Verify(m_numItems <= m_array.GetLength()); } } // //########################################################################### // DeletePlugs //########################################################################### // void Table::DeletePlugs() { Check_Object(this); int i = m_numItems; while (i > 0) { --i; Check_Object(m_array[i]); Check_Object(m_array[i]->GetPlug()); delete m_array[i]->GetPlug(); } } // //########################################################################### // GetSize //########################################################################### // unsigned Table::GetSize() { return m_numItems; } // //########################################################################### // GetNthImplementation //########################################################################### // void *Table::GetNthItem(unsigned index) { if (index < m_numItems) return m_array[index]->GetPlug(); return NULL; } // //############################################################################# // IsEmpty //############################################################################# // bool Table::IsEmpty() { Check_Object(this); return (m_numItems == (unsigned)0); } // //########################################################################### // AddValueImplementation //########################################################################### // void Table::AddValuePlug( Plug *m_plug, const void *value ) { Check_Object(this); TableEntry *link; /* * Verify that value has not been added */ Verify(HasUniqueEntries() ? (SearchForValue(value) == TableNullIndex) : true); /* * Make new table entry */ link = MakeTableEntry(m_plug, value); Register_Object(link); /* * Add, sort and send memo to iterators to update references */ AddTableEntry(link); SortTableEntries(); SendIteratorMemo(PlugAdded, link); } // //########################################################################### // FindImplementation //########################################################################### // Plug* Table::FindPlug(const void *value) { Check_Object(this); unsigned index; if ((index = SearchForValue(value)) != TableNullIndex) { Check_Object(m_array[index]); return m_array[index]->GetPlug(); } return NULL; } // //########################################################################### // AddTableEntry //########################################################################### // void Table::AddTableEntry( TableEntry *link ) { Check_Object(link); unsigned new_num_items = m_numItems+1; if (new_num_items > m_array.GetLength()) m_array.SetLength(new_num_items); m_array[m_numItems] = link; m_numItems = new_num_items; } // //########################################################################### // SortTableEntries //########################################################################### // void Table::SortTableEntries() { Check_Object(this); size_t i, j; TableEntry *temp; for (i = 1; i < m_numItems; i++) { temp = m_array[i]; j = i; Verify(j-1 < m_numItems); while (CompareTableEntries(m_array[j-1], temp) > 0) { Verify(j < m_numItems); Verify(j-1 < m_numItems); m_array[j] = m_array[j-1]; j--; if (j < 1) break; } Verify(j < m_numItems); m_array[j] = temp; } } // //########################################################################### // SearchForValue //########################################################################### // unsigned Table::SearchForValue( const void *value ) { Check_Object(this); unsigned n = m_numItems; unsigned i = 0, j; int k; while (i < n) { j = (i + n - 1) >> 1; if ((k = CompareValueToTableEntry(value, m_array[j])) == 0) return j; if (k < 0) n = j; else i = j + 1; } return TableNullIndex; } // //########################################################################### // SearchForTableEntry //########################################################################### // unsigned Table::SearchForTableEntry( TableEntry *link ) { Check_Object(this); unsigned i; for (i = 0; i < m_numItems; i++) { if (m_array[i] == link) return i; } return TableNullIndex; } // //########################################################################### // RemoveNthTableEntry //########################################################################### // void Table::RemoveNthTableEntry( unsigned index ) { Check_Object(this); char *itemPtr, *lastItem; size_t width; /* * Find the location of the item */ itemPtr = Cast_Pointer(char*, &m_array[index]); /* * Remove the item from the m_array */ width = sizeof(void*); lastItem = Cast_Pointer(char*, m_array.GetData()) + (m_numItems - 1) * width; if (itemPtr < lastItem) memmove(itemPtr, itemPtr + width, (size_t)(lastItem - itemPtr)); /* * Resize the m_array */ unsigned new_num_items = m_numItems-1; if (new_num_items == 0) m_array.SetLength(0); m_numItems = new_num_items; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~ TableIterator inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~ #if defined(_ARMOR) TableEntry* TableIterator::NthEntry( unsigned index ) { Check_Object(this); Table *table = Cast_Object(Table*, m_socket); Check_Object(table->m_array[index]); return table->m_array[index]; } #endif // //########################################################################### // TableIterator //########################################################################### // TableIterator::TableIterator(Table *table): SortedIterator(table) { if (table->m_array.GetLength() > 0) m_currentPosition = 0; else m_currentPosition = TableNullIndex; } // //########################################################################### //########################################################################### // TableIterator::~TableIterator() { } // //########################################################################### // First //########################################################################### // Iterator& TableIterator::First() { Table *table = Cast_Object(Table*,m_socket); if (table->m_array.GetLength()>0) m_currentPosition = 0; return *this; } // //########################################################################### // Last //########################################################################### // Iterator& TableIterator::Last() { Table *table = Cast_Object(Table*,m_socket); if (table->m_array.GetLength()>0) m_currentPosition = table->m_numItems - 1; return *this; } // //########################################################################### // Next //########################################################################### // Iterator& TableIterator::Next() { IncrementPosition(); return *this; } // //########################################################################### // Previous //########################################################################### // Iterator& TableIterator::Previous() { DecrementPosition(); return *this; } // //########################################################################### // ReadAndNextImplementation //########################################################################### // void *TableIterator::ReadAndNextItem() { if (m_currentPosition != TableNullIndex) { Plug *plug; plug = NthEntry(m_currentPosition)->GetPlug(); IncrementPosition(); return plug; } return NULL; } // //########################################################################### // ReadAndPreviousImplementation //########################################################################### // void *TableIterator::ReadAndPreviousItem() { if (m_currentPosition != TableNullIndex) { Plug *m_plug; m_plug = NthEntry(m_currentPosition)->GetPlug(); DecrementPosition(); return m_plug; } return NULL; } // //########################################################################### // GetCurrentItem //########################################################################### // void *TableIterator::GetCurrentItem() { if (m_currentPosition != TableNullIndex) { return NthEntry(m_currentPosition)->GetPlug(); } return NULL; } // //########################################################################### // GetNthImplementation //########################################################################### // void *TableIterator::GetNthItem(unsigned index) { Table *table = Cast_Object(Table*, m_socket); if (index < table->m_numItems) return table->m_array[m_currentPosition=index]->GetPlug(); return NULL; } // //########################################################################### // Remove //########################################################################### // void TableIterator::Remove() { if (m_currentPosition != TableNullIndex) { Check_Object(NthEntry(m_currentPosition)); delete NthEntry(m_currentPosition); } } // //########################################################################### // FindImplementation //########################################################################### // Plug *TableIterator::FindPlug(const void *value) { unsigned index; Table *table = Cast_Object(Table*, m_socket); if ((index = table->SearchForValue(value)) != TableNullIndex) { if (!table->HasUniqueEntries()) { while ( index-1 >= 0 && table->CompareTableEntries(NthEntry(index-1), NthEntry(index)) == 0 ) { index--; } } return (NthEntry(m_currentPosition = index)->GetPlug()); } m_currentPosition = TableNullIndex; return NULL; } // //########################################################################### // FindImplementation //########################################################################### // void* TableIterator::GetPlugValue() { Check_Object(this); STOP(("Not implemented")); return NULL; } // //########################################################################### // ReceiveMemo //########################################################################### // void TableIterator::ReceiveMemo( IteratorMemo memo, void *content ) { switch (memo) { case PlugAdded: { Table *table = Cast_Object(Table*, m_socket); Check_Object(table); // // If a m_plug is added before or at the current position then // the current position should be incremented one forward, // otherwise, no action is necessary // TableEntry *link; unsigned index; link = Cast_Object(TableEntry*, content); index = table->SearchForTableEntry(link); if (index <= m_currentPosition) m_currentPosition++; Verify(TableNullIndex == m_currentPosition || m_currentPosition < table->m_numItems); } break; case PlugRemoved: { Table *table = Cast_Object(Table*, m_socket); Check_Object(table); // // If a m_plug is removed before the current position then decrement // the current position, else if the current position is at the end // of the table then decrement the counter // unsigned index; index = *Cast_Pointer(unsigned*,content); if (m_currentPosition != TableNullIndex) { if (index < m_currentPosition || table->m_numItems <= m_currentPosition) m_currentPosition--; } Verify(TableNullIndex == m_currentPosition || m_currentPosition < table->m_numItems); } break; } }