#include "munga.h" #pragma hdrstop #include "vchain.h" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainLink ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // //########################################################################### // VChainLink //########################################################################### // VChainLink::VChainLink( VChain *vchain, Plug *plug ): Link(vchain, plug) { next = NULL; prev = NULL; } // //########################################################################### // ~VChainLink //########################################################################### // VChainLink::~VChainLink() { VChain *vchain = Cast_Object(VChain*, socket); // //------------------------------------------- // Notify iterators that deletion is occuring //------------------------------------------- // vchain->SendIteratorMemo(PlugRemoved, this); // //--------------------------- // Remove from existing links //--------------------------- // if (prev != NULL) { Check(prev); prev->next = next; } else { Check(vchain); vchain->head = next; } if (next != NULL) { Check(next); next->prev = prev; } else { Check(vchain); vchain->tail = prev; } prev = next = NULL; // //------------------------------------------ // Remove this link from any plug references //------------------------------------------ // ReleaseFromPlug(); // //------------------------------------------------------------- // Tell the node to release this link. Note that this link // is not referenced by the plug or the chain at this point in // time. //------------------------------------------------------------- // if (vchain->GetReleaseNode() != NULL) { Check(vchain->GetReleaseNode()); vchain->GetReleaseNode()->ReleaseLinkHandler(vchain, plug); } } // //########################################################################### // TestInstance //########################################################################### // Logical VChainLink::TestInstance() const { Link::TestInstance(); if (next != NULL) { Check_Signature(next); } if (prev != NULL) { Check_Signature(prev); } return True; } // //########################################################################### // SetupVChainLinks //########################################################################### // void VChainLink::SetupVChainLinks( VChainLink *next, VChainLink *prev ) { this->next = next; this->prev = prev; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // //########################################################################### // VChain //########################################################################### // VChain::VChain( Node *node, Logical has_unique_entries ): SortedSocket(node, has_unique_entries) { head = NULL; tail = NULL; } // //########################################################################### // ~VChain //########################################################################### // VChain::~VChain() { SetReleaseNode(NULL); while (head != NULL) { Unregister_Object(head); delete head; } } // //########################################################################### // TestInstance //########################################################################### // Logical VChain::TestInstance() const { SortedSocket::TestInstance(); if (head != NULL) { Check(head); } if (tail != NULL) { Check(tail); } return True; } // //########################################################################### // MakeVChainLink //########################################################################### // VChainLink *VChain::MakeVChainLink( Plug*, const void* ) { Fail("VChain::MakeVChainLink - Should never reach here"); return NULL; } // //########################################################################### // CompareVChainLinks //########################################################################### // int VChain::CompareVChainLinks( VChainLink*, VChainLink* ) { Fail("VChain::CompareVChainLinks - Should never reach here"); return 0; } // //########################################################################### // CompareValueToVChainLink //########################################################################### // int VChain::CompareValueToVChainLink( const void*, VChainLink* ) { Fail("VChain::CompareValueToVChainLink - Should never reach here"); return 0; } // //########################################################################### // AddImplementation //########################################################################### // void VChain::AddImplementation( Plug *plug ) { AddValueImplementation(plug, NULL); } // //########################################################################### // AddValueImplementation //########################################################################### // void VChain::AddValueImplementation( Plug *plug, const void *value ) { VChainLink *link; // //------------------------------------------------------------- // Verify that value has not been added //------------------------------------------------------------- // Verify(HasUniqueEntries() ? (SearchForValue(value) == NULL) : (Logical)True); // //------------------------------------------------------------- // Make new vchain link //------------------------------------------------------------- // link = MakeVChainLink(plug, value); Register_Object(link); // //------------------------------------------------------------- // Find insertion point for the new link //------------------------------------------------------------- // if (head == NULL) { link->SetupVChainLinks(NULL, NULL); head = link; tail = link; } else { VChainLink *greater_link; Check(head); Check(tail); for ( greater_link = head; greater_link != NULL; greater_link = greater_link->next ) { Check(greater_link); if (CompareValueToVChainLink(value, greater_link) < 0) break; } if (greater_link == NULL) { // // Add after tail // link->SetupVChainLinks(NULL, tail); tail->next = link; tail = link; } else if (greater_link == head) { // // Add before head // link->SetupVChainLinks(head, NULL); head->prev = link; head = link; } else { // // Add before greater_link // link->SetupVChainLinks(greater_link, greater_link->prev); greater_link->prev->next = link; greater_link->prev = link; } } SendIteratorMemo(PlugAdded, link); } // //########################################################################### // FindImplementation //########################################################################### // Plug* VChain::FindImplementation( const void *value ) { VChainLink *link; if ((link = SearchForValue(value)) != NULL) { Check(link); return link->GetPlug(); } return NULL; } // //########################################################################### // SearchForValue //########################################################################### // VChainLink* VChain::SearchForValue( const void *value ) { VChainLink *link; int ret; for (link = head; link != NULL; link = link->next) { Check(link); if ((ret = CompareValueToVChainLink(value, link)) == 0) break; if (ret < 0) return(NULL); } return link; } // //########################################################################### // VChainIterator //########################################################################### // VChainIterator::VChainIterator(VChain *vchain): SortedIterator(vchain) { Check(vchain); currentLink = vchain->head; } // //########################################################################### // VChainIterator //########################################################################### // VChainIterator::VChainIterator(const VChainIterator *iterator): SortedIterator(Cast_Object(VChain*, iterator->socket)) { Check(iterator); currentLink = iterator->currentLink; } // //########################################################################### //########################################################################### // VChainIterator::~VChainIterator() { } // //########################################################################### // TestInstance //########################################################################### // Logical VChainIterator::TestInstance() const { SortedIterator::TestInstance(); if (currentLink != NULL) { Check(currentLink); } return True; } // //########################################################################### // First //########################################################################### // void VChainIterator::First() { currentLink = Cast_Object(VChain*, socket)->head; } // //########################################################################### // Last //########################################################################### // void VChainIterator::Last() { currentLink = Cast_Object(VChain*, socket)->tail; } // //########################################################################### // Next //########################################################################### // void VChainIterator::Next() { Check(currentLink); currentLink = currentLink->next; } // //########################################################################### // Previous //########################################################################### // void VChainIterator::Previous() { Check(currentLink); currentLink = currentLink->prev; } // //########################################################################### // ReadAndNextImplementation //########################################################################### // void *VChainIterator::ReadAndNextImplementation() { if (currentLink != NULL) { Plug *plug; Check(currentLink); plug = currentLink->GetPlug(); currentLink = currentLink->next; return plug; } return NULL; } // //########################################################################### // ReadAndPreviousImplementation //########################################################################### // void *VChainIterator::ReadAndPreviousImplementation() { if (currentLink != NULL) { Plug *plug; Check(currentLink); plug = currentLink->plug; currentLink = currentLink->prev; return plug; } return NULL; } // //########################################################################### // GetCurrentImplementation //########################################################################### // void *VChainIterator::GetCurrentImplementation() { if (currentLink != NULL) { Check(currentLink); return currentLink->GetPlug(); } return NULL; } // //########################################################################### // GetSize //########################################################################### // CollectionSize VChainIterator::GetSize() { VChainLink *link; CollectionSize count; count = 0; for ( link = Cast_Object(VChain*, socket)->head; link != NULL; link = link->next ) { Check(link); count++; } return count; } // //########################################################################### // GetNthImplementation //########################################################################### // void *VChainIterator::GetNthImplementation( CollectionSize index ) { VChainLink *link; CollectionSize count; count = 0; for ( link = Cast_Object(VChain*, socket)->head; link != NULL; link = link->next ) { Check(link); if (count == index) { currentLink = link; return currentLink->GetPlug(); } count++; } return NULL; } // //########################################################################### // Remove //########################################################################### // void VChainIterator::Remove() { Check(currentLink); Unregister_Object(currentLink); delete currentLink; } // //########################################################################### // FindImplementation //########################################################################### // Plug* VChainIterator::FindImplementation( const void *value ) { VChainLink *link; if ((link = Cast_Object(VChain*, socket)->SearchForValue(value)) != NULL) { Check(link); return (currentLink = link)->GetPlug(); } return NULL; } // //########################################################################### // ReceiveMemo //########################################################################### // void VChainIterator::ReceiveMemo( IteratorMemo memo, void *content ) { if (memo == PlugRemoved) { if (content == currentLink) { Next(); } } } #if defined(TEST_CLASS) # include "vchain.tcp" #endif