#include "Col.ph" #ifdef __GNUG__ #pragma implementation #endif #include "ObjList.h" #include "Class.h" //---- private imports ---- #include "IterIter.h" #include "Error.h" #include "Storage.h" //---- ObjLink ----------------------------------------------------------------- NewMetaImpl(ObjLink,Object, (TP(next), TP(prev), TP(obj))); ObjLink::ObjLink(Object *op, ObjLink *lnk) { obj= op; next= lnk; prev= lnk->prev; prev->next= this; next->prev= this; } void ObjLink::FreeAll() { if (obj) { obj->FreeAll(); SafeDelete(obj); } } //---- ObjList ---------------------------------------------------------------- NewMetaImpl(ObjList,SeqCollection, (TP(head))); ObjList::ObjList() { head= new ObjLink; } ObjList::~ObjList() { register ObjLink *lnk, *tlk; lnk= head->Next(); while (lnk != head) { tlk= lnk; lnk= lnk->Next(); delete tlk; } delete head; } void ObjList::InitNew() { SeqCollection::InitNew(); head= new ObjLink; } void ObjList::Empty(int) { register ObjLink *ll, *l; l= head->next; while (l != head) { ll= l; l= l->next; delete ll; } head->next= head; head->prev= head; size= 0; if (HasIterators()) ForEachIterDo(ObjListIter, OnEmpty()); } void ObjList::FreeAll() { register ObjLink *l, *ll; l= head->next; while (l != head) { ll= l; l= l->next; ll->FreeAll(); delete ll; } head->next= head; head->prev= head; size= 0; if (HasIterators()) ForEachIterDo(ObjListIter, OnEmpty()); } //---- accessing ---- Iterator *ObjList::MakeIterator(bool dir, void *placement) { if (dir == cIterForward) return new(placement) ObjListIter(this); return new(placement) RevObjListIter(this); } //---- primitives ---- Object *ObjList::primAt(int idx) { return LinkAt(idx)->GetObject(); } Object *ObjList::primRemoveAt(int idx) { ObjLink *lnk= LinkAt(idx); Object *removed= lnk->GetObject(); RemoveLink(lnk); size--; Changed(); return removed; } Object *ObjList::primAddAt(Object *op, int idx) { InsertLink(op, LinkAt(idx)); return 0; } Object *ObjList::primPutAt(Object *op, int idx) { ObjLink *lnk= LinkAt(idx); Object *replaced= lnk->GetObject(); lnk->SetObject(op); if (op == replaced) Changed(); return replaced; } Object *ObjList::primIndexOf(Object *op, int offset, int *idx) { int i; ObjLink *lnk= FindLink(op, i); if (lnk) { int edx= i + offset; if (edx >= 0 && edx < Size()) { lnk= LinkByOffset(lnk, offset); if (idx) *idx= edx; return lnk->GetObject(); } } if (idx) *idx= -1; return 0; } Object *ObjList::primIndexOfPtr(Object *op, int offset, int *idx) { int i; ObjLink *lnk= FindLinkPtr(op, i); if (lnk) { int edx= i + offset; if (edx >= 0 && edx < Size()) { lnk= LinkByOffset(lnk, offset); if (idx) *idx= edx; return lnk->GetObject(); } } if (idx) *idx= -1; return 0; } Object *ObjList::AddRelative(Object *op, EqualType eq, int offset, Object *to) { ObjLink *lnk; int idx; if (eq) lnk= FindLink(to, idx); else lnk= FindLinkPtr(to, idx); if (lnk) { int edx= idx + offset; if (edx >= 0 && edx <= Size()) { lnk= LinkByOffset(lnk, offset); InsertLink(op, lnk); return 0; } return op; } return op; } Object *ObjList::RemoveRelative(Object *op, EqualType eq, int offset) { ObjLink *lnk; int idx; if (eq) lnk= FindLink(op, idx); else lnk= FindLinkPtr(op, idx); if (lnk) { int edx= idx + offset; if ( edx >= 0 && edx < Size() ) { lnk= LinkByOffset(lnk, offset); Object *removed= lnk->GetObject(); RemoveLink(lnk); size--; Changed(); return removed; } return 0; } return 0; } ObjLink *ObjList::NewLink(Object *op, ObjLink *prev) { return new ObjLink(op, prev); } void ObjList::DeleteLink(ObjLink *lnk) { delete lnk; } //---- implementation ---- ObjLink *ObjList::FindLink(Object *op, int &idx) { register ObjLink *lnk; idx= 0; lnk= head->next; while (lnk != head) { if (lnk->GetObject()->IsEqual(op)) return lnk; lnk= lnk->next; idx++; } return 0; } ObjLink *ObjList::FindLinkPtr(Object *op, int &idx) { idx= 0; register ObjLink *lnk= head->next; while (lnk != head) { if (lnk->GetObject() == op) return lnk; lnk= lnk->next; idx++; } return 0; } ObjLink *ObjList::LinkAt(int idx) { register int i= 0; register ObjLink *lnk= head->Next(); while (i < idx && lnk != head) { lnk= lnk->Next(); i++; } return lnk; } ObjLink *ObjList::LinkByOffset(ObjLink *lnk, int offset) { if (offset >= 0) { while (offset > 0) { offset--; lnk= lnk->Next(); } } else { while (offset < 0) { offset++; lnk= lnk->Prev(); } } return lnk; } void ObjList::RemoveLink(ObjLink *lnk) { if (HasIterators()) ForEachIterDo(ObjListIter, OnRemove(lnk)); lnk->prev->next= lnk->next; lnk->next->prev= lnk->prev; DeleteLink(lnk); } void ObjList::InsertLink(Object *op, ObjLink *prev) { NewLink(op, prev); size++; Changed(); } //---- ObjListIter ------------------------------------------------------------ ObjListIter::ObjListIter(ObjList *s) { list= s; ce= 0; } ObjListIter::~ObjListIter() { Terminate(); } void ObjListIter::Reset() { Iterator::Reset(); ce= 0; } Object* ObjListIter::operator()() { if (! Activated()) if (Activate()) ce= list->head; if (! Terminated()) { ce= ce->Next(); Object *op= ce->GetObject(); if (op) return op; Terminate(); return 0; } return 0; } Container *ObjListIter::GetContainer() { return list; } void ObjListIter::Detach() { list= 0; Iterator::Detach(); } void ObjListIter::OnEmpty() { if (IsActive()) ce= list->head; } void ObjListIter::OnRemove(ObjLink *lnk) { if (IsActive() && lnk == ce) ce= ce->prev; } //---- RevObjListIter --------------------------------------------------------- RevObjListIter::RevObjListIter(ObjList *s) : ObjListIter(s) { } Object* RevObjListIter::operator()() { if (! Activated()) if (Activate()) ce= list->head; if (! Terminated()) { ce= ce->Prev(); Object *op= ce->GetObject(); if (op) return op; Terminate(); return 0; } return 0; } void RevObjListIter::OnRemove(ObjLink *lnk) { if (IsActive() && lnk == ce) ce= ce->Next(); }