|
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "UT_STD.H" |
|
17 |
|
18 // Class CDbBasicWindowStage |
|
19 |
|
20 CDbBasicWindowStage::CDbBasicWindowStage(const TDbWindow& aWindow) |
|
21 : iWindow(aWindow), iRecords(EWindowArrayGranularity), iPos(-1) |
|
22 { |
|
23 __ASSERT(aWindow.Size()!=aWindow.ENone); |
|
24 } |
|
25 |
|
26 TBool CDbBasicWindowStage::GetRecord(TDbRecordId& aRecordId) |
|
27 { |
|
28 if (TUint(iPos)>=TUint(iRecords.Count())) |
|
29 return EFalse; |
|
30 aRecordId=iRecords[iPos]; |
|
31 return ETrue; |
|
32 } |
|
33 |
|
34 void CDbBasicWindowStage::Reset() |
|
35 // |
|
36 // Reset the window to initial state |
|
37 // |
|
38 { |
|
39 CDbDataStage::Reset(); |
|
40 iRecords.Reset(); |
|
41 iPos=-1; |
|
42 } |
|
43 |
|
44 TBool CDbBasicWindowStage::EvaluateL(TInt& aWork,TDbRecordId& aRecordId,TBool& aAtRow) |
|
45 // |
|
46 // Do as much work as we can to make the window match the desired shape |
|
47 // |
|
48 { |
|
49 TBool eval=CDbDataStage::EvaluateL(aWork,aRecordId,aAtRow); |
|
50 if (!eval) |
|
51 { |
|
52 eval=DoEvaluateL(aWork); |
|
53 aAtRow=GetRecord(aRecordId); |
|
54 } |
|
55 return eval; |
|
56 } |
|
57 |
|
58 TInt CDbBasicWindowStage::CountL() |
|
59 // |
|
60 // Window'd views only report the evaluated records |
|
61 // |
|
62 { |
|
63 return iRecords.Count(); |
|
64 } |
|
65 |
|
66 CDbBasicWindowStage::TGoto CDbBasicWindowStage::GotoL(TInt& /*aWork*/,TDbPosition aPosition,TDbRecordId& aRecordId) |
|
67 { |
|
68 switch (aPosition) |
|
69 { |
|
70 default: |
|
71 __ASSERT(0); |
|
72 break; |
|
73 case EDbFirst: |
|
74 iPos=0; |
|
75 break; |
|
76 case EDbLast: |
|
77 iPos=iRecords.Count()-1; |
|
78 break; |
|
79 case EDbNext: |
|
80 ++iPos; |
|
81 break; |
|
82 case EDbPrevious: |
|
83 --iPos; |
|
84 break; |
|
85 } |
|
86 return GetRecord(aRecordId) ? ESuccess : ENoRow; |
|
87 } |
|
88 |
|
89 TInt CDbBasicWindowStage::Find(TDbRecordId aRecordId,TInt& aPos) |
|
90 { |
|
91 TKeyArrayFix key(0,ECmpTUint32); |
|
92 return iRecords.Find(aRecordId,key,aPos); |
|
93 } |
|
94 |
|
95 TBool CDbBasicWindowStage::GotoL(TDbRecordId aRecordId) |
|
96 { |
|
97 return Find(aRecordId,iPos)==0; |
|
98 } |
|
99 |
|
100 void CDbBasicWindowStage::ReadRowL(TDbRecordId aRecordId) |
|
101 { |
|
102 TRAPD(r,CDbDataStage::ReadRowL(aRecordId)); |
|
103 if (r==KErrNotFound) |
|
104 { |
|
105 TInt pos; |
|
106 if (Find(aRecordId,pos)==KErrNone) |
|
107 { |
|
108 iRecords.Delete(pos); |
|
109 if (pos<iPos) |
|
110 --iPos; |
|
111 } |
|
112 } |
|
113 __LEAVE_IF_ERROR(r); |
|
114 } |
|
115 |
|
116 TDbRecordId CDbBasicWindowStage::WriteRowL(TWrite aWrite,TSynch aSynch) |
|
117 { |
|
118 TDbRecordId id=CDbDataStage::WriteRowL(aWrite,ENoSynch); |
|
119 if (aWrite==EAppend && iWindow.Size()==iWindow.EUnlimited) |
|
120 { |
|
121 iRecords.AppendL(id); |
|
122 if (aSynch==ESynch) |
|
123 iPos=iRecords.Count()-1; // follow the append |
|
124 } |
|
125 return id; |
|
126 } |
|
127 |
|
128 CDbBasicWindowStage::TDelete CDbBasicWindowStage::DeleteRowL(TDbRecordId& aRecordId,TSynch) |
|
129 // |
|
130 // Remove the row from the window if it is present |
|
131 // |
|
132 { |
|
133 CDbDataStage::DeleteRowL(aRecordId,ENoSynch); |
|
134 if (GotoL(aRecordId)) |
|
135 { |
|
136 iRecords.Delete(iPos); |
|
137 if (GetRecord(aRecordId)) |
|
138 return EDeletedAtNext; |
|
139 } |
|
140 return EDeletedAtEnd; |
|
141 } |
|
142 |
|
143 // Class CDbWindowStage |
|
144 |
|
145 CDbWindowStage::CDbWindowStage(const TDbWindow& aWindow) |
|
146 : CDbBasicWindowStage(aWindow), iIterPos(EAtBeginning), iView(EBeginning) |
|
147 {} |
|
148 |
|
149 void CDbWindowStage::Reset() |
|
150 // |
|
151 // Reset the window to initial state |
|
152 // |
|
153 { |
|
154 CDbBasicWindowStage::Reset(); |
|
155 iIterPos=EAtBeginning; |
|
156 iView=EBeginning; |
|
157 } |
|
158 |
|
159 TInt CDbWindowStage::WhatToEvaluate() |
|
160 // |
|
161 // count of slots to fill, <0 at beginning, >0 at end. 0 none |
|
162 // |
|
163 { |
|
164 if (iView==EAll) |
|
165 return 0; |
|
166 if (iWindow.Size()==iWindow.EUnlimited) |
|
167 return KMaxTInt; |
|
168 TInt space=iWindow.Size()-iRecords.Count(); |
|
169 TInt lag=iPos-iWindow.PreferredPos(); |
|
170 switch (iView) |
|
171 { |
|
172 default: |
|
173 __ASSERT(0); |
|
174 case EBeginning: |
|
175 return space+Max(lag,0); // fill up and use forward lag if any |
|
176 case EEnd: |
|
177 return Min(lag,0)-space; // fill up backwards and use rear lag if any |
|
178 case EMiddle: |
|
179 if (lag<0 && iIterPos==EAtBeginning) // use iterator position if we can |
|
180 return lag; |
|
181 if (space+lag>0) |
|
182 return space+lag; |
|
183 if (lag<0) |
|
184 return lag; |
|
185 return 0; |
|
186 } |
|
187 } |
|
188 |
|
189 TDbPosition CDbWindowStage::ResetIterToBeginningL() |
|
190 { |
|
191 for (TInt ii=iRecords.Count();--ii>=0;) |
|
192 { |
|
193 if (CDbDataStage::GotoL(iRecords[0])) |
|
194 return EDbPrevious; |
|
195 // has been deleted, try the next one |
|
196 iRecords.Delete(0); |
|
197 if (iPos>0) |
|
198 --iPos; |
|
199 } |
|
200 // no records to work with, start at the end |
|
201 return EDbLast; |
|
202 } |
|
203 |
|
204 TDbPosition CDbWindowStage::ResetIterToEndL() |
|
205 { |
|
206 for (TInt ii=iRecords.Count();--ii>=0;) |
|
207 { |
|
208 if (CDbDataStage::GotoL(iRecords[ii])) |
|
209 return EDbNext; |
|
210 // has been deleted, try the next one |
|
211 iRecords.Delete(ii); |
|
212 if (iPos>ii) |
|
213 --iPos; |
|
214 } |
|
215 // no records to work with, start at the beginning |
|
216 return EDbFirst; |
|
217 } |
|
218 |
|
219 TDbPosition CDbWindowStage::SetIteratorL(TInt anEval) |
|
220 // |
|
221 // Set the iterator for some work and return the first iterator direction |
|
222 // |
|
223 { |
|
224 switch (iIterPos) |
|
225 { |
|
226 default: |
|
227 __ASSERT(0); |
|
228 case EAtBeginning: |
|
229 if (anEval<0) |
|
230 return EDbPrevious; |
|
231 // turn around iterator to work at end |
|
232 iIterPos=EAtEnd; |
|
233 return ResetIterToEndL(); |
|
234 case EAtEnd: |
|
235 if (anEval>0) |
|
236 return EDbNext; |
|
237 // turn around iterator to work at beginning |
|
238 iIterPos=EAtBeginning; |
|
239 return ResetIterToBeginningL(); |
|
240 } |
|
241 } |
|
242 |
|
243 void CDbWindowStage::ExtendAtBeginningL(TInt aRecords,TDbPosition aFirst,TInt& aWork) |
|
244 { |
|
245 TDbRecordId id=iRecords.Count()>0 ? iRecords[0] : KDbNullRecordId; |
|
246 while (aRecords>0) |
|
247 { |
|
248 switch (CDbDataStage::GotoL(aWork,aFirst,id)) |
|
249 { |
|
250 default: |
|
251 __ASSERT(0); |
|
252 case EExhausted: |
|
253 return; |
|
254 case ESuccess: |
|
255 if (iRecords.Count()==iWindow.Size()) |
|
256 { // drop last record |
|
257 iRecords.Delete(iRecords.Count()-1); |
|
258 if (iView==EEnd) |
|
259 iView=EMiddle; |
|
260 } |
|
261 iRecords.InsertL(0,id); |
|
262 ++iPos; |
|
263 if (aFirst==EDbLast) |
|
264 aFirst=EDbPrevious; |
|
265 --aRecords; |
|
266 break; |
|
267 case ENoRow: // no more data that way |
|
268 iView=iView==EEnd ? EAll : EBeginning; |
|
269 return; |
|
270 case ESynchFailure: // have to do some work on the iterator now |
|
271 aFirst=ResetIterToBeginningL(); |
|
272 break; |
|
273 } |
|
274 } |
|
275 } |
|
276 |
|
277 void CDbWindowStage::ExtendAtEndL(TInt aRecords,TDbPosition aFirst,TInt& aWork) |
|
278 { |
|
279 TDbRecordId id=iRecords.Count()>0 ? iRecords[iRecords.Count()-1] : KDbNullRecordId; |
|
280 while (aRecords>0) |
|
281 { |
|
282 switch (CDbDataStage::GotoL(aWork,aFirst,id)) |
|
283 { |
|
284 default: |
|
285 __ASSERT(0); |
|
286 case EExhausted: |
|
287 return; |
|
288 case ESuccess: |
|
289 if (iRecords.Count()==iWindow.Size()) |
|
290 { // drop first record |
|
291 iRecords.Delete(0); |
|
292 --iPos; |
|
293 if (iView==EBeginning) |
|
294 iView=EMiddle; |
|
295 } |
|
296 iRecords.AppendL(id); |
|
297 if (aFirst==EDbFirst) |
|
298 aFirst=EDbNext; |
|
299 --aRecords; |
|
300 break; |
|
301 case ENoRow: |
|
302 iView=iView==EBeginning ? EAll : EEnd; |
|
303 return; |
|
304 case ESynchFailure: |
|
305 aFirst=ResetIterToEndL(); |
|
306 break; |
|
307 } |
|
308 } |
|
309 } |
|
310 |
|
311 TBool CDbWindowStage::DoEvaluateL(TInt& aWork) |
|
312 // |
|
313 // Do as much work as we can to make the window match the desired shape |
|
314 // |
|
315 { |
|
316 for (;;) |
|
317 { |
|
318 TInt eval=WhatToEvaluate(); |
|
319 if (eval==0) |
|
320 return EFalse; |
|
321 if (aWork<=0) |
|
322 return ETrue; |
|
323 TDbPosition dir=SetIteratorL(eval); |
|
324 if (eval>0) |
|
325 ExtendAtEndL(eval,dir,aWork); |
|
326 else |
|
327 ExtendAtBeginningL(-eval,dir,aWork); |
|
328 } |
|
329 } |
|
330 |
|
331 TBool CDbWindowStage::Unevaluated() |
|
332 // |
|
333 // Return whether it is worth Evaluating |
|
334 // |
|
335 { |
|
336 return WhatToEvaluate()==0 ? CDbDataStage::Unevaluated() : ETrue; |
|
337 } |