sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "UT_STD.H" sl@0: sl@0: // Class CDbBasicWindowStage sl@0: sl@0: CDbBasicWindowStage::CDbBasicWindowStage(const TDbWindow& aWindow) sl@0: : iWindow(aWindow), iRecords(EWindowArrayGranularity), iPos(-1) sl@0: { sl@0: __ASSERT(aWindow.Size()!=aWindow.ENone); sl@0: } sl@0: sl@0: TBool CDbBasicWindowStage::GetRecord(TDbRecordId& aRecordId) sl@0: { sl@0: if (TUint(iPos)>=TUint(iRecords.Count())) sl@0: return EFalse; sl@0: aRecordId=iRecords[iPos]; sl@0: return ETrue; sl@0: } sl@0: sl@0: void CDbBasicWindowStage::Reset() sl@0: // sl@0: // Reset the window to initial state sl@0: // sl@0: { sl@0: CDbDataStage::Reset(); sl@0: iRecords.Reset(); sl@0: iPos=-1; sl@0: } sl@0: sl@0: TBool CDbBasicWindowStage::EvaluateL(TInt& aWork,TDbRecordId& aRecordId,TBool& aAtRow) sl@0: // sl@0: // Do as much work as we can to make the window match the desired shape sl@0: // sl@0: { sl@0: TBool eval=CDbDataStage::EvaluateL(aWork,aRecordId,aAtRow); sl@0: if (!eval) sl@0: { sl@0: eval=DoEvaluateL(aWork); sl@0: aAtRow=GetRecord(aRecordId); sl@0: } sl@0: return eval; sl@0: } sl@0: sl@0: TInt CDbBasicWindowStage::CountL() sl@0: // sl@0: // Window'd views only report the evaluated records sl@0: // sl@0: { sl@0: return iRecords.Count(); sl@0: } sl@0: sl@0: CDbBasicWindowStage::TGoto CDbBasicWindowStage::GotoL(TInt& /*aWork*/,TDbPosition aPosition,TDbRecordId& aRecordId) sl@0: { sl@0: switch (aPosition) sl@0: { sl@0: default: sl@0: __ASSERT(0); sl@0: break; sl@0: case EDbFirst: sl@0: iPos=0; sl@0: break; sl@0: case EDbLast: sl@0: iPos=iRecords.Count()-1; sl@0: break; sl@0: case EDbNext: sl@0: ++iPos; sl@0: break; sl@0: case EDbPrevious: sl@0: --iPos; sl@0: break; sl@0: } sl@0: return GetRecord(aRecordId) ? ESuccess : ENoRow; sl@0: } sl@0: sl@0: TInt CDbBasicWindowStage::Find(TDbRecordId aRecordId,TInt& aPos) sl@0: { sl@0: TKeyArrayFix key(0,ECmpTUint32); sl@0: return iRecords.Find(aRecordId,key,aPos); sl@0: } sl@0: sl@0: TBool CDbBasicWindowStage::GotoL(TDbRecordId aRecordId) sl@0: { sl@0: return Find(aRecordId,iPos)==0; sl@0: } sl@0: sl@0: void CDbBasicWindowStage::ReadRowL(TDbRecordId aRecordId) sl@0: { sl@0: TRAPD(r,CDbDataStage::ReadRowL(aRecordId)); sl@0: if (r==KErrNotFound) sl@0: { sl@0: TInt pos; sl@0: if (Find(aRecordId,pos)==KErrNone) sl@0: { sl@0: iRecords.Delete(pos); sl@0: if (pos0 at end. 0 none sl@0: // sl@0: { sl@0: if (iView==EAll) sl@0: return 0; sl@0: if (iWindow.Size()==iWindow.EUnlimited) sl@0: return KMaxTInt; sl@0: TInt space=iWindow.Size()-iRecords.Count(); sl@0: TInt lag=iPos-iWindow.PreferredPos(); sl@0: switch (iView) sl@0: { sl@0: default: sl@0: __ASSERT(0); sl@0: case EBeginning: sl@0: return space+Max(lag,0); // fill up and use forward lag if any sl@0: case EEnd: sl@0: return Min(lag,0)-space; // fill up backwards and use rear lag if any sl@0: case EMiddle: sl@0: if (lag<0 && iIterPos==EAtBeginning) // use iterator position if we can sl@0: return lag; sl@0: if (space+lag>0) sl@0: return space+lag; sl@0: if (lag<0) sl@0: return lag; sl@0: return 0; sl@0: } sl@0: } sl@0: sl@0: TDbPosition CDbWindowStage::ResetIterToBeginningL() sl@0: { sl@0: for (TInt ii=iRecords.Count();--ii>=0;) sl@0: { sl@0: if (CDbDataStage::GotoL(iRecords[0])) sl@0: return EDbPrevious; sl@0: // has been deleted, try the next one sl@0: iRecords.Delete(0); sl@0: if (iPos>0) sl@0: --iPos; sl@0: } sl@0: // no records to work with, start at the end sl@0: return EDbLast; sl@0: } sl@0: sl@0: TDbPosition CDbWindowStage::ResetIterToEndL() sl@0: { sl@0: for (TInt ii=iRecords.Count();--ii>=0;) sl@0: { sl@0: if (CDbDataStage::GotoL(iRecords[ii])) sl@0: return EDbNext; sl@0: // has been deleted, try the next one sl@0: iRecords.Delete(ii); sl@0: if (iPos>ii) sl@0: --iPos; sl@0: } sl@0: // no records to work with, start at the beginning sl@0: return EDbFirst; sl@0: } sl@0: sl@0: TDbPosition CDbWindowStage::SetIteratorL(TInt anEval) sl@0: // sl@0: // Set the iterator for some work and return the first iterator direction sl@0: // sl@0: { sl@0: switch (iIterPos) sl@0: { sl@0: default: sl@0: __ASSERT(0); sl@0: case EAtBeginning: sl@0: if (anEval<0) sl@0: return EDbPrevious; sl@0: // turn around iterator to work at end sl@0: iIterPos=EAtEnd; sl@0: return ResetIterToEndL(); sl@0: case EAtEnd: sl@0: if (anEval>0) sl@0: return EDbNext; sl@0: // turn around iterator to work at beginning sl@0: iIterPos=EAtBeginning; sl@0: return ResetIterToBeginningL(); sl@0: } sl@0: } sl@0: sl@0: void CDbWindowStage::ExtendAtBeginningL(TInt aRecords,TDbPosition aFirst,TInt& aWork) sl@0: { sl@0: TDbRecordId id=iRecords.Count()>0 ? iRecords[0] : KDbNullRecordId; sl@0: while (aRecords>0) sl@0: { sl@0: switch (CDbDataStage::GotoL(aWork,aFirst,id)) sl@0: { sl@0: default: sl@0: __ASSERT(0); sl@0: case EExhausted: sl@0: return; sl@0: case ESuccess: sl@0: if (iRecords.Count()==iWindow.Size()) sl@0: { // drop last record sl@0: iRecords.Delete(iRecords.Count()-1); sl@0: if (iView==EEnd) sl@0: iView=EMiddle; sl@0: } sl@0: iRecords.InsertL(0,id); sl@0: ++iPos; sl@0: if (aFirst==EDbLast) sl@0: aFirst=EDbPrevious; sl@0: --aRecords; sl@0: break; sl@0: case ENoRow: // no more data that way sl@0: iView=iView==EEnd ? EAll : EBeginning; sl@0: return; sl@0: case ESynchFailure: // have to do some work on the iterator now sl@0: aFirst=ResetIterToBeginningL(); sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: void CDbWindowStage::ExtendAtEndL(TInt aRecords,TDbPosition aFirst,TInt& aWork) sl@0: { sl@0: TDbRecordId id=iRecords.Count()>0 ? iRecords[iRecords.Count()-1] : KDbNullRecordId; sl@0: while (aRecords>0) sl@0: { sl@0: switch (CDbDataStage::GotoL(aWork,aFirst,id)) sl@0: { sl@0: default: sl@0: __ASSERT(0); sl@0: case EExhausted: sl@0: return; sl@0: case ESuccess: sl@0: if (iRecords.Count()==iWindow.Size()) sl@0: { // drop first record sl@0: iRecords.Delete(0); sl@0: --iPos; sl@0: if (iView==EBeginning) sl@0: iView=EMiddle; sl@0: } sl@0: iRecords.AppendL(id); sl@0: if (aFirst==EDbFirst) sl@0: aFirst=EDbNext; sl@0: --aRecords; sl@0: break; sl@0: case ENoRow: sl@0: iView=iView==EBeginning ? EAll : EEnd; sl@0: return; sl@0: case ESynchFailure: sl@0: aFirst=ResetIterToEndL(); sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: TBool CDbWindowStage::DoEvaluateL(TInt& aWork) sl@0: // sl@0: // Do as much work as we can to make the window match the desired shape sl@0: // sl@0: { sl@0: for (;;) sl@0: { sl@0: TInt eval=WhatToEvaluate(); sl@0: if (eval==0) sl@0: return EFalse; sl@0: if (aWork<=0) sl@0: return ETrue; sl@0: TDbPosition dir=SetIteratorL(eval); sl@0: if (eval>0) sl@0: ExtendAtEndL(eval,dir,aWork); sl@0: else sl@0: ExtendAtBeginningL(-eval,dir,aWork); sl@0: } sl@0: } sl@0: sl@0: TBool CDbWindowStage::Unevaluated() sl@0: // sl@0: // Return whether it is worth Evaluating sl@0: // sl@0: { sl@0: return WhatToEvaluate()==0 ? CDbDataStage::Unevaluated() : ETrue; sl@0: }