#include "protoGraph.h"
#include "protoDebug.h"
#include "manetGraph.h"
ProtoGraph::VerticeQueue::VerticeQueue()
{
}
ProtoGraph::VerticeQueue::~VerticeQueue()
{
}
void ProtoGraph::VerticeQueue::Associate(Vertice& vertice, QueueState& queueState)
{
queueState.Associate(vertice, *this);
vertice.Reference(queueState);
}
void ProtoGraph::VerticeQueue::Disassociate(Vertice& vertice, QueueState& queueState)
{
vertice.Dereference(queueState);
queueState.Disassociate();
}
ProtoGraph::Vertice::Vertice()
: adjacency_queue(*this)
{
}
ProtoGraph::Vertice::~Vertice()
{
Cleanup();
}
void ProtoGraph::Vertice::Cleanup()
{
while (!queue_state_tree.IsEmpty())
{
VerticeQueue::QueueState::Entry*entry = static_cast<VerticeQueue::QueueState::Entry*>(queue_state_tree.GetRoot());
VerticeQueue* q = entry->GetQueueState().GetQueue();
ASSERT(NULL != q);
q->Remove(*this);
}
}
const char* ProtoGraph::Vertice::GetVerticeKey() const
{
return NULL;
}
unsigned int ProtoGraph::Vertice::GetVerticeKeysize() const
{
return 0;
}
ProtoTree::Endian ProtoGraph::Vertice::GetVerticeKeyEndian() const
{
return ProtoTree::ENDIAN_BIG;
}
bool ProtoGraph::Vertice::GetVerticeKeySigned() const
{
return false;
}
bool ProtoGraph::Vertice::GetVerticeKeyComplement2() const
{
return true;
}
ProtoGraph::VerticeQueue::QueueState::QueueState()
: vertice(NULL), queue(NULL), entry(*this)
{
}
ProtoGraph::VerticeQueue::QueueState::~QueueState()
{
Cleanup();
}
void ProtoGraph::VerticeQueue::QueueState::Cleanup()
{
if (NULL != vertice)
{
ASSERT(NULL != queue);
queue->Remove(*vertice);
}
}
ProtoGraph::VerticeQueue::QueueStatePool::QueueStatePool()
{
}
ProtoGraph::VerticeQueue::QueueStatePool::~QueueStatePool()
{
Destroy();
}
void ProtoGraph::VerticeQueue::QueueStatePool::Destroy()
{
while (!IsEmpty())
{
QueueState* theState = Get();
delete theState;
}
}
ProtoGraph::VerticeQueue::QueueState::Entry::Entry(QueueState& theState)
: queue_state(theState)
{
}
ProtoGraph::Vertice::SimpleList::Item::Item()
: prev(NULL), next(NULL)
{
}
ProtoGraph::Vertice::SimpleList::Item::~Item()
{
Cleanup();
}
ProtoGraph::Vertice::SimpleList::SimpleList(ItemPool* itemPool)
: head(NULL), tail(NULL), item_pool(itemPool)
{
}
ProtoGraph::Vertice::SimpleList::~SimpleList()
{
Empty();
}
bool ProtoGraph::Vertice::SimpleList::Prepend(Vertice& vertice)
{
Item* item = GetNewItem();
if (NULL == item)
{
PLOG(PL_ERROR, "ProtoGraph::Vertice::SimpleList::Prepend() NewItem() error: %s\n", GetErrorString());
return false;
}
Associate(vertice, *item);
PrependItem(*item);
return true;
}
bool ProtoGraph::Vertice::SimpleList::Append(Vertice& vertice)
{
Item* item = GetNewItem();
if (NULL == item)
{
PLOG(PL_ERROR, "ProtoGraph::Vertice::SimpleList::Append() NewItem() error: %s\n", GetErrorString());
return false;
}
Associate(vertice, *item);
AppendItem(*item);
return true;
}
void ProtoGraph::Vertice::SimpleList::Remove(Vertice& vertice)
{
Item* item = static_cast<Item*>(vertice.GetQueueState(*this));
ASSERT(NULL != item);
RemoveItem(*item);
Disassociate(vertice, *item);
if (NULL != item_pool)
item_pool->Put(*item);
else
delete item;
}
ProtoGraph::Vertice* ProtoGraph::Vertice::SimpleList::RemoveHead()
{
if (NULL != head)
{
Item* item = head;
Vertice* vertice = item->GetVertice();
ASSERT(NULL != vertice);
RemoveItem(*item);
Disassociate(*vertice, *item);
if (NULL != item_pool)
item_pool->Put(*item);
else
delete item;
return vertice;
}
else
{
return NULL;
}
}
void ProtoGraph::Vertice::SimpleList::Empty()
{
while (!IsEmpty()) RemoveHead();
}
void ProtoGraph::Vertice::SimpleList::PrependItem(Item& item)
{
item.Prepend(NULL);
if (NULL == head)
tail = &item;
else
head->Prepend(&item);
item.Append(head);
head = &item;
}
void ProtoGraph::Vertice::SimpleList::AppendItem(Item& item)
{
item.Prepend(tail);
if (NULL == tail)
head = &item;
else
tail->Append(&item);
item.Append(NULL);
tail = &item;
}
void ProtoGraph::Vertice::SimpleList::RemoveItem(Item& item)
{
Item* prevItem = item.GetPrev();
Item* nextItem = item.GetNext();
if (NULL != prevItem)
prevItem->Append(nextItem);
else
head = nextItem;
if (NULL != nextItem)
nextItem->Prepend(prevItem);
else
tail = prevItem;
}
ProtoGraph::Vertice::SimpleList::Iterator::Iterator(const Vertice::SimpleList& theList, bool reverse)
: list(theList), next_item(reverse ? theList.tail : theList.head), forward(!reverse)
{
}
ProtoGraph::Vertice::SimpleList::Iterator::~Iterator()
{
}
void ProtoGraph::Vertice::SimpleList::Iterator::Reset()
{
next_item = forward ? list.head : list.tail;
}
ProtoGraph::Vertice* ProtoGraph::Vertice::SimpleList::Iterator::GetNextVertice()
{
Item* item = next_item;
next_item = item ? (forward ? item->GetNext() : item->GetPrev()) : NULL;
return item ? item->GetVertice() : NULL;
}
ProtoGraph::Vertice::SimpleList::ItemPool::ItemPool()
{
}
ProtoGraph::Vertice::SimpleList::ItemPool::~ItemPool()
{
Destroy();
}
ProtoGraph::Vertice::SimpleList::Item* ProtoGraph::Vertice::SimpleList::ItemPool::GetItem()
{
if (IsEmpty())
{
Item* item = new Item();
if (NULL == item)
{
PLOG(PL_ERROR, "ProtoGraph::Vertice::SimpleList::ItemPool::GetItem() new Item error: %s\n",
GetErrorString());
return NULL;
}
else
{
return item;
}
}
else
{
return static_cast<Item*>(VerticeQueue::QueueStatePool::Get());
}
}
ProtoGraph::Vertice::SortedList::SortedList(ItemPool* itemPool)
: item_pool(itemPool)
{
}
ProtoGraph::Vertice::SortedList::~SortedList()
{
Empty();
}
bool ProtoGraph::Vertice::SortedList::Insert(Vertice& vertice)
{
Item* item = GetNewItem();
if (NULL == item)
{
DMSG(0, "ProtoGraph::Vertice::SortedList::Insert() GetNewItem() error: %s\n", GetErrorString());
return false;
}
Associate(vertice, *item);
InsertItem(*item);
return true;
}
bool ProtoGraph::Vertice::SortedList::Append(Vertice& vertice)
{
Item* item = GetNewItem();
if (NULL == item)
{
DMSG(0, "ProtoGraph::Vertice::SortedList::Append() GetNewItem() error: %s\n", GetErrorString());
return false;
}
Associate(vertice, *item);
AppendItem(*item);
return true;
}
void ProtoGraph::Vertice::SortedList::Remove(Vertice& vertice)
{
Item* item = static_cast<Item*>(vertice.GetQueueState(*this));
ASSERT(NULL != item);
RemoveItem(*item);
Disassociate(vertice, *item);
if (NULL != item_pool)
item_pool->Put(*item);
else
delete item;
}
ProtoGraph::Vertice* ProtoGraph::Vertice::SortedList::RemoveHead()
{
Item* headItem = static_cast<Item*>(sorted_item_tree.GetHead());
if (NULL != headItem)
{
Vertice* vertice = headItem->GetVertice();
ASSERT(NULL != vertice);
sorted_item_tree.Remove(*headItem);
Disassociate(*vertice, *headItem);
if (NULL != item_pool)
item_pool->Put(*headItem);
else
delete headItem;
return vertice;
}
else
{
return NULL;
}
}
void ProtoGraph::Vertice::SortedList::Empty()
{
while (!IsEmpty()) RemoveHead();
}
ProtoGraph::Vertice::SortedList::Item::Item()
{
}
ProtoGraph::Vertice::SortedList::Item::~Item()
{
Cleanup();
}
const char* ProtoGraph::Vertice::SortedList::Item::GetKey() const
{
ASSERT(NULL != GetVertice());
return GetVertice()->GetVerticeKey();
}
unsigned int ProtoGraph::Vertice::SortedList::Item::GetKeysize() const
{
ASSERT(NULL != GetVertice());
return GetVertice()->GetVerticeKeysize();
}
ProtoTree::Endian ProtoGraph::Vertice::SortedList::Item::GetEndian() const
{
ASSERT(NULL != GetVertice());
return GetVertice()->GetVerticeKeyEndian();
}
bool ProtoGraph::Vertice::SortedList::Item::UseSignBit() const
{
ASSERT(NULL != GetVertice());
return GetVertice()->GetVerticeKeySigned();
}
bool ProtoGraph::Vertice::SortedList::Item::UseComplement2() const
{
ASSERT(NULL != GetVertice());
return GetVertice()->GetVerticeKeyComplement2();
}
ProtoGraph::Vertice::SortedList::ItemPool::ItemPool()
{
}
ProtoGraph::Vertice::SortedList::ItemPool::~ItemPool()
{
}
ProtoGraph::Vertice::SortedList::Item* ProtoGraph::Vertice::SortedList::ItemPool::GetItem()
{
if (IsEmpty())
{
Item* item = new Item();
if (NULL == item)
{
PLOG(PL_ERROR, "ProtoGraph::Vertice::SortedList::ItemPool::GetItem() new Item error: %s\n",
GetErrorString());
return NULL;
}
else
{
return item;
}
}
else
{
return static_cast<Item*>(VerticeQueue::QueueStatePool::Get());
}
}
ProtoGraph::Vertice::SortedList::Iterator::Iterator(SortedList& theList)
: ProtoSortedTree::Iterator(theList.sorted_item_tree)
{
}
ProtoGraph::Vertice::SortedList::Iterator::~Iterator()
{
}
ProtoGraph::AdjacencyQueue::AdjacencyQueue(Vertice& srcVertice)
: src_vertice(srcVertice), adjacency_count(0)
{
}
ProtoGraph::AdjacencyQueue::~AdjacencyQueue()
{
Empty();
}
void ProtoGraph::AdjacencyQueue::Empty()
{
Edge* edge;
while (NULL != (edge = static_cast<Edge*>(adjacency_tree.GetRoot())))
{
Vertice* dst = edge->GetDst();
ASSERT(NULL != dst);
Disconnect(*dst);
}
}
void ProtoGraph::AdjacencyQueue::Connect(Vertice& dstVertice, Edge& edge)
{
if (static_cast<VerticeQueue*>(this) != edge.GetQueue())
{
Associate(dstVertice, edge);
adjacency_tree.Insert(edge);
dstVertice.AddConnector(edge);
adjacency_count++;
edge.OnConnect();
}
else
{
PLOG(PL_WARN, "ProtoGraph::AdjacencyQueue::Connect() warning: edge already in adjacency queue\n");
}
}
void ProtoGraph::AdjacencyQueue::Reconnect(Vertice& dstVertice, Edge& edge)
{
if (static_cast<VerticeQueue*>(this) != edge.GetQueue())
{
Associate(dstVertice, edge);
adjacency_tree.Insert(edge);
dstVertice.AddConnector(edge);
adjacency_count++;
}
else
{
PLOG(PL_WARN, "ProtoGraph::AdjacencyQueue::Reconnect() warning: edge already in adjacency queue\n");
}
}
void ProtoGraph::AdjacencyQueue::Disconnect(Vertice& dstVertice,
EdgePool* edgePool)
{
Edge* edge;
while (NULL != (edge = static_cast<Edge*>(dstVertice.GetQueueState(*this))))
{
edge->OnDisconnect();
RemoveEdge(dstVertice, *edge, edgePool);
}
}
void ProtoGraph::AdjacencyQueue::RemoveEdge(Vertice& dstVertice,
Edge& edge,
EdgePool* edgePool)
{
if (static_cast<VerticeQueue*>(this) == edge.GetQueue())
{
SuspendEdge(dstVertice, edge);
if (NULL != edgePool){
edgePool->Put(edge);
}
else{
delete &edge;
}
}
else
{
PLOG(PL_WARN, "ProtoGraph::AdjacencyQueue::RemoveEdge() warning: edge not in queue\n");
}
}
void ProtoGraph::AdjacencyQueue::SuspendEdge(Vertice& dstVertice,
Edge& edge)
{
if (static_cast<VerticeQueue*>(this) == edge.GetQueue())
{
dstVertice.RemoveConnector(edge);
adjacency_tree.Remove(edge);
Disassociate(dstVertice, edge);
adjacency_count--;
}
else
{
PLOG(PL_WARN, "ProtoGraph::AdjacencyQueue::SuspendEdge() warning: edge not in queue\n");
}
}
void ProtoGraph::AdjacencyQueue::AddConnector(Edge& edge)
{
connector_tree.Insert(edge.AccessTracker());
}
void ProtoGraph::AdjacencyQueue::RemoveConnector(Edge& edge)
{
connector_tree.Remove(edge.AccessTracker());
}
ProtoGraph::AdjacencyIterator::AdjacencyIterator(Vertice & vertice)
: adj_iterator(vertice.adjacency_queue.adjacency_tree),
con_iterator(vertice.adjacency_queue.connector_tree)
{
}
ProtoGraph::AdjacencyIterator::~AdjacencyIterator()
{
}
ProtoGraph::Vertice* ProtoGraph::AdjacencyIterator::GetNextAdjacency()
{
Edge* edge = static_cast<Edge*>(adj_iterator.GetNextItem());
return ((NULL != edge) ? edge->GetDst() : NULL);
}
ProtoGraph::Vertice* ProtoGraph::AdjacencyIterator::GetNextConnector()
{
Edge::Tracker* edgeTracker = static_cast<Edge::Tracker*>(con_iterator.GetNextItem());
return ((NULL != edgeTracker) ? edgeTracker->GetEdge().GetSrc() : NULL);
}
ProtoGraph::Edge::Tracker::Tracker(const Edge& theEdge)
: edge(theEdge)
{
}
ProtoGraph::Edge::Edge()
: tracker(*this)
{
}
ProtoGraph::Edge::~Edge()
{
}
void ProtoGraph::Edge::OnConnect()
{
}
void ProtoGraph::Edge::OnDisconnect()
{
}
const char* ProtoGraph::Edge::GetKey() const
{
return NULL;
}
unsigned int ProtoGraph::Edge::GetKeysize() const
{
return 0;
}
ProtoTree::Endian ProtoGraph::Edge::GetEndian() const
{
return ProtoSortedTree::Item::GetEndian();
}
bool ProtoGraph::Edge::UseSignBit() const
{
return ProtoSortedTree::Item::UseSignBit();
}
bool ProtoGraph::Edge::UseComplement2() const
{
return ProtoSortedTree::Item::UseComplement2();
}
ProtoGraph::Vertice* ProtoGraph::Edge::GetSrc() const
{
AdjacencyQueue* adjQueue = static_cast<AdjacencyQueue*>(QueueState::GetQueue());
if (NULL != adjQueue)
return &(adjQueue->GetSrc());
else
return NULL;
}
ProtoGraph::EdgePool::EdgePool()
{
}
ProtoGraph::EdgePool::~EdgePool()
{
Destroy();
}
ProtoGraph::SimpleTraversal::SimpleTraversal(const ProtoGraph& theGraph,
Vertice& startVertice,
bool depthFirst)
: graph(theGraph), start_vertice(startVertice), depth_first(depthFirst),
queue_pending(&item_pool), queue_visited(&item_pool)
{
Reset();
}
ProtoGraph::SimpleTraversal::~SimpleTraversal()
{
queue_visited.Empty();
queue_pending.Empty();
item_pool.Destroy();
}
bool ProtoGraph::SimpleTraversal::Reset()
{
current_level = 0;
trans_vertice = NULL;
queue_visited.Empty();
queue_pending.Empty();
if (!queue_pending.Append(start_vertice))
{
PLOG(PL_ERROR, "ProtoGraph::SimpleTraversal::Reset() error: couldn't enqueue start_vertice\n");
return false;
}
return true;
}
ProtoGraph::Vertice* ProtoGraph::SimpleTraversal::GetNextVertice(unsigned int* level)
{
Vertice* currentVertice = queue_pending.GetHead();
if (NULL != currentVertice)
{
queue_pending.TransferVertice(*currentVertice, queue_visited);
AdjacencyIterator it(*currentVertice);
Edge* nextEdge;
Vertice* transAdjacency = NULL;
while (NULL != (nextEdge = it.GetNextAdjacencyEdge()))
{
Vertice* nextVertice = nextEdge->GetDst();
ASSERT(NULL != nextVertice);
if (!nextVertice->IsInQueue(queue_visited) &&
!nextVertice->IsInQueue(queue_pending))
{
if (!AllowEdge(*currentVertice, *nextEdge)) continue;
if (depth_first)
{
queue_pending.Prepend(*nextVertice);
}
else
{
queue_pending.Append(*nextVertice);
if (NULL == transAdjacency)
transAdjacency = nextVertice;
}
}
}
if (NULL == trans_vertice)
{
trans_vertice = transAdjacency;
}
else if (trans_vertice == currentVertice)
{
current_level++;
trans_vertice = transAdjacency;
}
if (NULL != level) *level = current_level;
}
return currentVertice;
}
ProtoGraph::ProtoGraph()
: vertice_list(&vertice_list_item_pool)
{
}
ProtoGraph::~ProtoGraph()
{
Empty();
vertice_list_item_pool.Destroy();
edge_pool.Destroy();
}
ProtoGraph::Edge* ProtoGraph::GetEdge()
{
Edge* edge = edge_pool.GetEdge();
if (NULL == edge) edge = CreateEdge();
if (NULL == edge)
{
PLOG(PL_ERROR, "ProtoGraph::GetEdge() error: unable to allocate Edge\n");
return NULL;
}
return edge;
}
void ProtoGraph::Empty()
{
while (!vertice_list.IsEmpty())
{
Vertice* v = vertice_list.GetHead();
AdjacencyIterator it(*v);
Vertice* a;
while (NULL != (a = it.GetNextAdjacency()))
v->Disconnect(*a, &edge_pool);
vertice_list.Remove(*v);
}
}
bool ProtoGraph::InsertVertice(Vertice& vertice)
{
if (vertice.IsInQueue(vertice_list))
{
PLOG(PL_ERROR, "ProtoGraph::InsertVertice() error: vertice already in graph!\n");
return false;
}
else
{
return vertice_list.Insert(vertice);
}
}
void ProtoGraph::RemoveVertice(Vertice& vertice)
{
AdjacencyIterator it(vertice);
Vertice* next;
while (NULL != (next = it.GetNextAdjacency()))
{
Disconnect(vertice, *next);
}
while (NULL != (next = it.GetNextConnector()))
Disconnect(*next, vertice);
vertice_list.Remove(vertice);
}
ProtoGraph::Edge* ProtoGraph::Connect(Vertice& src, Vertice& dst)
{
ASSERT(src.IsInQueue(vertice_list) && dst.IsInQueue(vertice_list));
Edge* edge = GetEdge();
if (NULL == edge)
{
PLOG(PL_ERROR, "ProtoGraph::Connect() error: CreateEdge() error: %s\n", GetErrorString());
return NULL;
}
src.Connect(dst, *edge);
return edge;
}
void ProtoGraph::Reconnect(Vertice& src, Vertice& dst,Edge& edge)
{
ASSERT(src.IsInQueue(vertice_list) && dst.IsInQueue(vertice_list));
src.Reconnect(dst,edge);
return;
}
void ProtoGraph::Disconnect(Vertice& src, Vertice& dst, bool duplex)
{
src.Disconnect(dst, &edge_pool);
if (duplex) dst.Disconnect(src, &edge_pool);
}
ProtoGraph::VerticeIterator::VerticeIterator(ProtoGraph& theGraph)
: Vertice::SortedList::Iterator(theGraph.vertice_list)
{
}
ProtoGraph::VerticeIterator::~VerticeIterator()
{
}