//Cursor.cpp #include "stdio.h" #include "iostream.h" #include "stdlib.h" #include "math.h" #include "string.h" #include "assert.h" #include "SetDef.h" #include "rankedSetDef.h" #include "subsetHolder.h" Cursor::Cursor(){ Ecount++; cuState = NotInSet; } Cursor::~Cursor() { Ecount--; if (cuState != NotInSet) { fprintf(stderr, "Attempt to destroy a cursor still in set\n"); exit(1); } } /* If set is empty then findFirst and findLast will leave * RM.RM_memberID == NULLmID && cuPtr->cuState == NotInSet * All other attributes of Cursor will be unchanged. * * Find commands consider it an error if Cursor is already in * a set other than "this" set. */ RAandMID RankedSet::findFirst(Cursor * cuPtr) { return findFirstOrLast(cuPtr, First); } RAandMID RankedSet::findLast(Cursor * cuPtr) { return findFirstOrLast(cuPtr, Last); } RAandMID RankedSet::findFirstOrLast(Cursor * cuPtr, insertLocType ilt) { RAandMID RM; if (cuPtr==NULLCursor) { fprintf(stderr, "Attempt to find First or Last with NULL cursor pointer. \n"); exit(5); } if ((cuPtr->cuState!=NotInSet)&&(cuPtr->SetBeingExplored!=this)) { fprintf(stderr, "Attempt to find First or Last with cursor in wrong set.\n"); exit(6); } switch (cuPtr->cuState) { case NotInSet: break; case Loose: removeThisCursorFromLooseCursors(cuPtr); break; case Bound: (cuPtr->smhWhereBound)->removeThisCursorFromBoundCursors(cuPtr); break; default: assert(0==1); //This can't happen } if (nrInSet==0) { RM.RM_memberID=NULLmID; return RM; } cuPtr->SetBeingExplored = this; //in case not already set if (topLevelNr == 0) return (smhPtr->findFirstOrLast(cuPtr, ilt)); /*else*/ return (sshPtr->findFirstOrLast(cuPtr, ilt)); } RAandMID subsetHolder::findFirstOrLast(Cursor * cuPtr, insertLocType ilt) { int place; assert(firstInUseNr>=0); if (ilt == First) place = firstInUseNr; else place = lastInUseNr; if (levelNr>1) return repPtr[place].sshPtr->findFirstOrLast(cuPtr, ilt); //else return repPtr[place].smhPtr->findFirstOrLast(cuPtr, ilt); } RAandMID setMemberHolder::findFirstOrLast(Cursor * cuPtr, insertLocType ilt) { int i; if(ilt == First) assert( (i=firstInUseNr) >=0); else { assert(ilt == Last); assert((i = lastInUseNr) >=0); } return bindCursor(cuPtr, i); } RAandMID setMemberHolder::bindCursor(Cursor * cuPtr, int i) { RAandMID RM; assert (cuPtr != NULLCursor); RM.RM_memberID = memberID[i]; RM.RM_rankingAtt = rankingAtt[i]; cuPtr->cu_memberID = memberID[i]; cuPtr->cu_rankingAtt = rankingAtt[i]; cuPtr->cuState = Bound; cuPtr->slotWhereBound = i; cuPtr->smhWhereBound = this; assert (fileCursorInBoundCursors(cuPtr)==filed); return RM; } fileReturnCode setMemberHolder::fileCursorInBoundCursors(Cursor * cuPtr) { cuPtr->priorCursor=NULLCursor; cuPtr->nextCursor=firstBoundCursor; if (firstBoundCursor!=NULLCursor) firstBoundCursor->priorCursor=cuPtr; firstBoundCursor = cuPtr; partOf->cursorCount++; return filed; } fileReturnCode RankedSet::fileCursorInLooseCursors(Cursor * cuPtr) { assert (cuPtr != NULLCursor); cuPtr->priorCursor=NULLCursor; cuPtr->nextCursor=firstLooseCursor; if (firstLooseCursor!=NULLCursor) firstLooseCursor->priorCursor=cuPtr; firstLooseCursor = cuPtr; cuPtr->cuState = Loose; cursorCount++; return filed; } Cursor * setMemberHolder::removeFirstCursorFromBoundCursors() { Cursor * cuPtr; cuPtr = firstBoundCursor; if(cuPtr != NULLCursor) { cuPtr->cuState =NotInSet; firstBoundCursor = cuPtr->nextCursor; if (firstBoundCursor!=NULLCursor) firstBoundCursor->priorCursor = NULLCursor; cuPtr->nextCursor=NULLCursor; //OK, but not promised partOf->cursorCount--; } return cuPtr; } Cursor * RankedSet::removeFirstCursorFromLooseCursors() { Cursor * cuPtr; cuPtr = firstLooseCursor; if(cuPtr != NULLCursor) { cuPtr->cuState =NotInSet; firstLooseCursor = cuPtr->nextCursor; if (firstLooseCursor!=NULLCursor) firstLooseCursor->priorCursor = NULLCursor; cuPtr->nextCursor=NULLCursor; //OK but not promised cursorCount--; } return cuPtr; } removeReturnCode setMemberHolder::removeThisCursorFromBoundCursors (Cursor * cuPtr) { /* This method must not (and does not) change Cu_mID and * Cu_rankingATT. */ assert (cuPtr->cuState==Bound); assert (cuPtr->smhWhereBound==this); // assert (memberID[cuPtr->slotWhereBound]==cuPtr->Cu_memberID); // Re: above assert: By at least one path memberID[...] was already -1 if(cuPtr->priorCursor==NULLCursor) { assert(firstBoundCursor==cuPtr); firstBoundCursor = cuPtr->nextCursor; } else (cuPtr->priorCursor)->nextCursor = cuPtr->nextCursor; if(cuPtr->nextCursor!=NULLCursor) (cuPtr->nextCursor)->priorCursor = cuPtr->priorCursor; //In any case cuPtr->cuState=NotInSet; partOf->cursorCount--; return removed; } removeReturnCode RankedSet::removeThisCursorFromSet(Cursor * cuPtr) { setMemberHolder * smh; // Check for error conditions if(cuPtr==NULLCursor) { fprintf(stderr, "Error: Trying to remove NULL Cursor from set."); exit(10); } if(cuPtr->cuState==NotInSet) { fprintf(stderr, "Error: Trying to remove Cursor not in set."); exit(11); } if (cuPtr->SetBeingExplored!=this) { fprintf(stderr, "Error: Trying to remove Cursor in different set."); exit(12); } // Remove cursor as appropriate. // Don't decrement cursorCount here. That will be done in a called routine. // Also, cuState == NotInSet will be set if(cuPtr->cuState==Loose) return removeThisCursorFromLooseCursors(cuPtr); //else smh = cuPtr->smhWhereBound; assert(smh != NULL); return smh->removeThisCursorFromBoundCursors(cuPtr); } removeReturnCode RankedSet::removeThisCursorFromLooseCursors (Cursor * cuPtr) { assert(cuPtr!=NULLCursor); assert (cuPtr->cuState==Loose); assert (cuPtr->SetBeingExplored==this); if(cuPtr->priorCursor==NULLCursor) { assert(firstLooseCursor==cuPtr); firstLooseCursor = cuPtr->nextCursor; } else (cuPtr->priorCursor)->nextCursor = cuPtr->nextCursor; if(cuPtr->nextCursor!=NULLCursor) (cuPtr->nextCursor)->priorCursor = cuPtr->priorCursor; //In any case cuPtr->cuState=NotInSet; cursorCount--; return removed; } RAandMID Cursor::findNext() { return findNextOrPrior(Forward); } RAandMID Cursor::findPrior() { return findNextOrPrior(Backward); } RAandMID Cursor::findNextOrPrior(direction d) { /* If Cursor is bound to an SMH, this method tries * to advance the cursor to the member represented by * the next slot in the SMH. If it cannot, because it * is at last slot, the method removes the Cursor from * bound cursors, and from the set for the time being, * and calls RankedSet::findAsInstructed */ RAandMID RM; setMemberHolder * smhPtr; int i,j; if (cuState==NotInSet) { fprintf(stderr, "Attempt to find Next or Prior for Cursor not in a set. \n"); exit(3); } if (cuState==Bound) { smhPtr = smhWhereBound; i = slotWhereBound; assert(smhPtr->memberID[i]==cu_memberID); if(d == Forward) j = smhPtr->nextEnrollmentNr[i]; else j = smhPtr->priorEnrollmentNr[i]; if (j >= 0) { slotWhereBound = j; RM.RM_rankingAtt = smhPtr->rankingAtt[j]; cu_rankingAtt = RM.RM_rankingAtt; RM.RM_memberID = smhPtr->memberID[j]; cu_memberID = RM.RM_memberID; return RM; } // else (j == -1) Cursor moves out of its smh // Remove Cursor from Bound Cursors. Marks as out of set // but setBeingExplored is unchanged. // Use RankedSet method to find next or prior smhPtr->removeThisCursorFromBoundCursors(this); return(SetBeingExplored->findAsInstructed(this, (d==Forward)?NextHigher:NextLower)); } //else cuState==Loose SetBeingExplored->removeThisCursorFromLooseCursors(this); // sets this cuState=NotInSet //but SetBeingExplored is unchanged return (SetBeingExplored->findAsInstructed(this, (d==Forward)?NextHigher:NextLower)); } RAandMID RankedSet::findEqual(Cursor * cuPtr, RAType ra, memberType mID) { //If Cu_memberID is specified, as well as Cu_rankingAtt, //then this specific individual will be sought. //Otherwise, if Cu_memberID == NULLmID, then an individual //with lowest memberID and the specified ranking attribute //will be sought. cuPtr->cu_rankingAtt = ra; cuPtr->cu_memberID =mID; return findAsInstructed(cuPtr, Equal); } RAandMID RankedSet::findEqualOrHigher(Cursor * cuPtr, RAType ra, memberType mID) { cuPtr->cu_rankingAtt = ra; cuPtr->cu_memberID =mID; return findAsInstructed(cuPtr, EqualOrHigher); } RAandMID RankedSet::findEqualOrLower(Cursor * cuPtr, RAType ra, memberType mID) { cuPtr->cu_rankingAtt = ra; cuPtr->cu_memberID =mID; return findAsInstructed(cuPtr, EqualOrLower); } RAandMID RankedSet::findAsInstructed (Cursor * cuPtr, findInstruction fI) { /* * It is considered an error if Cursor is attached to some set * other than "this" set */ RAandMID RM; RAType cuRA; memberType cuMID; setMemberHolder *smh; int i; assert(cuPtr!=NULLCursor); //Is Cursor attached to some other set? if ((cuPtr->cuState != NotInSet)&&(cuPtr->SetBeingExplored!=this)) { printf("Attempt to Find in one set with Cursor attached to another set. \n"); exit(4); } switch (cuPtr->cuState) { case NotInSet: break; case Loose: removeThisCursorFromLooseCursors(cuPtr); break; case Bound: smh = cuPtr->smhWhereBound; i = cuPtr->slotWhereBound; if ( (cuPtr->cu_memberID==smh->memberID[i]) && (cuPtr->cu_rankingAtt==smh->rankingAtt[i]) ) { switch (fI) { case NextHigher: return cuPtr->findNextOrPrior(Forward); case NextLower: return cuPtr->findNextOrPrior(Backward); default: RM.RM_memberID = cuPtr->cu_memberID; RM.RM_rankingAtt = cuPtr->cu_rankingAtt; return RM; } } /*else*/ smh->removeThisCursorFromBoundCursors(cuPtr); break; default: assert(0==1); // This can't happen } //Can we infer that the request cannot be granted? if (nrInSet == 0) goto nonExistent; cuRA = cuPtr->cu_rankingAtt; cuMID = cuPtr->cu_memberID; if (cuMID == NULLmID) { if( ((fI==Equal)||(fI==EqualOrHigher)) && (maxRA < cuRA)) goto nonExistent; if ( (fI==NextHigher)&&(maxRA <= cuRA)) goto nonExistent; if( ((fI == Equal)||(fI == EqualOrLower)) && (minRA > cuRA)) goto nonExistent; if ( (fI==NextLower)&&(minRA >= cuRA)) goto nonExistent; } else //cuMID != NULLmID { if( ((fI == Equal)||(fI == EqualOrHigher)) && ( ((maxRA < cuRA) || (maxRA == cuRA) && (mIDofMax < cuMID) ) ) ) goto nonExistent; if( (fI == NextHigher) && ( ((maxRA < cuRA) || (maxRA == cuRA) && (mIDofMax <= cuMID) ) ) ) goto nonExistent; if( ((fI == Equal)||(fI == EqualOrLower)) && ( ((minRA > cuRA) || (minRA == cuRA) && (mIDofMin > cuMID) ) ) ) goto nonExistent; if( (fI == NextLower) && ( ((minRA > cuRA) || (minRA == cuRA) && (mIDofMin >= cuMID) ) ) ) goto nonExistent; } //mayExist: cuPtr->SetBeingExplored=this; //if set already, doesn't hurt to set again if (topLevelNr == 0) return (smhPtr->findAsInstructed (cuPtr, fI)); assert(topLevelNr>0); return (sshPtr->findAsInstructed (cuPtr, fI)); nonExistent: RM.RM_memberID = NULLmID; assert(cuPtr->cuState==NotInSet); return RM; } RAandMID setMemberHolder::findAsInstructed (Cursor * cuPtr, findInstruction fI) { RAandMID RM; RAType cuRA; memberType cuMID; int i; assert(cuPtr != NULLCursor); cuRA = cuPtr ->cu_rankingAtt; cuMID = cuPtr->cu_memberID; switch (fI) { case EqualOrHigher: assert( (maxRA>cuRA) || ( (maxRA == cuRA) && (mIDofMax>=cuMID) ) ); for (i = firstInUseNr; i >= 0; i = nextEnrollmentNr[i]) if ((cuRA < rankingAtt[i]) || ((cuRA == rankingAtt[i]) && (cuMID <= memberID[i]))) return bindCursor(cuPtr, i); assert(0==1); //This point should not be reached case NextHigher: assert( (maxRA>cuRA) || ( (maxRA == cuRA) && (mIDofMax>cuMID) ) ); for (i = firstInUseNr; i >= 0; i = nextEnrollmentNr[i]) if ((cuRA < rankingAtt[i]) || ((cuRA == rankingAtt[i]) && (cuMID < memberID[i]))) return bindCursor(cuPtr, i); assert(0==1); //This point should not be reached case EqualOrLower: assert( (minRA= 0; i = priorEnrollmentNr[i]) if ((cuRA > rankingAtt[i]) || ((cuRA == rankingAtt[i]) && (cuMID >= memberID[i]))) return bindCursor(cuPtr, i); assert(0==1); //This point should not be reached case NextLower: assert( (minRA= 0; i = priorEnrollmentNr[i]) if ((cuRA > rankingAtt[i]) || ((cuRA == rankingAtt[i]) && (cuMID > memberID[i]))) return bindCursor(cuPtr, i); assert(0==1); //This point should not be reached case Equal: if(cuMID==NULLmID) { assert( (maxRA>=cuRA) && (minRA<=cuRA)); for (i = firstInUseNr; i >= 0; i = nextEnrollmentNr[i]) { if (cuRA < rankingAtt[i]) goto nonExistent; if (cuRA == rankingAtt[i]) return bindCursor(cuPtr, i); } assert(0==1); //This point should not be reached } //else.. assert ( (maxRA > cuRA) || ( (maxRA==cuRA)&&(mIDofMax>=cuMID) ) ); assert ( (minRA < cuRA) || ( (minRA==cuRA)&&(mIDofMin<=cuMID) ) ); for (i = firstInUseNr; i >= 0; i = nextEnrollmentNr[i]) { if ((cuRA < rankingAtt[i]) || ((cuRA==rankingAtt[i])&& (cuMIDcuState==NotInSet); RM.RM_memberID=NULLmID; return RM; } RAandMID subsetHolder::findAsInstructed (Cursor * cuPtr, findInstruction fI) { RAandMID RM; RAType cuRA; memberType cuMID; int i; assert(cuPtr != NULLCursor); cuRA = cuPtr ->cu_rankingAtt; cuMID = cuPtr->cu_memberID; switch (fI) { case EqualOrHigher: assert( (grandMaxRA>cuRA) || ( (grandMaxRA == cuRA) && (mIDofGrandMax>=cuMID) ) ); for (i = firstInUseNr; i >= 0; i = nextRepNr[i]) if ((cuRA < maxRA[i]) || ((cuRA == maxRA[i]) && (cuMID <= mIDofMax[i]))) goto ContinueDownward; assert(0==1); //This point should not be reached case NextHigher: assert( (grandMaxRA>cuRA) || ( (grandMaxRA == cuRA) && (mIDofGrandMax>cuMID) ) ); for (i = firstInUseNr; i >= 0; i = nextRepNr[i]) if ((cuRA < maxRA[i]) || ((cuRA == maxRA[i]) && (cuMID < mIDofMax[i]))) goto ContinueDownward; assert(0==1); //This point should not be reached case EqualOrLower: assert( (grandMinRA= 0; i = priorRepNr[i]) if ((cuRA > minRA[i]) || ((cuRA == minRA[i]) && (cuMID >= mIDofMin[i]))) goto ContinueDownward; assert(0==1); //This point should not be reached case NextLower: assert( (grandMinRA= 0; i = priorRepNr[i]) if ((cuRA > minRA[i]) || ((cuRA == minRA[i]) && (cuMID > mIDofMin[i]))) goto ContinueDownward; assert(0==1); //This point should not be reached case Equal: if (cuMID != NULLmID) { assert( (grandMaxRA>cuRA) || ( (grandMaxRA == cuRA) && (mIDofGrandMax>=cuMID) ) ); assert( (grandMinRA= 0; i = nextRepNr[i]) if ((cuRA < maxRA[i]) || ((cuRA == maxRA[i]) && (cuMID <= mIDofMax[i]))) { if ( (cuRA>minRA[i]) || ((cuRA==minRA[i])&&(cuMID>=mIDofMin[i]))) goto ContinueDownward; /*else*/ goto NonExistent; } assert(0==1); //This point should not be reached } else //cuMID==NULLmID { assert( (grandMaxRA>=cuRA) && (grandMinRA<=cuRA) ); for (i = firstInUseNr; i >= 0; i = nextRepNr[i]) if (cuRA <= maxRA[i]) { if (cuRA >= minRA[i]) goto ContinueDownward; /*else*/ goto NonExistent; } assert(0==1); //This point should not be reached } } NonExistent: RM.RM_memberID = NULLmID; assert (cuPtr->cuState == NotInSet); return RM; ContinueDownward: if (levelNr == 1) return(repPtr[i].smhPtr->findAsInstructed(cuPtr, fI)); //else... return(repPtr[i].sshPtr->findAsInstructed(cuPtr, fI)); }