#include "Col.ph" #ifdef __GNUG__ #pragma implementation #endif #include "Container.h" #include "Class.h" #include "IterIter.h" #include "Error.h" #include "String.h" #include "ET_stdio.h" const char *cWarningActiveIterator= "there are active iterators", *cWarningNullArgument = "argument is a null pointer"; //---- Container --------------------------------------------------------------- NewAbstractMetaImpl(Container,Object, (T(size), T(nDeleted), T(iterCount))); Container *Container::currentContainer; Container::Container() { size= nDeleted= iterCount= 0; iterHead.Init(); } Container::~Container() { if (HasIterators()) DetachIterators(); } void Container::InitNew() { size= nDeleted= iterCount= 0; iterHead.Init(); } int Container::Capacity() { return size; } bool Container::assertclass(Class *cl) { register Object *op; Iter next(this); bool error= FALSE; if (cl == 0) { Error("assertclass", "class == 0"); return TRUE; } for (int i= 0; op= next(); i++) if (! op->IsA()->isKindOf(cl)) { Error("assertclass", "element %d is not instance of class %s (%s)", i, cl->Name(), op->ClassName()); error= TRUE; } return error; } void Container::InspectorId(char *b, int sz) { static char cb[100]; Object *op= AnyElement(); if (op) sprintf(cb, "[%d] <%s>", Size(), op->ClassName()); else sprintf(cb, "[%d]", Size()); strn0cpy(b, cb, sz-1); } //---- comparing bool Container::IsEqual(Object *col) { if (IsA() != col->IsA()) return FALSE; Iter next1(this), next2((Container*)col); register Object *op1, *op2; for (;;) { op1= next1(); op2= next2(); if (op1 == 0 && op2 == 0) return TRUE; if (op1 == 0 || op2 == 0) break; if (! op1->IsEqual(op2)) break; } return FALSE; } u_long Container::Hash() { Iter next(this); register Object *op; register unsigned long s= 0; while (op= next()) s^= op->Hash(); return s; } //---- accessing Iterator *Container::MakeIterator(bool, void*) { AbstractMethod("MakeIterator"); return 0; } Object *Container::AnyElement() { Iter next(this); return next(); } Object *Container::Find(Object *anOp) { register Object *op; if (anOp == 0) return 0; Iter next(this); while (op= next()) if (op->IsEqual(anOp)) return op; return 0; } Object *Container::FindPtr(Object *anOp) { register Object *op; if (anOp == 0) return 0; Iter next(this); while (op= next()) if (op == anOp) return op; return 0; } int Container::OccurrencesOf(Object *anOp) { register Object *op; register int n= 0; if (anOp == 0) { Warning("OccurrencesOf", cWarningNullArgument); return 0; } Iter next(this); while (op= next()) if (op->IsEqual(anOp)) n++; return n; } int Container::OccurrencesOfPtr(Object *anOp) { register Object *op; register int n= 0; if (anOp == 0) return FALSE; Iter next(this); while (op= next()) if (op == anOp) n++; return n; } //---- object i/o OStream &Container::PrintOn(OStream &os) { Object::PrintOn(os); os << size SP; return os; } IStream &Container::ReadFrom(IStream &is) { Object::ReadFrom(is); is >> size; iterHead.Init(); return is; } //---- robust iterators void Container::IteratorActivates(Iterator *it) { if (it) { iterCount++; it->ChainIn(&iterHead); } else Warning("IteratorActivates", cWarningNullArgument); } void Container::IteratorTerminates(Iterator *it) { if (it) { iterCount--; it->ChainOut(); if (iterCount < 0) Error("IteratorTerminate", "iterCount < 0"); if (HasDeletedObjects() && iterCount <= 0) RemoveDeleted(); } else Warning("IteratorTerminates", cWarningNullArgument); } void Container::DetachIterators() { register Iterator *it, *jt; it= iterHead.next; while (it != &iterHead) { jt= it; it= it->next; jt->Detach(); jt->ChainOut(); } } //---- robust iterators - Deleted Object approach (old style) void Container::RemoveDeleted() { // hook } //---- Iter -------------------------------------------------------------------- Iter::~Iter() { if (seq) { if ((char*)seq == space) seq->~Iterator(); else delete seq; seq= 0; } } void Iter::Reset(Container *coll, bool dir) { if (seq) { if ((char*)seq == space) delete seq; else seq->~Iterator(); seq= 0; } seq= coll->MakeIterator(dir, space); }